[英]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.