如何使用 PuLP select 数据帧行进行线性优化

How do I select dataframe rows using PuLP for linear optimisation

我正在尝试解决以下问题:

我有一个包含多列的 pandas 数据框 df。我想找到值 a 和 b 以最大化列 'result' 的总和除以数据帧中的 selected 行数,其中 a 和 b 用于数据帧的 select 行使用以下约束:

df['x'] >= a & df['y'] <= b
2.5 <= a <= 20
0.05 <= b <= 0.35

我尝试使用 PuLP,但之前从未使用过它,因此被卡住了。 这是问题的示例代码以及我如何尝试解决它:

import pandas as pd
from pulp import LpMaximize, LpProblem, LpStatus, lpSum, LpVariable

df = pd.DataFrame({'x': [2.94, 10.33, 8.67, 10.18, 2.82], 'y': [0.34, 0.21, 0.06, 0.24, 0.28], 'result': [-0.5, 9.55, 13.59, -0.2, 11.59]})
model = LpProblem(name='find_values', sense=LpMaximize)
a = LpVariable(name='a', lowBound=2.5, upBound=20)
b = LpVariable(name='b', lowBound=0.05, upBound=0.35)

# add constraints
model += a <= 20
model += b <= 0.35
# Set the objective
model += lpSum(
    df[(df['x'] >= a) & (df['y'] <= b)]['result']) / len(
    df[(df['x'] >= a) & (df['y'] <= b)])

print(model)
model.solve()
# Get the results
print(model.status)
print(LpStatus[model.status])
print(model.objective.value())
print(a.value())
print(b.value())

一旦这是 运行,将显示以下输出:

find_values:
MAXIMIZE
6.806
SUBJECT TO
_C1: a <= 20

_C2: b <= 0.35

VARIABLES
2.5 <= a <= 20 Continuous
0.05 <= b <= 0.35 Continuous

1
Optimal
Objective value
None
2.5
0.05

对我来说,错误似乎出在 objective 函数中,因为模型在那里有一个固定值,表明代码已经被评估。 但是,我不知道我必须如何制定它才能工作,或者这是否可以通过 PuLP 实现。

您只能使用纸浆变量来构建 objective 表达式。但是,由于您的 objective 表达式无法用纸浆变量表示,因此您需要重新表述问题并将其作为 mixed-integer 程序解决。

或者,您可以保留 objective(这似乎不可微分)并使用 black-box 优化 scipy.optimize.dual_annealing。但请注意,此方法不能保证局部最大值:

from scipy.optimize import dual_annealing

def objective(ab):
    a, b = ab
    mask = (df.x >= a) & (df.y <= b)
    if (mask == False).all():
        return -1000.0
    else:
        vals = df[mask].result.values
        return np.sum(vals) / vals.size

# transform the maximization problem into a minimization problem
res = dual_annealing(lambda ab: -1.0*objective(ab), bounds=((2.5, 20.0), (0.05, 0.35)))

这会产生一个解 (a=6.55, b=0.13),objective 值为 13.59。