The optimizer needs to select the appropriate discrete option to maximize an objective. It uses a lookup to correlate the option (0-5) to associated values that can then be used in the optimization definition. Here is a simplified version that demonstrates the issue:
Data
x_data = np.array([0, 1, 2, 3, 4, 5])
y_data = np.array([1000,2000,9000,4500,5000,900])
z_data = np.array([15,13,12,17,11,10])
I found this related post that demonstrates how to use a cspline function to create the relationship between the discrete choice x variable and the dependent y and z variables. I've created the x variable as an sos1 type that selects one from the list of values.
from gekko import GEKKO
import numpy as np
# Define Data Points
x_data = np.array([0, 1, 2, 3, 4, 5])
y_data = np.array([1000,2000,9000,4500,5000,900])
z_data = np.array([15,13,12,17,11,10])
# Create Variables
m = GEKKO()
x = m.sos1(x_data)
y,z = m.Array(m.Var,2)
m.cspline(x, y, x_data, y_data)
m.cspline(x, z, x_data, z_data)
# Define objective and solve
m.Maximize(y*z)
m.options.SOLVER = 1
m.solve(disp=True)
# Print the results
print(f'x: {x.value[0]}, y: {y.value[0]}, z: {z.value[0]}')
print('Objective:', y.value[0]*z.value[0])
print(y_data*z_data)
I get the wrong answer (maybe local solution) when solving this problem.
x: 0.0, y: 1000.0, z: 15.0
Objective: 15000.0
It may have something to do with a local minimum that is created by the cubic spline. Do you have any suggestions to find the maximum for this synthetic function?
Try initializing with a different guess value for
x. A local minimum is found when thex<0.3is used as the initial guess value. Withx>=0.3, it finds the global maximum value. If the order ofxis arbitrary, remove the local minima by first sortingy_data*z_datato create a new index forx_data. Becausex_dataare all integer options, you also don't need to usem.sos1()but can use an integer decision variable instead.The
m.sos1()object creates a new binary variable for each option. It is best to use this type when the options are discrete, but not integer values such as select from a list of pipe diameters of 0.5, 1.5, 2.0, 5.0. Here is a complete script:When dealing with local minima, try creating a plot of the objective function with respect to one decision variable at a time. Here is the cspline objective plot of the objective function.
Another option is to use a piece-wise linear function
m.pwl()instead of cubic splines although the way the problem is posed with slack variables may cause a problem with more complex problems and multiple objective functions. For example, the "curved" interpolation points indicate a potential issue with this function.