简体   繁体   中英

How to use sos1 with GEKKO Array in python?

I'm trying to solve an optimization problem using GEKKO where I have to set specific constraints regarding the values of the solution. I'm using sos1 to do that. However, I'm having a hard time trying to use sos1 with an GEKKO.Array().

If I use the following code I have a result that relies on the constraints:

from gekko import GEKKO
import numpy as np

# Initialize Model
m = GEKKO(remote=True)
eq = m.Param(value=40)
x1 = m.sos1([1.2, 1.5, 2, 3, 3.5])
x2 = m.sos1([i for i in np.arange(1, 5, 1)])
x3 = m.sos1([i for i in np.arange(1, 5, 1)])
x4 = m.sos1([i for i in np.arange(1, 5, 0.5)])

x1.value = 1
x2.value = 5
x3.value = 5
x4.value = 1

x1.lower = 1
x2.lower = 1
x3.lower = 1
x4.lower = 1

x1.upper = 5
x2.upper = 5
x3.upper = 5
x4.upper = 5

m.Equation(x1*x2*x3*x4>=25)
m.Equation(x1**2+x2**2+x3**2+x4**2==eq)

#Objective
m.Obj(x1*x4*(x1+x2+x3)+x3)

#Set global options
m.options.IMODE = 3 #steady state optimization

m.solve()

#Results
print('')
print('Results')
print('x1: ' + str(x1.value))
print('x2: ' + str(x2.value))
print('x3: ' + str(x3.value))
print('x4: ' + str(x4.value))

I'm trying to use sos1 with Array as follows:

from gekko import GEKKO
import numpy as np

# Initialize Model
m = GEKKO(remote=True)
eq = m.Param(value=40)
x = m.Array(m.Var, 4)
i = 0
value = [1, 5, 5, 1]
l = [1, 1, 1, 1]
u = [5, 5, 5, 5]
specific_values = [[1.2, 1.5, 2, 3, 3.5], [1, 2, 3, 4], [1, 2, 3, 4], [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5]]

for xi in x:
    xi.value = value[i]
    xi.lower = l[i]
    xi.upper = u[i]
    xi = m.sos1(specific_values[i])
    i+=1

m.Equation(np.prod(x)>=25)
m.Equation(x[0]**2+x[1]**2+x[2]**2+x[3]**2==eq)

#Objective
m.Obj(x[0]*x[3]*(x[0]+x[1]+x[2])+x[2])

#Set global options
m.options.IMODE = 3 #steady state optimization

m.solve()

#Results
print('')
print(x[0].value, x[1].value, x[2].value, x[3].value)

The result is the same as if I try to optimize the function without the sos1. Also, seems like the sos1 is overwriting the values of lower bound and upper bound. What am I doing wrong? Is there a way to use sos1 with gekko array?

Edit : I checked that Array doesn't support sos1, so instead of creating an Array I tried to create a list of sos1 individually in a for loop and it worked. It requires some minor modifications in the Equation definition, but it is straightforward.

from gekko import GEKKO
import numpy as np
# Initialize Model
m = GEKKO(remote=True)
eq = m.Param(value=40)
specific_values = [[1.2, 1.5, 2, 3, 3.5], [1, 2, 3, 4], [1, 2, 3, 4], [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5]]

x = [m.sos1(specific_values[i]) for i in range(4)] # m.Array(m.Var, 4)
i = 0
value = [1, 5, 5, 1]
l = [1, 1, 1, 1]
u = [5, 5, 5, 5]

for xi in x:
    xi.value = value[i]
    print(specific_values[i])
    xi.lower = l[i]
    xi.upper = u[i]
    
    print(xi.lower, xi.upper, xi.value)
    i+=1

m.Equation(np.prod(np.asarray(x))>=25)
m.Equation(np.sum(np.asarray(x)**2)==eq)

#Objective
m.Obj(x[0]*x[3]*(x[0]+x[1]+x[2])+x[2])

#Set global options
m.options.IMODE = 3 #steady state optimization

m.solve()

# Results
print('')
print(x[0].value, x[1].value, x[2].value, x[3].value)

As discussed in the edit by the author, use a for loop or list comprehension to create a list of Special Ordered Set ( sos1() ) variables. Here is the example from the answer provided by the author of the question:

specific_values = [[1.2, 1.5, 2, 3, 3.5],
                   [1, 2, 3, 4],
                   [1, 2, 3, 4],
                   [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5]]
x = [m.sos1(specific_values[i]) for i in range(4)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM