0

我正在尝试使用 CBC 求解器(版本:2.9.8 )解决 pyomo( Pyomo 5.3(Linux 3.10.0-514.26.2.el7.x86_64 上的 CPython 2.7.13)的优化问题,并在求解器中指定时间限制60 秒。求解器得到了一个可行的解决方案(-1415.8392),但显然还不是最优的(-1415.84),如下所示。

时间限制结束后,模型似乎以错误代码退出。我想在指定的时间限制内使用 CBC 打印或获取可行解决方案的所有变量的值。或者是否有任何其他方式可以设置,如果模型获得 99% 的最佳解决方案值,则退出并打印可行解决方案。

错误代码贴在下面。

Cbc0004I 在 357760 次迭代和 29278 个节点(47.87 秒)后找到 -1415.8392 的整数解
Cbc0010I 在 30000 个节点之后,树上 6350 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(48.87 秒)
Cbc0010I 在 31000 个节点之后,树上 6619 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(50.73 秒)
Cbc0010I 在 32000 个节点之后,树上 6984 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(52.49 秒)
Cbc0010I 在 33000 个节点之后,树上 7384 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(54.31 秒)
Cbc0010I 在 34000 个节点之后,树上 7419,-1415.8392 最佳解决方案,最佳可能 -1415.84(55.73 秒)
Cbc0010I 在 35000 个节点之后,树上 7824 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(57.37 秒)
回溯(最近一次通话最后):
  文件“model_final.py”,第 392 行,在
    solver.solve(模型,时间限制= 60 * 1,三通=真)
  文件“/home/aditya/0r/lib/python2.7/site-packages/pyomo/opt/base/solvers.py”,第 655 行,在求解
    default_variable_value=self._default_variable_value)
  文件“/home/aditya/0r/lib/python2.7/site-packages/pyomo/core/base/PyomoModel.py”,第 242 行,在 load_from
    % str(results.solver.status))
ValueError:无法加载状态不佳的 SolverResults 对象:错误

当我使用与 pyomo 相同的命令行参数手动运行 pyomo 生成的模型时,/usr/bin/cbc -sec 60 -printingOptions all -import /tmp/tmpJK1ieR.pyomo.lp -import -stat=1 -solve -solu /tmp/tmpJK1ieR.pyomo.soln它似乎正常退出并且还编写了如下所示的解决方案。

Cbc0010I 在 35000 个节点之后,树上 7824 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(57.06 秒)
Cbc0038I 完全问题 205 行 289 列,减少到 30 行 52 列
Cbc0010I 在 36000 个节点之后,树上 8250 个,-1415.8392 最佳解决方案,最佳可能 -1415.84(58.73 秒)
Cbc0020I 以最长时间退出
Cbc0005I 部分搜索 - 最佳目标 -1415.8392(可能的最佳 -1415.84),进行了 464553 次迭代和 36788 个节点(60.11 秒)
Cbc0032I 强分支完成 15558 次(38451 次迭代),测算 350 个节点并固定 2076 个变量
Cbc0035I 最大深度 203、5019 个变量固定在降低的成本上
Cbc0038I 探测尝试了 31933 次并创建了 138506 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(4.431 秒)
Cbc0038I Gomory 尝试了 30898 次并创建了 99534 个剪辑,其中 0 个在添加轮次剪辑后处于活动状态(4.855 秒)
Cbc0038I 背包尝试了 30898 次并创建了 12926 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(8.271 秒)
Cbc0038I Clique 尝试了 100 次并创建了 0 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(0.000 秒)
Cbc0038I MixedIntegerRounding2 尝试了 30898 次并创建了 13413 个切割,其中 0 个在添加切割轮后处于活动状态(3.652 秒)
Cbc0038I FlowCover 尝试了 100 次并创建了 4 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(0.019 秒)
Cbc0038I TwoMirCuts 尝试了 30898 次并创建了 15292 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(2.415 秒)
Cbc0038I 从第一个开始存储已尝试 30898 次并创建了 15734 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(0.000 秒)
Cbc0012I 在 467825 次迭代和 36838 个节点(60.12 秒)后通过缩减搜索找到 -1411.9992 的整数解
Cbc0020I 以最长时间退出
Cbc0005I 部分搜索 - 最佳目标 -1411.9992(可能的最佳 -1415.4522),进行了 467825 次迭代和 36838 个节点(60.12 秒)
Cbc0032I 强分支完成 476 次(1776 次迭代),测透 1 个节点并固定 18 个变量
Cbc0035I 最大深度 21,39 个变量固定在降低的成本上
根节点处的切割将目标从 -1484.12 更改为 -1415.45
探测尝试了 133 次并创建了 894 个切割,其中 32 个在添加多轮切割后处于活动状态(0.060 秒)
Gomory 被尝试了 133 次并创建了 1642 次剪辑,其中 0 次在添加轮次后处于活动状态(0.047 秒)
背包尝试了 133 次并创建了 224 次切割,其中 0 次在添加轮次切割后处于活动状态(0.083 秒)
Clique 尝试了 100 次并创建了 0 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(0.001 秒)
MixedIntegerRounding2 尝试了 133 次并创建了 163 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(0.034 秒)
FlowCover 尝试了 100 次并创建了 5 个剪辑,其中 0 个在添加几轮剪辑后处于活动状态(0.026 秒)
TwoMirCuts 尝试了 133 次并创建了 472 个剪辑,其中 0 个在添加轮次剪辑后处于活动状态(0.021 秒)
ImpplicationCuts 尝试了 25 次并创建了 41 个剪辑,其中 0 个在添加轮次剪辑后处于活动状态(0.003 秒)

结果 - 按时停止

目标值:-1411.99922848
下限:-1415.452
差距:0.00
枚举节点:36838
总迭代次数:467825
时间(CPU 秒):60.13
时间(挂钟秒):60.98

总时间(CPU 秒):60.13(Wallclock 秒):61.01

CBC 解决方案文件的前几行是:

准时停止 - 目标值 -1411.99922848
      0 c_e_x1454_ 0 0
      1 c_e_x1455_ 0 0
      2 c_e_x1456_ 0 0
      3 c_e_x1457_ 0 0
      4 c_e_x1458_ 0 0
      5 c_e_x1459_ 0 0
      6 c_e_x1460_ 0 0
      7 c_e_x1461_ 0 0
      8 c_e_x1462_ 0 0

谁能告诉我如何在不产生任何错误的情况下获得这些值?

提前致谢。

4

2 回答 2

0

创建了一个拉取请求https://github.com/Pyomo/pyomo/pull/265来解决这个问题。

对于那些立即想要补丁的人:

在文件pyomo/solvers/plugins/solvers/CBCplugin.py

@@ -264,7 +264,8 @@ def _check_and_escape_options(options):
             cmd.append('-AMPL')

             if self._timelimit is not None and self._timelimit > 0.0:
-                cmd.extend(['-sec', str(self._timelimit)])
+                cmd.extend(['-sec', str(self._timelimit - 1 )])
+                cmd.extend(['-timeMode', "elapsed"])
             if "debug" in self.options:
                 cmd.extend(["-log","5"])
             for key, val in _check_and_escape_options(self.options):
@@ -276,7 +277,8 @@ def _check_and_escape_options(options):
                         #"-stat"])
         else:
             if self._timelimit is not None and self._timelimit > 0.0:
-                cmd.extend(['-sec', str(self._timelimit)])
+                cmd.extend(['-sec', str(self._timelimit - 1 )])
+                cmd.extend(['-timeMode', "elapsed"])
             if "debug" in self.options:
                 cmd.extend(["-log","5"])
             # these must go after options that take a value

时间限制设置为比提供的选项低 1 秒,以确保 CBC 进程在 pyutilib.subprocess.processmngr 检查退出代码之前有时间正确退出。在我的测试运行中,进程管理器在 T+0.02 秒时检查了退出状态,而 CBC 进程通常在 T+0.1 秒后退出。

还更改了 CBC 代码以使用默认 CPU 秒数的挂钟秒数,因为进程管理器也在检查相同的值。

于 2017-11-27T09:54:05.807 回答
0

您可以尝试设置边界间隙容差,使其接受另一个答案。如果找到可行的解决方案,我很惊讶求解器状态会返回错误。你能打印出整个结果对象吗?

于 2017-11-16T17:52:44.623 回答