Search code examples
pythonconvergencegekko

How to check solver convergence with GEKKO and APOPT


I am dealing with small MILP problems for which I have fixed the maximum number of iterations. I would like to determine the instances for which we are sure that we have reached the optimum.

When calling m.solve(disp=True), if the solver stops early, it displays the warning:

Warning: reached maximum MINLP iterations, returning best solution

I would like to check programmatically whether we are in such a situation. I tried

1) looking at the documentation but it says m.options.SOLVESTATUS is always 1 and m.options.APPINFO is always 0 from the moment the solver found a feasible solution.

2)

optimum = m.options.ITERATIONS < m.options.MAX_ITER

but it does not work because in fact m.options.ITERATIONS doesn't do what I thought (it is always much lower than m.options.MAX_ITER).

3) raise and then catch the warning:

import warnings
warnings.filterwarnings("error")

try:
    self.model.solve()
    optimum = True
except:
    optimum = False

But it doesn't work either (no error is raised).


So I have 2 questions:

1) How to check the number of iterations that have been used by the solver ?

2) How to determine whether the solver did check every candidate and thus found the best instanciation ?


Solution

  • From John Hedengren's answer :

    1) How to check the number of iterations that have been used by the solver ?

    Right now, there is no way to report the number of Mixed Integer iterations from APOPT

    2) How to determine whether the solver did check every candidate and thus found the best instanciation ?

    I added this as a feature request on Github: github.com/BYU-PRISM/GEKKO/issues/81

    For now I have implemented an ugly solution :

    # redirect stdout
    sys.stdout = open('tmp_output', 'w')
    
    # solve and output to the tmp file
    try:
        self.model.solve(disp=True)
    except:
        pass #solution not found
    
    # read the file
    with open('tmp_output', 'r') as f:
        line = f.readline()
    
        # skip the first lines
        while line[:5] != "Iter:":
            line = f.readline()
    
        # skip the next lines (one line per iteration)
        while line[:5] in ["Iter:", "--Int"]:
            line = f.readline()
    
        # check the warning
        optimal = line != " Warning: reached maximum MINLP iterations, returning best solution\n"
    
    return optimal