I am trying to solve a model with Pyomo and struggling with indexing. Below is a simple problem instance, where you can also see the error. The message is straightforward and self-explanatory but failed to resolve the issue. It stems from using the k_nearest_vehicles
dictionary which is keyed by the items of the Riders
list. I tried to use Xindex
as solution but didn't quite work. Please let me know where I am doing wrong.
import pyomo.environ as pio
M_threshold = 30
Riders = [(1926.0, 0, 0)]
k_nearest_vehicles = {(1926.0, 0, 0): [(913.0, 0, 36), (913.0, 0, 37), (917.0, 0, 0)]}
zone_to_zone_tt = {(913.0, 1926.0): 27.523453,
(917.0, 1926.0): 29.937351}
m= pio.ConcreteModel('Transportation_Problem')
Xindex = [(i,j) for j in Riders for i in k_nearest_vehicles[j]]
m.x = pio.Var([i for i in k_nearest_vehicles[j] for j in Riders],
[j for j in Riders],domain=pio.NonNegativeReals)
m.OBJ = pio.Objective(expr = (sum((zone_to_zone_tt[i[0],j[0]]-M_threshold)*m.x[i,j]
for (i,j) in Xindex)), sense=pio.minimize)
def Cons1(m,i):
return (sum(m.x[i,j] for j in Riders) <= 1)
m.AxbConstraint1 = pio.Constraint([i for i in k_nearest_vehicles[j] for j in Riders], rule=Cons1)
def Cons2(m,j):
return (sum(m.x[i,j] for i in k_nearest_vehicles[j]) <= 1)
m.AxbConstraint2 = pio.Constraint(Riders, rule=Cons2)
opt = pio.SolverFactory()
results = opt.solve(m, tee=True)
ERROR: Rule failed when generating expression for constraint AxbConstraint1
with index (913.0, 0, 36): TypeError: Cons1() takes 2 positional arguments
but 4 were given
ERROR: Constructing component 'AxbConstraint1' from data=None failed:
TypeError: Cons1() takes 2 positional arguments but 4 were given
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~/anaconda3/lib/python3.7/site-packages/pyomo/core/base/misc.py in apply_indexed_rule(obj, rule, model, index, options)
56 if index.__class__ is tuple:
---> 57 return rule(model, *index)
58 elif index is None and not obj.is_indexed():
TypeError: Cons1() takes 2 positional arguments but 4 were given
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
~/anaconda3/lib/python3.7/site-packages/pyomo/core/base/misc.py in apply_indexed_rule(obj, rule, model, index, options)
71 if options is None:
---> 72 return rule(model)
73 else:
TypeError: Cons1() missing 1 required positional argument: 'i'
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
<ipython-input-62-353b262f79fa> in <module>
14 def Cons1(m,i):
15 return (sum(m.x[i,j] for j in Riders) <= 1)
---> 16 m.AxbConstraint1 = pio.Constraint([i for i in k_nearest_vehicles[j] for j in Riders], rule=Cons1)
17
18 def Cons2(m,j):
~/anaconda3/lib/python3.7/site-packages/pyomo/core/base/block.py in __setattr__(self, name, val)
576 # Pyomo components are added with the add_component method.
577 #
--> 578 self.add_component(name, val)
579 else:
580 #
~/anaconda3/lib/python3.7/site-packages/pyomo/core/base/block.py in add_component(self, name, val)
1129 _blockName, str(data))
1130 try:
-> 1131 val.construct(data)
1132 except:
1133 err = sys.exc_info()[1]
~/anaconda3/lib/python3.7/site-packages/pyomo/core/base/constraint.py in construct(self, data)
777 _init_rule,
778 _self_parent,
--> 779 ndx)
780 except Exception:
781 err = sys.exc_info()[1]
~/anaconda3/lib/python3.7/site-packages/pyomo/core/base/misc.py in apply_indexed_rule(obj, rule, model, index, options)
78 if options is None:
79 if index.__class__ is tuple:
---> 80 return rule(model, *index)
81 elif index is None and not obj.is_indexed():
82 return rule(model)
TypeError: Cons1() takes 2 positional arguments but 4 were given
I also wanted to share the Gurobi way of modeling, which works like a champ. But, I am trying to re-write this in Pyomo to be able to use open source solvers.
from gurobipy import *
m = Model("My_problem")
x = {(i,j):m.addVar(vtype=GRB.CONTINUOUS, name= "x%s"%str([i,j]))
for j in Riders for i in k_nearest_vehicles[j]}
m.setObjective(quicksum((zone_to_zone_tt[i[0],j[0]]-M_threshold)*x[i,j]
for (i,j) in x.keys()), GRB.MINIMIZE)
for i in Vehicles:
m.addConstr(quicksum(x[i,j] for j in Riders if (i,j) in x.keys()) <= 1,
name="each_vehicle_to_at_most_one_rider%s"%([i]))
for j in Riders:
m.addConstr(quicksum(x[i,j] for i in Vehicles if (i,j) in x.keys()) <= 1,
name="each_rider_to_at_most_one_vehicle%s"%([j]))
m.update()
m.optimize()
Riders
andVehicles
. Based on a k-nearest logic, I create a dictionary calledk_nearest_vehicles
which is a subset ofVehicles
for a given rider inRiders
. Hence,k_nearest_vehicles
includes a bunch of unique vehicle ids for a given index inRiders
. $\endgroup$(1926.0, 0, 0)
. In this example, I have three vehicles with ids of(913.0, 0, 36), (913.0, 0, 37), (917.0, 0, 0)
. I understand the confusion. I wish I made an example with two riders. The second rider could have(917.0, 0, 0)
, which appears in the first rider, and some other vehicles. $\endgroup$