Reduce expression into a single value
Hello!
I'd just like to start of with saying thanks for all the help I've been getting so far. It's been imperative for my work!
I'm runing into a problem where my model is significantly slowed down due to dense constraints. In my bigger model I'm iterating over 864000 values and for every instance I need to note the value of the previous instance plus the instance of the current instance. (This is a battery state of charge problem).
Below you can find a simpel model that runs.
However I would like to reduce the value of "bat_SOC1" in every instance so that the expression dosen't become so large as in my real model the constraints become extremly dense due to size of the linear expression.
https://www.gurobi.com/documentation/9.0/refman/py_lex_getvalue.html
Something like this but for my expression would be what I need I imagine.
import gurobipy as gp
from gurobipy import GRB
#Declaring decision variables here. Change here to alter model.
up_soc_limit = 0.9
lower_soc_limit = 0.1
intake = 0.1 # kW, power capacity
output = 0.1 # kW, power capacity
in_eff = 0.9
out_eff = 0.9
bat_size = 0.3 # kWh
c_bat_up = bat_size * up_soc_limit #Used in constrains
c_bat_down = bat_size * lower_soc_limit
time = range(11)
e_s = [1,1,1,1,10,10,10,10,10,10,1] # EUR/MWh, sell
e_b = [10,10,10,1,100,100,0,0,0,100,8] # EUR/MWh, buy
m = gp.Model()
time1 = pd.DataFrame() #Create empty dataframe (matrix)
time1["Price_Sell"] = e_s #Add a collumn
time1["Price_Buy"] = e_b
time1["Time"] = time
bat_SOC1 = bat_size / 2
bat_SOC_test = bat_SOC1
tot_rev = []
for i, linerow in time1.iterrows():
bat_out = m.addVar(0,output, name = "sell" ) #Creates a output energy variable with 0 as the lower bound and out as the max bound for the batteries output
bat_in = m.addVar(0,intake, name = "buy") #Creates a charging energy variable with 0 as the lower bound and intake as the max bound for the batteries input
bat_SOC = m.addVar(c_bat_down,c_bat_up,name="bat_SOC")
revenue = bat_out * e_s[i] * out_eff  bat_in * e_b[i]
tot_rev.append(revenue) #add the variables input to the final calculation
bat_delta = bat_in * 0.9  bat_out # Sums the total in  out that was used
bat_SOC1 += bat_delta #Adjusts the battery SoC to the energy that was used.
m.addConstr(bat_SOC1, GRB.EQUAL, bat_SOC)
bob = gp.quicksum(tot_rev)
m.setObjective(bob,GRB.MAXIMIZE) #Maximizes our revenue
m.optimize()
print(bat_SOC1.size()) #Shows the size of our expression
How do I reduce the size of bat_SOC1 so that it only gives me the value at that instance? So at the end it would give me the final bat_SOC1 value?
My problem is that I need the variable bat_SOC to "know" it's value for every timestep and I haven't been able to solve this problem in any other way than this.
I hope I could get some help on this as it's making my larger model unusable due to the size of the expressions that are being generated.
Best regards,
Bill Edwall.

I tried to utilize the .getValue() function but the problem ( I imagine?) is that since the optimization isen't completed yet it can't get the value of the expression before that since the variables aren't set. So I wind up with this error AttributeError: Index out of range for attribute 'X'.
The implementation I tried looking at was adding the expression like this.
bat_SOC2 = bat_SOC1.getValue()
m.addConstr(bat_SOC2, GRB.EQUAL, bat_SOC)I'm thinking of perhaps making a function to sum the value every time through using an optimization to give the variables values but that seems quite strange and I suppose it would break the overall optimization...
EDIT: I'm working on a recursive solution that I think might work but as I'm very unfamiliar with this I'll gladly take any help I can get. Will update if I solve the problem. 
I belive I've resolved my issue. I created a tupledict and stored the values in the tupledict. Its reduced the nonzeros (logs found below) signifigantly but I'll try utilising it in my bigger model tomorrow. This way the constraint dosen't become so dense atleast.
If someone that is more knowledgable than me about these things tell me if they belive that this is a good solution?Logs can be seen here.
1# My new version is first.Old version can be seen here.
Please sign in to leave a comment.
Comments
2 comments