Инициализировать целочисленные переменные в CyLP
Я сейчас использую CyLP
пакет на Python для смешанно-целочисленного линейного программирования. Однако я не могу инициализировать целочисленные переменные. Согласно документации я прошелisInt = True
к addVariable
метод, но он ничего не делает.
Ниже показан минимальный пример моей программы. Оптимальное значение должно быть 2, когдаx = y = 1
, но результат не такой, как ожидалось.
import cylp
from cylp.cy import CyClpSimplex
print(cylp.__version__) # 0.91.0
s = CyClpSimplex()
x = s.addVariable('x', 1, isInt = True)
y = s.addVariable('y', 1, isInt = True)
s += x >= 0.5
s += y >= 0.7
s.objective = x + y
s.optimizationDirection = 'min'
s.primal()
# Clp3002W Empty problem - 0 rows, 2 columns and 0 elements
# Clp0000I Optimal - objective value 1.2
x_opt = s.primalVariableSolution['x'][0]
y_opt = s.primalVariableSolution['y'][0]
print(x_opt, y_opt) # 0.5, 0.7
Есть ли другой способ инициализировать целочисленные переменные в CyLP
? Или я что-то упускаюaddVariable
метод?
Кстати, интересно, что Clp3002W Empty problem
означает на выходе s.primal()
.
Заранее спасибо.
1 ответ
Это немного подло.
Clp - это решающая программа для линейного программирования, пока вы пытаетесь выполнить смешанное целочисленное программирование.
Вам нужно будет использовать Cbc, который построен поверх Clp (тот же человек / те же люди). Я думаю, что можно понять, что большая часть этого проекта - это работа одного человека на протяжении десятилетий (неинтуитивный дизайн; возможно).
Да, CyLp основан на Cbc, но использование по-прежнему требует осторожности!
Предполагая, что ваши определения переменных в порядке (не проверяли), вам нужно будет сделать что-то вроде:
# model = CyClpSimplex()
# ...
cbcModel = model.getCbcModel() # Clp -> Cbc model / LP -> MIP
status = cbcModel.solve() #-> "Call CbcMain. Solve the problem
# "using the same parameters used
# "by CbcSolver."
# This deviates from cylp's docs which are sparse!
# -> preprocessing will be used and is very important!
См. Также эту обертку:
if data[s.BOOL_IDX] or data[s.INT_IDX]:
# MIP
# Convert model
cbcModel = model.getCbcModel()
# cylp: /cylp/cy/CyCbcModel.pyx#L134
# Call CbcMain. Solve the problem using the same parameters used by
# CbcSolver. Equivalent to solving the model from the command line
# using cbc's binary.
cbcModel.solve()
status = cbcModel.status
else:
# LP
# cylp: /cylp/cy/CyClpSimplex.pyx
# Run CLP's initialSolve. It does a presolve and uses primal or dual
# Simplex to solve a problem.
status = model.initialSolve()
Я написал эти вещи много времени назад, поэтому я не могу дать вам точных деталей (предыстория этих звонков и комментариев).
Но в целом: трудно понять, что именно происходит внутри Cbc (хотя, я думаю, была некоторая работа по улучшению API; вероятно, НЕ отражена в Cylp). Например: нетривиально использовать Cbc из кода так же, как ведет себя исполняемый файл Cbc.
Кстати, мне интересно, что означает проблема Clp3002W Empty в выводе s.primal ().
Clp3002W Пустая задача - 0 строк, 2 столбца и 0 элементов
Моя интерпретация:
Ваша (преобразованная) модель не имеет ограничений. Вы добавили ограничения для принудительного применения границ переменных, но Clp/Cbc достаточно продвинутый (он очень продвинутый), чтобы преобразовать эти ограничения в границы переменных (больше никаких ограничений!), Которые обрабатываются специальной обработкой в Simplex-Routine.
0 rows = 0 constraints
0 elements = 0 non-zero elements in your constraint-matrix of size
rows * cols = 0 * 2 = 0