How to Generate Decision Variable Values Iteratively
AnsweredI have a problem that I am trying to model: Given a known table of ToU Tariff Prices and initial State of Charge of BEVs to be charged, find the optimal cheapest charging schedule. The objective function is to minimise the product of tariff and the charging decision i.e. minimise the charging cost.
minCost=gp.quicksum(chargeSchedule[i]*chargePower[i]*tou[i])
m.setObjective(minCost,GRB.MINIMIZE)
I am thinking that there is one binary decision variable chargeSchedule that captures whether or not an EV is charged during a time period, i.
There must also be another variable that captures the state of charge (SoC) of an EV over its charging duration. While I can assign the initial SoC value, I don't know how or if it is possible to refer to a previous SoC(i-1) value to calculate the SoC(i) value? How would I incorporate the binary chargeSchedule variable into the calculation of SoC(i)?
Currently, I am doing the following in Python, which results in a TypeError: unsupported operand type(s) for -: 'generator' and "NoneType".
keyINDEX = [(i, j+1) for i in time_intervalStartINDEX for j in range(len(enterSoC)) ]
SoC = m.addVars(keyINDEX, lb=0.1, ub=0.9, vtype=GRB.CONTINUOUS, name="SoC")
m.addConstr(SoC[i, j] == SoC[i-1, j] +incrementSoC for i in time_intervalStartINDEX for j in range(len(enterSoC)))
Could someone also help me clarify what is the generator data type? I tried deleting the "+incrementSoC" term and still received the same TypeError although i thought SoC[i, j] and SoC[i-1, j] would both be NoneType. Thanks in advance.
-
Hi,
Let us use a simpler example to understand the error. Running the script below results in the exact same error:
TypeError: unsupported operand type(s) for -: 'generator' and 'NoneType'import gurobipy as gp
m = gp.Model()
x = m.addVars(10, name="x")
m.addConstr(x[i] == x[i+1] for i in range(9))The method Model.addConstr(constr, name="" ) is used to add constraints one by one to the model and its first argument should be a TempConstr object. In the example script above, the first argument passed to this method, however, is a generator expression where we are defining 9 constraints in the form \(x_i = x_{i+1}\). The method Model.addConstrs(generator, name="") should be used to add multiple constraints to the model using a Python generator expression. Specifically, the above code should be corrected as below:
m.addConstrs((x[i] == x[i+1] for i in range(9)), name="c")
To learn more about Python generators, please check the Real Python documentation.
Best regards,
Maliheh
1 -
Thank you! This helped me achieve what I wanted.
However, I run into a similar issue when trying to add a condition via m.addGenConstrIndicator().
I want to take x[i+1] = x[i] + someFloat only if a binary decision variable, schedule, at i is true i.e. if schedule[i] == 1, x[i+1] = x[i] + someFloat. else, x[i+1] = x[i]. I think using an indicator constraint is the most direct way to achieve this. However, although I tried to imitate the example given in https://www.gurobi.com/documentation/current/refman/py_model_agc_indicator.html, I get errors again?
Using "Alternative Form"
m.addGenConstrIndicator((schedule[count,b] for count in range(noPeriods) for b in range(noEV)),True,(SoC[count+1,b] == SoC[count,b] +incrementSoC for count in range(noPeriods) for b in range(noEV)))
returns
GurobiError: Invalid lhs argument for general constraint of indicator typeUsing "Overloaded Form"
m.addConstr((schedule[count,b] ==1 for count in range(noPeriods) for b in range(noEV))>>(SoC[count+1,b] == SoC[count,b] +incrementSoC for count in range(noPeriods) for b in range(noEV)))
returns
TypeError: unsupported operand type(s) for >>: 'generator' and 'generator'From the article about indicator constraints, I'm guessing that I can apply m.addGenConstrIndicator() only by referring to each single gurobipy.Var decision variable that is in the tupledict of decision variables generated by m.addVars? However, trying to do so results in a generator, which creates an error. How may I approach this problem?
0 -
Hello again! I found a solution from https://www.gurobi.com/documentation/10.0/refman/py_model_addconstrs.html . However,I don't understand why the following is valid while my original code wasnt?
Example valid code:
m.addConstrs((x[i] == 1) >> (y[i] + z[i] <= 5) for i in range(5))
My original problematic code (using simple variables):
m.addConstr((u[i] ==1 for i in range(9)) >> (x[i+1] == x[i] + 0.5 for i in range(9) ))
Although I found a solution to my programming problem, could I still clarify what the difference in logic was? Why did my original code create an "unsupported operand type(s) for >>: 'generator' and 'generator'" error while the example code here does not?
0 -
Although I found a solution to my programming problem, could I still clarify what the difference in logic was? Why did my original code create an "unsupported operand type(s) for >>: 'generator' and 'generator'" error while the example code here does not?
Its because the for statements should be common for both the brackets, as shown in the example. You cannot have two for statements.
2 -
Yes, Rahul's point is valid.
The expression \( \texttt{(u[i]==1 for i in range(9))}\) is a generator and the expression \(\texttt{(x[i+1] == x[i] + 0.5 for i in range(9)})\) is another generator. The operands of the overloaded \(\texttt{>>}\) operator should be Gurobi expressions and not Python generators. That's why the correct form is \(\texttt{((u[i] == 1) >> (x[i+1] == x[i] + 0.5) for i in range(9))}\).
1
Please sign in to leave a comment.
Comments
5 comments