Исходный вопрос можно найти здесь.
Я новичок в использовании этого пакета, и большая часть приведенного ниже кода была заимствована из примеров, приведенных в официальной документации для GEKKO.
Обычный импорт:
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
Инициализация модели и определение моментов времени:
m = GEKKO() # initialize gekko
nt = 501
m.time = np.linspace(0.0,1.0,nt)
t = m.Param(value=m.time)
p = np.zeros(nt) # mark final time point
p[-1] = 1.0
final = m.Param(value=p)
Определение переменных состояния и управления:
x = m.Var(value=0.0)
y = m.Var(value=0.0)
z = m.Var(value=0.0)
V = m.FV(value=2.0, lb=0.0, ub=100.0)
V.STATUS = 1
theta = m.CV(1.0)
theta.STATUS = 1
theta.SPHI = 0
theta.SPLO = 6.28
V
был выбран в качестве фиксированной переменной, поскольку в формулировке задачи упоминается, что:
V - постоянная скалярная скорость.
Предполагается, что theta
находится в [0,2*pi]
, поскольку он не упоминается напрямую в формулировке проблемы.
z
используется в качестве прокси-переменной для реализации интегральной цели.
Уравнения связи определены:
m.Equation(x.dt()==V*m.cos(theta))
m.Equation(y.dt()==V*m.sin(theta))
m.Equation(x*final==1.2)
m.Equation(y*final==1.6)
m.Equation(((x-0.4)**2)+((y-0.5)**2)>=0.1)
m.Equation(((x-0.8)**2)+((y-1.5)**2)>=0.1)
Определение переменных, необходимых для получения производных 2-го порядка:
dx = m.Var(value = 0.0)
dy = m.Var(value = 0.0)
ddx = m.Var(value = 0.0)
ddy = m.Var(value = 0.0)
Соответствующие уравнения для работы:
m.Equation(dx==x.dt())
m.Equation(dy==y.dt())
m.Equation(ddx==dx.dt())
m.Equation(ddy==dy.dt())
Установка производных прокси-переменной в качестве цели внутри интеграла и решение:
m.Equation(z.dt()==(ddx**2)+(ddy**2))
m.Obj(z*final)
m.options.IMODE = 6 # optimal control mode
m.solve(disp=True)
Я не совсем уверен, верен ли способ, которым я закодировал данный вопрос. Как видно по данной ссылке, решение проблемы существует. Я пробовал использовать APOPT и IPOPT для решения этой проблемы, но оба решателя не смогли найти решение. COLD_START
нельзя использовать с DOF < 0
. Любая помощь с этим будет принята с благодарностью!