繁体   English   中英

编写 COIN-OR CBC 日志文件

[英]Writing COIN-OR CBC Log File

我正在使用 COIN-OR 的 CBC 求解器来解决一些数值优化问题。 我正在通过 PuLP 在 Python 中构建优化问题。

我注意到像 GUROBI 和 CPLEX 这样的求解器会创建日志文件,但我似乎无法弄清楚如何让 CBC 创建日志文件(而不是将优化器的进度打印到屏幕上)。

有人知道 CBC 中设置日志文件的选项吗? 将所有标准输出重定向到一个文件对我来说不起作用,因为我正在并行解决一堆问题并希望将它们的日志文件分开。

这是我如何调用求解器的示例。 这很好用,并将进度打印到终端。

prob.solve(pulp.COIN_CMD(msg=1, options=['DivingVectorlength on','DivingSome on']))

这是我认为应该如何构建解决方案的方式(尽管显然LogFileName不是有效的 CBC 选项)。

prob.solve(pulp.COIN_CMD(msg=1, options=['DivingVectorlength on', 'DivingSome on', 'LogFileName stats.log']))

对此的任何帮助将不胜感激。 几个小时以来,我一直在浏览互联网、文档和 CBC 互动会议,试图弄清楚这一点。

我无法在不更改pulp源代码的情况下找到答案,但如果这不打扰您,那么请走以下路线:

导航到您的纸浆安装库的目录并查看solvers.py文件。

感兴趣的功能是solve_CBCCOIN_CMD类。 在该方法中,参数形成单个命令传递给cbc-64求解器程序,然后使用subprocess.Popen方法调用它。 此方法的stdout参数要么设置为None要么os.devnull对我们来说都不是很有用。 您可以在第 1340 行(对于 PuLP 1.5.6)看到进程调用。

cbc = subprocess.Popen((self.path + cmds).split(), stdout = pipe,
                     stderr = pipe)

该来源还揭示了问题 (mps) 和解决方案 (sol) 文件被写入/tmp目录(在 UNIX 机器上),并且文件名包括调用它的解释器的pid 我使用这个 id 打开一个文件并将它传递给那个参数。 像这样:

logFilename = os.path.join(self.tmpDir, "%d-cbc.log" % pid)
logFile = open(logFilename, 'a')
cbc = subprocess.Popen((self.path + cmds).split(), stdout = logFile,
                     stderr = pipe)

果然,运行后在/tmp目录下看到了我的日志文件。 您可以使用log N设置详细程度,请参阅 cbc 帮助以获取更多文档。 由于这会为每个进程 ID 创建一个不同的文件,我认为它将解决您并行运行多个求解器的问题。

有关在调用 PuLP 和 CBC 的脚本中只需要几行代码的解决方案,请参阅 James Vogel( https://github.com/voglster ,也许)在https://groups.google.com/forum 上的解决方案/#!topic/pulp-or-discuss/itbmTC7uNCQ ,基于os.dup()os.dup2()

我希望将它复制到这里以防止链接腐烂不是不合适的,但是请参阅原始帖子以获取逐行解释以及我从 tempfile 包中不了解的一些复杂内容。 我自己的用法不太复杂,使用实际的永久文件名:

from os import dup, dup2, close
f = open('capture.txt', 'w')
orig_std_out = dup(1)
dup2(f.fileno(), 1)

status = prob.solve (PULP_CBC_CMD(maxSeconds = i_max_sec, fracGap = d_opt_gap, msg=1))  #  CBC time limit and relative optimality gap tolerance
print('Completion code: %d; Solution status: %s; Best obj value found: %s' % (status, LpStatus[prob.status], value(prob.objective)))    

dup2(orig_std_out, 1)
close(orig_std_out)
f.close()

这会在当前目录中的capture.txt中为您留下有用的信息。

重用@Mike 的答案,PuLP(自 2.2 起)现在包括通过将logPath参数与要写入的文件的路径一起传递来将日志写入文件的可能性。

所以你现在可以这样做:

prob.solve(pulp.COIN_CMD(msg=1, logPath="stats.log", options=['DivingVectorlength on', 'DivingSome on']))

唯一的警告是您不能再“在屏幕上”看到它,因为它将输出重定向到文件。 在这种情况下,您不需要提供msg=1 ,只需提供logPath

logPath参数在以下几个求解器中是一致的(在 PuLP >= 2.2 中):PULP_CBC_CMD、COIN_CMD、PULP_COIN_CMD、GUROBI、CPLEX、CPLEX_CMD、GUROBI_CMD。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM