Search code examples
pythonpandasgekko

Gekko is not respecting the restrictions of the variables


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]

Solution

  • 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))