Support for Constraint::StatusVar() in C++, automatic conversion in Python

This commit is contained in:
lperron@google.com
2012-03-19 17:14:57 +00:00
parent 659222920b
commit 9ffab85b6e
9 changed files with 429 additions and 33 deletions

View File

@@ -3242,6 +3242,10 @@ bool Constraint::IsCastConstraint() const {
return ContainsKey(solver()->cast_constraints_, this);
}
IntVar* Constraint::StatusVar() {
return NULL;
}
// ----- Class IntExpr -----
void IntExpr::Accept(ModelVisitor* const visitor) const {

View File

@@ -83,6 +83,7 @@
#include "base/map-util.h"
#include "base/hash.h"
#include "base/random.h"
#include "util/tuple_set.h"
class Closure;
class File;
@@ -1642,6 +1643,29 @@ class Solver {
int64 initial_state,
const std::vector<int>& final_states);
#if defined(SWIGPYTHON)
// Compatibility layer for python API.
Constraint* MakeAllowedAssignments(const std::vector<IntVar*>& vars,
const std::vector<std::vector<int64> >& raw_tuples) {
IntTupleSet tuples(vars.size());
tuples.InsertAll(raw_tuples);
return MakeAllowedAssignments(vars, tuples);
}
Constraint* MakeTransitionConstraint(
const std::vector<IntVar*>& vars,
const std::vector<std::vector<int64> >& raw_transitions,
int64 initial_state,
const std::vector<int>& final_states) {
IntTupleSet transitions(3);
transitions.InsertAll(raw_transitions);
return MakeTransitionConstraint(vars,
transitions,
initial_state,
final_states);
}
#endif
// ----- Packing constraint -----
@@ -3433,6 +3457,11 @@ class Constraint : public PropagationBaseObject {
// Is the constraint created by a cast from expression to integer variable?
bool IsCastConstraint() const;
// Creates an boolean variable representing the status of the
// variable (false = constraint is violated, true constraint is
// satisfied). It returns NULL if the constraint does not support his API.
virtual IntVar* StatusVar();
private:
DISALLOW_COPY_AND_ASSIGN(Constraint);
};

View File

@@ -283,24 +283,91 @@ class PyDecisionBuilder(object):
%rename("%(strip:[Make])s", %$isfunction) "";
namespace operations_research {
%typemap(in) IntExpr* const {
operations_research::IntExpr* t;
if (SWIG_ConvertPtr($input,
(void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 ) == -1) {
operations_research::Constraint* c;
if (SWIG_ConvertPtr($input,
(void**)&c,
SWIGTYPE_p_operations_research__Constraint,
SWIG_POINTER_EXCEPTION | 0 ) != -1) {
operations_research::IntVar* const v = c->StatusVar();
if (v == NULL) {
SWIG_fail;
} else {
$1 = v;
}
} else {
SWIG_fail;
}
} else {
$1 = t;
}
}
%typecheck(SWIG_TYPECHECK_POINTER) IntExpr* const {
operations_research::IntExpr* t;
operations_research::Constraint* c;
$1 = (SWIG_ConvertPtr($input,
(void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 ) != -1 ||
SWIG_ConvertPtr($input,
(void**)&c,
SWIGTYPE_p_operations_research__Constraint,
SWIG_POINTER_EXCEPTION | 0 ) != -1);
if ($1 == 0) {
PyErr_Clear();
}
}
%typemap(in) IntVar* const {
operations_research::IntExpr* t;
if (SWIG_ConvertPtr($input,
(void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 ) == -1) {
SWIG_fail;
operations_research::Constraint* c;
if (SWIG_ConvertPtr($input,
(void**)&c,
SWIGTYPE_p_operations_research__Constraint,
SWIG_POINTER_EXCEPTION | 0 ) != -1) {
if (c == NULL) {
PyErr_SetString(PyExc_TypeError, "Invalid LanguageCode");
SWIG_fail;
}
operations_research::IntVar* const v = c->StatusVar();
if (v == NULL) {
SWIG_fail;
} else {
$1 = v;
}
} else {
SWIG_fail;
}
} else {
$1 = t->Var();
}
$1 = t->Var();
}
%typecheck(SWIG_TYPECHECK_POINTER) IntVar* const {
operations_research::IntExpr* t;
$1 = SWIG_ConvertPtr($input,
(void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 ) != -1;
PyErr_Clear();
operations_research::Constraint* c;
$1 = (SWIG_ConvertPtr($input,
(void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 ) != -1 ||
SWIG_ConvertPtr($input,
(void**)&c,
SWIGTYPE_p_operations_research__Constraint,
SWIG_POINTER_EXCEPTION | 0 ) != -1);
if ($1 == 0) {
PyErr_Clear();
}
}
%typemap(in) const IntVar* const {
@@ -342,13 +409,31 @@ namespace operations_research {
if ((SWIG_ConvertPtr(obj, (void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 )) == -1) {
SWIG_fail;
operations_research::Constraint* c;
if (SWIG_ConvertPtr(obj,
(void**)&c,
SWIGTYPE_p_operations_research__Constraint,
SWIG_POINTER_EXCEPTION | 0 ) != -1) {
if (c == NULL) {
PyErr_SetString(PyExc_TypeError, "Invalid LanguageCode");
SWIG_fail;
}
operations_research::IntVar* const v = c->StatusVar();
if (v == NULL) {
SWIG_fail;
} else {
temp[i] = v;
}
} else {
SWIG_fail;
}
} else {
if (t == NULL) {
PyErr_SetString(PyExc_TypeError, "Invalid LanguageCode");
SWIG_fail;
}
temp[i] = t->Var();
}
if (t == NULL) {
PyErr_SetString(PyExc_TypeError, "Invalid LanguageCode");
SWIG_fail;
}
temp[i] = t->Var();
}
$1 = &temp;
}
@@ -364,9 +449,14 @@ namespace operations_research {
PyObject* const obj =
is_tuple ? PyTuple_GetItem($input, i) : PyList_GetItem($input, i);
operations_research::IntExpr* t;
operations_research::Constraint* c;
if ((SWIG_ConvertPtr(obj, (void**)&t,
SWIGTYPE_p_operations_research__IntExpr,
SWIG_POINTER_EXCEPTION | 0 )) == -1) {
SWIG_POINTER_EXCEPTION | 0 )) == -1 &&
SWIG_ConvertPtr(obj,
(void**)&c,
SWIGTYPE_p_operations_research__Constraint,
SWIG_POINTER_EXCEPTION | 0 ) == -1) {
PyErr_Clear();
failed = true;
break;
@@ -856,6 +946,9 @@ static void SetPythonFlags(bool trace_propagation,
IntExpr* __add__(IntExpr* other) {
return self->solver()->MakeSum(self, other);
}
IntExpr* __add__(Constraint* other) {
return self->solver()->MakeSum(self, other->StatusVar());
}
IntExpr* __add__(int64 v) {
return self->solver()->MakeSum(self, v);
}
@@ -865,6 +958,9 @@ static void SetPythonFlags(bool trace_propagation,
IntExpr* __sub__(IntExpr* other) {
return self->solver()->MakeDifference(self, other);
}
IntExpr* __sub__(Constraint* other) {
return self->solver()->MakeDifference(self, other->StatusVar());
}
IntExpr* __sub__(int64 v) {
return self->solver()->MakeSum(self, -v);
}
@@ -874,6 +970,9 @@ static void SetPythonFlags(bool trace_propagation,
IntExpr* __mul__(IntExpr* other) {
return self->solver()->MakeProd(self, other);
}
IntExpr* __mul__(Constraint* other) {
return self->solver()->MakeProd(self, other->StatusVar());
}
IntExpr* __mul__(int64 v) {
return self->solver()->MakeProd(self, v);
}
@@ -930,6 +1029,24 @@ static void SetPythonFlags(bool trace_propagation,
Constraint* __lt__(IntExpr* other) {
return self->solver()->MakeLess(self->Var(), other->Var());
}
Constraint* __eq__(Constraint* other) {
return self->solver()->MakeEquality(self->Var(), other->StatusVar());
}
Constraint* __ne__(Constraint* other) {
return self->solver()->MakeNonEquality(self->Var(), other->StatusVar());
}
Constraint* __ge__(Constraint* other) {
return self->solver()->MakeGreaterOrEqual(self->Var(), other->StatusVar());
}
Constraint* __gt__(Constraint* other) {
return self->solver()->MakeGreater(self->Var(), other->StatusVar());
}
Constraint* __le__(Constraint* other) {
return self->solver()->MakeLessOrEqual(self->Var(), other->StatusVar());
}
Constraint* __lt__(Constraint* other) {
return self->solver()->MakeLess(self->Var(), other->StatusVar());
}
Constraint* MapTo(const std::vector<IntVar*>& vars) {
return self->solver()->MakeMapDomain(self->Var(), vars);
}
@@ -941,6 +1058,127 @@ static void SetPythonFlags(bool trace_propagation,
}
}
// Add arithmetic operators to integer expressions.
%extend Constraint {
IntExpr* __add__(IntExpr* other) {
return self->solver()->MakeSum(self->StatusVar(), other);
}
IntExpr* __add__(Constraint* other) {
return self->solver()->MakeSum(self->StatusVar(), other->StatusVar());
}
IntExpr* __add__(int64 v) {
return self->solver()->MakeSum(self->StatusVar(), v);
}
IntExpr* __radd__(int64 v) {
return self->solver()->MakeSum(self->StatusVar(), v);
}
IntExpr* __sub__(IntExpr* other) {
return self->solver()->MakeDifference(self->StatusVar(), other);
}
IntExpr* __sub__(Constraint* other) {
return self->solver()->MakeDifference(self->StatusVar(),
other->StatusVar());
}
IntExpr* __sub__(int64 v) {
return self->solver()->MakeSum(self->StatusVar(), -v);
}
IntExpr* __rsub__(int64 v) {
return self->solver()->MakeDifference(v, self->StatusVar());
}
IntExpr* __mul__(IntExpr* other) {
return self->solver()->MakeProd(self->StatusVar(), other);
}
IntExpr* __mul__(Constraint* other) {
return self->solver()->MakeProd(self->StatusVar(), other->StatusVar());
}
IntExpr* __mul__(int64 v) {
return self->solver()->MakeProd(self->StatusVar(), v);
}
IntExpr* __rmul__(int64 v) {
return self->solver()->MakeProd(self->StatusVar(), v);
}
IntExpr* __floordiv__(int64 v) {
return self->solver()->MakeDiv(self->StatusVar(), v);
}
IntExpr* __neg__() {
return self->solver()->MakeOpposite(self->StatusVar());
}
IntExpr* __abs__() {
return self->solver()->MakeAbs(self->StatusVar());
}
IntExpr* Square() {
return self->solver()->MakeSquare(self->StatusVar());
}
Constraint* __eq__(int64 v) {
return self->solver()->MakeEquality(self->StatusVar(), v);
}
Constraint* __ne__(int64 v) {
return self->solver()->MakeNonEquality(self->StatusVar(), v);
}
Constraint* __ge__(int64 v) {
return self->solver()->MakeGreaterOrEqual(self->StatusVar(), v);
}
Constraint* __gt__(int64 v) {
return self->solver()->MakeGreater(self->StatusVar(), v);
}
Constraint* __le__(int64 v) {
return self->solver()->MakeLessOrEqual(self->StatusVar(), v);
}
Constraint* __lt__(int64 v) {
return self->solver()->MakeLess(self->StatusVar(), v);
}
Constraint* __eq__(IntExpr* other) {
return self->solver()->MakeEquality(self->StatusVar(), other->Var());
}
Constraint* __ne__(IntExpr* other) {
return self->solver()->MakeNonEquality(self->StatusVar(), other->Var());
}
Constraint* __ge__(IntExpr* other) {
return self->solver()->MakeGreaterOrEqual(self->StatusVar(), other->Var());
}
Constraint* __gt__(IntExpr* other) {
return self->solver()->MakeGreater(self->StatusVar(), other->Var());
}
Constraint* __le__(IntExpr* other) {
return self->solver()->MakeLessOrEqual(self->StatusVar(), other->Var());
}
Constraint* __lt__(IntExpr* other) {
return self->solver()->MakeLess(self->StatusVar(), other->Var());
}
Constraint* __eq__(Constraint* other) {
return self->solver()->MakeEquality(self->StatusVar(), other->StatusVar());
}
Constraint* __ne__(Constraint* other) {
return self->solver()->MakeNonEquality(self->StatusVar(),
other->StatusVar());
}
Constraint* __ge__(Constraint* other) {
return self->solver()->MakeGreaterOrEqual(self->StatusVar(),
other->StatusVar());
}
Constraint* __gt__(Constraint* other) {
return self->solver()->MakeGreater(self->StatusVar(), other->StatusVar());
}
Constraint* __le__(Constraint* other) {
return self->solver()->MakeLessOrEqual(self->StatusVar(),
other->StatusVar());
}
Constraint* __lt__(Constraint* other) {
return self->solver()->MakeLess(self->StatusVar(), other->StatusVar());
}
Constraint* MapTo(const std::vector<IntVar*>& vars) {
return self->solver()->MakeMapDomain(self->StatusVar(), vars);
}
IntExpr* IndexOf(const std::vector<int64>& vars) {
return self->solver()->MakeElement(vars, self->StatusVar());
}
IntExpr* IndexOf(const std::vector<IntVar*>& vars) {
return self->solver()->MakeElement(vars, self->StatusVar());
}
}
%extend BaseLNS {
int64 __getitem__(int index) {
return self->Value(index);

View File

@@ -1413,6 +1413,10 @@ class ModelCache {
VAR_VAR_MAX,
VAR_VAR_MIN,
VAR_VAR_SUM,
VAR_VAR_IS_EQUAL,
VAR_VAR_IS_NOT_EQUAL,
VAR_VAR_IS_LESS,
VAR_VAR_IS_LESS_OR_EQUAL,
VAR_VAR_EXPRESSION_MAX,
};

View File

@@ -41,6 +41,9 @@ class EqualityExprCst : public Constraint {
virtual ~EqualityExprCst() {}
virtual void Post();
virtual void InitialPropagate();
virtual IntVar* StatusVar() {
return solver()->MakeIsEqualCstVar(expr_->Var(), value_);
}
virtual string DebugString() const;
virtual void Accept(ModelVisitor* const visitor) const {
@@ -97,6 +100,9 @@ class GreaterEqExprCst : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsGreaterOrEqualCstVar(expr_->Var(), value_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kGreaterOrEqual, this);
@@ -162,6 +168,9 @@ class LessEqExprCst : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsLessOrEqualCstVar(expr_->Var(), value_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kLessOrEqual, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
@@ -226,6 +235,9 @@ class DiffCst : public Constraint {
virtual void InitialPropagate();
void BoundPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsDifferentCstVar(var_, value_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kNonEqual, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,

View File

@@ -4551,7 +4551,31 @@ IntVar* Solver::MakeIsEqualVar(IntExpr* const v1, IntExpr* const v2) {
} else if (v2->Bound()) {
return MakeIsEqualCstVar(v1->Var(), v2->Min());
}
return MakeIsEqualCstVar(MakeDifference(v1, v2)->Var(), 0);
IntVar* const var1 = v1->Var();
IntVar* const var2 = v2->Var();
IntExpr* const cache = model_cache_->FindVarVarExpression(
var1,
var2,
ModelCache::VAR_VAR_IS_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
string name1 = var1->name();
if (name1.empty()) {
name1 = var1->DebugString();
}
string name2 = var2->name();
if (name2.empty()) {
name2 = var2->DebugString();
}
IntVar* const boolvar = MakeIsEqualCstVar(MakeDifference(v1, v2)->Var(), 0);
model_cache_->InsertVarVarExpression(
boolvar,
var1,
var2,
ModelCache::VAR_VAR_IS_EQUAL);
return boolvar;
}
}
Constraint* Solver::MakeIsEqualCt(IntExpr* const v1,
@@ -4575,7 +4599,32 @@ IntVar* Solver::MakeIsDifferentVar(IntExpr* const v1, IntExpr* const v2) {
} else if (v2->Bound()) {
return MakeIsDifferentCstVar(v1->Var(), v2->Min());
}
return MakeIsDifferentCstVar(MakeDifference(v1, v2)->Var(), 0);
IntVar* const var1 = v1->Var();
IntVar* const var2 = v2->Var();
IntExpr* const cache = model_cache_->FindVarVarExpression(
var1,
var2,
ModelCache::VAR_VAR_IS_NOT_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
string name1 = var1->name();
if (name1.empty()) {
name1 = var1->DebugString();
}
string name2 = var2->name();
if (name2.empty()) {
name2 = var2->DebugString();
}
IntVar* const boolvar =
MakeIsDifferentCstVar(MakeDifference(v1, v2)->Var(), 0);
model_cache_->InsertVarVarExpression(
boolvar,
var1,
var2,
ModelCache::VAR_VAR_IS_NOT_EQUAL);
return boolvar;
}
}
Constraint* Solver::MakeIsDifferentCt(IntExpr* const v1,
@@ -4600,7 +4649,32 @@ IntVar* Solver::MakeIsLessOrEqualVar(
} else if (right->Bound()) {
return MakeIsLessOrEqualCstVar(left->Var(), right->Min());
}
return MakeIsLessOrEqualCstVar(MakeDifference(left, right)->Var(), 0);
IntVar* const var1 = left->Var();
IntVar* const var2 = right->Var();
IntExpr* const cache = model_cache_->FindVarVarExpression(
var1,
var2,
ModelCache::VAR_VAR_IS_LESS_OR_EQUAL);
if (cache != NULL) {
return cache->Var();
} else {
string name1 = var1->name();
if (name1.empty()) {
name1 = var1->DebugString();
}
string name2 = var2->name();
if (name2.empty()) {
name2 = var2->DebugString();
}
IntVar* const boolvar =
MakeIsLessOrEqualCstVar(MakeDifference(left, right)->Var(), 0);
model_cache_->InsertVarVarExpression(
boolvar,
var1,
var2,
ModelCache::VAR_VAR_IS_LESS_OR_EQUAL);
return boolvar;
}
}
Constraint* Solver::MakeIsLessOrEqualCt(
@@ -4624,7 +4698,32 @@ IntVar* Solver::MakeIsLessVar(
} else if (right->Bound()) {
return MakeIsLessCstVar(left->Var(), right->Min());
}
return MakeIsLessCstVar(MakeDifference(left, right)->Var(), 0);
IntVar* const var1 = left->Var();
IntVar* const var2 = right->Var();
IntExpr* const cache = model_cache_->FindVarVarExpression(
var1,
var2,
ModelCache::VAR_VAR_IS_LESS);
if (cache != NULL) {
return cache->Var();
} else {
string name1 = var1->name();
if (name1.empty()) {
name1 = var1->DebugString();
}
string name2 = var2->name();
if (name2.empty()) {
name2 = var2->DebugString();
}
IntVar* const boolvar =
MakeIsLessCstVar(MakeDifference(left, right)->Var(), 0);
model_cache_->InsertVarVarExpression(
boolvar,
var1,
var2,
ModelCache::VAR_VAR_IS_LESS);
return boolvar;
}
}
Constraint* Solver::MakeIsLessCt(

View File

@@ -32,6 +32,9 @@ class RangeEquality : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsEqualVar(left_, right_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kEquality, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
@@ -83,6 +86,9 @@ class RangeLessOrEqual : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsLessOrEqualVar(left_, right_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kLessOrEqual, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
@@ -135,6 +141,9 @@ class RangeGreaterOrEqual : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsGreaterOrEqualVar(left_, right_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kGreaterOrEqual, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
@@ -187,6 +196,9 @@ class RangeLess : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsLessVar(left_, right_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kLess, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
@@ -238,6 +250,9 @@ class RangeGreater : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsGreaterVar(left_, right_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kGreater, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);
@@ -289,6 +304,10 @@ class DiffVar : public Constraint {
virtual void Post();
virtual void InitialPropagate();
virtual string DebugString() const;
virtual IntVar* StatusVar() {
return solver()->MakeIsDifferentVar(left_, right_);
}
virtual void Accept(ModelVisitor* const visitor) const {
visitor->BeginVisitConstraint(ModelVisitor::kNonEqual, this);
visitor->VisitIntegerExpressionArgument(ModelVisitor::kLeftArgument, left_);

View File

@@ -62,17 +62,12 @@ def alldifferent_except_0(solver, a):
n = len(a)
for i in range(n):
for j in range(i):
bi = solver.IsDifferentCstVar(a[i],0)
bj = solver.IsDifferentCstVar(a[j],0)
bij = solver.IsDifferentVar(a[i],a[j])
solver.Add(bi*bj <= bij)
solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j]))
# more compact version:
def alldifferent_except_0_b(solver, a):
n = len(a)
[solver.Add(solver.IsDifferentCstVar(a[i],0)*
solver.IsDifferentCstVar(a[j],0) <=
solver.IsDifferentVar(a[i],a[j]))
[solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j]))
for i in range(n) for j in range(i)]
@@ -87,7 +82,8 @@ def main(unused_argv):
# declare variables
x = [solver.IntVar(0,n-1, 'x%i' % i) for i in range(n)]
z = solver.IntVar(0,n-1, 'z') # number of zeros
# Number of zeros.
z = solver.Sum([x[i] == 0 for i in range(n)]).VarWithName('z')
#
# constraints
@@ -95,13 +91,8 @@ def main(unused_argv):
alldifferent_except_0(solver, x)
# we require 2 0's
z_tmp = [solver.BoolVar('z_tmp % i' % i) for i in range(n)]
for i in range(n):
solver.Add(solver.IsEqualCstCt(x[i], 0, z_tmp[i]))
solver.Add(solver.Sum(z_tmp) == z)
solver.Add(z == 2)
#
# solution and search
#

View File

@@ -41,7 +41,7 @@ def BuildPairs(rows, cols):
rows: the number of rows in the grid
cols: the number of columns in the grid
"""
results = pywrapcp.IntTupleSet(2)
results = []
for x in range(rows):
for y in range(cols):
for dx in (-1, 0, 1):
@@ -51,7 +51,7 @@ def BuildPairs(rows, cols):
y + dy >= 0 and
y + dy < cols and
(dx != 0 or dy != 0)):
results.Insert2(x * cols + y, (x + dx) * cols + (y + dy))
results.append((x * cols + y, (x + dx) * cols + (y + dy)))
return results