簡體   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