#python #or-tools #cp-sat-solver
#python #или-инструменты #cp-sat-решатель
Вопрос:
Используя интерфейс Python для решателя OR-Tools CP-CAT (ссылка), я хотел бы иметь возможность сохранять cp_model, загружать его позже или из другого процесса и продолжать взаимодействовать с ним.
Я могу сериализовать модель в Protubuf, а затем загрузить и решить ее:
from google.protobuf import text_format
from ortools.sat.python import cp_model
def create_model():
model = cp_model.CpModel()
a = model.NewIntVar(0, 10, "var_a")
b = model.NewIntVar(0, 10, "var_b")
model.Maximize(a b)
return model
def clone_model(model):
new_model = cp_model.CpModel()
text_format.Parse(str(model), new_model.Proto())
return new_model
def solve_model(model):
solver = cp_model.CpSolver()
status = solver.Solve(new_model)
print(solver.StatusName(status))
print(solver.ObjectiveValue())
# Works fine
model = create_model()
new_model = clone_model(model)
solve_model(new_model)
Тем не менее, я хотел бы продолжать взаимодействовать с моделью после ее загрузки. Например, я хочу иметь возможность делать что-то вроде:
model = create_model()
new_model = clone_model(model)
c = new_model.NewIntVar(0, 5, "var_c")
new_model.Add(a < c)
Проблема в том, что эта последняя строка не работает, потому a
что не определена; и я не смог найти никакого способа доступа к переменным существующей модели.
Я ищу что-то вроде: a = new_model.getExistingVariable("var_a")
что позволит мне продолжать взаимодействовать с уже существующими переменными в модели после ее загрузки.
Комментарии:
1. Это не реализовано.
2. Я думаю, вы могли бы попытаться выбрать модель вместе с переменными
3. Что ж, похоже, что подход pickle работает. Я чувствую себя немного глупо 🙂 Я не уверен, насколько надежным он будет для новых версий, но, поскольку он, похоже, работает, я добавлю его в качестве ответа — позволит людям легко указывать на проблемы
Ответ №1:
Подход, который, похоже, работает, основанный на комментарии @Stradivari, заключается в том, чтобы просто pickle
использовать модель вместе с ее переменными.
Например:
from ortools.sat.python import cp_model
import pickle
class ClonableModel:
def __init__(self):
self.model = cp_model.CpModel()
self.vars = {}
def create_model(self):
self.vars['a'] = self.model.NewIntVar(0, 10, "var_a")
self.vars['b'] = self.model.NewIntVar(0, 10, "var_b")
self.model.Maximize(self.vars['a'] self.vars['b'])
# Also possible to serialize via a file / over network
def clone(self):
return pickle.loads(pickle.dumps(self))
def solve(self):
solver = cp_model.CpSolver()
status = solver.Solve(self.model)
return '%s: %i' % (solver.StatusName(status), solver.ObjectiveValue())
Теперь следующее работает, как и ожидалось:
model = ClonableModel()
model.create_model()
new_model = model.clone()
new_model.model.NewIntVar(0,5,"c")
new_model.model.Add(new_model.vars['a'] < c)
print('Original model: %s' % model.solve())
print('Cloned model: %s' % new_model.solve())
# Original model: OPTIMAL: 20
# Cloned model: OPTIMAL: 14