Support for Constraint::StatusVar() in C++, automatic conversion in Python
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -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
|
||||
#
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user