从 ortools 获取 SAT 解决方案列表
Obtain list of SAT solutions from ortools
我正在尝试找出如何从 ortools.sat.python.cp_model
中获取可能解决方案的完整列表。我知道我可以打印它们,如下例所示,但我不清楚如何获取这些值,例如作为嵌套列表或字典列表。我尝试通过修改 VarArraySolutionPrinter
并将解决方案附加到列表属性来编写自己的回调 class,但由于某种原因,这始终导致 python 内核崩溃。无论如何,必须有更直接的方法。我不认为解析打印输出是一个选项。
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x00 = model.NewBoolVar('x00')
x01 = model.NewBoolVar('x01')
x02 = model.NewBoolVar('x02')
model.AddBoolOr([x00, x01, x02.Not()])
model.AddBoolOr([x00.Not(), x02.Not()])
# Create a solver and solve.
solver = cp_model.CpSolver()
solution_printer = cp_model.VarArraySolutionPrinter([x00, x01, x02])
solver.SearchForAllSolutions(model, solution_printer)
## Prints:
Solution 0, time = 0.00 s
x00 = 0 x01 = 1 x02 = 0
Solution 1, time = 0.01 s
x00 = 0 x01 = 0 x02 = 0
Solution 2, time = 0.01 s
x00 = 0 x01 = 1 x02 = 1
Solution 3, time = 0.01 s
x00 = 1 x01 = 1 x02 = 0
Solution 4, time = 0.01 s
x00 = 1 x01 = 0 x02 = 0
事实证明,编写自定义回调 class 确实有效:
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x00 = model.NewBoolVar('x00')
x01 = model.NewBoolVar('x01')
x02 = model.NewBoolVar('x02')
model.AddBoolOr([x00, x01, x02.Not()])
model.AddBoolOr([x00.Not(), x02.Not()])
class VarArraySolutionCollector(cp_model.CpSolverSolutionCallback):
def __init__(self, variables):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__variables = variables
self.solution_list = []
def on_solution_callback(self):
self.solution_list.append([self.Value(v) for v in self.__variables])
# Create a solver and solve.
solver = cp_model.CpSolver()
solution_collector = VarArraySolutionCollector([x00, x01, x02])
solver.SearchForAllSolutions(model, solution_collector)
solution_collector.solution_list
Out[33]: [[0, 1, 0], [0, 0, 0], [0, 1, 1], [1, 1, 0], [1, 0, 0]]
我正在尝试找出如何从 ortools.sat.python.cp_model
中获取可能解决方案的完整列表。我知道我可以打印它们,如下例所示,但我不清楚如何获取这些值,例如作为嵌套列表或字典列表。我尝试通过修改 VarArraySolutionPrinter
并将解决方案附加到列表属性来编写自己的回调 class,但由于某种原因,这始终导致 python 内核崩溃。无论如何,必须有更直接的方法。我不认为解析打印输出是一个选项。
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x00 = model.NewBoolVar('x00')
x01 = model.NewBoolVar('x01')
x02 = model.NewBoolVar('x02')
model.AddBoolOr([x00, x01, x02.Not()])
model.AddBoolOr([x00.Not(), x02.Not()])
# Create a solver and solve.
solver = cp_model.CpSolver()
solution_printer = cp_model.VarArraySolutionPrinter([x00, x01, x02])
solver.SearchForAllSolutions(model, solution_printer)
## Prints:
Solution 0, time = 0.00 s
x00 = 0 x01 = 1 x02 = 0
Solution 1, time = 0.01 s
x00 = 0 x01 = 0 x02 = 0
Solution 2, time = 0.01 s
x00 = 0 x01 = 1 x02 = 1
Solution 3, time = 0.01 s
x00 = 1 x01 = 1 x02 = 0
Solution 4, time = 0.01 s
x00 = 1 x01 = 0 x02 = 0
事实证明,编写自定义回调 class 确实有效:
from ortools.sat.python import cp_model
model = cp_model.CpModel()
x00 = model.NewBoolVar('x00')
x01 = model.NewBoolVar('x01')
x02 = model.NewBoolVar('x02')
model.AddBoolOr([x00, x01, x02.Not()])
model.AddBoolOr([x00.Not(), x02.Not()])
class VarArraySolutionCollector(cp_model.CpSolverSolutionCallback):
def __init__(self, variables):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__variables = variables
self.solution_list = []
def on_solution_callback(self):
self.solution_list.append([self.Value(v) for v in self.__variables])
# Create a solver and solve.
solver = cp_model.CpSolver()
solution_collector = VarArraySolutionCollector([x00, x01, x02])
solver.SearchForAllSolutions(model, solution_collector)
solution_collector.solution_list
Out[33]: [[0, 1, 0], [0, 0, 0], [0, 1, 1], [1, 1, 0], [1, 0, 0]]