Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gekko Non-Linear optimization, object type error in constraint function evaluating if statement

I'm trying to solve a non-linear optimization problem. I've duplicated my issue by creating the code below. Python returns TypeError: object of type 'int' has no len(). How can I include an IF statement in my constraint functions?

Console prints the following:

  File "<ipython-input-196-8d29d410dcea>", line 1, in <module>
    runfile('C:/Users/***/Documents/***/Project/untitled.py', wdir='C:/Users/***/Documents/***/***/Project')

  File "C:\Users\***\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 704, in runfile
    execfile(filename, namespace)

  File "C:\Users\***\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Users/***/Documents/***/***/Project/untitled.py", line 27, in <module>
    m.Equation(Cx(x1,x2,x3,x4) < 0)

  File "C:/Users/***/Documents/***/***/Project/untitled.py", line 17, in Cx
    if K > 15:

  File "C:\Users\***\Anaconda3\lib\site-packages\gekko\gk_operators.py", line 25, in __len__
    return len(self.value)

  File "C:\Users\***\Anaconda3\lib\site-packages\gekko\gk_operators.py", line 134, in __len__
    return len(self.value)

TypeError: object of type 'int' has no len()

-

from gekko import GEKKO
m = GEKKO()


def Cr(x1,x2,x3,x4):
    return (x1*x4*(x1+x2+x3)+x3**2)

def Cw(x1,x2,x3,x4):
    return x1*x2*x3*x4

def Ck(x1,x2,x3,x4):
    return x1*x2*x3*x4+1

def Cx(x1,x2,x3,x4):
    K = Ck(x1,x2,x3,x4)
    if K > 15:  #Issue here
        K = 15
    return x1**2+x2**2+x3**2+x4**2 - K

x1 = m.Var(value=1,lb=-5000,ub=5000)
x2 = m.Var(value=1,lb=-5000,ub=5000)
x3 = m.Var(value=1,lb=-5000,ub=5000)
x4 = m.Var(value=1,lb=-5000,ub=5000)

m.Equation(Cw(x1,x2,x3,x4) >= 14)
m.Equation(Cx(x1,x2,x3,x4) < 0)

m.Obj(Cr(x1,x2,x3,x4))

m.solve(disp=False)
print(x1.value)
print(x2.value)
print(x3.value)
print(x4.value)

-

I am looking to have GEKKO run with the IF statement in the constraint, I'm not concerned if the optimization problem in the code has a solution. Thank you in advance.

like image 557
diveblock1 Avatar asked Mar 30 '19 22:03

diveblock1


2 Answers

(Disclaimer: i don't know this lib or what it will do for you)

The if-statement makes this problen non-differentiable which invalidates the assumption of NLP solvers (like Ipopt).

In terms of MINLP solvers (Bonmin, Couenne), this could be achieved by reformulation (and the resulting problem is differentiable when the needed auxiliary binary variables have been relaxed). It's hardly questionable to expect the lib to do it for you.

So it seems you need to play by the rules of some MINLP model like for example described by Bonmin here. There is no concept for "if-based branching".

Either introduce an indicator-variable like it's common in the MIP world, see here. Ignoring the overhead the idea would be something like:

K_ = Ck(x1,x2,x3,x4)
I = K_ > 15 (binary variable; see link for formulation idea)

return x1**2+x2**2+x3**2+x4**2 - I*15 - (1-I) * K_

This is an MINLP then.

You might get away without using an additional binary variable (and touching MINLPs) when interpreting your equation like:

return x1**2+x2**2+x3**2+x4**2 - min(Ck(x1,x2,x3,x4), 15)

This is also non-differentiable, but can be easily reformulated (with a quirk) like:

return x1**2+x2**2+x3**2+x4**2 - A

# extra constraints
A <= Ck(x1,x2,x3,x4)
A <= 15

if we could enforce moving towards the biggest A possible. This means, it must be part of the objective:

m.Obj(Cr(x1,x2,x3,x4) + c * A) (if it's a maximization problem)

This would be a NLP then, but the value of c needs some care (it must be big enough).

like image 129
sascha Avatar answered Nov 18 '22 07:11

sascha


I recommend that you use the min2 or min3 functions or the recently added if3 function in GEKKO.

K = m.min3(Ck(x1,x2,x3,x4),15)

Here is additional information on MPCCs and Binary Switching variables. You can't use functions that have non-continuous gradients because it causes problems with the solvers and how they search for a solution. The min3 and if3 functions use binary variables and solve the problem as a Mixed Integer problem and min2 uses MPCCs. Here is a short example that demonstrates the use of min2 and min3.

Example use of min2 and min3 functions

import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
m = GEKKO(remote=False) 
p = m.Param(value=np.linspace(10,20,21))
x = m.Var()
m.Equation(x==p)
# with MPCCs
y2 = m.min2(p,15)
# with integer variables
y3 = m.min3(p,16)
m.options.IMODE = 2
m.solve()
plt.plot(p,x,'b-',label='x')
plt.plot(p,y2,'g:',label='MPCC')
plt.plot(p,y3,'r--',label='Integer Switch')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()
like image 2
John Hedengren Avatar answered Nov 18 '22 06:11

John Hedengren