Search code examples
gekkomixed-integer-programming

Gekko - APMonitor had a hard time in converging for a MINLP problem with linear-fractional objective function?


Gekko - APMonitor Optimization Suite is unable to solve an optimization problem. I am trying to solve Max a^Tx/b^Tx with the constraint d<=c^Tx <=e, where the decision vector x=[x_1, x_2, ..., x_n] are non-negative integers, and vectors a,b,c are positive real-number vectors, and constants d and e are positive lower and upper bounds. The problem is feasible because I got a feasible solution with the objective being replaced by 0. I was wondering whether APMonitor is capable of solving linear-fractional objective problems or not.

Anyone has experience with how to handle this kind of issues? Is there any options in the solver I could try to turn on to resolve the issue?

The option I was using is below:

from gekko import GEKKO

model = GEKKO() 
model.options.SOLVER=1 

model.solver_options = ['minlp_maximum_iterations 100', \
                        'minlp_max_iter_with_int_sol 10', \
                        'minlp_as_nlp 0', \
                        'nlp_maximum_iterations 50', \
                        'minlp_branch_method 1', \
                        'minlp_print_level 8',  \
                        'minlp_integer_tol 0.05', \
                        'minlp_gap_tol 0.001']
model.solve(disp=True)

The output looks like below, where the solver status is inconsistent with APPSTATUS and APPINFO. This may be a APMonitor reporting issue.

apm 67.162.115.84_gk_model0 <br><pre> ----------------------------------------------- 
-----------------
APMonitor, Version 1.0.1
APMonitor Optimization Suite
----------------------------------------------------------------


--------- APM Model Size ------------
Each time step contains
Objects      :            7
Constants    :            0
Variables    :         5626
Intermediates:            0
Connections  :         4914
Equations    :         4913
Residuals    :         4913

Number of state variables:           5626
Number of total equations: -         4919
Number of slack variables: -            2
 ---------------------------------------
Degrees of freedom       :            705

----------------------------------------------
Steady State Optimization with APOPT Solver
----------------------------------------------
Iter:     1 I: -9 Tm:     75.50 NLPi:  251 Dpth:    0 Lvs:    0 Obj:  0.00E+00 Gap:       
 NaN
 Warning: no more possible trial points and no integer solution
 Maximum iterations

 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :    75.5581999999995      sec
 Objective      :                      NaN
 Unsuccessful with error code            0
 ---------------------------------------------------

 Creating file: infeasibilities.txt
 Use command apm_get(server,app,'infeasibilities.txt') to retrieve file
 @error: Solution Not Found
 Not successful
 Gekko Solvetime: 1.0 s


 #################################################

 APPINFO = 0  -  a successful solution
 APPSTATUS =1 - solver converges to a successful solution

 Solver status - Not successful, exception thrown

 decision variable =[0,0, ...,0].

Solution

  • To maximize the objective, the solver minimizes the value of b so that the objective function goes to +infinity. Try setting a lower bound on b to a small number such as 0.001 to prevent the unbounded solution. Starting with non-zero values (default) can also help to find the solution.

    b = model.Array(m.Var,n,value=1,lb=0.001)
    

    Another suggestion is to set a lower bound constraint on b^Tx in case x also goes to zero.

    model.Equation(b@x>=0.01)
    

    If the APOPT solver does not converge with the modified problem, try using an NLP solver such as the Interior Point Method solver IPOPT to initialize the solution. Gekko retains the solution values from one solve to use as the initial guess for the next solve.

    model.options.SOLVER=3
    model.solve()
    model.options.SOLVER=1
    model.solver_options = ['minlp_maximum_iterations 100', \
                            'minlp_max_iter_with_int_sol 10', \
                            'minlp_as_nlp 0', \
                            'nlp_maximum_iterations 50', \
                            'minlp_branch_method 1', \
                            'minlp_print_level 8',  \
                            'minlp_integer_tol 0.05', \
                            'minlp_gap_tol 0.001']
    model.solve()
    

    Please post a complete and minimal example if more specific suggestions are needed.