如何在Python Pulp目标函数中使用绝对值?

3

我试图在目标函数中使用绝对值。我想要最小化以下方程的绝对值。

    |(m[i] - (x1 * a1[i] + x2 * a2[i] + x3 * a3[i])|

我尝试了以下方法

from pulp import LpVariable, LpProblem, lpSum, LpMinimize, LpStatus, value
import numpy as np
import pandas as pd

df = pd.DataFrame({
                    'm':[375575.583,367790.9166,353404.7496],
                    'a1':[351170.56,359097.94,321573.44],
                    'a2':[785612.241849173,762821.6656155427,724076.4664063533],
                    'a3':[410363.40625,378311.78125,397014.53125]
                    },index = ['2020-01-01','2020-01-02', '2020-01-03' ])

prob = LpProblem('Ensemble', LpMinimize)

date_index = list(df.index)
a1 = dict(zip(date_index, df.iloc[:,1]))
a2 = dict(zip(date_index, df.iloc[:,2]))
a3 = dict(zip(date_index, df.iloc[:,3]))
m = dict(zip(date_index, df.iloc[:, 0]))

index_var = LpVariable.dict("Date", date_index, lowBound = 0, upBound = 1, cat = 'Continuous')

x1 = LpVariable('x1', lowBound = 0, upBound = 1, cat = 'Continuous')
x2 = LpVariable('x2', lowBound = 0, upBound = 1, cat = 'Continuous')
x3 = LpVariable('x3', lowBound = 0, upBound = 1, cat = 'Continuous')

prob += np.abs(lpSum((m[i] - (x1 * a1[i] + x2 * a2[i] + x3 * a3[i])) for i in date_index))

limit = x1 + x2 + x3
prob += (limit == 1)

prob.solve()
print(LpStatus[prob.status])

for v in prob.variables():
    print(v.name, "=", v.varValue)
value(prob.objective)

并收到以下错误消息:

    prob += np.abs(lpSum((m[i] - (x1 * a1[i] + x2 * a2[i] + x3 * a3[i])) for i in date_index))

    TypeError: bad operand type for abs(): 'LpAffineExpression'

如何使用目标函数差的绝对值?


1
这个回答解决了你的问题吗?:https://stackoverflow.com/a/59566067/4988601 - kabdulla
@kabdulla,我发现你的例子有点难以理解,因为我在Python中实现LP的经验不多。你能否请用我提供的代码来解释一下? - iselim
1个回答

4

一种方法是定义一个变量代表你的和,然后再定义另一个变量代表该和的绝对值,你可以限制这个变量大于和的正负值。

这将约束绝对值参数“至少与总和参数大小相同”。请注意,它可能会更大,但这不是问题,因为问题设置为最小化此绝对值总和变量。

from pulp import LpVariable, LpProblem, lpSum, LpMinimize, LpStatus, value
import numpy as np
import pandas as pd

df = pd.DataFrame({
                    'm':[375575.583,367790.9166,353404.7496],
                    'a1':[351170.56,359097.94,321573.44],
                    'a2':[785612.241849173,762821.6656155427,724076.4664063533],
                    'a3':[410363.40625,378311.78125,397014.53125]
                    },index = ['2020-01-01','2020-01-02', '2020-01-03' ])

prob = LpProblem('Ensemble', LpMinimize)

date_index = list(df.index)
a1 = df['a1']
a2 = df['a2']
a3 = df['a3']
m = df['m']

index_var = LpVariable.dict("Date", date_index, lowBound = 0, upBound = 1, cat = 'Continuous')

x1 = LpVariable('x1', lowBound = 0, upBound = 1, cat = 'Continuous')
x2 = LpVariable('x2', lowBound = 0, upBound = 1, cat = 'Continuous')
x3 = LpVariable('x3', lowBound = 0, upBound = 1, cat = 'Continuous')

# Variable to hold sum
sum_var = LpVariable('sum_var')
abs_sum_var = LpVariable('abs_sum_var')

# Objective
prob += abs_sum_var

# Constraints which define sum_var and abs_sum_var
prob += sum_var == lpSum([(m[i] - (x1 * a1[i] + x2 * a2[i] + x3 * a3[i])) for i in date_index])
prob += abs_sum_var >= sum_var
prob += abs_sum_var >= -sum_var

# Constraint
prob += (x1 + x2 + x3 == 1)

prob.solve()
print(LpStatus[prob.status])

for v in prob.variables():
    print(v.name, "=", v.varValue)
value(prob.objective)

返回:

abs_sum_var = 0.0
sum_var = -1.7462298e-10
x1 = 0.94766587
x2 = 0.052334135
x3 = 0.0 

我怀疑abs_sum_var的小差异和它应该是1.7462298e-10,可能与求解器的约束容忍度有关--你可以修改--参见更改PuLP(用于Python)的约束容忍度


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接