Вопрос об условном выражении ('m.if3') в GEKKO

Я хотел бы добавить несколько условных операторов в код GEKKO.

Я добавил приведенный ниже оператор с помощью «m.if3». Однако он вернул синтаксическую ошибку, которой у меня не было бы без условного оператора.

'R1_1 = m.if3(R1<0, 0, R1)'

#%% GEKKO
m = GEKKO(remote=False)

#print(m.version)
#m.time = np.linspace(0, 3600, 100)
m.time = np.array([0,tstep])

cH = m.CV(value=cs0[0])
cM = m.CV(value=cs0[1])
cW = m.CV(value=cs0[2])
cF = m.CV(value=cs0[3])

R1_1 = m.Var()

r3 = m.Intermediate(r0*(1-cF/cFeMax)**(1/3))
r2 = m.Intermediate(r0*((2*cH + 3*cM)/cFeMax)**(1/3))
r1 = m.Intermediate(r0*(2*cH/cFeMax)**(1/3))
x = m.Intermediate(r1/r0)
y = m.Intermediate(r2/r0)
z = m.Intermediate(r3/r0)
A1 = m.Intermediate(1/x**2/(kd[0]*(1+1/Keq[0])))
A2 = m.Intermediate(1/y**2/(kd[1]*(1+1/Keq[1])))
A3 = m.Intermediate(1/z**2/(kd[2]*(1+1/Keq[2])))
B1 = m.Intermediate((y-x)/x/y*r0/Dif[1])
B2 = m.Intermediate((z-y)/y/z*r0/Dif[2])
B3 = m.Intermediate((1-z)/z*r0/Dif[3])
F = 0
W = m.Intermediate((A1+B1)*(A3*(A2+B2+B3+F)+(A2+B2)*(B3+F))+A2*(A3*(B2+B3+F))+B2*(B3+F))
ceq1 = m.Intermediate((cg0[0]+cg0[1])/(1+Keq[0]))
ceq2 = m.Intermediate((cg0[0]+cg0[1])/(1+Keq[1]))
ceq3 = m.Intermediate((cg0[0]+cg0[1])/(1+Keq[2]))

R1 = m.Intermediate(3/r0/W*((A3*(A2+B2+B3+F)+(A2+B2)*(B3+F))*(cg0[0]-ceq1) \
                     -(A3*(B2+B3+F)+B2*(B3+F))*(cg0[0]-ceq2) \
                     -A2*(B3+F)*(cg0[0]-ceq3)))
R2 = m.Intermediate(3/r0/W*(-(B2*(A3+B3+F)+A3*(B3+F))*(cg0[0]-ceq1) \
                     +((A1+B1+B2)*(A3+B3+F)+A3*(B3+F))*(cg0[0]-ceq2) \
                     -(A1+B1)*(B3+F)*(cg0[0]-ceq3)))
R3 = m.Intermediate(3/r0/W*(-A2*(B3+F)*(cg0[0]-ceq1) \
                    -(A1+B1)*(B3+F)*(cg0[0]-ceq2) \
                    +((A1+B1)*(A2+B2+B3+F)+A2*(B2+B1+F))*(cg0[0]-ceq3)))

R1_1 = m.if3(R1<0, 0, R1)

m.Equation(cH.dt() == nus[0].dot([R1_1, R2, R3]))
m.Equation(cM.dt() == nus[1].dot([R1_1, R2, R3]))
m.Equation(cW.dt() == nus[2].dot([R1_1, R2, R3]))
m.Equation(cF.dt() == nus[3].dot([R1_1, R2, R3]))

m.options.IMODE = 4
m.options.SOLVER = 3
m.options.nodes = 2

Исключение: @error: Model Expression *** Ошибка в синтаксисе функциональной строки: несоответствие круглых скобок

Позиция: 4
(0))) - ((((1-int_v5)) * (i35) -slk_1?


person Junho Park    schedule 19.06.2019    source источник
comment
Я не вижу slk_1 в опубликованном вами коде. Вы уверены, что это код с ошибкой?   -  person Barmar    schedule 20.06.2019
comment
Хорошее наблюдение! Переменные Slack автоматически добавляются при наличии ограничения неравенства, чтобы преобразовать его обратно в ограничение равенства (с переменной slack). Slk_1 - дополнительная переменная.   -  person John Hedengren    schedule 20.06.2019


Ответы (1)


Вам понадобится всего одно исправление (удалите <0), чтобы использовать функцию if3 в Gekko.

R1_1 = m.if3(R1, 0, R1)

Функция m.if3 использует условие, которое переключает то, что используется (аргумент 2 или 3), в зависимости от того, является ли условие меньше нуля или больше или равно нулю. Вот результат справки (m.if3) с некоторыми дополнительными пояснениями:

if3(condition, x1, x2) method of gekko.gekko.GEKKO instance

IF conditional with a binary switch variable.
The traditional method for IF statements is not continuously
differentiable and can cause a gradient-based optimizer to fail
to converge.

Usage: y = m.if3(condition,x1,x2)
Inputs:
   condition: GEKKO variable, parameter, or expression
   x1 and x2: GEKKO variable, parameter, or expression
Output: GEKKO variable y = x1 when condition<0
                       y = x2 when condition>=0

Еще одна вещь, которую следует учитывать, заключается в том, что функция if3 использует двоичные переменные, и вам нужно будет использовать решатель смешанных целых чисел, чтобы найти целочисленное решение. Вы можете либо удалить строку, которая переключает решатель на IPOPT (if3 переключает на решатель APOPT по умолчанию), либо вы можете переключить опцию на APOPT вручную.

m.options.SOLVER = 1

Некоторые константы отсутствовали в вашем скрипте. Я добавил несколько фиктивных переменных, чтобы заставить его работать.

from gekko import GEKKO
import numpy as np

m = GEKKO()

help(m.if3)

tstep = 1.0
cs0=[1,1,1,1]
r0 = 1.0
cFeMax = 1.0
kd = [1,1,1]
Keq = [1,1,1]
Dif = [1,1,1,1]
cg0 = [1,1,1]
nus = np.array([[1,1,1],[1,1,1],[1,1,1],[1,1,1]])

m.time = np.array([0,tstep])

cH = m.CV(value=cs0[0])
cM = m.CV(value=cs0[1])
cW = m.CV(value=cs0[2])
cF = m.CV(value=cs0[3])

R1_1 = m.Var()

r3 = m.Intermediate(r0*(1-cF/cFeMax)**(1/3))
r2 = m.Intermediate(r0*((2*cH + 3*cM)/cFeMax)**(1/3))
r1 = m.Intermediate(r0*(2*cH/cFeMax)**(1/3))
x = m.Intermediate(r1/r0)
y = m.Intermediate(r2/r0)
z = m.Intermediate(r3/r0)
A1 = m.Intermediate(1/x**2/(kd[0]*(1+1/Keq[0])))
A2 = m.Intermediate(1/y**2/(kd[1]*(1+1/Keq[1])))
A3 = m.Intermediate(1/z**2/(kd[2]*(1+1/Keq[2])))
B1 = m.Intermediate((y-x)/x/y*r0/Dif[1])
B2 = m.Intermediate((z-y)/y/z*r0/Dif[2])
B3 = m.Intermediate((1-z)/z*r0/Dif[3])
F = 0
W = m.Intermediate((A1+B1)*(A3*(A2+B2+B3+F)+(A2+B2)*(B3+F))+A2*(A3*(B2+B3+F))+B2*(B3+F))
ceq1 = m.Intermediate((cg0[0]+cg0[1])/(1+Keq[0]))
ceq2 = m.Intermediate((cg0[0]+cg0[1])/(1+Keq[1]))
ceq3 = m.Intermediate((cg0[0]+cg0[1])/(1+Keq[2]))

R1 = m.Intermediate(3/r0/W*((A3*(A2+B2+B3+F)+(A2+B2)*(B3+F))*(cg0[0]-ceq1) \
                     -(A3*(B2+B3+F)+B2*(B3+F))*(cg0[0]-ceq2) \
                     -A2*(B3+F)*(cg0[0]-ceq3)))
R2 = m.Intermediate(3/r0/W*(-(B2*(A3+B3+F)+A3*(B3+F))*(cg0[0]-ceq1) \
                     +((A1+B1+B2)*(A3+B3+F)+A3*(B3+F))*(cg0[0]-ceq2) \
                     -(A1+B1)*(B3+F)*(cg0[0]-ceq3)))
R3 = m.Intermediate(3/r0/W*(-A2*(B3+F)*(cg0[0]-ceq1) \
                    -(A1+B1)*(B3+F)*(cg0[0]-ceq2) \
                    +((A1+B1)*(A2+B2+B3+F)+A2*(B2+B1+F))*(cg0[0]-ceq3)))

R1_1 = m.if3(R1, 0, R1)

m.Equation(cH.dt() == nus[0].dot([R1_1, R2, R3]))
m.Equation(cM.dt() == nus[1].dot([R1_1, R2, R3]))
m.Equation(cW.dt() == nus[2].dot([R1_1, R2, R3]))
m.Equation(cF.dt() == nus[3].dot([R1_1, R2, R3]))

m.options.IMODE = 4
m.options.SOLVER = 1
m.options.nodes = 2

m.solve()
person John Hedengren    schedule 20.06.2019
comment
Спасибо за любезный ответ. У меня есть дополнительный вопрос. Могу ли я добавить условный оператор к переменным, которые появляются в m.Equation непосредственно в строке m.Equation? Например, для «cH» в уравнении. Или мне нужно добавить еще одну фиктивную переменную для установки условия? - person Junho Park; 21.06.2019
comment
Да, вы можете добавить функцию непосредственно в уравнение, например, в этом примере вы можете удалить переменную R1_1 с помощью: m.Equation(cH.dt() == nus[0].dot([m.if3(R1, 0, R1), R2, R3])), m.Equation(cM.dt() == nus[1].dot([m.if3(R1, 0, R1), R2, R3])), ... Лучше определить R1_1 один раз выше и использовать его несколько раз, чтобы минимизировать дополнительные переменные, которые идут с m.if3. - person John Hedengren; 22.06.2019