Аппроксимация нелинейной функции кусочно-линейными отрезками - PullRequest
4 голосов
/ 03 ноября 2019

Я думаю, смогу ли я использовать GEKKO для решения следующей проблемы. Пожалуйста, не стесняйтесь делиться своими комментариями. Заранее спасибо.

Учитывая, что я хотел бы аппроксимировать некоторые нелинейные функции кусочно-линейными (PWL) сегментами. Например, я хотел бы использовать N сегментов PWL для аппроксимации функции Гаусса. Можно ли использовать GEKKO для решения проблемы? Какие доступные примеры вы предлагаете изучать?

Спасибо

Ответы [ 2 ]

4 голосов
/ 04 ноября 2019

Ссылка, отправленная Junho , хороша, если у вас есть прерывистые функции, которые являются линейными или нелинейными с условиями переключения. Если у вас есть данные, то в Gekko есть функция PWL, которую вы можете использовать без двоичного режима или условий переключения MPCC. Ниже приведен простой пример PWL на Python. Вместо точек данных, которые я включил, вы можете использовать сегменты PWL для аппроксимации функции Гаусса.

PWL approximation

import matplotlib.pyplot as plt
from gekko import GEKKO
import numpy as np
m = GEKKO(remote=False)
m.options.SOLVER = 1
x = m.FV(value = 4.5)
y = m.Var()
xp = np.array([1, 2, 3, 3.5,   4, 5])
yp = np.array([1, 0, 2, 2.5, 2.8, 3])
m.pwl(x,y,xp,yp)
m.solve()
plt.plot(xp,yp,'rx-',label='PWL function')
plt.plot(x,y,'bo',label='Data')
plt.show()

Если есть набор данных смного точек, иногда желательно совмещать только несколько точек с сегментами PWL. Это еще один пример, который показывает, как соответствовать приближению PWL. В этом случае вы не можете использовать объект PWL в Gekko.

PWL fit

from scipy import optimize
import matplotlib.pyplot as plt
from gekko import GEKKO
import numpy as np

m = GEKKO()
m.options.SOLVER = 3
m.options.IMODE = 2

xzd = np.linspace(1,5,100)
yzd = np.sin(xzd)

xz = m.Param(value=xzd)
yz = m.CV(value=yzd)
yz.FSTATUS = 1

xp_val = np.array([1, 2, 3, 3.5,   4, 5])
yp_val = np.array([1, 0, 2, 2.5, 2.8, 3])
xp = [m.FV(value=xp_val[i],lb=xp_val[0],ub=xp_val[-1]) for i in range(6)]
yp = [m.FV(value=yp_val[i]) for i in range(6)]
for i in range(6):
    xp[i].STATUS = 0
    yp[i].STATUS = 1
for i in range(5):
    m.Equation(xp[i+1]>=xp[i]+0.05)

x = [m.Var(lb=xp[i],ub=xp[i+1]) for i in range(5)]
x[0].lower = -1e20
x[-1].upper = 1e20

# Variables
slk_u = [m.Var(value=1,lb=0) for i in range(4)]
slk_l = [m.Var(value=1,lb=0) for i in range(4)]

# Intermediates
slope = []
for i in range(5):
    slope.append(m.Intermediate((yp[i+1]-yp[i]) / (xp[i+1]-xp[i])))

y = []
for i in range(5):
    y.append(m.Intermediate((x[i]-xp[i])*slope[i]))

for i in range(4):
    m.Obj(1000*(slk_u[i] + slk_l[i]))

m.Equation(xz == x[0]   + slk_u[0])
for i in range(3):
    m.Equation(xz == x[i+1] + slk_u[i+1] - slk_l[i])
m.Equation(xz == x[4] - slk_l[3])

m.Equation(yz == yp[0] + y[0] + y[1] + y[2] + y[3] + y[4])

m.solve()
#y_val = yz.value
#print(y_val)

import matplotlib.pyplot as plt
plt.plot(xp,yp,'rx-',label='PWL function')
plt.plot(xzd,yzd,'b.',label='Data')
plt.show()
1 голос
/ 04 ноября 2019

Пожалуйста, проверьте ссылку ниже для примеров PWL, использующих двоичные переменные решения.

Логические условия в оптимизации

...