3

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

soumyajt
  • 35
  • 3

1 Answers1

1

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)
John Hedengren
  • 12,068
  • 1
  • 21
  • 25
  • 1
    Thanks John. Will try this way. Yes, I anticipated the denominator becoming 0 was the issue, so added a small fraction in the denominator and it was giving me optimal solution, but with different size of the fraction I was getting different variable solution (was trying on larger data). But your way justifies the root cause more accurately. Thank you. – soumyajt Jun 30 '23 at 20:17