Rajarshi Bhadra
Rajarshi Bhadra

Reputation: 1944

Using Rsolnp for optimization

I have data frame which looks like this

> Data_bounded
       Key channel oas        spend      beta        alpha  LB UB        Lower        Upper
1  DRM_BBY     DRM BBY 3.599127e+06 0.4355527 3.790177e+04  30 30 2.519389e+06 4.678865e+06
2  DRM_ESS     DRM ESS 1.560708e+07 1.0000000 0.000000e+00  30 30 1.092496e+07 2.028921e+07
3  DRM_STG     DRM STG 2.053543e+06 0.4846562 6.602477e+04  30 30 1.437480e+06 2.669605e+06
4  DRM_UNU     DRM UNU 2.541332e+06 0.5000000 1.296799e+03  30 30 1.778932e+06 3.303732e+06
5  EML_BBY     EML BBY 0.000000e+00 1.0000000 0.000000e+00   0  0 0.000000e+00 0.000000e+00
6  EML_BTY     EML BTY 0.000000e+00 1.0000000 0.000000e+00   0  0 0.000000e+00 0.000000e+00
7  EML_SHL     EML SHL 0.000000e+00 1.0000000 0.000000e+00   0  0 0.000000e+00 0.000000e+00
8  ETC_BTY     ETC BTY 0.000000e+00 1.0000000 0.000000e+00 100 10 0.000000e+00 0.000000e+00
9  ETC_ESS     ETC ESS 3.040605e+06 0.5430741 3.661138e+03 100 10 0.000000e+00 3.344666e+06
10 ETC_LAM     ETC LAM 2.184844e+07 0.5570489 2.379726e+04 100 10 0.000000e+00 2.403328e+07
11 ETN_ESS     ETN ESS 2.571237e+06 0.5122024 1.400936e+03 100 10 0.000000e+00 2.828361e+06
12 ETN_LAM     ETN LAM 3.446503e+07 0.6619932 5.246261e+03 100 10 0.000000e+00 3.791154e+07
13 ETS_BTY     ETS BTY 0.000000e+00 1.0000000 0.000000e+00 100 10 0.000000e+00 0.000000e+00
14 ETS_ESS     ETS ESS 3.179937e+05 0.5747293 4.705728e+03 100 10 0.000000e+00 3.497930e+05
15 ETS_LAM     ETS LAM 4.071746e+06 0.7597932 2.232724e+03 100 10 0.000000e+00 4.478921e+06
16 FSI_BTY     FSI BTY 7.093370e+04 1.0000000 0.000000e+00   5 60 6.738701e+04 1.134939e+05
17 FSI_STG     FSI STG 5.852890e+05 0.3000000 1.216848e+06   5 60 5.560246e+05 9.364624e+05
18 MAG_BBY     MAG BBY 1.591777e+06 0.5816724 1.753382e+04  10  5 1.432599e+06 1.671366e+06
19 MAG_BTY     MAG BTY 8.526921e+06 0.3000000 1.704103e+05  10  5 7.674229e+06 8.953267e+06
20 MAG_SHL     MAG SHL 5.546460e+05 0.6597280 1.604735e+03  10  5 4.991814e+05 5.823783e+05
21 MAG_UNU     MAG UNU 6.349920e+05 0.7000000 2.145462e+02  10  5 5.714928e+05 6.667416e+05
22 MSM_BTY     MSM BTY 5.953225e+06 1.0000000 0.000000e+00  30 30 4.167258e+06 7.739193e+06
23 MSM_CLI     MSM CLI 3.095554e+05 1.0000000 0.000000e+00  30 30 2.166888e+05 4.024220e+05
24 MSM_STG     MSM STG 2.051692e+06 0.5000000 1.161424e+03  30 30 1.436184e+06 2.667199e+06
25 OND_BBY     OND BBY 1.195467e+06 0.4000000 1.279868e+03  20 20 9.563732e+05 1.434560e+06
26 OND_BTY     OND BTY 7.513692e+05 0.3048512 3.194817e+05  20 20 6.010953e+05 9.016430e+05
27 OND_CLI     OND CLI 1.901847e+05 0.5009272 1.597470e+03  20 20 1.521478e+05 2.282217e+05
28 OND_ESS     OND ESS 8.269617e+05 0.3000000 1.479966e+05  20 20 6.615694e+05 9.923540e+05
29 OND_SHL     OND SHL 2.844579e+06 0.5606207 5.739453e+02  20 20 2.275663e+06 3.413495e+06
30 OND_STG     OND STG 6.673592e+04 1.0000000 0.000000e+00  20 20 5.338874e+04 8.008310e+04
31 OND_UNU     OND UNU 5.940489e+05 0.5097571 1.905513e+03  20 20 4.752391e+05 7.128586e+05
32 OOH_BBY     OOH BBY 3.149710e+05 1.0000000 0.000000e+00  10  5 2.834739e+05 3.307195e+05
33 OOH_BTY     OOH BTY 5.000000e-07 1.0000000 0.000000e+00  10  5 4.500000e-07 5.250000e-07
34 OOH_CLI     OOH CLI 1.299990e+05 0.3000000 1.657615e+04  10  5 1.169991e+05 1.364990e+05
35 OOH_STG     OOH STG 7.059643e+02 1.0000000 0.000000e+00  10  5 6.353679e+02 7.412625e+02
36 PSS_BBY     PSS BBY 9.281210e+05 0.7092288 2.608441e+02  10 10 8.353089e+05 1.020933e+06
37 PSS_BTY     PSS BTY 7.408000e+04 0.4885998 1.246914e+04  10 10 6.667200e+04 8.148800e+04
38 PSS_CLI     PSS CLI 7.849900e+04 0.7897747 1.361035e+02  10 10 7.064910e+04 8.634890e+04
39 PSS_SHL     PSS SHL 1.003498e+06 0.5183048 8.555700e+03  10 10 9.031482e+05 1.103848e+06
40 PSS_STG     PSS STG 3.353000e+05 0.3000000 3.811032e+05  10 10 3.017700e+05 3.688300e+05
41 PSS_UNU     PSS UNU 2.394850e+05 0.4749274 1.651913e+03  10 10 2.155365e+05 2.634335e+05
42 RAD_BBY     RAD BBY 9.182681e+05 0.5000000 1.979574e+03  10 10 8.264413e+05 1.010095e+06
43 RAD_ESS     RAD ESS 0.000000e+00 1.0000000 0.000000e+00  10 10 0.000000e+00 0.000000e+00
44 RAD_STG     RAD STG 2.852897e+06 0.4176579 4.354847e+04  10 10 2.567607e+06 3.138186e+06
45 RCM_BTY     RCM BTY 1.246777e+05 0.4000000 7.491181e+03   0 15 1.246777e+05 1.433794e+05
46 RCM_ESS     RCM ESS 2.242704e+04 1.0000000 0.000000e+00   0 15 2.242704e+04 2.579110e+04
47 RCM_FOB     RCM FOB 1.094317e+06 0.3684433 1.062531e+05   0 15 1.094317e+06 1.258465e+06
48 ROP_CLI     ROP CLI 1.564082e+05 1.0000000 0.000000e+00  20  5 1.251266e+05 1.642286e+05
49 ROP_SHL     ROP SHL 1.512256e+05 0.6284284 2.321274e+01  20  5 1.209804e+05 1.587868e+05
50 ROP_STG     ROP STG 6.431417e+06 0.4100540 1.510802e+04  20  5 5.145133e+06 6.752987e+06
51 STC_ESS     STC ESS 0.000000e+00 1.0000000 0.000000e+00 100 10 0.000000e+00 0.000000e+00
52 STC_LAM     STC LAM 2.822590e+05 0.6630324 6.334003e+03 100 10 0.000000e+00 3.104849e+05
53 STE_LAM     STE LAM 1.023410e+06 0.6736357 4.057302e+03  10  5 9.210691e+05 1.074581e+06
54 STN_ESS     STN ESS 0.000000e+00 1.0000000 0.000000e+00 100 10 0.000000e+00 0.000000e+00
55 STN_LAM     STN LAM 4.273955e+06 0.7610039 3.018853e+03 100 10 0.000000e+00 4.701351e+06
56 STS_ESS     STS ESS 0.000000e+00 1.0000000 0.000000e+00  10  5 0.000000e+00 0.000000e+00
57 STS_LAM     STS LAM 5.558187e+05 0.4623422 5.090183e+04  10  5 5.002369e+05 5.836097e+05
58 VDO_ESS     VDO ESS 2.206729e+06 0.8000000 2.697051e+02   0 15 2.206729e+06 2.537739e+06
59 VDO_LAM     VDO LAM 2.759217e+06 0.7601210 8.131849e+01   0 15 2.759217e+06 3.173100e+06
60 VDO_UNU     VDO UNU 0.000000e+00 1.0000000 0.000000e+00   0 15 0.000000e+00 0.000000e+00

I am using the optimization package Rsolnp

Now my objective is to minimize the function:

-sum(alpha*Spend^beta)

subject to the constraint spend lies between Lower and Upper and that sum of optimum spend values be equal to sum of column spend. However the solution is not yielding any result.Any help will be greatly appreciated. The code I am using is

Data_bounded is my data.

alpha<-Data_bounded$alpha
beta<-Data_bounded$beta

LB_data<-Data_bounded$Lower
UB_data<-Data_bounded$Upper

total_spend<-sum(Data_bounded$spend)

fn1<-function(x)
{
  z<-seq(0,0,length=nrow(Data_bounded))
  for(i in (1:nrow(Data_bounded))){
    z[i]<- alpha[i]*(x[i])^beta[i]
  }
  return(-sum(z))
}



eq1<-function(x)
{
  sum(x)
}


x0 = Data_bounded$spend

opti<-solnp(x0,fun=fn1,LB=LB_data,UB=UB_data,eqfun=eq1,eqB=total_spend)

optimum_spend<-opti$pars

> SAS_soln
   channel oas       spend    beta      alpha     key     UpperBd     LowerBd Optimum_Spend opt_Inc_Sales
1      DRM BBY  3599126.68 0.43555   37901.77 DRM_BBY  4678864.68  2519388.67    4678864.68    30468915.4
2      DRM ESS 15607084.43 1.00000       0.00 DRM_ESS 20289209.76 10924959.10   10924959.10             0
3      DRM STG  2053542.67 0.48466   66024.77 DRM_STG  2669605.47  1437479.87    2669605.47   85965546.97
4      DRM UNU  2541332.00 0.50000    1296.80 DRM_UNU  3303731.59  1778932.40    1778932.40    1729627.27
5      EML BBY        0.00 1.00000       0.00 EML_BBY        0.00        0.00          0.00             .
6      EML BTY        0.00 1.00000       0.00 EML_BTY        0.00        0.00          0.00             .
7      EML SHL        0.00 1.00000       0.00 EML_SHL        0.00        0.00          0.00             .
8      ETC BTY        0.00 1.00000       0.00 ETC_BTY        0.00        0.00          0.00             .
9      ETC ESS  3040605.45 0.54307    3661.14 ETC_ESS  3344666.00        0.00    3344666.00   12788595.53
10     ETC LAM 21848435.35 0.55705   23797.26 ETC_LAM 24033278.89        0.00   24033278.89   307610216.1
11     ETN ESS  2571237.02 0.51220    1400.94 ETN_ESS  2828360.72        0.00    1436429.44    1996155.78
12     ETN LAM 34465032.77 0.66199    5246.26 ETN_LAM 37911536.05        0.00   37911536.05     545688932
13     ETS BTY        0.00 1.00000       0.00 ETS_BTY        0.00        0.00          0.00             .
14     ETS ESS   317993.68 0.57473    4705.73 ETS_ESS   349793.05        0.00     349793.05    7224665.67
15     ETS LAM  4071746.49 0.75979    2232.72 ETS_LAM  4478921.14        0.00    4478921.14   252552248.9
16     FSI BTY    70933.70 1.00000       0.00 FSI_BTY   113493.92    67387.02      67387.02             0
17     FSI STG   585289.02 0.30000 1216848.42 FSI_STG   936462.43   556024.57     936462.43   75280689.89
18     MAG BBY  1591777.00 0.58167   17533.82 MAG_BBY  1671365.85  1432599.30    1671365.85   73057646.57
19     MAG BTY  8526921.00 0.30000  170410.33 MAG_BTY  8953267.05  7674228.90    8660097.95   20547204.92
20     MAG SHL   554646.00 0.65973    1604.74 MAG_SHL   582378.30   499181.40     582378.30   10206360.44
21     MAG UNU   634992.00 0.70000     214.55 MAG_UNU   666741.60   571492.80     666741.60    2560301.93
22     MSM BTY  5953225.18 1.00000       0.00 MSM_BTY  7739192.73  4167257.63    4167257.63             0
23     MSM CLI   309555.42 1.00000       0.00 MSM_CLI   402422.05   216688.80     216688.80             0
24     MSM STG  2051691.88 0.50000    1161.42 MSM_STG  2667199.44  1436184.32    1436184.32    1391860.93
25     OND BBY  1195466.55 0.40000    1279.87 OND_BBY  1434559.86   956373.24     956373.24     315802.98
26     OND BTY   751369.17 0.30485  319481.69 OND_BTY   901643.00   601095.33     901643.00   20885532.25
27     OND CLI   190184.72 0.50093    1597.47 OND_CLI   228221.67   152147.78     228221.67     771932.76
28     OND ESS   826961.70 0.30000  147996.58 OND_ESS   992354.04   661569.36     992354.04     9316476.3
29     OND SHL  2844578.87 0.56062     573.95 OND_SHL  3413494.65  2275663.10    2275663.10    2102793.14
30     OND STG    66735.92 1.00000       0.00 OND_STG    80083.10    53388.74      53388.74             0
31     OND UNU   594048.85 0.50976    1905.51 OND_UNU   712858.62   475239.08     712858.62    1834941.14
32     OOH BBY   314971.00 1.00000       0.00 OOH_BBY   330719.55   283473.90     283473.90             0
33     OOH BTY        0.00 1.00000       0.00 OOH_BTY        0.00        0.00          0.00             .
34     OOH CLI   129999.00 0.30000   16576.15 OOH_CLI   136498.95   116999.10     136498.95     575469.83
35     OOH STG      705.96 1.00000       0.00 OOH_STG      741.26      635.37        635.37             0
36     PSS BBY   928121.00 0.70923     260.84 PSS_BBY  1020933.10   835308.90    1020933.10    4765788.27
37     PSS BTY    74080.00 0.48860   12469.14 PSS_BTY    81488.00    66672.00      81488.00    3128929.49
38     PSS CLI    78499.00 0.78977     136.10 PSS_CLI    86348.90    70649.10      86348.90    1077457.67
39     PSS SHL  1003498.00 0.51830    8555.70 PSS_SHL  1103847.80   903148.20    1103847.80   11596424.97
40     PSS STG   335300.00 0.30000  381103.19 PSS_STG   368830.00   301770.00     368830.00   17827500.41
41     PSS UNU   239485.00 0.47493    1651.91 PSS_UNU   263433.50   215536.50     263433.50     620029.25
42     RAD BBY   918268.08 0.50000    1979.57 RAD_BBY  1010094.89   826441.27    1010094.89    1989541.09
43     RAD ESS        0.00 1.00000       0.00 RAD_ESS        0.00        0.00          0.00             .
44     RAD STG  2852896.79 0.41766   43548.47 RAD_STG  3138186.47  2567607.11    3138186.47      22509301
45     RCM BTY   124677.72 0.40000    7491.18 RCM_BTY   143379.38   124677.72     143379.38     865256.72
46     RCM ESS    22427.04 1.00000       0.00 RCM_ESS    25791.10    22427.04      22427.04             0
47     RCM FOB  1094317.32 0.36844  106253.06 RCM_FOB  1258464.92  1094317.32    1258464.92   18783966.92
48     ROP CLI   156408.20 1.00000       0.00 ROP_CLI   164228.61   125126.56     125126.56             0
49     ROP SHL   151225.56 0.62843      23.21 ROP_SHL   158786.84   120980.45     120980.45      36295.19
50     ROP STG  6431416.66 0.41005   15108.02 ROP_STG  6752987.49  5145133.33    5145133.33    8535764.15
51     STC ESS        0.00 1.00000       0.00 STC_ESS        0.00        0.00          0.00             .
52     STC LAM   282258.99 0.66303    6334.00 STC_LAM   310484.89        0.00     310484.89    27738245.2
53     STE LAM  1023410.08 0.67364    4057.30 STE_LAM  1074580.58   921069.07    1074580.58   46891593.84
54     STN ESS        0.00 1.00000       0.00 STN_ESS        0.00        0.00          0.00             .
55     STN LAM  4273955.04 0.76100    3018.85 STN_LAM  4701350.54        0.00    4701350.54   360935113.7
56     STS ESS        0.00 1.00000       0.00 STS_ESS        0.00        0.00          0.00             .
57     STS LAM   555818.74 0.46234   50901.83 STS_LAM   583609.68   500236.87     583609.68   23586050.24
58     VDO ESS  2206729.31 0.80000     269.71 VDO_ESS  2537738.71  2206729.31    2537738.71   35846491.57
59     VDO LAM  2759217.12 0.76012      81.32 VDO_LAM  3173099.69  2759217.12    3173099.69    7113833.91
60     VDO UNU        0.00 1.00000       0.00 VDO_UNU        0.00        0.00          0.00             .
   Spends_change
1            30%
2           -30%
3            30%
4           -30%
5              .
6              .
7              .
8              .
9            10%
10           10%
11          -44%
12           10%
13             .
14           10%
15           10%
16           -5%
17           60%
18            5%
19            2%
20            5%
21            5%
22          -30%
23          -30%
24          -30%
25          -20%
26           20%
27           20%
28           20%
29          -20%
30          -20%
31           20%
32          -10%
33             .
34            5%
35          -10%
36           10%
37           10%
38           10%
39           10%
40           10%
41           10%
42           10%
43             .
44           10%
45           15%
46         0.00%
47           15%
48          -20%
49          -20%
50          -20%
51             .
52           10%
53            5%
54             .
55           10%
56             .
57            5%
58           15%
59           15%
60             .

Upvotes: 1

Views: 4887

Answers (1)

LyzandeR
LyzandeR

Reputation: 37879

Took me a while to debug but I made it. First of all I made a few improvements to your functions to make them run faster:

library(Rsolnp)

#first thing to do is calculate the sum of data bounded before subsetting
#the Data_bounded data.frame below
total_spend<-sum(Data_bounded$spend)

#those rows with alpha=0 will always have spend=0 since you maximize.
#So, you don't need them in the calculation. You only cause it 
#to be more slow and increase the number of parameters
#when you know that these will always have spend=0
#Therefore I am excluding them
Data_bounded <- na.omit(Data_bounded[Data_bounded$alpha > 0,])

IMPORTANT

Another reason you need to exclude the rows where alpha == 0 is that in many cases you get the lower bound equal to zero and also the upper bound equal to zero i.e. the spend variable cannot take any number and produces NANs and cause the algorithm to fail (as an example see the last row of your data.frame).

alpha<-Data_bounded$alpha
beta<-Data_bounded$beta

#this is what causes big trouble (see below in the answer)
LB_data<-Data_bounded$Lower
UB_data<-Data_bounded$Upper 


#I simplified your objective function. Using a for-loop is
#100 times slower
fn1<-function(spend)
{
  -sum(alpha * spend^beta)
}


#the constraint equation
eq1<-function(spend)
{
  sum(spend)
}

The above settings will cause a non-convergence simply because the range of the lower and upper bounds for each of the parameters are dramatically different:

> summary(LB_data)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
      0  105400  563800 1045000 1433000 7674000 
> summary(UB_data)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
   81490   529000  1089000  3367000  3206000 37910000 

Using these makes the hessian estimation impossible to calculate and the algorithm does not converge:

> solnp(rep(0.5,40),fun=fn1,LB=LB_data,UB=UB_data,eqfun=eq1,eqB=total_spend)

solnp-->The linearized problem has no feasible
solnp-->solution.  The problem may not be feasible.

Iter: 1 fn: -504199815.6409  Pars:  4667300.58566 1428556.94211 1769551.34256       0.50002       0.50002       0.50002       0.50002       0.50002       0.50002  920038.05845 1423762.10411 8943897.27854  506400.51947  655335.69677 1427283.02003 1424483.55152  892622.98201  142709.47599  984386.60168 3367895.50511  472422.09101  107401.43750 1010577.85985   57016.73234   60975.13135 1093896.28870  292081.76334  206116.88396  999731.21048 3128070.24034  115116.37073 1248989.03752  111401.37452 5138141.05109       0.50002 1065101.70687       0.50002  508212.67696 2209897.98640 3164060.56280
solnp--> Solution not reliable....Problem Inverting Hessian.

The only solution is to provide good boundaries for your parameters (the sum of estimated spend will still obviously be equal to total_spend so this is for sure correct). And this will work:

#so just set all the boundaries between 0 and Inf. 
#solnp will easily be able to find the optimal parameters even though
#the search space is big.
#this took a few seconds on my laptop
opti<-solnp(rep(0.5,40),fun=fn1,LB=rep(0,40),UB=rep(Inf,40),eqfun=eq1,eqB=total_spend)

And you got your convergence and optimal values!!

> opti
$pars
 [1] 5.214072e+05 5.457175e+05 1.226056e+02 2.459264e+04 6.727744e+06 4.592510e+02 1.144198e+07 3.482826e+05 2.222721e+07 1.146275e+06 7.594007e+06
[12] 1.338454e+05 1.903417e+05 3.010091e+01 3.705320e+06 1.092090e+00 4.652869e+05 2.935163e+01 3.307376e+03 2.073538e+02 4.628795e+04 1.267862e+03
[23] 4.366613e+02 1.796496e+06 1.396554e+03 3.488297e+06 7.859770e+05 2.858621e+06 1.218379e+02 2.200433e+05 3.241032e+02 3.490860e+04 1.837521e+00
[34] 3.846448e+04 1.237474e+07 1.134505e+07 2.552423e+07 5.201814e+06 1.525503e+06 3.634506e+00

$convergence
[1] 0

EDIT

Now that you showed me the SAS output I can see that you can have a spend amount greater than zero even if the alpha is zero. Keeping this in mind and only excluding cases where the upper and lower limits are zero (spend for these is implied to be zero - same as in the SAS output) this works and converges and uses the actual upper and lower boundaries:

library(Rsolnp)

#first thing to do is calculate the sum of data bounded before subsetting
#the Data_bounded data.frame below
total_spend<-sum(Data_bounded$spend)

Data_bounded <- na.omit(Data_bounded[!(Data_bounded$Lower == 0 & Data_bounded$Upper == 0), ])

alpha<-Data_bounded$alpha
beta<-Data_bounded$beta

#this is what causes big trouble (see below in the answer)
LB_data<-Data_bounded$Lower
UB_data<-Data_bounded$Upper 


#I simplified your objective function. Using a for-loop is
#100 times slower
fn1<-function(spend)
{
  -sum(alpha * spend^beta)
}


#the constraint equation
eq1<-function(spend)
{
  sum(spend)
}


opti<-solnp(rep(0.5,40),fun=fn1,LB=rep(0,40),UB=rep(Inf,40),eqfun=eq1,eqB=total_spend)

Output:

> opti
$pars
 [1] 1.863565e+06 8.537037e-02 4.980553e+06 5.078493e+04 1.756843e+07 2.178128e+07 2.455468e+07 1.681695e+07 7.889301e+06 2.746788e+07
[11] 8.545552e-02 5.534938e+05 7.639648e+06 6.134385e+05 7.901136e+05 2.876899e+06 8.545261e-02 8.545261e-02 2.943462e+03 1.178904e+02
[21] 9.985594e+05 9.349150e+02 5.105370e+05 8.303612e+02 8.545261e-02 3.959562e+05 8.545261e-02 8.545261e-02 9.386337e+05 8.545257e-02
[31] 1.607354e+02 2.848127e+04 2.931769e+02 3.296281e+04 8.193187e+05 3.486277e+06 2.300425e+03 1.352874e+05 2.158217e+04 8.545291e-02

$convergence
[1] 0

Upvotes: 3

Related Questions