Запись файла журнала COIN-OR CBC

Я использую CBC-решатель COIN-OR для решения некоторых задач численной оптимизации. Я структурирую проблему оптимизации в Python через PuLP.

Я заметил, что решатели, такие как GUROBI и CPLEX, создают файлы журналов, но я не могу понять, как заставить CBC создать файл журнала (в отличие от вывода прогресса оптимизатора на экран).

Кто-нибудь знает вариант в CBC, чтобы установить файл журнала? Перенаправление всех stdout в файл не работает для меня, так как я параллельно решаю кучу проблем и хочу хранить их файлы журналов отдельно.

Вот пример того, как я называю решатель. Это прекрасно работает и печатает прогресс в терминал.

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, пытаясь понять это.

2 ответа

Решение

Для решения, требующего всего несколько строк кода в вашем сценарии, который вызывает PuLP и CBC, см. Решение Джеймса Фогеля (возможно, https://github.com/voglster) по адресу https://groups.google.com/forum/, основываясь на os.dup() а также os.dup2(),

Я надеюсь, что неуместно копировать его здесь для защиты от linkrot, но посмотрите оригинальное сообщение для построчного объяснения и некоторые сложные вещи, которые я не понимаю из пакета 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.

Я не смог найти ответ без изменения pulp исходный код, но если это вас не беспокоит, то выберите следующий маршрут:

перейдите в каталог вашей библиотеки установки целлюлозы и посмотрите на solvers.py файл.

Функция интереса solve_CBC в COIN_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 переводчик называет это. Я открываю файл, используя этот идентификатор, и передаю его этому аргументу. как это:

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 для получения дополнительной документации. Так как это создает разные файлы для каждого идентификатора процесса, я думаю, что это решит вашу проблему параллельного запуска нескольких решателей.

Другие вопросы по тегам