I am using pyomo for optimization in python and I plan to use indices in the range (t_start,t_end). Now these t_start and t_end values are a function of EV such that:
m = pyo.ConcreteModel()
m.EV = pyo.RangeSet(0,len(chargedata))
m.t = pyo.RangeSet(round(100*chargedata['t_start'][m.EV]),round(100*chargedata['t_end'][m.EV]))
Hence the m.t should be:
m.t = [[t_start[EV1],t_end[EV1]],[t_start[EV2],t_end[EV2]],.....]
and I want to use these time values for summing up a function. However, I am receiving the following error:
Constructing component 't' from data=None failed: ValueError: The
truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(),
a.any() or a.all().
How do I solve it? Thanks in advance for your help :)
What you are looking for is an "indexed set" in pyomo
. This is a set that is indexed by another set. You appear to be looking for a set of time periods for each EV. So I'd set it up as below. Note the first parameter in the construction is the set that the other set should be indexed by. When you want to use a set of times within m.EV_T
you have to access it by the EV
index.
Depending on your constraints, you will almost certainly want to have a set of "all available time periods" for various purposes, so I included that too.
There are several ways to "ingest" this data depending on what you are starting with, a dictionary is shown, but it could be a .csv file, data frame, etc.
import pyomo.environ as pyo
from itertools import chain
data = {'Tesla': [2, 3, 4, 5, 6, 7],
'Bolt' : [4, 5, 6],
'Rivian': [13, 14, 15]}
times = set(chain(*data.values()))
all_times = list(range(min(times), max(times)+1))
m = pyo.ConcreteModel()
m.EV = pyo.Set(initialize=data.keys())
m.T = pyo.Set(initialize=all_times)
m.EV_T = pyo.Set(m.EV, initialize=data)
m.pprint()
3 Set Declarations
EV : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {'Tesla', 'Bolt', 'Rivian'}
EV_T : Size=3, Index=EV, Ordered=Insertion
Key : Dimen : Domain : Size : Members
Bolt : 1 : Any : 3 : {4, 5, 6}
Rivian : 1 : Any : 3 : {13, 14, 15}
Tesla : 1 : Any : 6 : {2, 3, 4, 5, 6, 7}
T : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 14 : {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
Below is an enhanced model that shows use of the indexed set. As you discovered, you cannot use the indexed set to index a variable (to my knowledge). You need to "flatten" out the tree set to all pairs and use that for a variable to cover all of the possible combinations. Of note, you could also just index your variable in the full "cross set" of m.EV * m.T, but that is just adding bloat if the combination is sparse.
Anyhow, here is an extension which shows the construction of a convenience "flat set" and a couple of constraints that use this
import pyomo.environ as pyo
from itertools import chain
data = {'Tesla': [2, 3, 4, 5, 6, 7],
'Bolt' : [4, 5, 6],
'Rivian': [13, 14, 15]}
times = set(chain(*data.values()))
all_times = list(range(min(times), max(times)+1))
m = pyo.ConcreteModel()
# SETS
m.EV = pyo.Set(initialize=data.keys())
m.T = pyo.Set(initialize=all_times)
# an indexed set... index is EV
m.EV_T = pyo.Set(m.EV, initialize=data)
# make a "flat" set of the tree set in m.EV_T
m.EV_T_flat = pyo.Set(within=m.EV * m.T, initialize={(k,v) for k in data.keys() for v in data.get(k)})
# VARS
m.charge = pyo.Var(m.EV_T_flat)
# CONSTRAINTS
# each EV can only receive 10 charge units
@m.Constraint(m.EV)
def vehicle_limit(m, ev):
return sum(m.charge[ev, t] for t in m.EV_T[ev]) <= 10
# the charger can only deliver 5 charge units per time period
@m.Constraint(m.T)
def charger_capacity(m, t):
elig_vehicles = {(ev, tt) for (ev, tt) in m.EV_T_flat if tt==t}
# if no elig vehicles, return Skip
if not elig_vehicles:
return pyo.Constraint.Skip
return sum(m.charge[ev, t] for ev in m.EV if (ev, t) in m.EV_T_flat) <= 5
# OBJ
# maximize charge
m.obj = pyo.Objective(expr=sum(m.charge[ev, t] for (ev, t) in m.EV_T_flat), sense=pyo.maximize)
m.pprint()
5 Set Declarations
EV : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {'Tesla', 'Bolt', 'Rivian'}
EV_T : Size=3, Index=EV, Ordered=Insertion
Key : Dimen : Domain : Size : Members
Bolt : 1 : Any : 3 : {4, 5, 6}
Rivian : 1 : Any : 3 : {13, 14, 15}
Tesla : 1 : Any : 6 : {2, 3, 4, 5, 6, 7}
EV_T_flat : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 2 : EV_T_flat_domain : 12 : {('Tesla', 7), ('Tesla', 4), ('Bolt', 5), ('Tesla', 3), ('Rivian', 14), ('Tesla', 6), ('Bolt', 6), ('Rivian', 13), ('Tesla', 5), ('Tesla', 2), ('Rivian', 15), ('Bolt', 4)}
EV_T_flat_domain : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : EV*T : 42 : {('Tesla', 2), ('Tesla', 3), ('Tesla', 4), ('Tesla', 5), ('Tesla', 6), ('Tesla', 7), ('Tesla', 8), ('Tesla', 9), ('Tesla', 10), ('Tesla', 11), ('Tesla', 12), ('Tesla', 13), ('Tesla', 14), ('Tesla', 15), ('Bolt', 2), ('Bolt', 3), ('Bolt', 4), ('Bolt', 5), ('Bolt', 6), ('Bolt', 7), ('Bolt', 8), ('Bolt', 9), ('Bolt', 10), ('Bolt', 11), ('Bolt', 12), ('Bolt', 13), ('Bolt', 14), ('Bolt', 15), ('Rivian', 2), ('Rivian', 3), ('Rivian', 4), ('Rivian', 5), ('Rivian', 6), ('Rivian', 7), ('Rivian', 8), ('Rivian', 9), ('Rivian', 10), ('Rivian', 11), ('Rivian', 12), ('Rivian', 13), ('Rivian', 14), ('Rivian', 15)}
T : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 14 : {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
1 Var Declarations
charge : Size=12, Index=EV_T_flat
Key : Lower : Value : Upper : Fixed : Stale : Domain
('Bolt', 4) : None : None : None : False : True : Reals
('Bolt', 5) : None : None : None : False : True : Reals
('Bolt', 6) : None : None : None : False : True : Reals
('Rivian', 13) : None : None : None : False : True : Reals
('Rivian', 14) : None : None : None : False : True : Reals
('Rivian', 15) : None : None : None : False : True : Reals
('Tesla', 2) : None : None : None : False : True : Reals
('Tesla', 3) : None : None : None : False : True : Reals
('Tesla', 4) : None : None : None : False : True : Reals
('Tesla', 5) : None : None : None : False : True : Reals
('Tesla', 6) : None : None : None : False : True : Reals
('Tesla', 7) : None : None : None : False : True : Reals
1 Objective Declarations
obj : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : charge[Tesla,7] + charge[Tesla,4] + charge[Bolt,5] + charge[Tesla,3] + charge[Rivian,14] + charge[Tesla,6] + charge[Bolt,6] + charge[Rivian,13] + charge[Tesla,5] + charge[Tesla,2] + charge[Rivian,15] + charge[Bolt,4]
2 Constraint Declarations
charger_capacity : Size=9, Index=T, Active=True
Key : Lower : Body : Upper : Active
2 : -Inf : charge[Tesla,2] : 5.0 : True
3 : -Inf : charge[Tesla,3] : 5.0 : True
4 : -Inf : charge[Tesla,4] + charge[Bolt,4] : 5.0 : True
5 : -Inf : charge[Tesla,5] + charge[Bolt,5] : 5.0 : True
6 : -Inf : charge[Tesla,6] + charge[Bolt,6] : 5.0 : True
7 : -Inf : charge[Tesla,7] : 5.0 : True
13 : -Inf : charge[Rivian,13] : 5.0 : True
14 : -Inf : charge[Rivian,14] : 5.0 : True
15 : -Inf : charge[Rivian,15] : 5.0 : True
vehicle_limit : Size=3, Index=EV, Active=True
Key : Lower : Body : Upper : Active
Bolt : -Inf : charge[Bolt,4] + charge[Bolt,5] + charge[Bolt,6] : 10.0 : True
Rivian : -Inf : charge[Rivian,13] + charge[Rivian,14] + charge[Rivian,15] : 10.0 : True
Tesla : -Inf : charge[Tesla,2] + charge[Tesla,3] + charge[Tesla,4] + charge[Tesla,5] + charge[Tesla,6] + charge[Tesla,7] : 10.0 : True
9 Declarations: EV T EV_T EV_T_flat_domain EV_T_flat charge vehicle_limit charger_capacity obj