24#include "absl/log/check.h"
25#include "absl/strings/str_cat.h"
26#include "absl/strings/str_format.h"
27#include "absl/strings/str_join.h"
49class ActionDemon :
public Demon {
51 explicit ActionDemon(
const Solver::Action& action) : action_(action) {
52 CHECK(action !=
nullptr);
55 ~ActionDemon()
override {}
57 void Run(Solver*
const solver)
override { action_(solver); }
63class ClosureDemon :
public Demon {
65 explicit ClosureDemon(
const Solver::Closure& closure) : closure_(closure) {
66 CHECK(closure !=
nullptr);
69 ~ClosureDemon()
override {}
71 void Run(Solver*
const solver)
override { closure_(); }
79class TrueConstraint :
public Constraint {
81 explicit TrueConstraint(Solver*
const s) : Constraint(s) {}
82 ~TrueConstraint()
override {}
84 void Post()
override {}
85 void InitialPropagate()
override {}
86 std::string DebugString()
const override {
return "TrueConstraint()"; }
88 void Accept(ModelVisitor*
const visitor)
const override {
92 IntVar* Var()
override {
return solver()->MakeIntConst(1); }
95class FalseConstraint :
public Constraint {
97 explicit FalseConstraint(Solver*
const s) : Constraint(s) {}
98 FalseConstraint(Solver*
const s,
const std::string& explanation)
99 : Constraint(s), explanation_(explanation) {}
100 ~FalseConstraint()
override {}
102 void Post()
override {}
103 void InitialPropagate()
override { solver()->Fail(); }
104 std::string DebugString()
const override {
105 return absl::StrCat(
"FalseConstraint(", explanation_,
")");
108 void Accept(ModelVisitor*
const visitor)
const override {
112 IntVar* Var()
override {
return solver()->MakeIntConst(0); }
115 const std::string explanation_;
124class MapDomain :
public Constraint {
126 MapDomain(Solver*
const s, IntVar*
const var,
127 const std::vector<IntVar*>& actives)
128 : Constraint(s), var_(
var), actives_(actives) {
129 holes_ =
var->MakeHoleIterator(
true);
132 ~MapDomain()
override {}
134 void Post()
override {
137 var_->WhenDomain(vd);
141 std::unique_ptr<IntVarIterator> domain_it(
142 var_->MakeDomainIterator(
false));
143 for (
const int64_t
index : InitAndGetValues(domain_it.get())) {
144 if (
index >= 0 &&
index < actives_.size() && !actives_[
index]->Bound()) {
146 solver(),
this, &MapDomain::UpdateActive,
"UpdateActive",
index);
147 actives_[
index]->WhenDomain(d);
152 void InitialPropagate()
override {
153 for (
int i = 0;
i < actives_.size(); ++
i) {
154 actives_[
i]->SetRange(int64_t{0}, int64_t{1});
155 if (!var_->Contains(i)) {
156 actives_[
i]->SetValue(0);
157 }
else if (actives_[i]->Max() == 0LL) {
158 var_->RemoveValue(i);
160 if (actives_[i]->Min() == 1LL) {
169 void UpdateActive(int64_t
index) {
170 IntVar*
const act = actives_[
index];
171 if (act->Max() == 0) {
172 var_->RemoveValue(
index);
173 }
else if (act->Min() == 1) {
174 var_->SetValue(
index);
179 const int64_t oldmin = var_->OldMin();
180 const int64_t oldmax = var_->OldMax();
181 const int64_t vmin = var_->Min();
182 const int64_t vmax = var_->Max();
183 const int64_t
size = actives_.size();
184 for (int64_t j = std::max(oldmin, int64_t{0}); j < std::min(vmin,
size);
186 actives_[j]->SetValue(0);
188 for (
const int64_t j : InitAndGetValues(holes_)) {
189 if (j >= 0 && j <
size) {
190 actives_[j]->SetValue(0);
193 for (int64_t j = std::max(vmax + int64_t{1}, int64_t{0});
194 j <= std::min(oldmax,
size - int64_t{1}); ++j) {
195 actives_[j]->SetValue(int64_t{0});
200 const int64_t val = var_->Min();
201 if (val >= 0 && val < actives_.size()) {
202 actives_[val]->SetValue(1);
205 std::string DebugString()
const override {
206 return absl::StrFormat(
"MapDomain(%s, [%s])", var_->DebugString(),
210 void Accept(ModelVisitor*
const visitor)
const override {
221 std::vector<IntVar*> actives_;
222 IntVarIterator* holes_;
227class LexicalLessOrEqual :
public Constraint {
229 LexicalLessOrEqual(Solver*
const s, std::vector<IntVar*> left,
230 std::vector<IntVar*> right, std::vector<int64_t> offsets)
232 left_(
std::move(left)),
233 right_(
std::move(right)),
235 offsets_(
std::move(offsets)),
238 CHECK_EQ(left_.size(), right_.size());
239 CHECK_EQ(offsets_.size(), right_.size());
240 CHECK(std::all_of(offsets_.begin(), offsets_.end(),
241 [](
int step) { return step > 0; }));
244 ~LexicalLessOrEqual()
override {}
246 void Post()
override {
247 const int position = JumpEqualVariables(0);
248 active_var_.SetValue(solver(), position);
249 if (position < left_.size()) {
250 demon_ = solver()->MakeConstraintInitialPropagateCallback(
this);
255 void InitialPropagate()
override {
256 const int position = JumpEqualVariables(active_var_.Value());
257 if (position >= left_.size())
return;
258 if (position != active_var_.Value()) {
260 active_var_.SetValue(solver(), position);
262 const int next_non_equal = JumpEqualVariables(position + 1);
263 if (next_non_equal < left_.size() &&
264 left_[next_non_equal]->Min() > right_[next_non_equal]->Max()) {
266 left_[position]->SetMax(
267 CapSub(right_[position]->Max(), offsets_[position]));
268 right_[position]->SetMin(
269 CapAdd(left_[position]->Min(), offsets_[position]));
271 left_[position]->SetMax(right_[position]->Max());
272 right_[position]->SetMin(left_[position]->Min());
276 if (next_non_equal < left_.size()) {
277 AddDemon(next_non_equal);
281 std::string DebugString()
const override {
282 return absl::StrFormat(
287 void Accept(ModelVisitor*
const visitor)
const override {
298 int JumpEqualVariables(
int start_position)
const {
299 int position = start_position;
300 while (position < left_.size() &&
301 left_[position]->Max() <= right_[position]->Min() &&
302 CapSub(right_[position]->Max(),
CapSub(offsets_[position], 1)) <=
303 left_[position]->Min()) {
308 void AddDemon(
int position) {
309 if (demon_added_.Value(position))
return;
310 left_[position]->WhenRange(demon_);
311 right_[position]->WhenRange(demon_);
312 demon_added_.SetValue(solver(), position,
true);
315 std::vector<IntVar*> left_;
316 std::vector<IntVar*> right_;
317 NumericalRev<int> active_var_;
318 std::vector<int64_t> offsets_;
319 RevArray<bool> demon_added_;
325class InversePermutationConstraint :
public Constraint {
327 InversePermutationConstraint(Solver*
const s,
328 const std::vector<IntVar*>& left,
329 const std::vector<IntVar*>& right)
333 left_hole_iterators_(left.
size()),
334 left_domain_iterators_(left_.
size()),
335 right_hole_iterators_(right_.
size()),
336 right_domain_iterators_(right_.
size()) {
337 CHECK_EQ(left_.size(), right_.size());
338 for (
int i = 0;
i < left_.size(); ++
i) {
339 left_hole_iterators_[
i] = left_[
i]->MakeHoleIterator(
true);
340 left_domain_iterators_[
i] = left_[
i]->MakeDomainIterator(
true);
341 right_hole_iterators_[
i] = right_[
i]->MakeHoleIterator(
true);
342 right_domain_iterators_[
i] = right_[
i]->MakeDomainIterator(
true);
346 ~InversePermutationConstraint()
override {}
348 void Post()
override {
349 for (
int i = 0;
i < left_.size(); ++
i) {
352 &InversePermutationConstraint::PropagateHolesOfLeftVarToRight,
353 "PropagateHolesOfLeftVarToRight", i);
354 left_[
i]->WhenDomain(left_demon);
357 &InversePermutationConstraint::PropagateHolesOfRightVarToLeft,
358 "PropagateHolesOfRightVarToLeft", i);
359 right_[
i]->WhenDomain(right_demon);
361 solver()->AddConstraint(
362 solver()->MakeAllDifferent(left_,
false));
363 solver()->AddConstraint(
364 solver()->MakeAllDifferent(right_,
false));
367 void InitialPropagate()
override {
368 const int size = left_.size();
369 for (
int i = 0;
i <
size; ++
i) {
370 left_[
i]->SetRange(0,
size - 1);
371 right_[
i]->SetRange(0,
size - 1);
373 for (
int i = 0;
i <
size; ++
i) {
374 PropagateDomain(i, left_[i], left_domain_iterators_[i], right_);
375 PropagateDomain(i, right_[i], right_domain_iterators_[i], left_);
379 void PropagateHolesOfLeftVarToRight(
int index) {
380 PropagateHoles(
index, left_[
index], left_hole_iterators_[
index], right_);
383 void PropagateHolesOfRightVarToLeft(
int index) {
384 PropagateHoles(
index, right_[
index], right_hole_iterators_[
index], left_);
387 std::string DebugString()
const override {
388 return absl::StrFormat(
"InversePermutationConstraint([%s], [%s])",
393 void Accept(ModelVisitor*
const visitor)
const override {
404 void PropagateHoles(
int index, IntVar*
const var, IntVarIterator*
const holes,
405 const std::vector<IntVar*>& inverse) {
406 const int64_t oldmin = std::max(
var->OldMin(), int64_t{0});
407 const int64_t oldmax =
408 std::min(
var->OldMax(),
static_cast<int64_t
>(left_.size() - 1));
409 const int64_t vmin =
var->Min();
410 const int64_t vmax =
var->Max();
414 for (
const int64_t hole : InitAndGetValues(holes)) {
415 if (hole >= 0 && hole < left_.size()) {
416 inverse[hole]->RemoveValue(
index);
424 void PropagateDomain(
int index, IntVar*
const var,
425 IntVarIterator*
const domain,
426 const std::vector<IntVar*>& inverse) {
428 tmp_removed_values_.clear();
429 for (
const int64_t
value : InitAndGetValues(domain)) {
431 tmp_removed_values_.push_back(
value);
436 if (!tmp_removed_values_.empty()) {
437 var->RemoveValues(tmp_removed_values_);
441 std::vector<IntVar*> left_;
442 std::vector<IntVar*> right_;
443 std::vector<IntVarIterator*> left_hole_iterators_;
444 std::vector<IntVarIterator*> left_domain_iterators_;
445 std::vector<IntVarIterator*> right_hole_iterators_;
446 std::vector<IntVarIterator*> right_domain_iterators_;
449 std::vector<int64_t> tmp_removed_values_;
454class IndexOfFirstMaxValue :
public Constraint {
456 IndexOfFirstMaxValue(Solver* solver, IntVar*
index,
457 const std::vector<IntVar*>& vars)
458 : Constraint(solver), index_(
index),
vars_(vars) {}
460 ~IndexOfFirstMaxValue()
override {}
462 void Post()
override {
464 solver()->MakeDelayedConstraintInitialPropagateCallback(
this);
465 index_->WhenRange(demon);
466 for (IntVar*
const var : vars_) {
467 var->WhenRange(demon);
471 void InitialPropagate()
override {
472 const int64_t vsize =
vars_.size();
473 const int64_t imin = std::max(int64_t{0}, index_->Min());
474 const int64_t imax = std::min(vsize - 1, index_->Max());
475 int64_t max_max = std::numeric_limits<int64_t>::min();
476 int64_t max_min = std::numeric_limits<int64_t>::min();
479 for (
int i = imin;
i <= imax; ++
i) {
480 max_max = std::max(max_max, vars_[i]->Max());
481 max_min = std::max(max_min, vars_[i]->Min());
486 for (
int i = 0;
i < imin; ++
i) {
487 vars_[
i]->SetMax(max_max - 1);
489 for (
int i = imax + 1;
i < vsize; ++
i) {
490 vars_[
i]->SetMax(max_max);
494 int64_t min_index = imin;
495 while (vars_[min_index]->Max() < max_min) {
498 int64_t max_index = imax;
499 while (vars_[max_index]->Max() < max_min) {
502 index_->SetRange(min_index, max_index);
505 std::string DebugString()
const override {
506 return absl::StrFormat(
"IndexMax(%s, [%s])", index_->DebugString(),
510 void Accept(ModelVisitor*
const visitor)
const override {
515 IntVar*
const index_;
516 const std::vector<IntVar*>
vars_;
523 return RevAlloc(
new ActionDemon(action));
527 return RevAlloc(
new ClosureDemon(closure));
531 DCHECK(true_constraint_ !=
nullptr);
532 return true_constraint_;
536 DCHECK(false_constraint_ !=
nullptr);
537 return false_constraint_;
540 return RevAlloc(
new FalseConstraint(
this, explanation));
543void Solver::InitCachedConstraint() {
544 DCHECK(true_constraint_ ==
nullptr);
545 true_constraint_ =
RevAlloc(
new TrueConstraint(
this));
546 DCHECK(false_constraint_ ==
nullptr);
547 false_constraint_ =
RevAlloc(
new FalseConstraint(
this));
551 const std::vector<IntVar*>& actives) {
552 return RevAlloc(
new MapDomain(
this,
var, actives));
556 const std::vector<IntVar*>& right) {
557 std::vector<IntVar*> adjusted_left = left;
559 std::vector<IntVar*> adjusted_right = right;
562 std::move(adjusted_left), std::move(adjusted_right),
563 std::vector<int64_t>(left.size() + 1, 1));
567 const std::vector<IntVar*>& right) {
569 left, right, std::vector<int64_t>(left.size(), 1));
573 std::vector<IntVar*> left, std::vector<IntVar*> right,
574 std::vector<int64_t> offsets) {
575 return RevAlloc(
new LexicalLessOrEqual(
this, std::move(left),
576 std::move(right), std::move(offsets)));
580 std::vector<IntVar*> left, std::vector<IntVar*> right,
581 std::vector<int64_t> offsets,
IntVar* boolvar) {
582 std::vector<IntVar*> adjusted_left = std::move(left);
583 adjusted_left.insert(adjusted_left.begin(), boolvar);
584 std::vector<IntVar*> adjusted_right = std::move(right);
585 adjusted_right.insert(adjusted_right.begin(),
MakeIntConst(1));
586 std::vector<int64_t> adjusted_offsets = std::move(offsets);
587 adjusted_offsets.insert(adjusted_offsets.begin(), 1);
589 std::move(adjusted_right),
590 std::move(adjusted_offsets));
594 const std::vector<IntVar*>& left,
const std::vector<IntVar*>& right) {
595 return RevAlloc(
new InversePermutationConstraint(
this, left, right));
600 return RevAlloc(
new IndexOfFirstMaxValue(
this,
index, vars));
605 std::vector<IntVar*> opp_vars(vars.size());
606 for (
int i = 0; i < vars.size(); ++i) {
609 return RevAlloc(
new IndexOfFirstMaxValue(
this,
index, opp_vars));
const std::vector< IntVar * > vars_
virtual void InitialPropagate()=0
virtual IntVar * Var()=0
Creates a variable from the expression.
static const char kLexLess[]
static const char kFalseConstraint[]
static const char kTargetArgument[]
static const char kMapDomain[]
static const char kRightArgument[]
static const char kValuesArgument[]
static const char kVarsArgument[]
static const char kLeftArgument[]
static const char kInversePermutation[]
static const char kTrueConstraint[]
Constraint * MakeIsLexicalLessOrEqualWithOffsetsCt(std::vector< IntVar * > left, std::vector< IntVar * > right, std::vector< int64_t > offsets, IntVar *boolvar)
Semi-reified version of the above: boolvar -> LexLE(left, right, offsets).
Demon * MakeClosureDemon(Closure closure)
Creates a demon from a closure.
Constraint * MakeLexicalLess(const std::vector< IntVar * > &left, const std::vector< IntVar * > &right)
std::function< void(Solver *)> Action
IntExpr * MakeOpposite(IntExpr *expr)
-expr
Constraint * MakeLexicalLessOrEqual(const std::vector< IntVar * > &left, const std::vector< IntVar * > &right)
Constraint * MakeIndexOfFirstMinValueConstraint(IntVar *index, const std::vector< IntVar * > &vars)
Constraint * MakeIndexOfFirstMaxValueConstraint(IntVar *index, const std::vector< IntVar * > &vars)
std::function< void()> Closure
Constraint * MakeMapDomain(IntVar *var, const std::vector< IntVar * > &actives)
Constraint * MakeTrueConstraint()
This constraint always succeeds.
Demon * MakeDelayedConstraintInitialPropagateCallback(Constraint *ct)
Constraint * MakeLexicalLessOrEqualWithOffsets(std::vector< IntVar * > left, std::vector< IntVar * > right, std::vector< int64_t > offsets)
Demon * MakeConstraintInitialPropagateCallback(Constraint *ct)
Constraint * MakeFalseConstraint()
This constraint always fails.
IntVar * MakeIntConst(int64_t val, const std::string &name)
IntConst will create a constant expression.
Demon * MakeActionDemon(Action action)
Creates a demon from a callback.
Constraint * MakeInversePermutationConstraint(const std::vector< IntVar * > &left, const std::vector< IntVar * > &right)
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
problem is infeasible or unbounded (default).
In SWIG mode, we don't want anything besides these top-level includes.
int64_t CapAdd(int64_t x, int64_t y)
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
Join v[i]->DebugString().
int64_t CapSub(int64_t x, int64_t y)
Demon * MakeDelayedConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
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)