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.
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:
(10**6*(1-fooditems_params[i][1])*(1-fooditems_params[i][2]))
to remove the potential divide-by-zero.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
---------------------------------------------------