24#include "absl/strings/str_cat.h"
25#include "absl/strings/str_format.h"
47class ActionDemon :
public Demon {
49 explicit ActionDemon(
const Solver::Action& action) : action_(action) {
50 CHECK(action !=
nullptr);
53 ~ActionDemon()
override {}
55 void Run(Solver*
const solver)
override { action_(solver); }
61class ClosureDemon :
public Demon {
63 explicit ClosureDemon(
const Solver::Closure& closure) : closure_(closure) {
64 CHECK(closure !=
nullptr);
67 ~ClosureDemon()
override {}
69 void Run(Solver*
const solver)
override { closure_(); }
77class TrueConstraint :
public Constraint {
79 explicit TrueConstraint(Solver*
const s) : Constraint(s) {}
80 ~TrueConstraint()
override {}
82 void Post()
override {}
83 void InitialPropagate()
override {}
84 std::string DebugString()
const override {
return "TrueConstraint()"; }
86 void Accept(ModelVisitor*
const visitor)
const override {
90 IntVar* Var()
override {
return solver()->MakeIntConst(1); }
93class FalseConstraint :
public Constraint {
95 explicit FalseConstraint(Solver*
const s) : Constraint(s) {}
96 FalseConstraint(Solver*
const s,
const std::string& explanation)
97 : Constraint(s), explanation_(explanation) {}
98 ~FalseConstraint()
override {}
100 void Post()
override {}
101 void InitialPropagate()
override { solver()->Fail(); }
102 std::string DebugString()
const override {
103 return absl::StrCat(
"FalseConstraint(", explanation_,
")");
106 void Accept(ModelVisitor*
const visitor)
const override {
110 IntVar* Var()
override {
return solver()->MakeIntConst(0); }
113 const std::string explanation_;
122class MapDomain :
public Constraint {
124 MapDomain(Solver*
const s, IntVar*
const var,
125 const std::vector<IntVar*>& actives)
126 : Constraint(s), var_(
var), actives_(actives) {
130 ~MapDomain()
override {}
132 void Post()
override {
135 var_->WhenDomain(vd);
139 std::unique_ptr<IntVarIterator> domain_it(
140 var_->MakeDomainIterator(
false));
141 for (
const int64_t
index : InitAndGetValues(domain_it.get())) {
142 if (
index >= 0 &&
index < actives_.size() && !actives_[
index]->Bound()) {
144 solver(),
this, &MapDomain::UpdateActive,
"UpdateActive",
index);
145 actives_[
index]->WhenDomain(d);
150 void InitialPropagate()
override {
151 for (
int i = 0; i < actives_.size(); ++i) {
152 actives_[i]->SetRange(int64_t{0}, int64_t{1});
153 if (!var_->Contains(i)) {
154 actives_[i]->SetValue(0);
155 }
else if (actives_[i]->Max() == 0LL) {
156 var_->RemoveValue(i);
158 if (actives_[i]->Min() == 1LL) {
167 void UpdateActive(int64_t
index) {
168 IntVar*
const act = actives_[
index];
169 if (act->Max() == 0) {
170 var_->RemoveValue(
index);
171 }
else if (act->Min() == 1) {
172 var_->SetValue(
index);
177 const int64_t oldmin = var_->OldMin();
178 const int64_t oldmax = var_->OldMax();
179 const int64_t vmin = var_->Min();
180 const int64_t vmax = var_->Max();
181 const int64_t size = actives_.size();
184 actives_[j]->SetValue(0);
186 for (
const int64_t j : InitAndGetValues(
holes_)) {
187 if (j >= 0 && j < size) {
188 actives_[j]->SetValue(0);
191 for (int64_t j =
std::max(vmax + int64_t{1}, int64_t{0});
192 j <=
std::min(oldmax, size - int64_t{1}); ++j) {
193 actives_[j]->SetValue(int64_t{0});
198 const int64_t val = var_->Min();
199 if (val >= 0 && val < actives_.size()) {
200 actives_[val]->SetValue(1);
203 std::string DebugString()
const override {
204 return absl::StrFormat(
"MapDomain(%s, [%s])", var_->DebugString(),
208 void Accept(ModelVisitor*
const visitor)
const override {
219 std::vector<IntVar*> actives_;
225class LexicalLess :
public Constraint {
227 LexicalLess(Solver*
const s,
const std::vector<IntVar*>& left,
228 const std::vector<IntVar*>& right,
bool strict)
235 CHECK_EQ(left.size(), right.size());
238 ~LexicalLess()
override {}
240 void Post()
override {
241 const int position = JumpEqualVariables(0);
242 active_var_.
SetValue(solver(), position);
243 if (position < left_.size()) {
244 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
245 left_[position]->WhenRange(demon_);
246 right_[position]->WhenRange(demon_);
250 void InitialPropagate()
override {
251 const int position = JumpEqualVariables(active_var_.
Value());
252 if (position >= left_.size()) {
258 if (position != active_var_.
Value()) {
259 left_[position]->WhenRange(demon_);
260 right_[position]->WhenRange(demon_);
261 active_var_.
SetValue(solver(), position);
263 const int next_non_equal = JumpEqualVariables(position + 1);
264 if ((strict_ && next_non_equal == left_.size()) ||
265 (next_non_equal < left_.size() &&
266 left_[next_non_equal]->Min() > right_[next_non_equal]->Max())) {
269 left_[position]->SetMax(right_[position]->Max() - 1);
270 right_[position]->SetMin(left_[position]->Min() + 1);
272 left_[position]->SetMax(right_[position]->Max());
273 right_[position]->SetMin(left_[position]->Min());
277 std::string DebugString()
const override {
278 return absl::StrFormat(
279 "%s([%s], [%s])", strict_ ?
"LexicalLess" :
"LexicalLessOrEqual",
283 void Accept(ModelVisitor*
const visitor)
const override {
294 int JumpEqualVariables(
int start_position)
const {
295 int position = start_position;
296 while (position < left_.size() && left_[position]->Bound() &&
297 right_[position]->Bound() &&
298 left_[position]->Min() == right_[position]->Min()) {
304 std::vector<IntVar*> left_;
305 std::vector<IntVar*> right_;
306 NumericalRev<int> active_var_;
313class InversePermutationConstraint :
public Constraint {
315 InversePermutationConstraint(Solver*
const s,
316 const std::vector<IntVar*>& left,
317 const std::vector<IntVar*>& right)
321 left_hole_iterators_(left.size()),
322 left_domain_iterators_(left_.size()),
323 right_hole_iterators_(right_.size()),
324 right_domain_iterators_(right_.size()) {
325 CHECK_EQ(left_.size(), right_.size());
326 for (
int i = 0; i < left_.size(); ++i) {
327 left_hole_iterators_[i] = left_[i]->MakeHoleIterator(
true);
328 left_domain_iterators_[i] = left_[i]->MakeDomainIterator(
true);
329 right_hole_iterators_[i] = right_[i]->MakeHoleIterator(
true);
330 right_domain_iterators_[i] = right_[i]->MakeDomainIterator(
true);
334 ~InversePermutationConstraint()
override {}
336 void Post()
override {
337 for (
int i = 0; i < left_.size(); ++i) {
340 &InversePermutationConstraint::PropagateHolesOfLeftVarToRight,
341 "PropagateHolesOfLeftVarToRight", i);
342 left_[i]->WhenDomain(left_demon);
345 &InversePermutationConstraint::PropagateHolesOfRightVarToLeft,
346 "PropagateHolesOfRightVarToLeft", i);
347 right_[i]->WhenDomain(right_demon);
349 solver()->AddConstraint(
350 solver()->MakeAllDifferent(left_,
false));
351 solver()->AddConstraint(
352 solver()->MakeAllDifferent(right_,
false));
355 void InitialPropagate()
override {
356 const int size = left_.size();
357 for (
int i = 0; i < size; ++i) {
358 left_[i]->SetRange(0, size - 1);
359 right_[i]->SetRange(0, size - 1);
361 for (
int i = 0; i < size; ++i) {
362 PropagateDomain(i, left_[i], left_domain_iterators_[i], right_);
363 PropagateDomain(i, right_[i], right_domain_iterators_[i], left_);
367 void PropagateHolesOfLeftVarToRight(
int index) {
368 PropagateHoles(
index, left_[
index], left_hole_iterators_[
index], right_);
371 void PropagateHolesOfRightVarToLeft(
int index) {
372 PropagateHoles(
index, right_[
index], right_hole_iterators_[
index], left_);
375 std::string DebugString()
const override {
376 return absl::StrFormat(
"InversePermutationConstraint([%s], [%s])",
381 void Accept(ModelVisitor*
const visitor)
const override {
392 void PropagateHoles(
int index, IntVar*
const var, IntVarIterator*
const holes,
393 const std::vector<IntVar*>& inverse) {
394 const int64_t oldmin =
std::max(
var->OldMin(), int64_t{0});
395 const int64_t oldmax =
396 std::min(
var->OldMax(),
static_cast<int64_t
>(left_.size() - 1));
397 const int64_t vmin =
var->Min();
398 const int64_t vmax =
var->Max();
402 for (
const int64_t hole : InitAndGetValues(holes)) {
403 if (hole >= 0 && hole < left_.size()) {
404 inverse[hole]->RemoveValue(
index);
412 void PropagateDomain(
int index, IntVar*
const var,
413 IntVarIterator*
const domain,
414 const std::vector<IntVar*>& inverse) {
416 tmp_removed_values_.clear();
417 for (
const int64_t
value : InitAndGetValues(domain)) {
419 tmp_removed_values_.push_back(
value);
424 if (!tmp_removed_values_.empty()) {
425 var->RemoveValues(tmp_removed_values_);
429 std::vector<IntVar*> left_;
430 std::vector<IntVar*> right_;
431 std::vector<IntVarIterator*> left_hole_iterators_;
432 std::vector<IntVarIterator*> left_domain_iterators_;
433 std::vector<IntVarIterator*> right_hole_iterators_;
434 std::vector<IntVarIterator*> right_domain_iterators_;
437 std::vector<int64_t> tmp_removed_values_;
442class IndexOfFirstMaxValue :
public Constraint {
444 IndexOfFirstMaxValue(Solver* solver, IntVar*
index,
445 const std::vector<IntVar*>& vars)
446 : Constraint(solver), index_(
index),
vars_(vars) {}
448 ~IndexOfFirstMaxValue()
override {}
450 void Post()
override {
452 solver()->MakeDelayedConstraintInitialPropagateCallback(
this);
453 index_->WhenRange(demon);
454 for (IntVar*
const var : vars_) {
455 var->WhenRange(demon);
459 void InitialPropagate()
override {
460 const int64_t vsize =
vars_.size();
461 const int64_t imin =
std::max(int64_t{0}, index_->Min());
462 const int64_t imax =
std::min(vsize - 1, index_->Max());
467 for (
int i = imin; i <= imax; ++i) {
468 max_max =
std::max(max_max, vars_[i]->Max());
469 max_min =
std::max(max_min, vars_[i]->Min());
474 for (
int i = 0; i < imin; ++i) {
475 vars_[i]->SetMax(max_max - 1);
477 for (
int i = imax + 1; i < vsize; ++i) {
478 vars_[i]->SetMax(max_max);
482 int64_t min_index = imin;
483 while (vars_[min_index]->Max() < max_min) {
486 int64_t max_index = imax;
487 while (vars_[max_index]->Max() < max_min) {
490 index_->SetRange(min_index, max_index);
493 std::string DebugString()
const override {
494 return absl::StrFormat(
"IndexMax(%s, [%s])", index_->DebugString(),
498 void Accept(ModelVisitor*
const visitor)
const override {
503 IntVar*
const index_;
504 const std::vector<IntVar*>
vars_;
511 return RevAlloc(
new ActionDemon(action));
515 return RevAlloc(
new ClosureDemon(closure));
519 DCHECK(true_constraint_ !=
nullptr);
520 return true_constraint_;
524 DCHECK(false_constraint_ !=
nullptr);
525 return false_constraint_;
528 return RevAlloc(
new FalseConstraint(
this, explanation));
531void Solver::InitCachedConstraint() {
532 DCHECK(true_constraint_ ==
nullptr);
533 true_constraint_ =
RevAlloc(
new TrueConstraint(
this));
534 DCHECK(false_constraint_ ==
nullptr);
535 false_constraint_ =
RevAlloc(
new FalseConstraint(
this));
539 const std::vector<IntVar*>& actives) {
540 return RevAlloc(
new MapDomain(
this,
var, actives));
544 const std::vector<IntVar*>& right) {
545 return RevAlloc(
new LexicalLess(
this, left, right,
true));
549 const std::vector<IntVar*>& right) {
550 return RevAlloc(
new LexicalLess(
this, left, right,
false));
554 const std::vector<IntVar*>& left,
const std::vector<IntVar*>& right) {
555 return RevAlloc(
new InversePermutationConstraint(
this, left, right));
560 return RevAlloc(
new IndexOfFirstMaxValue(
this,
index, vars));
565 std::vector<IntVar*> opp_vars(vars.size());
566 for (
int i = 0; i < vars.size(); ++i) {
569 return RevAlloc(
new IndexOfFirstMaxValue(
this,
index, opp_vars));
const std::vector< IntVar * > vars_
#define CHECK_EQ(val1, val2)
#define DCHECK(condition)
A constraint is the main modeling object.
virtual void InitialPropagate()=0
This method performs the initial propagation of the constraint.
A Demon is the base element of a propagation queue.
virtual IntVar * Var()=0
Creates a variable from the expression.
The class IntVar is a subset of IntExpr.
static const char kTargetArgument[]
static const char kTrueConstraint[]
static const char kMapDomain[]
static const char kValueArgument[]
static const char kLeftArgument[]
static const char kLexLess[]
static const char kVarsArgument[]
static const char kRightArgument[]
static const char kFalseConstraint[]
static const char kInversePermutation[]
void SetValue(Solver *const s, const T &val)
Constraint * MakeMapDomain(IntVar *const var, const std::vector< IntVar * > &actives)
This constraint maps the domain of 'var' onto the array of variables 'actives'.
Constraint * MakeFalseConstraint()
This constraint always fails.
Constraint * MakeIndexOfFirstMinValueConstraint(IntVar *index, const std::vector< IntVar * > &vars)
Creates a constraint that binds the index variable to the index of the first variable with the minimu...
Demon * MakeActionDemon(Action action)
Creates a demon from a callback.
Constraint * MakeLexicalLess(const std::vector< IntVar * > &left, const std::vector< IntVar * > &right)
Creates a constraint that enforces that left is lexicographically less than right.
Demon * MakeClosureDemon(Closure closure)
!defined(SWIG)
IntExpr * MakeOpposite(IntExpr *const expr)
-expr
Demon * MakeConstraintInitialPropagateCallback(Constraint *const ct)
This method is a specialized case of the MakeConstraintDemon method to call the InitiatePropagate of ...
Constraint * MakeTrueConstraint()
This constraint always succeeds.
Constraint * MakeLexicalLessOrEqual(const std::vector< IntVar * > &left, const std::vector< IntVar * > &right)
Creates a constraint that enforces that left is lexicographically less than or equal to right.
Constraint * MakeInversePermutationConstraint(const std::vector< IntVar * > &left, const std::vector< IntVar * > &right)
Creates a constraint that enforces that 'left' and 'right' both represent permutations of [0....
Demon * MakeDelayedConstraintInitialPropagateCallback(Constraint *const ct)
This method is a specialized case of the MakeConstraintDemon method to call the InitiatePropagate of ...
std::function< void()> Closure
std::function< void(Solver *)> Action
Constraint * MakeIndexOfFirstMaxValueConstraint(IntVar *index, const std::vector< IntVar * > &vars)
Creates a constraint that binds the index variable to the index of the first variable with the maximu...
T * RevAlloc(T *object)
Registers the given object as being reversible.
std::vector< IntVarIterator * > holes_
Collection of objects used to extend the Constraint Solver library.
Demon * MakeDelayedConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
std::string JoinDebugStringPtr(const std::vector< T > &v, const std::string &separator)
Demon * MakeConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)