OrTools 中如何使用系数进行约束优化?

How do constraint optimization in OrTools with coefficents?

我想使用 ortools 生成一个简单问题的所有可能组合,如以下程序所示。在这种情况下,我希望 x 和 y 是 5 的乘法,另外如果 start 是 7,那么 x 的值应该是 7、10、15、20、25 等等。我该如何更改以下代码?

  model = cp_model.CpModel()

  start = 7
  end = 20
  x = model.NewIntVar(start , end - 1, "x")
  y = model.NewIntVar(start , end - 1, "y")
  # Create the constraints.
  model.Add(x != y)
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from ortools.sat.python import cp_model


class VarArraySolutionPrinter(cp_model.CpSolverSolutionCallback):
  """Print intermediate solutions."""

  def __init__(self, variables):
    self.__variables = variables
    self.__solution_count = 0

  def NewSolution(self):
    self.__solution_count += 1
    for v in self.__variables:
      print('%s=%i' % (v, self.Value(v)), end=' ')
    print()

  def SolutionCount(self):
    return self.__solution_count


def mod_or_start():
  model = cp_model.CpModel()

  start = 7
  end = 20
  x = model.NewIntVar(start, end - 1, 'x')  # 8..19
  y = model.NewIntVar(start, end - 1, 'y')  # 8..19

  x_is_start = model.NewBoolVar('x_is_start')
  y_is_start = model.NewBoolVar('y_is_start')
  x_is_modulo_5 = model.NewBoolVar('x_is_modulo_5')
  y_is_modulo_5 = model.NewBoolVar('y_is_modulo_5')

  model.Add(x == start).OnlyEnforceIf(x_is_start)
  model.Add(y == start).OnlyEnforceIf(y_is_start)

  # Buggy.
  # model.AddModuloEquality(0, x, 5).OnlyEnforceIf(x_is_modulo_5)
  # model.AddModuloEquality(0, y, 5).OnlyEnforceIf(y_is_modulo_5)

  # Workaround until the modulo code is fixed.
  sub_x = model.NewIntVar(start // 5, end // 5, 'sub_x')
  sub_y = model.NewIntVar(start // 5, end // 5, 'sub_y')
  model.Add(x == 5 * sub_x).OnlyEnforceIf(x_is_modulo_5)
  model.Add(y == 5 * sub_y).OnlyEnforceIf(y_is_modulo_5)
  # Remove duplicate solutions
  model.Add(sub_x == start // 5).OnlyEnforceIf(x_is_modulo_5.Not())
  model.Add(sub_y == start // 5).OnlyEnforceIf(y_is_modulo_5.Not())

  # At least one option is true.
  model.AddBoolOr([x_is_start, x_is_modulo_5])
  model.AddBoolOr([y_is_start, y_is_modulo_5])

  # Create a solver and solve.
  solver = cp_model.CpSolver()
  solution_printer = VarArraySolutionPrinter([x, y])
  status = solver.SearchForAllSolutions(model, solution_printer)
  print('Status = %s' % solver.StatusName(status))
  print('Number of solutions found: %i' % solution_printer.SolutionCount())


mod_or_start()

输出:

x=15 y=15 
x=15 y=7 
x=10 y=7 
x=7 y=7 
x=7 y=15 
x=7 y=10 
x=10 y=15 
x=10 y=10 
x=15 y=10 
Status = FEASIBLE
Number of solutions found: 9