I am currently working on modeling a facility location-allocation using optimization with Pyomo module. For my model, I'd like to employ Piecewise linear function, with the constrained variables have two indices. I have tried three approaches that can be seen below, nonetheless none of them seems working properly (or having error)
Does anybody have any ideas on how to solve this?
piece_wise = {'ab': {0:1,1:1,2:2}, 'cd': {0:1,1:1,2:3}, 'ef': {0:1,1:2,2:4}}
piece_wise_ab = {0:1,1:1,2:2}
piece_wise_cd = {0:1,1:1,2:3}
piece_wise_ef = {0:1,1:2,2:4}
################# Option 1 - not working
model.y_ab = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers))
model.arriv_ab = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers))
model.y_cd = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers))
model.arriv_cd = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers))
model.y_ef = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers))
model.arriv_ef = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers))
model.piece_wise_ab = Piecewise(model.Nodes, model.Vehicles, model.arriv_ab, model.y_ab,
pw_pts = list(piece_wise_ab.values()), f_rule = list(piece_wise_ab.keys()), pw_repn = 'SOS2', pw_constr_type='EQ',unbounded_domain_var=True)
model.piece_wise_cd = Piecewise(model.Nodes, model.Vehicles, model.arriv_cd, model.y_cd,
pw_pts = list(piece_wise_cd.values()), f_rule = list(piece_wise_cd.keys()), pw_repn = 'SOS2', pw_constr_type='EQ',unbounded_domain_var=True)
model.piece_wise_ef = Piecewise(model.Nodes, model.Vehicles, model.arriv_cd, model.y_cd,
pw_pts = list(piece_wise_ef.values()), f_rule = list(piece_wise_ef.keys()), pw_repn = 'SOS2', pw_constr_type='EQ',unbounded_domain_var=True)
def service_rule (model,i,veh):
try:
if 'ab' in veh:
return sum(model.arrival [o,d,veh] * model.lam[i,o,d,veh] for o,d in model.sp) <= model.y_ab[i]
elif 'cd' in veh:
return sum(model.arrival [o,d,veh] * model.lam[i,o,d,veh] for o,d in model.sp) <= model.y_cd[i]
elif 'ef' in veh:
return sum(model.arrival [o,d,veh] * model.lam[i,o,d,veh] for o,d in model.sp) <= model.y_ef[i]
except:
return Constraint.Skip
model.service = Constraint(model.Nodes, model.Vehicles, rule = service_rule)
#################################### Option 2 - not working
model.piecewise_constraint = ConstraintList()
all_breakpoints = set(breakpoint for breakpoints in piece_wise.values() for breakpoint in breakpoints)
model.y_pc = Var(model.Nodes, model.Vehicles, within = NonNegativeIntegers, bounds = (0, max_chargers) )
model.arriv_pc = Var(model.Nodes, model.Vehicles, all_breakpoints, within = Binary)
for veh in model.Vehicles:
for node in model.Nodes:
breakpoints = list(piece_wise[veh].keys())
values_at_breakpoints = list(piece_wise[veh].values())
print(breakpoints, all_breakpoints)
model.piecewise_constraint.add(model.y_pc[node, veh] == sum(values_at_breakpoints[k] * model.arriv_pc[node, veh, k] for k in breakpoints))
############################## Option 3 - Not working
for node in model.Nodes:
for veh in model.Vehicles:
if "ab" in veh:
model.piecewise_constraint.add (model.y_pc [node, veh] == Piecewise (expr = [(model.arriv_pc [node, veh], model.y_pc [node, veh])],
pw_pts = list(piece_wise_ab.values()), f_rule = list(piece_wise_ab.keys()), pw_repn = 'SOS2',
pw_constr_type='EQ',unbounded_domain_var=True))
elif "cd" in veh:
model.piecewise_constraint.add (model.y_pc [node, veh] == Piecewise (expr = model.arriv_pc [node, veh],
pw_pts = list(piece_wise_cd.values()), f_rule = list(piece_wise_cd.keys()), pw_repn = 'SOS2',
pw_constr_type='EQ',unbounded_domain_var=True))
elif "ef" in veh:
model.piecewise_constraint.add (model.y_pc [node, veh] == Piecewise (expr = model.arriv_pc [node, veh],
pw_pts = list(piece_wise_ef.values()), f_rule = list(piece_wise_ef.keys()), pw_repn = 'SOS2',
pw_constr_type='EQ',unbounded_domain_var=True))
Thank you in Advance!
Here is an example that develops a piecewise linear constraint between variables
xandy, both of which are dual-indexed variables.You aren't following the dox located here for construction of the Piecewise constraint. Specifically, see the guidance on the f_rule.
Code
Partial Output: