用纸浆蟒蛇求解模型

时间:2020-08-16 19:15:19

标签: python pulp

我一直在努力解决以下问题: 我将一些值存储在变量 returns 中,我想将它们乘以权重( x_vars ),以求乘积的总和并获得变量 target_return 。如下式:

$$\sum_{i=0}^{n}(returns_i\cdot x_var_i)  = target_return$$

我正在为返回的答案而苦苦挣扎,因为它说x_13 =1。但这是不正确的。我已经尝试使用常规约束和弹性来做到这一点,但我没有正确的答案。我可以容忍误差为0.01%。

有猜到吗?

谢谢

import pulp as plp
# Name model
# set variables   
target_return = 0.0204185791833761
returns = [0.025865338474480914,
 0.031617753987556174,
 0.017530329404997325,
 -0.0008543358059154293,
 0.010510143115372461,
 0.012048338516174262,
 0.04959181591738604,
 0.06059545751936519,
 0.05926623356137273,
 0.058971753714631814,
 0.03442022388647947,
 0.013688974565667422,
 0.02104075216985901,
 -0.0021299262578251543,
 0.017882182143459602,
 0.018964184657020766,
 0.005792320704504306,
 0.018823216764509265,
 -0.0015860431556348198,
 0.008352716776521163,
 0.030728674721250515,
 0.016529301951210496,
 0.0184734317514465,
 -0.0008822232596910062,
 0.010912806711330658,
 0.023530497410194418,
 0.0378090116601979,
 0.009456335242604919,
 0.005556382185357922,
 0.020013334218681678,
 0.05852489326632937,
 0.047988175193893645,
 0.016134386609760742,
 0.014350880108888964,
 0.006756782462879585]

# Initialize model
prob=plp.LpProblem("Find Weights Model", plp.LpMinimize)
x_vars=plp.LpVariable.dicts("x", range(0, len(returns)), 0, 1)
for index in range(len(returns)):
    x_vars[index].setInitialValue(0.5)

#Set problem
prob += plp.lpSum([x_vars[i] for i in x_vars]) == 1

#Set constrain
constrain=plp.LpConstraint(plp.lpSum(
    [returns[i]*x_vars[i] for i in range(0, len(returns))]), rhs=target_return)
# To use standard constrain uncomment following line
#prob.addConstraint(constrain)
# To use elastic constrain uncomment following line
elastic_constrain=constrain.makeElasticSubProblem(penalty = 500000,proportionFreeBoundList  =[0.001,0.0001])
prob.extend(elastic_constrain) 


prob.solve(plp.PULP_CBC_CMD(msg=True, warmStart=True))
final_weights={}
for v in prob.variables():
    final_weights[v.name]=v.varValue

print("Status:", plp.LpStatus[prob.status])

final_weights

可能的解决方案:

solution1 = [0.00962135141677065,
0.00962135141677065,
0.0277264834687149,
0.0297957188693739,
0.0324961558793471,
0.030826881062523,
0.0306009427392119,
0.0250863577897657,
0.0234700849350161,
0.0236653284777789,
0.0237085827820698,
0.0273148420035226,
0.0303599573647406,
0.0292800893464517,
0.0326835213770196,
0.0297440370126145,
0.0295851066643113,
0.0315198597719625,
0.0296058126214705,
0.0326036329340179,
0.0311437752841399,
0.0278570759221869,
0.0299427552142207,
0.0296571910611703,
0.0325002521378998,
0.0307677356659276,
0.0289143823239777,
0.0268170787933395,
0.0309816698637205,
0.0315545156635921,
0.0294310019878726,
0.023774220455596,
0.0253219090166822,
0.0300007623180508,
0.0302627332639599]

solution2 = [0.0291039150753347,
0.0291039150753347,
0.028739103831572,
0.0296325128619877,
0.0307984495156388,
0.0300777243941537,
0.0299801757193628,
0.027599206714805,
8.34695965451632E-05,
0.0269856659961344,
0.0270043421537945,
0.0285613748092319,
0.0298761263170002,
0.0294098868961038,
0.0308793458966854,
0.0296102001652331,
0.0295415791679557,
0.0303769265588311,
0.0295505206943934,
0.0308448536374279,
0.0302145485146196,
0.0287954885757358,
0.0296959977222549,
0.0295727013961937,
0.030800217918514,
0.0300521885203749,
0.0292519883685474,
0.0283464607865791,
0.0301445556616913,
0.030391887092054,
0.0294750434895131,
0.0270326804365011,
0.0277009088398652,
0.0297210421051448,
0.0298341506415484]

在excel中,我使用以下配置获得了解决方案: enter image description here

1 个答案:

答案 0 :(得分:1)

我认为您从纸浆(CBC)中获得的解决方案是正确的,只是与Excel中的解决方案不同。要确认遵守约束条件,您可以执行以下操作:

solution3 = [x.value() for x in x_vars.values()]

# objective: 0.0204185791833761
sum(val*returns[i] for i, val in enumerate(solution1))
# 0.02053629325573023
sum(val*returns[i] for i, val in enumerate(solution3))
# 0.02039816058427895

# constraint:
sum(val for i, val in enumerate(solution1))
# 0.9782431569057903
sum(val for i, val in enumerate(solution3))
# 0.999999999

实际上,纸浆的解离目标更近,并且对sum()= 1的约束要尊重得多。