I am trying to optimize the price reduction for items bought at a local market using weights to determine the price. I have quantities bought by each user, and a certain self-consumption parameter:
cons = {'user1' :np.array([1,2,3,4]),
'user2' : np.array([5,6,7,8]),
'user3' : np.array([0.8,1,5,9]),
'user4' : np.array([16,8,7,1])}
auto = {
'user1': 0.7,
'user2' : 0.6,
'user3' : 0.32,
'user4': 0.44
}
m=GEKKO(remote=False)
m.options.IMODE = 2
m.options.SOLVER = 1
m.options.CV_TYPE = 2
m.options.RTOL=1e-4
m.options.OTOL=1e-4
delta_user = {} # Price reduction for the margin of local-market shared energ
ml_bought={} # quantity bought in the local market
benefit_user = {} # quantity bought in the local market * price (delta)
self_cons = {} # weight factor - self consumption
fondos = m.Const(value =30)
delta_basic = 30/sum(cons['user1'] +cons['user2']+cons['user3']+cons['user4'])
delta_min = delta_basic*0.75
delta_max = delta_basic*1.25
for user in cons:
# min, max and start values are calculated with the mean price to obtain that reduction
delta_user[user] = m.Var(lb = delta_min, ub = delta_max, value= delta_basic)
self_cons[user] = m.Param(auto[user])
ml_bought[user] = m.Param(cons[user])
benefit_user[user] = m.Intermediate(np.sum(ml_bought[user]*delta_user[user]))
# # Function: Sum of all reduced prices for the energy market cannot be greater than the maximum money available for the market.
m.Equation(m.sum([benefit_user[user] for user in cons]) <= fondos)
m.Maximize(m.sum([benefit_user[user]*(self_cons[user]**2) for user in cons]))
m.solve()
The problem is solved, but the quantity obtained in this equation is not smaller than 30 as it should be, but 35.7:
m.Equation(m.sum([benefit_user[user] for user in cons]) <= fondos)
37.5 is the value i get if I use all the maximum values for delta, but there is not enough money for that
Also, my intention is to have 1 delta per user:
delta_use['user1'] = 0.3 #for example
Instead, if I run the following code I get an array
delta_use['user1'] = [0.3, 0.3, 0.3, 0.3] # For example
Clearly something is wrong, I just can't figure out what
In IMODE=2
, use the m.vsum()
function to get a summation across the data dimension.
s = m.Var()
m.Equation(s == m.sum([benefit_user[user] for user in cons]))
m.Equation(m.vsum(s) <= fondos)
This enforces the correct constraint:
sum(s) = 30.0 <fondos 30
To get a single value instead of an array of decision variables, use delta_user[user] = m.FV()
with delta_user[user].STATUS=1
instead of m.Var()
. This calculates a single decision variable across the data dimension. It displays the multiple values with print(delta_user[user].value)
, but they are constrained to be the same value in the optimization problem.
Here is a modified and complete script:
from gekko import GEKKO
import numpy as np
cons = {'user1' :np.array([1,2,3,4]),
'user2' : np.array([5,6,7,8]),
'user3' : np.array([0.8,1,5,9]),
'user4' : np.array([16,8,7,1])}
auto = {
'user1': 0.7,
'user2' : 0.6,
'user3' : 0.32,
'user4': 0.44
}
m=GEKKO(remote=False)
m.options.IMODE = 2
m.options.SOLVER = 1
m.options.CV_TYPE = 2
m.options.RTOL=1e-4
m.options.OTOL=1e-4
delta_user = {} # Price reduction for the margin of local-market shared energ
ml_bought={} # quantity bought in the local market
benefit_user = {} # quantity bought in the local market * price (delta)
self_cons = {} # weight factor - self consumption
fondos = m.Const(value =30)
delta_basic = 30/sum(cons['user1'] +cons['user2']+cons['user3']+cons['user4'])
delta_min = delta_basic*0.75
delta_max = delta_basic*1.25
for user in cons:
# min, max and start values are calculated with the mean price to obtain that reduction
delta_user[user] = m.FV(lb = delta_min, ub = delta_max, value= delta_basic)
delta_user[user].STATUS = 1
self_cons[user] = m.Param(auto[user])
ml_bought[user] = m.Param(cons[user])
benefit_user[user] = m.Intermediate(np.sum(ml_bought[user]*delta_user[user]))
# # Function: Sum of all reduced prices
s = m.Var()
m.Equation(s == m.sum([benefit_user[user] for user in cons]))
m.Equation(m.vsum(s) <= fondos)
m.Maximize(m.sum([benefit_user[user]*(self_cons[user]**2) for user in cons]))
m.solve()
print(f'sum(s) = {sum(s.value)} < fondos {fondos.value}')
for user in cons:
print('-'*30)
print(f'user: {user}')
print(f'delta_user: {delta_user[user].value[0]}')
print(f'self_cons: {self_cons[user].value}')
print(f'ml_bought: {ml_bought[user].value}')
print(f'benefit_user: {benefit_user[user].value}')
Here is the solver output:
Number of state variables: 53
Number of total equations: - 49
Number of slack variables: - 4
---------------------------------------
Degrees of freedom : 0
----------------------------------------------
Model Parameter Estimation with APOPT Solver
----------------------------------------------
Iter Objective Convergence
0 -5.92655E+00 3.00000E+01
1 -8.68352E+00 1.87498E-11
2 -8.68352E+00 1.11022E-16
3 -8.68352E+00 1.11022E-16
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 0.019999999999999997 sec
Objective : -8.683517899761338
Successful solution
---------------------------------------------------
and the printed results:
sum(s) = 30.0 < fondos 30
------------------------------
user: user1
delta_user: 0.44749403341
self_cons: [0.7, 0.7, 0.7, 0.7]
ml_bought: [1.0, 2.0, 3.0, 4.0]
benefit_user: [0.44749403341, 0.89498806683, 1.3424821002, 1.7899761337]
------------------------------
user: user2
delta_user: 0.44749403341
self_cons: [0.6, 0.6, 0.6, 0.6]
ml_bought: [5.0, 6.0, 7.0, 8.0]
benefit_user: [2.2374701671, 2.6849642005, 3.1324582339, 3.5799522673]
------------------------------
user: user3
delta_user: 0.26849642005
self_cons: [0.32, 0.32, 0.32, 0.32]
ml_bought: [0.8, 1.0, 5.0, 9.0]
benefit_user: [0.21479713604, 0.26849642005, 1.3424821002, 2.4164677804]
------------------------------
user: user4
delta_user: 0.30149910501
self_cons: [0.44, 0.44, 0.44, 0.44]
ml_bought: [16.0, 8.0, 7.0, 1.0]
benefit_user: [4.8239856802, 2.4119928401, 2.1104937351, 0.30149910501]