pythonoptimizationnonlinear-optimizationgekkomaximize

Getting solution as nan for mixed integer non linear programming problem with objective function as a fraction


I wanted to maximize gross profit margin (total profit/total revenue) with binary variables, say whether products will be in the mix or not by that variables will be 1 or 0 (binary), trying to solve with gekko mixed integer non linear programming

here is the example for 3 products, where we want to keep any 2 products

variables for 3 products, x1, x2 and x3

total profit = 150*x1 + 120*x2 + 100*x3

total revenue = 200*x1 + 150x2 + 250*x3

gross profit margin = total profit/ total revenue

solution tried

m = GEKKO()
x1 = m.Var(integer=True, lb=0, ub=1)
x2 = m.Var(integer=True, lb=0, ub=1)
x3 = m.Var(integer=True, lb=0, ub=1)
m.Maximize((150*x1 + 120*x2 + 100*x3)/(200*x1 + 150*x2 + 250*x3))
m.Equation(x1 + x2 + x3 == 2)
m.options.SOLVER = 1
m.solve()

result

x1: 0
x2: 0
x3: 0
objective function: nan

things tried

i) tried with adding one more constraint with the denominator > 0, getting same solution
ii) tried with changing lb=0 to any other integer value and it is working (say lb=1, ub=2), not sure if anything particularly needs to be added for using lb=0
ii) tried absolute profit maximization (removing the denominator) and it is working fine

any help will be appreciated, thanks in advance


Solution

  • Try using a different initial guess than 0 for at least one of the variables:

    x1 = m.Var(value=1,integer=True, lb=0, ub=1)
    

    Gekko uses a default starting value of 0. Gradient-based optimizers need to calculate a search direction and the initial guesses of zero lead to an Inf evaluation of the objective function. Here is the complete script with a condensed way to define the variables:

    from gekko import GEKKO
    m = GEKKO()
    x1,x2,x3 = m.Array(m.Var,3,value=1,integer=True,lb=0,ub=1)
    m.Maximize((150*x1 + 120*x2 + 100*x3)/(200*x1 + 150*x2 + 250*x3))
    m.Equation(x1 + x2 + x3 == 2)
    m.options.SOLVER = 1
    m.solve()
    

    This gives a successful solution:

     ---------------------------------------------------
     Solver         :  APOPT (v1.0)
     Solution time  :   3.579999999965366E-002 sec
     Objective      :  -0.771428571428571     
     Successful solution
     ---------------------------------------------------
    

    Gekko converts maximization problems to minimization problems that are standard for MINLP and NLP solvers so the objective function value is the negative of the true value. Use this to get the Maximization objective of 0.7714:

    print(-m.options.OBJFCNVAL)