I implemented a concrete model in pyomo. It is about a Course planning problem. Courses have to be scheduled within a planning horizon. Teachers, periods and stations have to be linked to the course within a time horizon.
The data for the concrete model is being read from Excel. I ran the model with different data. Everything worked well and correct! I changed my data a bit and following Error Message occured:
ERROR: Rule failed when generating expression for Constraint max_kurs_pro_lehrer_in_periode with index ('AMU', 'CW40-Mon'): ValueError: Invalid constraint expression. The constraint expression resolved to a trivial Boolean (True) instead of a Pyomo object. Please modify your rule to return Constraint.Feasible instead of True. Error thrown for Constraint 'max_kurs_pro_lehrer_in_periode[AMU,CW40-Mon]' ERROR: Constructing component 'max_kurs_pro_lehrer_in_periode' from data=None failed: ValueError: Invalid constraint expression. The constraint expression resolved to a trivial Boolean (True) instead of a Pyomo object. Please modify your rule to return Constraint.Feasible instead of True.
It is about the following constraint:
def max_kurs_pro_lehrer_in_periode_rule(model, l, t): return sum(model.gamma[l, k, s, t] for m in ML[l] if m not in D_gesamt for k in KM[m] for s in SM[m]) <= lcap[l, t] model.max_kurs_pro_lehrer_in_periode = Constraint(L, T, rule=max_kurs_pro_lehrer_in_periode_rule)
The constraint ensures that teacher l is assigned a maximum of lcap(l,t) courses per period. Notation
Indizes and Index sets | Explain |
---|---|
l in L |
Teachers |
m in M |
Course types |
k in K |
Courses |
s in S |
Stations |
t in T |
Periods |
m in ML(l) |
Subset of course types that the teacher l can teach |
k in KM(m) |
Subset of courses corresponding to course type m. |
s in SM(m) |
Subset of stations at which the course type m can take place. |
m in Dgesamt |
Subset of course types that are ignored in this constraint. |
Parameters | Explain |
---|---|
lcap(l,t) | Teacher availability per teacher l and period t. The parameter takes value of 1 if teacher is available in periode t, 0 otherwise. |
Decison variable | Explain |
---|---|
model.gamma(l,k,s,t) | Binary decision variable that takes the value 1 if course k is taught by teacher l at station s in period t, 0 otherwise. |
At first I thought that something went wrong when reading the data. So that for example a 0 or something else was forgotten in Excel. This isn’t the case!
I found out why this Error occurs, but i don’t know how to fix it.
Before I go into the problem in more detail, some knowledge is needed. As mentioned above, a distinction is made here between course types and courses. For example, a course type could be m=Math. It can be that in the considered planning horizon the course type math is demanded three times, so that three courses k=Math-1, k=Math-2 and k=Math-3 have to be scheduled. The mentioned courses belong to the course type math. So {Math:[Math-1,Math-2, Math-3]}
for k in
KM(m).
Let us consider that only the teacher AMU can teach courses of the course type math.
Now, in the considered planning horizon the course type math isn’t demanded. So the index set k in
KM(m]) is empty : {Math:[]}
, because no courses have to be scheduled. This leads to that, that the above presented constraint is for the teacher l=AMU and for all periods t in
T: 0 <= 1 or 0<=0, which is correct, but at the same time leads to the above presented Error. How can I fix that problem? With intensive Research i did not find anything.
I would be really happy, if someone could help me! Thanks in advance!
Advertisement
Answer
You are almost certainly getting this error because the summation inside your constraint is empty, meaning: no members qualify the two conditions.
So you have now:
return sum(<stuff> if <condition>) <= <some fixed parameter>
If no stuff
satisfies condition
then this reduces to:
return 0 <= <some fixed parameter>
and after that is evaluated (it has no variables, so it is just evaluated as a python expression) you are:
return True
So, the easiest fix is to test to see if the subset you want to sum over contains anything, and in the case that it is empty, just skip the constraint like:
temp = {<stuff> if <condition>} if temp is None: return pyo.Constraint.Skip else: return sum(temp) <= <some fixed parameter>