在 DocPlex 中将线性表达式传递给二次形式时出错

问题描述

我有一个带有“主动风险”术语的 cplex/docplex 模型。我相信我正在搞乱 Pandas 和 DocPlex 的混合,但我担心我正在尝试做一些不可能的事情。

该术语应该只是二次形式(目标-最优)\Sigma(目标-最优)。

from docplex.mp.advmodel import AdvModel
from numpy import identity
from pandas import Series,DataFrame

model = AdvModel()
assets = ['AAA','BBB','CCC','DDD']
optimal = Series(1 / 4,assets)
covariances = DataFrame(identity(4) * 0.10,index=assets,columns=assets)

target = Series(model.continuous_var_list(assets,name='Target',lb=0,ub=1),index=assets)

active_risk = model.quad_matrix_sum(covariances,target - optimal) / 2
print(active_risk)

给出错误

AttributeError: 'LinearExpr' object has no attribute '_index'

有趣的是,像下面这样的东西是有效的。因此,我可以将所有变量转变为差异,但如果可能,我会尽量避免这种情况,因为这会使优化中的其他复杂术语变得不那么清晰。

# lb,ub are complicated now
difference = Series(model.continuous_var_list(assets,lb=lb,ub=ub),index=assets)
model.quad_matrix_sum(covariances,difference) / 2

解决方法

问题来自两个事件的结合:

  1. Model.quad_sum 需要变量,而不是表达式,如文档中所述
  2. 出于性能原因,类 AdvModel 禁用参数的类型检查。但这可以重新启用。

重新启用 AdvModel 的类型检查(例如调用 AdvModel(checker='on') 会产生正确的错误消息:

docplex.mp.utils.DOcplexException: Expecting an iterable returning variables,docplex.mp.LinearExpr(Target_AAA-0.250) was passed at position 0

要计算表达式的二次形式,请使用 Model.sum(),如下所示:

#active_risk = model.quad_matrix_sum(covariances,target - optimal) / 2
size = len(assets)
active_risk = model.sum(covariances.iloc[i,j] * (target[i] - optimal[i]) * (target[j] - optimal[j])
                        for i in range(size) for j in range(size))

print(active_risk)

产生的结果

0.100Target_AAA^2+0.100Target_BBB^2+0.100Target_CCC^2+0.100Target_DDD^2-0.050Target_AAA-0.050Target_BBB-0.050Target_CCC-0.050Target_DDD+0.025

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...