Reputation: 128
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]
Upvotes: 2
Views: 84
Reputation: 14346
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))
Upvotes: 1