简体   繁体   中英

How to use absolute value in python pulp objective function?

I am trying to use absolute value in the objective function. I want to minimize the absolute value of the following equation

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

I tried the following

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)

and get the following error

    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'

How do I use the absolute value of the difference in the objective function?

One way to do it is to define a variable to represent your sum, and then another variable to represent the absolute value of that sum which you can constrain to be larger than both the positive and negative value of the sum.

This constrains the absolute value varaible to be 'at least as large as the magnitude of the sum variable'. Note that it could be larger but this isn't a problem as the problem is set up to minimize this absolute-value-of-sum variable.

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)

Returns:

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

The small discrepency between the abs_sum_var and what it should be 1.7462298e-10 , I suspect is to do with the constraint tolerance of the solver - which you might be able to modify - see change PuLP's (for Python) constraint tolerance .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM