[英]Constraint on objective function in Python Gekko
有沒有辦法將目標函數限制在 Python Gekko 的范圍內? 我正在研究一個商業漁業超過 10 年的經營經濟學的示例優化問題。 可調參數是魚的生產速度(收獲率)。 目標函數是 10 年期間的運營利潤。 數學上的優化問題是:
解決方案和Python Gekko代碼是:
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
# create GEKKO model
m = GEKKO()
# time points
n=501
m.time = np.linspace(0,10,n)
# constants
E = 1
c = 17.5
r = 0.71
k = 80.5
U_max = 20
# fishing rate
u = m.MV(value=1,lb=0,ub=1)
u.STATUS = 1
u.DCOST = 0
# fish population
x = m.Var(value=70)
# fish population balance
m.Equation(x.dt() == r*x*(1-x/k)-u*U_max)
# objective (profit)
J = m.Var(value=0)
# final objective
Jf = m.FV()
Jf.STATUS = 1
m.Connection(Jf,J,pos2='end')
m.Equation(J.dt() == (E-c/x)*u*U_max)
# maximize profit
m.Maximize(Jf)
# options
m.options.IMODE = 6 # optimal control
m.options.NODES = 3 # collocation nodes
m.options.SOLVER = 3 # solver (IPOPT)
# solve optimization problem
m.solve()
# print profit
print('Optimal Profit: ' + str(Jf.value[0]))
# plot results
plt.figure(1)
plt.subplot(2,1,1)
plt.plot(m.time,J.value,'r--',label='profit')
plt.plot(m.time[-1],Jf.value[0],'ro',markersize=10,\
label='final profit = '+str(Jf.value[0]))
plt.plot(m.time,x.value,'b-',label='fish population')
plt.ylabel('Value')
plt.legend()
plt.subplot(2,1,2)
plt.plot(m.time,u.value,'k.-',label='fishing rate')
plt.ylabel('Rate')
plt.xlabel('Time (yr)')
plt.legend()
plt.show()
我在化學制造中的觀察結果之一是,優化有時會導致非直觀的解決方案,因為優化器 (IPOPT) 會將過程帶到絕對極限,以實現甚至多出幾美元的盈利能力。 有沒有辦法限制目標函數(在這種情況下是利潤),以便業務保持可行,但優化器不會提供推動設備(或在這種情況下的魚類種群)極限的解決方案。
您可以通過添加上限來設置目標的限制,例如:
Jf = m.FV(ub=100) # final objective
這將上限ub
為100
。 盡管您可以這樣做,但您可能不想對目標施加限制的原因有很多。 一是如果優化器無法達到該限制,這可能會導致不可行的解決方案。 另一個原因是,您可能仍然無法實現“直觀的解決方案”,或者在某些時期內不會將您的設備(例如漁船或化學制造廠)推向極限。 正如 Tim 在評論中提到的,更好的方法是對您可以控制的事物(例如釣魚率)施加限制。 您可能會發現一些有用的參數是移動抑制因子DCOST
、最大移動DMAX
和釣魚速率COST
。 也許在一年內提高到全捕撈率然后在 5 年以上下降到 40% 是不合理的。 建立捕撈船隊可能還會產生相關成本,而這些成本不會反映在您當前的解決方案中。
您還可以將目標設置為某些目標值之間的軟約束,然后讓其他目標(例如最大化魚類種群)作為決定盈利能力上限和下限目標的驅動力。
# objective (profit)
J = m.CV(value=0)
J.SPHI = 100; J.WSPHI = 1000
J.SPLO = 80; J.WSPLO = 1000
m.options.CV_WGT_START = n-1 # start at n-1
J.STATUS = 1
m.Maximize(x) # maximize fish population
這提供了介於 80 到 100 之間的利潤限制的解決方案,但也最大化了魚類種群。
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
# create GEKKO model
m = GEKKO()
# time points
n=501
m.time = np.linspace(0,10,n)
# constants
E = 1
c = 17.5
r = 0.71
k = 80.5
U_max = 20
# fishing rate
u = m.MV(value=1,lb=0,ub=1)
u.STATUS = 1
u.DCOST = 0
# fish population
x = m.Var(value=70)
# fish population balance
m.Equation(x.dt() == r*x*(1-x/k)-u*U_max)
# objective (profit)
J = m.CV(value=0)
J.SPHI = 100; J.WSPHI = 1000
J.SPLO = 80; J.WSPLO = 1000
m.options.CV_WGT_START = n-1 # start at n-1
J.STATUS = 1
m.Maximize(x) # maximize fish population
m.Equation(J.dt() == (E-c/x)*u*U_max)
# options
m.options.IMODE = 6 # optimal control
m.options.NODES = 3 # collocation nodes
m.options.SOLVER = 3 # solver (IPOPT)
# solve optimization problem
m.solve()
# print profit
print('Optimal Profit: ' + str(J.value[-1]))
# plot results
plt.figure(1)
plt.subplot(2,1,1)
plt.plot([0,10],[100,100],'k:',label='target profit range')
plt.plot([0,10],[80,80],'k:')
plt.plot(m.time,J.value,'r--',label='profit')
plt.plot(m.time[-1],J.value[-1],'ro',markersize=10,\
label='final profit = '+str(J.value[-1]))
plt.plot(m.time,x.value,'b-',label='fish population')
plt.ylabel('Value')
plt.legend()
plt.subplot(2,1,2)
plt.plot(m.time,u.value,'k.-',label='fishing rate')
plt.ylabel('Rate')
plt.xlabel('Time (yr)')
plt.legend()
plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.