When I solve the following code, the binaries for the lines_selection
variable is not respected by PuLP. Can anyone please point me out to the reason why this could occur?
I've also attached the output LP file for reference.
import pandas as pd
plants = {1:('Plant 1'), 2: ('Plant 2')}
customers = {1: ('Customer 1'), 2: ('Customer 2'), 3: ('Customer 3')}
demands = {1: 50, 2: 50, 3: 25}
line_options = [1, 2]#{1:('Base'), 2: ('Double Base')}
line_options_cost = {1: 0, 2: 10}
line_options_capacity = {1: 50, 2: 100}
costs = {(1, 1): 1, (1, 2): 1.5, (1,3): 1.5, (2,1): 1, (2,2): 1, (2,3): 1}
#Declare the problem
Investment_Decisions_Problem = LpProblem("Investment_Decisions", LpMinimize)
#Variable - Config of plant lines
lines_selection = LpVariable.dicts("Line Selection", [(i, j) for i in line_options for j in plants], cat='binary')
#lines_selection = LpVariable.dicts("Line Selection", [(i, j) for i in line_options for j in plants], lowBound = 0, upBound = 1, cat='interger')
#Variable - Flow of product from plant to customer
flow_vars = LpVariable.dicts("Flow", [(j, k) for j in plants for k in customers], lowBound = 0, cat = 'continuous')
#Adding an internal flow variable
internal_flow = LpVariable.dicts("Flow_Internal", [(j) for j in plants], lowBound = 0, cat = 'continuous')
#Setting objective
total_cost = lpSum(flow_vars[j,k] * costs[j,k] for j in plants for k in customers) + lpSum(lpSum(lines_selection[i,j] * line_options_cost[i] for i in line_options) for j in plants)
# Constraints
# C1 - All customer demand must be satisfied
for k in customers:
Investment_Decisions_Problem += LpConstraint(e = lpSum([flow_vars[j,k] for j in plants]),
sense = LpConstraintEQ,
name = 'Demand_Satisfied_'+str(k),
rhs = demands[k])
# C2 - Flow must be less than capacity
for j in plants:
Investment_Decisions_Problem += LpConstraint(e = lpSum([flow_vars[j,k] for k in customers]) - internal_flow[j],
sense = LpConstraintEQ,
name = 'Equalizing_multi_echlon_flow_'+str(j),
rhs = 0)
# C3 - Balancing internal flow
for j in plants:
Investment_Decisions_Problem += LpConstraint(e = lpSum([lines_selection[i,j] * line_options_capacity[i] for i in line_options]) - internal_flow[j],
sense = LpConstraintEQ,
name = 'Multi_Echelon_Flow_vs_capacity'+str(j),
rhs = 0)
# C4 - Only one line options is possible
for j in plants:
Investment_Decisions_Problem += LpConstraint(e = lpSum([lines_selection[i,j] for i in line_options]),
sense = LpConstraintEQ,
name = 'Only one option'+str(j),
rhs = 1)
# Setting problem objective
Investment_Decisions_Problem.setObjective(total_cost)
# The problem data is written to an .lp file
Investment_Decisions_Problem.writeLP("Investment_Decisions_Flow.lp")
# The problem is solved using PuLP's choice of Solver
Investment_Decisions_Problem.solve()
Output LP file:
* Investment_Decisions *
Minimize
OBJ: Flow_(1,1) + 1.5 Flow(1,2) + 1.5 Flow(1,3) + Flow(2,_1)
- Flow_(2,2) + Flow(2,3) + 10 Line_Selection(2,_1)
- 10 Line_Selection_(2,2) Subject To Demand_Satisfied_1: Flow(1,1) + Flow(2,1) = 50 Demand_Satisfied_2: Flow(1,2) + Flow(2,2) = 50 Demand_Satisfied_3: Flow(1,3) + Flow(2,3) = 25 Equalizing_multi_echlon_flow_1: Flow(1,1) + Flow(1,2) + Flow(1,_3)
- Flow_Internal_1 = 0 Equalizing_multi_echlon_flow_2: Flow_(2,1) + Flow(2,2) + Flow(2,_3)
- Flow_Internal_2 = 0 Multi_Echelon_Flow_vs_capacity1: - Flow_Internal_1 + 50 Line_Selection_(1,_1)
- 100 Line_Selection_(2,1) = 0 Multi_Echelon_Flow_vs_capacity2: - Flow_Internal_2 + 50 Line_Selection(1,_2)
- 100 Line_Selection_(2,2) = 0 Only_one_option1: Line_Selection(1,1) + Line_Selection(2,1) = 1 Only_one_option2: Line_Selection(1,2) + Line_Selection(2,2) = 1 Bounds 0 <= Flow(1,1) 0 <= Flow(1,2) 0 <= Flow(1,3) 0 <= Flow(2,1) 0 <= Flow(2,2) 0 <= Flow(2,3) 0 <= Flow_Internal_1 0 <= Flow_Internal_2 Line_Selection(1,1) free Line_Selection(1,2) free Line_Selection(2,1) free Line_Selection(2,_2) free End
Clearly mentions that
Line_Selection_(1,1) free Line_Selection(1,2) free Line_Selection(2,1) free Line_Selection(2,_2) free
are all free or unrestricted variables. Any idea what I am doing wrong? TIA