Or-Tools CP-SAT 求解器导出/导入:加载模型后如何访问变量?
Posted
技术标签:
【中文标题】Or-Tools CP-SAT 求解器导出/导入:加载模型后如何访问变量?【英文标题】:Or-Tools CP-SAT solver export/import: how to access vars after loading a model? 【发布时间】:2020-12-08 12:57:54 【问题描述】:使用 OR-Tools CP-CAT 求解器(reference) 的 Python 接口,我希望能够保存 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)
(source)
但是,我想在加载后继续与模型进行交互。例如,我希望能够执行以下操作:
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")
的内容,这将允许我在加载模型后继续与模型中预先存在的变量进行交互。
【问题讨论】:
这个没有实现。 我想您可以尝试将模型与变量一起腌制 好吧,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
【讨论】:
以上是关于Or-Tools CP-SAT 求解器导出/导入:加载模型后如何访问变量?的主要内容,如果未能解决你的问题,请参考以下文章
addDivisionEquality with Java google or-tools CP-SAT
Google OR-Tools(使用 SCIP 求解器) - 如何访问求解器找到的中间解决方案?
如何在 MiniZinc 中安装 Google 的 CP 求解器 OR-Tools?