windyvation
windyvation

Reputation: 551

Absolute value formulation for an optimization problem with PuLP

I shared below a simplified version of the problem I'm trying to solve. There must be something wrong in my formulation, perhaps regarding the decision variables. All of the flow is sent to Destination1 by the model, but I am attempting to build a model that would evenly distribute the flow. When I force Destination2 to receive flow with an additional constraint, the objective value improves, so I'm not sure why such a solution is not found instead of the less optimal.

I appreciate your thoughts and am happy to answer any questions about this model.

Warehouses = ["A","B","C","D"]
origin_supply = {"A": 53, "B": 62, "C": 45, "D": 65}
Destinations = ['Destination1','Destination2']
Routes = [(o,d) for o in origin_supply for d in destinations]
model = LpProblem("Testing-absolute-value-objective", LpMinimize)

supply = [53,62,45,65]
destination_mean = sum(supply) / len(destinations)

# decision variables
route_vars = LpVariable.dicts("Route",(Warehouses,Destinations),cat = "Integer", lowBound = 0)
sum_for_diff = LpVariable.dicts("sum",(Destinations),cat = "Continuous")
sum_for_diff_abs = LpVariable.dicts("sum_abs",(Destinations),cat = "Continuous", lowBound = 0)

# objective function is to minimize the absolute value of the difference supplied to the two destinations
obj_func = lpSum(sum_for_diff_abs)

# constraints
# absolute value constraints for the difference
for d in destinations:
    model += sum_for_diff_abs[d] >= sum_for_diff[d]
    model += sum_for_diff_abs[d] >= -sum_for_diff[d]

# The supply constraints (in this case all supply must be sent)
for w in Warehouses:
    model += lpSum([route_vars[w][d] for d in Destinations]) == origin_supply[w]

# calculate the difference from the average amount sent to each destination 
# the reasoning is that in the full model there will be many destinations, so this logic could scale
for d in Destinations:
    model += sum_for_diff[d] == lpSum( route_vars[w][d] for w in Warehouses) - destination_mean 
    
model.solve() 
print(LpStatus[model.status])
print(pulp.value(obj_func))
for v in model.variables():
    print (v.name + " = " + str(v.varValue))

Upvotes: 0

Views: 186

Answers (1)

abc
abc

Reputation: 11929

You are not setting the objective function.
This line

obj_func = lpSum(sum_for_diff_abs)

should be

model+= lpSum(sum_for_diff_abs)

Upvotes: 1

Related Questions