I am currently attempting to solve a network problem that is not fully connected.Thus,I have attempted to do some preprocessing of data so as to form a set of tuples, e.g. {(a,b , (c,e)}..., i.e. from a to b, from c to e.
I am able to declare binary decision variables with keys such as (a,b), (c,e), via using the set of tuples for indexing.
However, when I tried to use rules to declare constraints, with decision variables such as x[i][j], errors are thrown stating that (a,b) is an invalid index.
Hence, I would like to ask if tuples can be used as indices for decision variables.
If not, is there a way to only declare the only decision variables that are needed, rather than declaring all, and then setting those unneeded to 0.
Thank you!
Welcome to the site.
You certainly CAN index variables with tuples of arbitrary dimensionality. The code I have below shows an example of indexing bad_X
with a tuple of nodes. This makes sense when you have a variable that has a logical representation for all combinations of your indices or you control the indices somehow with smart set notation or you risk a whole bunch of nonsense variables as you can see in my example below with bad_X
in the printout.
For your network, I would suggest just making a set of ARCS that are the valid combination of the NODES. This set would just contain the tuples of the valid connections. Note in my example below, the set of NODES could be blown away as it is not needed. You could just create ARCS directly. Sometimes it is handy to have both if you have some node-based data like supply/demand.
import pyomo.environ as pyo
mdl = pyo.ConcreteModel()
arc_data = { ('a', 'b'): 10,
('c', 'd'): 5,
('e', 'j'): 44,
('a', 'j'): 2,
('j', 'e'): 12}
# collapse the nodes into a set from the keys of the arc data
node_set = set()
for k in arc_data.keys():
node_set.update(*k)
# Sets
mdl.NODES = pyo.Set(initialize=node_set)
mdl.ARCS = pyo.Set(within=mdl.NODES * mdl.NODES, initialize=arc_data.keys())
# Params
mdl.cost = pyo.Param(mdl.NODES, mdl.NODES, initialize=arc_data)
# Selection Variable: poor choice...
mdl.bad_X = pyo.Var(mdl.NODES, mdl.NODES, domain=pyo.Binary)
# some examples of using this "bad X"
print('printing just to show how to access...this will produce a None')
print(mdl.bad_X['a', 'e'].value)
print(mdl.bad_X[('c', 'd')].value) # also valid
# Better selection variable
mdl.X = pyo.Var(mdl.ARCS, domain=pyo.Binary)
# toy constraint...ensure at least 3 are selected
mdl.c1 = pyo.Constraint(expr=sum(mdl.X[arc] for arc in mdl.ARCS) >= 3)
# Objective: Minimize cost of 3 selected arcs
mdl.OBJ = pyo.Objective(expr=sum(mdl.X[arc] * mdl.cost[arc] for arc in mdl.ARCS))
# to show the difference between the choices of variables
mdl.pprint()
# solve and show results
solver = pyo.SolverFactory('cbc')
results = solver.solve(mdl)
for arc in mdl.ARCS:
print(arc, mdl.X[arc].value)
printing just to show how to access...this will produce a None
None
None
5 Set Declarations
ARCS : Dim=0, Dimen=2, Size=5, Domain=ARCS_domain, Ordered=False, Bounds=None
[('a', 'b'), ('a', 'j'), ('c', 'd'), ('e', 'j'), ('j', 'e')]
ARCS_domain : Dim=0, Dimen=2, Size=36, Domain=None, Ordered=False, Bounds=None
Virtual
NODES : Dim=0, Dimen=1, Size=6, Domain=None, Ordered=False, Bounds=None
['a', 'b', 'c', 'd', 'e', 'j']
bad_X_index : Dim=0, Dimen=2, Size=36, Domain=None, Ordered=False, Bounds=None
Virtual
cost_index : Dim=0, Dimen=2, Size=36, Domain=None, Ordered=False, Bounds=None
Virtual
1 Param Declarations
cost : Size=5, Index=cost_index, Domain=Any, Default=None, Mutable=False
Key : Value
('a', 'b') : 10
('a', 'j') : 2
('c', 'd') : 5
('e', 'j') : 44
('j', 'e') : 12
2 Var Declarations
X : Size=5, Index=ARCS
Key : Lower : Value : Upper : Fixed : Stale : Domain
('a', 'b') : 0 : None : 1 : False : True : Binary
('a', 'j') : 0 : None : 1 : False : True : Binary
('c', 'd') : 0 : None : 1 : False : True : Binary
('e', 'j') : 0 : None : 1 : False : True : Binary
('j', 'e') : 0 : None : 1 : False : True : Binary
bad_X : Size=36, Index=bad_X_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('a', 'a') : 0 : None : 1 : False : True : Binary
('a', 'b') : 0 : None : 1 : False : True : Binary
('a', 'c') : 0 : None : 1 : False : True : Binary
('a', 'd') : 0 : None : 1 : False : True : Binary
('a', 'e') : 0 : None : 1 : False : True : Binary
('a', 'j') : 0 : None : 1 : False : True : Binary
('b', 'a') : 0 : None : 1 : False : True : Binary
('b', 'b') : 0 : None : 1 : False : True : Binary
('b', 'c') : 0 : None : 1 : False : True : Binary
('b', 'd') : 0 : None : 1 : False : True : Binary
('b', 'e') : 0 : None : 1 : False : True : Binary
('b', 'j') : 0 : None : 1 : False : True : Binary
('c', 'a') : 0 : None : 1 : False : True : Binary
('c', 'b') : 0 : None : 1 : False : True : Binary
('c', 'c') : 0 : None : 1 : False : True : Binary
('c', 'd') : 0 : None : 1 : False : True : Binary
('c', 'e') : 0 : None : 1 : False : True : Binary
('c', 'j') : 0 : None : 1 : False : True : Binary
('d', 'a') : 0 : None : 1 : False : True : Binary
('d', 'b') : 0 : None : 1 : False : True : Binary
('d', 'c') : 0 : None : 1 : False : True : Binary
('d', 'd') : 0 : None : 1 : False : True : Binary
('d', 'e') : 0 : None : 1 : False : True : Binary
('d', 'j') : 0 : None : 1 : False : True : Binary
('e', 'a') : 0 : None : 1 : False : True : Binary
('e', 'b') : 0 : None : 1 : False : True : Binary
('e', 'c') : 0 : None : 1 : False : True : Binary
('e', 'd') : 0 : None : 1 : False : True : Binary
('e', 'e') : 0 : None : 1 : False : True : Binary
('e', 'j') : 0 : None : 1 : False : True : Binary
('j', 'a') : 0 : None : 1 : False : True : Binary
('j', 'b') : 0 : None : 1 : False : True : Binary
('j', 'c') : 0 : None : 1 : False : True : Binary
('j', 'd') : 0 : None : 1 : False : True : Binary
('j', 'e') : 0 : None : 1 : False : True : Binary
('j', 'j') : 0 : None : 1 : False : True : Binary
1 Objective Declarations
OBJ : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : 10*X[a,b] + 5*X[c,d] + 44*X[e,j] + 2*X[a,j] + 12*X[j,e]
1 Constraint Declarations
c1 : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 3.0 : X[a,b] + X[c,d] + X[e,j] + X[a,j] + X[j,e] : +Inf : True
10 Declarations: NODES ARCS_domain ARCS cost_index cost bad_X_index bad_X X c1 OBJ
('a', 'b') 1.0
('c', 'd') 1.0
('e', 'j') 0.0
('a', 'j') 1.0
('j', 'e') 0.0
[Finished in 4.3s]