【问题标题】:How to define variables, constrains to Pandas Dataframe when using CVXPY for optimization?使用 CVXPY 进行优化时如何定义变量、约束 Pandas Dataframe?
【发布时间】:2019-01-23 21:42:02
【问题描述】:
import pandas as pd
import numpy as np
import re
import cvxpy as cvx

data = pd.read_excel('Optimality_V3.xlsx', encoding='latin-1')

如您所见,我刚刚导入了一个 csv 文件作为数据框。现在我想使用 CVXPY 库解决一个最大化函数,以识别行数据['D'] 的最佳值,以使数据['B'] 的值之和最大。

我的目标函数是二次的,因为我的决策变量 data['D'] 函数是这样的:

数据['B'] = 数据['C'] * 数据['D']**2 / 数据['E'].

我要分配给每一行数据的约束['D']:

数据['D'] * 0.8

decision_variables = []
variable_constraints = []

for rownum, row in data.iterrows():
    var_ind = str('x' + str(rownum))
    var_ind = cvx.Variable()
    con_ind = var_ind * 0.8 <= var_ind <= var_ind * 1.2 
    decision_variables.append(str(var_ind))
    variable_constraints.append(str(con_ind))

上面的代码是我的尝试。我是 CVXPY 的新手,并试图弄清楚如何使用约束 con_ind 创建名为 var_ind 的变量。

【问题讨论】:

  • data['D'] * 0.8 &lt;= data['D'] &lt;= data['D'] * 1.2 真的很奇怪。你可能想检查你的数学。
  • data['D'] 是一个变量,其范围在自身的 0.8 倍和自身的 1.2 倍之间。我应该更好地提出这个问题,你可以在下面看到一个更新的版本!

标签: pandas mathematical-optimization pulp cvxopt cvxpy


【解决方案1】:

查看文档以获取许多示例:https://www.cvxpy.org/index.html

data = pd.DataFrame(data={
    'A': [1, 2, 3, 4, 5],
    'B': [0, 50, 40, 80, 20],
    'C': [1200, 600, 900, 6500, 200],
    'D': [0.4, 1.2, 0.8, 1.6, 1.1],
    'E': [0.4, 0.5, 0.6, 0.4, 0.5],
    'F': [0.8, 0.4, 1.2, 1.6, 1],
})

x = cvx.Variable(data.index.size)

constraints = [
    x * 0.8 <= x,
    x <= x * 1.2
]
objective = cvx.Minimize(
    cvx.sum(
        cvx.multiply((data['C']/data['E']).tolist(), x**2)
    )
)
prob = cvx.Problem(objective, constraints)
prob.solve()
print x.value

【讨论】:

  • 嘿,戴夫。感谢您的回复……喜欢您如何构建方程式。我使用了您的代码并添加了进一步的约束并且即使我尝试以多种方式重新构建此约束也遇到了错误。你可以在下面看到我更新的问题
【解决方案2】:

我的优化器的目标是计算列 D 的新值,使得新值始终为 (D*0.8

最大化函数为:

cvx.sum[cvx.multiply((data['C']*data['F']/data['D']).tolist(), x)]

我还有一个限制:

cvx.sum[cvx.multiply((data['F']*data['E']*data['C']/data['D']).tolist(), x**2) ] == 数据['C'].sum()

import pandas as pd
import numpy as np
import re
import cvxpy as cvx

data = pd.DataFrame(data={
    'A': [1, 2, 3, 4, 5],
    'B': [100, 50, 40, 80, 20],
    'C': [1200, 600, 900, 6500, 200],
    'D': [0.4, 1.2, 0.8, 1.6, 1.1],
    'E': [0.4, 0.5, 0.6, 0.4, 0.5],
    'F': [0.8, 0.4, 1.2, 1.6, 1],
})

x = cvx.Variable(data.index.size)

现在,我想添加第三个附加二次约束,表示 C 列的总和始终是常数。

constraints = [
    x * 0.8 <= x,
    x <= x * 1.2,
    cvx.sum(
        cvx.multiply((data['F']*data['E']*data['C']/data['D']).tolist(), x**2)
    ) == data['C'].sum()
]

如您所见,最小化函数非常简单并且是线性的。不过,如何将其转换为最大化函数?

objective = cvx.Minimmize(
    cvx.sum(
        cvx.multiply((data['C']*data['F']/data['D']).tolist(), x)
    )
)

prob = cvx.Problem(objective, constraints)
prob.solve()
print(x.value)

我正在阅读 CVXPY 文档,它对我有很大帮助!但我没有看到任何具有与我的类似设计的第三个约束的示例,并且我收到错误“DCPError:问题不遵循 DCP 规则。”

【讨论】:

  • 约束必须是线性的,不能添加二次约束。如果无法用绝对值重写问题(如[x &gt;= 1, x &lt;= -1]),则必须使用非线性求解器,如Ipopt。你应该更新问题,而不是像答案一样写。
  • 约束0.8x ≤ x ≤ 1.2x 确实不正确。它只是意味着x≥0
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 2021-04-21
  • 1970-01-01
相关资源
最近更新 更多