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