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

Viewed 71

I am trying to solve an optimization problem using the GEKKO solver on Python, but keep obtaining an NAN objective value, even though the problem is successfully solved. There seems to be something I am missing, but I have not been able to identify what it is. I tried to make sure that nothing is being divided by zero, but as far as I can tell, that is not the case. The code I have is:

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()

Any help to identify the problem would be highly appreciated. Many thanks.

1 Answers

The optimizer tries to maximize the objective function by making (foodvars[i][0]+foodvars[i][1]-foodvars[i][2]) approach zero. This gives an infinity objective function that results in the NaN result. Two suggestions:

  • Multiply both sides of equation 2 by (10**6*(1-fooditems_params[i][1])*(1-fooditems_params[i][2])) to remove the potential divide-by-zero.
  • Set bounds on foodvars to prevent divide-by-zero in the 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()

This gives a successful solution with an objective of 450. Gekko converts a maximization problem to a minimization by multiplying by -1 so the objective looks like it is negative.

 ----------------------------------------------
 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
 ---------------------------------------------------
Related