Why do I still get the "TypeError: object of type 'int' has no len()" error at the if-conditional even after defining my arrays as GEKKO params?

Viewed 44

I am trying to define arrays as GEKKO params, that will be used with comparison operators such as >, <, >=, != and even within other functions outside the ones shown in the code below. How can I handle such without the TypeError: object of type 'int' has no len() error?. Running the code as shown below, throws the TypeError: object of type 'int' has no len error. Any guidance will be hugely appreciated.

import numpy as np
from scipy import interpolate
from gekko import GEKKO

def check_p_u(u_hub_next):
    m = GEKKO(remote=True)
    u_hub_next = m.Param(value = u_hub_next)

    if 0 <= u_hub_next < 3:
        p_u = 0
        return p_u
    elif 3 <= u_hub_next < 3.5:
        p_u = 8
        return p_u
    elif 3.5 <= u_hub_next < 4.5:
        p_u = 10.5
        return p_u    
    else:
        return 0.1

def intpolatn(u_hub_next):
    m = GEKKO(remote=True)    

    u_hub_next = m.Param(value = u_hub_next)    
    windvel = m.Param(np.array([0, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
    thrust_coeff = m.Param(np.array([0, 0.88, 0.88, 0.87, 0.87, 0.86, 0.84, 0.79, 0.71, 0.6]))

    f = interpolate.interp1d(windvel, thrust_coeff, kind = 'cubic')

    if windvel[0] <= u_hub_next < windvel[1]:
        m = 0
        c_t = 0
        axial = 0
        p_u = check_p_u(u_hub_next) 
        u_hub_next = 0
        return [u_hub_next, c_t, axial, p_u]

    elif windvel[1] <= u_hub_next < windvel[2]:
        c_t = f(u_hub_next)
        axial = 0.5 * (1 - np.sqrt(1 - c_t))
        p_u = check_p_u(u_hub_next)
        return [u_hub_next, c_t, axial, p_u]

    elif windvel[2] <= u_hub_next < windvel[3]:
        c_t = f(u_hub_next)
        axial = 0.5 * (1 - np.sqrt(1 - c_t))
        p_u = check_p_u(u_hub_next)
        return [u_hub_next, c_t, axial, p_u]

    elif windvel[3] <= u_hub_next < windvel[4]:
        c_t = f(u_hub_next)
        axial = 0.5 * (1 - np.sqrt(1 - c_t))
        p_u = check_p_u(u_hub_next)
        return [u_hub_next, c_t, axial, p_u]


y = intpolatn(3.2)
print(y)
1 Answers

Gekko calls the function only once when building the model. The model is compiled with the function call m.solve() and the problem is given to a solver to find a solution. To use if statements in a model, use either the MPCC form with m.if2() or the mixed integer form with m.if3() (preferred). Here is additional help on logical conditions in optimization problems.

Because Gekko also needs to compile the model for automatic differentiation, some functions are not supported (such as scipy.interpolate.interp1d). Use the Gekko m.cspline() function instead. Below is an example.

Cubic Spline

from gekko import gekko 
import numpy as np
import matplotlib.pyplot as plt

"""
minimize y
s.t.     y = f(x)

using cubic spline with random sampling of data
"""

# Function to generate data for cspline
def f(x):
    return 3*np.sin(x) - (x-3) 

# Create model
c = gekko()

# Cubic spline
x = c.Var(value=15)
y = c.Var()
x_data = np.random.rand(50)*10+10
y_data = f(x_data)
c.cspline(x,y,x_data,y_data,True)
c.Obj(y)

# Options
c.options.IMODE = 3
c.options.CSV_READ = 0
c.options.SOLVER = 3
c.solve()

# Generate continuous trend for plot
z = np.linspace(10,20,100)

# Check if solved successfully
if c.options.SOLVESTATUS == 1:
    plt.figure()
    plt.plot(z,f(z),'r-',label='original')
    plt.scatter(x_data,y_data,5,'b',label='data')
    plt.scatter(x.value,y.value,200,'k','x',label='minimum')
    plt.legend(loc='best')
else:
    print ('Failed to converge!')
    plt.figure()
    plt.plot(z,f(z),'r-',label='original')
    plt.scatter(x_data,y_data,5,'b')
    plt.legend(loc='best')
plt.show()
Related