如何使用 GEKKO 和 APOPT 检查求解器的收敛性

How to check solver convergence with GEKKO and APOPT

我正在处理我已固定最大迭代次数的小型 MILP 问题。我想确定我们确信我们已经达到最佳状态的实例。

调用m.solve(disp=True)时,如果解算器提前停止,它会显示警告:

Warning: reached maximum MINLP iterations, returning best solution

我想以编程方式检查我们是否处于这种情况。我试过了

1) 查看文档,但它说 m.options.SOLVESTATUS 始终为 1,并且 m.options.APPINFO 从求解器找到可行解决方案的那一刻起始终为 0。

2)

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

但它不起作用,因为实际上 m.options.ITERATIONS 并不像我想的那样(它总是比 m.options.MAX_ITER 低很多)。

3) 引发然后捕获警告:

import warnings
warnings.filterwarnings("error")

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

但它也不起作用(未引发错误)。


所以我有两个问题:

1) 如何查看求解器已经使用的迭代次数?

2) 如何确定求解器是否检查了每个候选并因此找到了最佳实例?

目前,无法从 APOPT 报告混合整数迭代次数。但是,您可以通过将 minlp_maximum_iterations 设置为较大的值(例如 100000)来确保 APOPT 永远不会过早停止。 m.options.ITERATIONS 报告上次分支评估的 NLP 次迭代。

您可以通过将 minlp_gap_tol 设置为零来确保评估所有候选解决方案。如果间隙公差条件得到满足,求解器将终止。将其设置为零意味着将评估所有选项。但是,评估所有选项可能需要更长的时间。

from gekko import GEKKO
m = GEKKO(remote=False) # Initialize gekko
m.options.SOLVER=1  # APOPT is an MINLP solver

# optional solver settings with APOPT
m.solver_options = ['minlp_maximum_iterations 100000', \
                    # minlp iterations with integer solution
                    'minlp_max_iter_with_int_sol 10', \
                    # nlp sub-problem max iterations
                    'nlp_maximum_iterations 50', \
                    # covergence tolerance
                    'minlp_gap_tol 0.00']

# Initialize variables
x1 = m.Var(value=1,lb=1,ub=5)
x2 = m.Var(value=5,lb=1,ub=5)
# Integer constraints for x3 and x4
x3 = m.Var(value=5,lb=1,ub=5,integer=True)
x4 = m.Var(value=1,lb=1,ub=5,integer=True)
# Equations
m.Equation(x1*x2*x3*x4>=25)
m.Equation(x1**2+x2**2+x3**2+x4**2==40)
m.Obj(x1*x4*(x1+x2+x3)+x3) # Objective
m.solve(disp=True) # Solve
print('Results')
print('Iterations: ' + str(m.options.ITERATIONS))
print('x1: ' + str(x1.value))
print('x2: ' + str(x2.value))
print('x3: ' + str(x3.value))
print('x4: ' + str(x4.value))
print('Objective: ' + str(m.options.objfcnval))

还有information on solver options.

来自 :

1) 如何查看求解器已经使用的迭代次数?

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

2) 如何确定求解器是否确实检查了每个候选并因此找到了最佳实例?

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

现在我已经实现了一个丑陋的解决方案:

# 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