在 Python 上使用 GEKKO 成功解决优化问题获得 NAN 值

Obtaining NAN value for successfully solved optimization problem using GEKKO on Python

我正在尝试在 Python 上使用 GEKKO 求解器解决优化问题,但即使问题已成功解决,仍会继续获取 NAN objective 值。似乎缺少了什么,但我无法确定是什么。我试图确保没有任何东西被零除,但据我所知,情况并非如此。我的代码是:

class FoodItem(): 
    def__init__(self,name,wastefactor,lossfactor,prioritylevel):
            self.name = name 
            self.wastefactor = wastefactor
            self.lossfactor = lossfactor 
            self.prioritylevel = prioritylevel 

wheatflour = FoodItem(name='WheatFlour',wastefactor= 0.15, lossfactor= 0.15, prioritylevel=1)

tomatoes = FoodItem(name='Tomatoes', wastefactor=0.15, lossfactor=0.15, prioritylevel=2)

oranges = FoodItem(name='Oranges', wastefactor=0.15, lossfactor=0.15, prioritylevel=2)

beans = FoodItem(name='Beans', wastefactor=0.15, lossfactor=0.15, prioritylevel=2)

beef = FoodItem(name='Beef',wastefactor=0.15, lossfactor=0.15, prioritylevel=1)

milk = FoodItem(name='Milk',wastefactor=0.15,lossfactor=0.15, prioritylevel=1)

fooditems = [wheatflour, tomatoes, oranges, beans, beef, milk]

m = GEKKO(remote=False)

foodvars = m.Array(m.Var,(len(fooditems),5))
fooditems_params = m.Array(m.Param,(len(fooditems),4))

def fillparametersFood(i,j):
    fooditems_params[j][0] = i.name
    fooditems_params[j][1] = i.wastefactor
    fooditems_params[j][2] = i.lossfactor
    fooditems_params[j][3] = i.prioritylevel
    return

j=0
for i in fooditems:
    fillparametersFood(i,j)
    j +=1

pop=1000
for i in range(len(foodvars)):    
    m.Equation(foodvars[i][0]+foodvars[i][1]-foodvars[i][2]==foodvars[i][3])
   
    m.Equation(foodvars[i][3]==(foodvars[i][4]*pop*365.25)/(10**6*(1-fooditems_params[i][1])*(1-fooditems_params[i][2])))


ssr_priority=0 

for i in range(len(foodvars)):
    ssr_priority += (foodvars[i][0]/(foodvars[i][0]+foodvars[i][1]-foodvars[i][2]))/fooditems_params[i][3]
    
m.Maximize(ssr_priority)

m.solve()

如果您能帮助我们找出问题,我们将不胜感激。非常感谢。

优化器试图通过使 (foodvars[i][0]+foodvars[i][1]-foodvars[i][2]) 接近零来最大化 objective 函数。这给出了导致 NaN 结果的无限 objective 函数。两条建议:

  • 将等式 2 两边乘以 (10**6*(1-fooditems_params[i][1])*(1-fooditems_params[i][2])) 以消除潜力 divide-by-zero。
  • foodvars 上设置界限以防止 divide-by-zero 在 objective.
from gekko import GEKKO
m = GEKKO(remote=False)

class FoodItem(): 
    def __init__(self,name,wastefactor,lossfactor,prioritylevel):
            self.name = name 
            self.wastefactor = wastefactor
            self.lossfactor = lossfactor 
            self.prioritylevel = prioritylevel 

wheatflour = FoodItem(name='WheatFlour',wastefactor= 0.15, lossfactor= 0.15, prioritylevel=1)

tomatoes = FoodItem(name='Tomatoes', wastefactor=0.15, lossfactor=0.15, prioritylevel=2)

oranges = FoodItem(name='Oranges', wastefactor=0.15, lossfactor=0.15, prioritylevel=2)

beans = FoodItem(name='Beans', wastefactor=0.15, lossfactor=0.15, prioritylevel=2)

beef = FoodItem(name='Beef',wastefactor=0.15, lossfactor=0.15, prioritylevel=1)

milk = FoodItem(name='Milk',wastefactor=0.15,lossfactor=0.15, prioritylevel=1)

fooditems = [wheatflour, tomatoes, oranges, beans, beef, milk]

m = GEKKO(remote=False)

foodvars = m.Array(m.Var,(len(fooditems),5),lb=1,ub=100)
fooditems_params = m.Array(m.Param,(len(fooditems),4))

def fillparametersFood(i,j):
    fooditems_params[j][0] = i.name
    fooditems_params[j][1] = i.wastefactor
    fooditems_params[j][2] = i.lossfactor
    fooditems_params[j][3] = i.prioritylevel
    return

j=0
for i in fooditems:
    fillparametersFood(i,j)
    j +=1

pop=1000
for i in range(len(foodvars)):    
    m.Equation(foodvars[i][0]+foodvars[i][1]-foodvars[i][2]\
    ==foodvars[i][3])
   
    m.Equation((10**6*(1-fooditems_params[i][1])*(1-fooditems_params[i][2]))*foodvars[i][3]==(foodvars[i][4]*pop*365.25))


ssr_priority=0 

for i in range(len(foodvars)):
    ssr_priority += (foodvars[i][0]/(foodvars[i][0]+foodvars[i][1]-foodvars[i][2]))/fooditems_params[i][3]
    
m.Maximize(ssr_priority)

m.solve()

这给出了 objective 为 450 的成功解决方案。Gekko 通过乘以 -1 将最大化问题转换为最小化问题,因此 objective 看起来像是负数。

 ----------------------------------------------
 Steady State Optimization with APOPT Solver
 ----------------------------------------------
 
 Iter    Objective  Convergence
    0 -6.37500E+00  6.81400E-01
    1 -1.31250E+01  1.37806E-10
    2 -3.19432E+01  0.00000E+00
    3 -2.20125E+02  0.00000E+00
    4 -3.49596E+02  0.00000E+00
    5 -3.50465E+02  0.00000E+00
    6 -3.59156E+02  0.00000E+00
    7 -4.46063E+02  0.00000E+00
    8 -4.50000E+02  0.00000E+00
 
 Iter    Objective  Convergence
   10 -4.50000E+02  0.00000E+00
 Successful solution
 
 ---------------------------------------------------
 Solver         :  IPOPT (v3.12)
 Solution time  :   9.600000019418076E-003 sec
 Objective      :   -450.000000000000     
 Successful solution
 ---------------------------------------------------