cvxpy:将非线性约束转换为等效的线性约束
cvxpy: Converting a nonlinear constraint to an equivalent linear constraint
上下文:我是 PyPortfolioOpt 的开发者,这是一个 python 投资组合优化库,我正在尝试允许用户向最大夏普比率问题添加约束。
目前,用户可以将他们的约束作为 lambda 函数传递,例如使所有权重都大于 1%:
ef = EfficientFrontier(mu, S) # mu and S are expected return and covariance
ef.add_constraint(lambda w: w >= 0.01) # example new constraint
ef.min_volatility() # optimise with constraint
在后端,我将一个 cvxpy 变量 w = cp.Variable(n)
传递给约束 lambda 函数,以创建有效的 cvxpy 约束,然后将其传递给 cp.Problem
并解决它。
我遇到的麻烦是最大化夏普比率需要您进行变量替换。 Ax ~ b
形式的约束(其中 ~
表示相等或不等)必须变为 Ax ~ k * b
,其中 k
是非负优化变量。
我尝试的一件事是将 w / k
传递给 lambda 函数。这将导致约束 w / k >= 0.01
,我希望它等同于 w >= k * 0.01
,但遗憾的是,这给出了:
DCPError: Problem does not follow DCP rules. Specifically:
The following constraints are not DCP:
0.01 <= var2817 / Promote(var2818, (20,)) , because the following subexpressions are not:
|-- var2817 / Promote(var2818, (20,))
然后我想我也许可以采用非线性约束 constr = (w / k >= 0.01)
并将其乘以 k
得到 k * constr = (w >= 0.01 * k)
,但你不能在 cvxpy 中乘以约束。
TL;DR:如何将表示 w / k >= 0.01
的 cvxpy 约束对象(已实例化)转换为表示 w >= k * 0.01
的 cvxpy 约束对象?
或者失败了,我有什么办法可以重新设计它吗?我想保留 lambda 函数 API.
Perhaps there is some API for decomposing an already instantiated constraint so that I can put in a variable?
约束在设计上是不可变的。不变性简化了 CVXPY 的大部分逻辑。
为什么不构造一个新的约束?您当然可以检查约束的左侧和右侧。现在,这可以通过检查 args
属性来完成(参见 https://github.com/cvxgrp/cvxpy/blob/master/cvxpy/constraints/nonpos.py#L97)。
上下文:我是 PyPortfolioOpt 的开发者,这是一个 python 投资组合优化库,我正在尝试允许用户向最大夏普比率问题添加约束。
目前,用户可以将他们的约束作为 lambda 函数传递,例如使所有权重都大于 1%:
ef = EfficientFrontier(mu, S) # mu and S are expected return and covariance
ef.add_constraint(lambda w: w >= 0.01) # example new constraint
ef.min_volatility() # optimise with constraint
在后端,我将一个 cvxpy 变量 w = cp.Variable(n)
传递给约束 lambda 函数,以创建有效的 cvxpy 约束,然后将其传递给 cp.Problem
并解决它。
我遇到的麻烦是最大化夏普比率需要您进行变量替换。 Ax ~ b
形式的约束(其中 ~
表示相等或不等)必须变为 Ax ~ k * b
,其中 k
是非负优化变量。
我尝试的一件事是将 w / k
传递给 lambda 函数。这将导致约束 w / k >= 0.01
,我希望它等同于 w >= k * 0.01
,但遗憾的是,这给出了:
DCPError: Problem does not follow DCP rules. Specifically:
The following constraints are not DCP:
0.01 <= var2817 / Promote(var2818, (20,)) , because the following subexpressions are not:
|-- var2817 / Promote(var2818, (20,))
然后我想我也许可以采用非线性约束 constr = (w / k >= 0.01)
并将其乘以 k
得到 k * constr = (w >= 0.01 * k)
,但你不能在 cvxpy 中乘以约束。
TL;DR:如何将表示 w / k >= 0.01
的 cvxpy 约束对象(已实例化)转换为表示 w >= k * 0.01
的 cvxpy 约束对象?
或者失败了,我有什么办法可以重新设计它吗?我想保留 lambda 函数 API.
Perhaps there is some API for decomposing an already instantiated constraint so that I can put in a variable?
约束在设计上是不可变的。不变性简化了 CVXPY 的大部分逻辑。
为什么不构造一个新的约束?您当然可以检查约束的左侧和右侧。现在,这可以通过检查 args
属性来完成(参见 https://github.com/cvxgrp/cvxpy/blob/master/cvxpy/constraints/nonpos.py#L97)。