首页 > 解决方案 > cp_model.CpModel() 中是否有与 pywrapcp.Solver() 中的 IsEqualCstVar 类似的功能?

问题描述

由于缺少 AddModuloEquality,我不得不将程序从 Solver 更改为 CpModel。我对 IsEqualCstVar 有以下约束,我无法“翻译”:

# with solver
from ortools.constraint_solver import pywrapcp
solver = pywrapcp.Solver("")
a = solver.IntVar(1, 10, 'a')
b = solver.IntVar(1, 10, 'b')
c = solver.IntVar(1, 10, 'c')
d = solver.IntVar(1, 10, 'd')
e = solver.IntVar(1, 10, 'e')

entities = [a, b, c, d, e]
old_values = [3, 5, 7, 1, 5]

solver.Add(solver.AllDifferent([entity for entity in entities]))
db = solver.Phase(entities, solver.INT_VAR_SIMPLE, solver.CHOOSE_RANDOM)

same = solver.Sum([solver.IsEqualCstVar(entities[x], old_values[x]) for x in range(len(entities))])
objective = solver.Maximize(same, 1)
solver.NewSearch(db, objective)

while solver.NextSolution():
    print("a:{}\tb: {}\tc: {}\td: {}\te: {}\t".format(a.Value(), b.Value(), c.Value(), d.Value(), e.Value()))range(len(entities))])

我怎样才能对模型做同样的事情?

# with model
from ortools.sat.python import cp_model

model = cp_model.CpModel()

a = model.NewIntVar(1, 10, 'a')
b = model.NewIntVar(1, 10, 'b')
c = model.NewIntVar(1, 10, 'c')
d = model.NewIntVar(1, 10, 'd')
e = model.NewIntVar(1, 10, 'e')

entities = [a, b, c, d, e]
old_values = [3, 5, 7, 1, 5]

model.AddAllDifferent(entities)

????

solver = cp_model.CpSolver()
solver.Solve(model)
print("a:{}\tb: {}\tc: {}\td: {}\te: {}\t".format(solver.Value(a), solver.Value(b), solver.Value(c), solver.Value(d), solver.Value(e)))

通过 Laurent Perron 的第一个答案,我能够找到一个解决方案,但只能使用与 old_values 数组中具有相同值的变量数量的固定定义。

"""Link integer constraints together."""

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):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.__variables = variables
        self.__solution_count = 0

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

    def solution_count(self):

        return self.__solution_count


def ChannelingSampleSat():
    """Demonstrates how to link integer constraints together."""

    # Create the CP-SAT model.
    model = cp_model.CpModel()

    # Declare primary variables.
    a = model.NewIntVar(1, 10, 'a')
    b = model.NewIntVar(1, 10, 'b')
    c = model.NewIntVar(1, 10, 'c')
    d = model.NewIntVar(1, 10, 'd')
    e = model.NewIntVar(1, 10, 'e')

    # Declare intermediate boolean variables.
    a1 = model.NewBoolVar('a1')
    b1 = model.NewBoolVar('b1')
    c1 = model.NewBoolVar('c1')
    d1 = model.NewBoolVar('d1')
    e1 = model.NewBoolVar('e1')

    primary = [a, b, c, d, e]
    intermediate = [a1, b1, c1, d1, e1]
    old_values = [3, 5, 7, 1, 5]

    for i in range(len(primary)):
        model.Add(primary[i] == old_values[i]).OnlyEnforceIf(intermediate[i])

    model.AddAllDifferent(primary)
    model.Add(sum([i for i in intermediate]) == 4)

    # Search for x values in increasing order.
    model.AddDecisionStrategy([e], cp_model.CHOOSE_FIRST,
                            cp_model.SELECT_MAX_VALUE)    

    solver = cp_model.CpSolver()
#    f = model.Add(sum([i for i in intermediate]))
#    model.Maximize(f)

    # Force the solver to follow the decision strategy exactly.
    solver.parameters.search_branching = cp_model.FIXED_SEARCH

    # Search and print out all solutions.
    solution_printer = VarArraySolutionPrinter(primary)
    solver.SearchForAllSolutions(model, solution_printer)

ChannelingSampleSat()

标签: pythonconstraint-programmingor-tools

解决方案


Everything is explained here

You need to add a pair of enforced linear constraints.

For example:

# Declare our two primary variables.
x = model.NewIntVar(0, 10, 'x')
y = model.NewIntVar(0, 10, 'y')

# Declare our intermediate boolean variable.
b = model.NewBoolVar('b')

# Implement b == (x >= 5).
model.Add(x >= 5).OnlyEnforceIf(b)
model.Add(x < 5).OnlyEnforceIf(b.Not())

推荐阅读