Gekko is not respecting the restrictions, and because of that is not being able to find the same solutions as excel solver for example.
Here is the problem to solve, a minimization of errors
from gekko import GEKKO
import numpy as np
obj = 0
obj2 = 0
m = GEKKO(remote=False)
v0 = m.Var(0.002, -0.005, 0.005)
v1 = m.Var(0.004, -0.005, 0.005)
v2 = m.Var(0.002, -0.005, 0.005)
v3 = m.Var(0.002, -0.005, 0.005)
v4 = m.Var(0.002, -0.005, 0.005)
v5 = m.Var(0.001, -0.005, 0.005)
v6 = m.Var(0.003, -0.005, 0.005)
v7 = m.Var(-0.005, -0.005, 0.005)
v8 = m.Var(-0.002, -0.005, 0.005)
v9 = m.Var(-0.001, -0.005, 0.005)
y = []
y.append(v0)
y.append(v1)
y.append(v2)
y.append(v3)
y.append(v4)
y.append(v5)
y.append(v6)
y.append(v7)
y.append(v8)
objetivos = []
obj = 0
pq = []
p = ponderaciones[:9]
p2 = ponderaciones[9:]
r = rentabilidades[:9]
r2 = rentabilidades[9:]
for j in range(len(r2) + len(r)):
if j < (len(r)):
obj += p[j]/(1+y[j])*r[j]
else:
iterator = j - len(r)
obj += p2[iterator]*r2[iterator]
objetivos.append(obj)
pq.append(obj)
a = np.array(objetivos)
b = un_pickle
print(b[0])
z = (np.sum(b[0]- a[0]))**2
m.Minimize(z)
m.solve(disp=False)
print(y)
print('Objective = '+str(m.options.objfcnval*1000000000/5))
I tried to restrict the variables by doing this,
yb = m.Array(m.Var, 0.004, lb = -0.005, ub = 0.005)
but it didn't work either.
The final solution and the variables end like this
[[0.00039421467367], [0.00078856597697], [0.00039428301399], [0.00039428298849], [0.00039428298849], [0.00019714149424], [0.00059142448273], [-0.00096599525378], [-0.0003942834613]]
Objective = 9.2421428926
I'm not sure why the restrictions are not working.
For recreating the problem, i restricted the amount of data, but in the complete case ponderaciones and rentabilidades are dictionaries with many DF insides, in this case they are only a series each.
ponderaciones = pd.Series({'ACC': 0.07645771,
'UAA': 0.0,
'EOAO': 0.000712,
'CIA': 0.0055,
'BJA': 0.01,
'BOEA': 0.03,
'UA': 0.110,
'EOA': 0.0712,
'CI': 0.00557,
'BJ': 0.0161,
'BOE': 0.0355,
'U': 0.0553,
'E': 0.00071231,
'C': 0.005555,
'B': 0.0157,
'E': 0.0335}
)
rentabilidades = pd.Series({'ACC': 0.0035323168,
'UAA': 0.033975,
'EOAO': -0.0016047,
'CIA': -0.00248652,
'BJA': -0.0075425,
'BOEA': 0.0016429,
'UA': 0.550,
'EOA': 0.0512,
'CI': 0.00157,
'BJ': 0.0861,
'BOE': 0.0555,
'U': 0.0593,
'E': 0.00231,
'C': 0.0555,
'B': 0.07,
'E': 0.05
})
un_pickle = [0.00119, 0.00107, 0.0013, 0.00105, 0.00182]
The script gives a solution that is within the bounds -0.005<y<0.005
for all variables. One potential reason that the bounds are not observed is that the solver failed to find a solution. Switching to disp=True
displays the solver output to ensure that a successful solution is found.
EXIT: Optimal Solution Found.
The solution was found.
The final value of the objective function is 0.005269679643169275
---------------------------------------------------
Solver : IPOPT (v3.12)
Solution time : 0.011 sec
Objective : 0.005269679643169275
Successful solution
---------------------------------------------------
[[0.00080192314638], [0.00066898310209], [0.00033248534634], [0.00031046466289], \
[0.00020163446647], [0.00025390495361], [0.004994273964], [0.0049445497412], \
[-0.00031911076974]]
Objective = 1053935.92864
One other thing to check is that the objective function is defined correctly.
z = (np.sum(b[0]- a[0]))**2
m.Minimize(z)
This statement is a summation of only one value with the square **2
on the outside of the summation. If it is sum of squared errors, the square is typically performed before the summation. In this case, it doesn't change the problem outcome because b[0]
and a[0]
are only one value and expression.
from gekko import GEKKO
import numpy as np
import pandas as pd
obj = 0
obj2 = 0
ponderaciones = pd.Series({'ACC': 0.07645771,
'UAA': 0.0,
'EOAO': 0.000712,
'CIA': 0.0055,
'BJA': 0.01,
'BOEA': 0.03,
'UA': 0.110,
'EOA': 0.0712,
'CI': 0.00557,
'BJ': 0.0161,
'BOE': 0.0355,
'U': 0.0553,
'E': 0.00071231,
'C': 0.005555,
'B': 0.0157,
'E': 0.0335}
)
rentabilidades = pd.Series({'ACC': 0.0035323168,
'UAA': 0.033975,
'EOAO': -0.0016047,
'CIA': -0.00248652,
'BJA': -0.0075425,
'BOEA': 0.0016429,
'UA': 0.550,
'EOA': 0.0512,
'CI': 0.00157,
'BJ': 0.0861,
'BOE': 0.0555,
'U': 0.0593,
'E': 0.00231,
'C': 0.0555,
'B': 0.07,
'E': 0.05
})
un_pickle = [0.00119, 0.00107, 0.0013, 0.00105, 0.00182]
m = GEKKO(remote=False)
v0 = m.Var(0.002, -0.005, 0.005)
v1 = m.Var(0.004, -0.005, 0.005)
v2 = m.Var(0.002, -0.005, 0.005)
v3 = m.Var(0.002, -0.005, 0.005)
v4 = m.Var(0.002, -0.005, 0.005)
v5 = m.Var(0.001, -0.005, 0.005)
v6 = m.Var(0.003, -0.005, 0.005)
v7 = m.Var(-0.005, -0.005, 0.005)
v8 = m.Var(-0.002, -0.005, 0.005)
v9 = m.Var(-0.001, -0.005, 0.005)
y = []
y.append(v0)
y.append(v1)
y.append(v2)
y.append(v3)
y.append(v4)
y.append(v5)
y.append(v6)
y.append(v7)
y.append(v8)
objetivos = []
obj = 0
pq = []
p = ponderaciones[:9]
p2 = ponderaciones[9:]
r = rentabilidades[:9]
r2 = rentabilidades[9:]
for j in range(len(r2) + len(r)):
if j < (len(r)):
obj += p[j]/(1+y[j])*r[j]
else:
iterator = j - len(r)
obj += p2[iterator]*r2[iterator]
objetivos.append(obj)
pq.append(obj)
a = np.array(objetivos)
b = un_pickle
print(b[0])
z = (np.sum(b[0]- a[0]))**2
m.Minimize(z)
m.solve(disp=True)
print(y)
print('Objective = '+str(m.options.objfcnval*1000000000/5))