23#include "absl/strings/str_format.h"
24#include "absl/strings/string_view.h"
35 BaseAllDifferent(Solver*
const s,
const std::vector<IntVar*>& vars)
36 : Constraint(s), vars_(vars) {}
37 ~BaseAllDifferent()
override {}
38 std::string DebugStringInternal(absl::string_view name)
const {
43 const std::vector<IntVar*> vars_;
44 int64_t size()
const {
return vars_.size(); }
50class ValueAllDifferent :
public BaseAllDifferent {
52 ValueAllDifferent(Solver*
const s,
const std::vector<IntVar*>& vars)
53 : BaseAllDifferent(s, vars) {}
54 ~ValueAllDifferent()
override {}
57 void InitialPropagate()
override;
58 void OneMove(
int index);
61 std::string DebugString()
const override {
62 return DebugStringInternal(
"ValueAllDifferent");
64 void Accept(ModelVisitor*
const visitor)
const override {
73 RevSwitch all_instantiated_;
76void ValueAllDifferent::Post() {
77 for (
int i = 0;
i < size(); ++
i) {
78 IntVar* var = vars_[
i];
85void ValueAllDifferent::InitialPropagate() {
86 for (
int i = 0;
i < size(); ++
i) {
87 if (vars_[i]->Bound()) {
93void ValueAllDifferent::OneMove(
int index) {
95 const int64_t val = vars_[index]->Value();
96 for (
int j = 0; j < size(); ++j) {
98 if (vars_[j]->Size() < 0xFFFFFF) {
99 vars_[j]->RemoveValue(val);
101 solver()->AddConstraint(solver()->MakeNonEquality(vars_[j], val));
108bool ValueAllDifferent::AllMoves() {
109 if (all_instantiated_.
Switched() || size() == 0) {
112 for (
int i = 0;
i < size(); ++
i) {
113 if (!vars_[i]->Bound()) {
117 std::unique_ptr<int64_t[]> values(
new int64_t[size()]);
118 for (
int i = 0;
i < size(); ++
i) {
119 values[
i] = vars_[
i]->Value();
121 std::sort(values.get(), values.get() + size());
122 for (
int i = 0;
i < size() - 1; ++
i) {
123 if (values[i] == values[i + 1]) {
128 all_instantiated_.
Switch(solver());
135class RangeBipartiteMatching {
144 RangeBipartiteMatching(Solver*
const solver,
int size)
147 intervals_(new Interval[size + 1]),
148 min_sorted_(new Interval*[size]),
149 max_sorted_(new Interval*[size]),
150 bounds_(new int64_t[2 * size + 2]),
151 tree_(new int[2 * size + 2]),
152 diff_(new int64_t[2 * size + 2]),
153 hall_(new int[2 * size + 2]),
155 for (
int i = 0;
i < size; ++
i) {
156 max_sorted_[
i] = &intervals_[
i];
157 min_sorted_[
i] = max_sorted_[
i];
161 void SetRange(
int index, int64_t imin, int64_t imax) {
162 intervals_[index].min = imin;
163 intervals_[index].max = imax;
169 const bool modified1 = PropagateMin();
170 const bool modified2 = PropagateMax();
171 return modified1 || modified2;
174 int64_t Min(
int index)
const {
return intervals_[index].min; }
176 int64_t Max(
int index)
const {
return intervals_[index].max; }
182 std::sort(min_sorted_.get(), min_sorted_.get() + size_,
183 CompareIntervalMin());
184 std::sort(max_sorted_.get(), max_sorted_.get() + size_,
185 CompareIntervalMax());
187 int64_t min = min_sorted_[0]->min;
188 int64_t max = max_sorted_[0]->max + 1;
189 int64_t last = min - 2;
196 if (i < size_ && min <= max) {
199 bounds_[++nb] = last;
201 min_sorted_[
i]->min_rank = nb;
203 min = min_sorted_[
i]->min;
208 bounds_[++nb] = last;
210 max_sorted_[j]->max_rank = nb;
214 max = max_sorted_[j]->max + 1;
218 bounds_[nb + 1] = bounds_[nb] + 2;
222 bool PropagateMin() {
223 bool modified =
false;
225 for (
int i = 1;
i <= active_size_ + 1; ++
i) {
228 diff_[
i] = bounds_[
i] - bounds_[
i - 1];
231 for (
int i = 0;
i < size_; ++
i) {
232 const int x = max_sorted_[
i]->min_rank;
233 const int y = max_sorted_[
i]->max_rank;
234 int z = PathMax(tree_.get(), x + 1);
236 if (--diff_[z] == 0) {
238 z = PathMax(tree_.get(), z + 1);
241 PathSet(x + 1, z, z, tree_.get());
242 if (diff_[z] < bounds_[z] - bounds_[y]) {
246 int w = PathMax(hall_.get(), hall_[x]);
247 max_sorted_[
i]->min = bounds_[
w];
248 PathSet(x,
w,
w, hall_.get());
251 if (diff_[z] == bounds_[z] - bounds_[y]) {
252 PathSet(hall_[y], j - 1, y, hall_.get());
259 bool PropagateMax() {
260 bool modified =
false;
262 for (
int i = 0;
i <= active_size_;
i++) {
265 diff_[
i] = bounds_[
i + 1] - bounds_[
i];
268 for (
int i = size_ - 1;
i >= 0; --
i) {
269 const int x = min_sorted_[
i]->max_rank;
270 const int y = min_sorted_[
i]->min_rank;
271 int z = PathMin(tree_.get(), x - 1);
273 if (--diff_[z] == 0) {
275 z = PathMin(tree_.get(), z - 1);
278 PathSet(x - 1, z, z, tree_.get());
279 if (diff_[z] < bounds_[y] - bounds_[z]) {
284 int w = PathMin(hall_.get(), hall_[x]);
285 min_sorted_[
i]->max = bounds_[
w] - 1;
286 PathSet(x,
w,
w, hall_.get());
289 if (diff_[z] == bounds_[y] - bounds_[z]) {
290 PathSet(hall_[y], j + 1, y, hall_.get());
301 struct CompareIntervalMin {
302 bool operator()(
const Interval* i1,
const Interval* i2)
const {
303 return (i1->min < i2->min);
308 struct CompareIntervalMax {
309 bool operator()(
const Interval* i1,
const Interval* i2)
const {
310 return (i1->max < i2->max);
314 void PathSet(
int start,
int end,
int to,
int*
const tree) {
323 int PathMin(
const int*
const tree,
int index) {
325 while (tree[i] < i) {
331 int PathMax(
const int*
const tree,
int index) {
333 while (tree[i] > i) {
339 Solver*
const solver_;
341 std::unique_ptr<Interval[]> intervals_;
342 std::unique_ptr<Interval*[]> min_sorted_;
343 std::unique_ptr<Interval*[]> max_sorted_;
346 std::unique_ptr<int64_t[]> bounds_;
347 std::unique_ptr<int[]> tree_;
348 std::unique_ptr<int64_t[]> diff_;
349 std::unique_ptr<int[]> hall_;
353class BoundsAllDifferent :
public BaseAllDifferent {
355 BoundsAllDifferent(Solver*
const s,
const std::vector<IntVar*>& vars)
356 : BaseAllDifferent(s, vars), matching_(s, vars.size()) {}
358 ~BoundsAllDifferent()
override {}
360 void Post()
override {
362 solver(),
this, &BoundsAllDifferent::IncrementalPropagate,
363 "IncrementalPropagate");
365 for (
int i = 0;
i < size(); ++
i) {
366 vars_[
i]->WhenRange(range);
368 &BoundsAllDifferent::PropagateValue,
369 "PropagateValue", i);
370 vars_[
i]->WhenBound(bound);
374 void InitialPropagate()
override {
375 IncrementalPropagate();
376 for (
int i = 0;
i < size(); ++
i) {
377 if (vars_[i]->Bound()) {
383 virtual void IncrementalPropagate() {
384 for (
int i = 0;
i < size(); ++
i) {
385 matching_.SetRange(i, vars_[i]->Min(), vars_[i]->Max());
388 if (matching_.Propagate()) {
389 for (
int i = 0;
i < size(); ++
i) {
390 vars_[
i]->SetRange(matching_.Min(i), matching_.Max(i));
395 void PropagateValue(
int index) {
396 const int64_t to_remove = vars_[index]->Value();
397 for (
int j = 0; j < index; j++) {
398 if (vars_[j]->Size() < 0xFFFFFF) {
399 vars_[j]->RemoveValue(to_remove);
401 solver()->AddConstraint(solver()->MakeNonEquality(vars_[j], to_remove));
404 for (
int j = index + 1; j < size(); j++) {
405 if (vars_[j]->Size() < 0xFFFFFF) {
406 vars_[j]->RemoveValue(to_remove);
408 solver()->AddConstraint(solver()->MakeNonEquality(vars_[j], to_remove));
413 std::string DebugString()
const override {
414 return DebugStringInternal(
"BoundsAllDifferent");
417 void Accept(ModelVisitor*
const visitor)
const override {
418 visitor->BeginVisitConstraint(ModelVisitor::kAllDifferent,
this);
419 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
421 visitor->VisitIntegerArgument(ModelVisitor::kRangeArgument, 1);
422 visitor->EndVisitConstraint(ModelVisitor::kAllDifferent,
this);
426 RangeBipartiteMatching matching_;
429class SortConstraint :
public Constraint {
431 SortConstraint(Solver*
const solver,
432 const std::vector<IntVar*>& original_vars,
433 const std::vector<IntVar*>& sorted_vars)
434 : Constraint(solver),
435 ovars_(original_vars),
437 mins_(original_vars.size(), 0),
438 maxs_(original_vars.size(), 0),
439 matching_(solver, original_vars.size()) {}
441 ~SortConstraint()
override {}
443 void Post()
override {
445 solver()->MakeDelayedConstraintInitialPropagateCallback(
this);
446 for (
int i = 0;
i < size(); ++
i) {
447 ovars_[
i]->WhenRange(demon);
448 svars_[
i]->WhenRange(demon);
452 void InitialPropagate()
override {
453 for (
int i = 0;
i < size(); ++
i) {
456 ovars_[
i]->Range(&vmin, &vmax);
461 std::sort(mins_.begin(), mins_.end());
462 std::sort(maxs_.begin(), maxs_.end());
463 for (
int i = 0;
i < size(); ++
i) {
464 svars_[
i]->SetRange(mins_[i], maxs_[i]);
467 for (
int i = 0;
i < size() - 1; ++
i) {
468 svars_[
i + 1]->SetMin(svars_[i]->Min());
470 for (
int i = size() - 1;
i > 0; --
i) {
471 svars_[
i - 1]->SetMax(svars_[i]->Max());
474 for (
int i = 0;
i < size(); ++
i) {
477 FindIntersectionRange(i, &imin, &imax);
478 matching_.SetRange(i, imin, imax);
480 matching_.Propagate();
481 for (
int i = 0;
i < size(); ++
i) {
482 const int64_t vmin = svars_[matching_.Min(i)]->Min();
483 const int64_t vmax = svars_[matching_.Max(i)]->Max();
484 ovars_[
i]->SetRange(vmin, vmax);
488 void Accept(ModelVisitor*
const visitor)
const override {
489 visitor->BeginVisitConstraint(ModelVisitor::kSortingConstraint,
this);
490 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
492 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kTargetArgument,
494 visitor->EndVisitConstraint(ModelVisitor::kSortingConstraint,
this);
497 std::string DebugString()
const override {
503 int64_t size()
const {
return ovars_.size(); }
505 void FindIntersectionRange(
int index, int64_t*
const range_min,
506 int64_t*
const range_max)
const {
510 while (imin < size() && NotIntersect(index, imin)) {
513 if (imin == size()) {
516 int64_t imax = size() - 1;
517 while (imax > imin && NotIntersect(index, imax)) {
524 bool NotIntersect(
int oindex,
int sindex)
const {
525 return ovars_[oindex]->Min() > svars_[sindex]->Max() ||
526 ovars_[oindex]->Max() < svars_[sindex]->Min();
529 const std::vector<IntVar*> ovars_;
530 const std::vector<IntVar*> svars_;
531 std::vector<int64_t> mins_;
532 std::vector<int64_t> maxs_;
533 RangeBipartiteMatching matching_;
538class AllDifferentExcept :
public Constraint {
540 AllDifferentExcept(Solver*
const s, std::vector<IntVar*> vars,
541 int64_t escape_value)
542 : Constraint(s), vars_(std::move(vars)), escape_value_(escape_value) {}
544 ~AllDifferentExcept()
override {}
546 void Post()
override {
547 for (
int i = 0;
i < vars_.size(); ++
i) {
548 IntVar*
const var = vars_[
i];
550 solver(),
this, &AllDifferentExcept::Propagate,
"Propagate", i);
555 void InitialPropagate()
override {
556 for (
int i = 0;
i < vars_.size(); ++
i) {
557 if (vars_[i]->Bound()) {
563 void Propagate(
int index) {
564 const int64_t val = vars_[index]->Value();
565 if (val != escape_value_) {
566 for (
int j = 0; j < vars_.size(); ++j) {
568 vars_[j]->RemoveValue(val);
574 std::string DebugString()
const override {
575 return absl::StrFormat(
"AllDifferentExcept([%s], %d",
579 void Accept(ModelVisitor*
const visitor)
const override {
580 visitor->BeginVisitConstraint(ModelVisitor::kAllDifferent,
this);
581 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
583 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, escape_value_);
584 visitor->EndVisitConstraint(ModelVisitor::kAllDifferent,
this);
588 std::vector<IntVar*> vars_;
589 const int64_t escape_value_;
597class NullIntersectArrayExcept :
public Constraint {
599 NullIntersectArrayExcept(Solver*
const s, std::vector<IntVar*> first_vars,
600 std::vector<IntVar*> second_vars,
601 int64_t escape_value)
603 first_vars_(std::move(first_vars)),
604 second_vars_(std::move(second_vars)),
605 escape_value_(escape_value),
606 has_escape_value_(
true) {}
608 NullIntersectArrayExcept(Solver*
const s, std::vector<IntVar*> first_vars,
609 std::vector<IntVar*> second_vars)
611 first_vars_(std::move(first_vars)),
612 second_vars_(std::move(second_vars)),
614 has_escape_value_(
false) {}
616 ~NullIntersectArrayExcept()
override {}
618 void Post()
override {
619 for (
int i = 0;
i < first_vars_.size(); ++
i) {
620 IntVar*
const var = first_vars_[
i];
622 solver(),
this, &NullIntersectArrayExcept::PropagateFirst,
623 "PropagateFirst", i);
626 for (
int i = 0;
i < second_vars_.size(); ++
i) {
627 IntVar*
const var = second_vars_[
i];
629 solver(),
this, &NullIntersectArrayExcept::PropagateSecond,
630 "PropagateSecond", i);
635 void InitialPropagate()
override {
636 for (
int i = 0;
i < first_vars_.size(); ++
i) {
637 if (first_vars_[i]->Bound()) {
641 for (
int i = 0;
i < second_vars_.size(); ++
i) {
642 if (second_vars_[i]->Bound()) {
648 void PropagateFirst(
int index) {
649 const int64_t val = first_vars_[index]->Value();
650 if (!has_escape_value_ || val != escape_value_) {
651 for (
int j = 0; j < second_vars_.size(); ++j) {
652 second_vars_[j]->RemoveValue(val);
657 void PropagateSecond(
int index) {
658 const int64_t val = second_vars_[index]->Value();
659 if (!has_escape_value_ || val != escape_value_) {
660 for (
int j = 0; j < first_vars_.size(); ++j) {
661 first_vars_[j]->RemoveValue(val);
666 std::string DebugString()
const override {
667 return absl::StrFormat(
"NullIntersectArray([%s], [%s], escape = %d",
673 void Accept(ModelVisitor*
const visitor)
const override {
674 visitor->BeginVisitConstraint(ModelVisitor::kNullIntersect,
this);
675 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kLeftArgument,
677 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kRightArgument,
679 visitor->VisitIntegerArgument(ModelVisitor::kValueArgument, escape_value_);
680 visitor->EndVisitConstraint(ModelVisitor::kNullIntersect,
this);
684 std::vector<IntVar*> first_vars_;
685 std::vector<IntVar*> second_vars_;
686 const int64_t escape_value_;
687 const bool has_escape_value_;
696 bool stronger_propagation) {
697 const int size = vars.size();
698 for (
int i = 0; i < size; ++i) {
699 CHECK_EQ(
this, vars[i]->solver());
703 }
else if (size == 2) {
705 const_cast<IntVar* const
>(vars[1]));
707 if (stronger_propagation) {
708 return RevAlloc(
new BoundsAllDifferent(
this, vars));
710 return RevAlloc(
new ValueAllDifferent(
this, vars));
716 const std::vector<IntVar*>& sorted) {
717 CHECK_EQ(vars.size(), sorted.size());
718 return RevAlloc(
new SortConstraint(
this, vars, sorted));
722 int64_t escape_value) {
723 int escape_candidates = 0;
724 for (
int i = 0; i < vars.size(); ++i) {
725 escape_candidates += (vars[i]->Contains(escape_value));
727 if (escape_candidates <= 1) {
730 return RevAlloc(
new AllDifferentExcept(
this, vars, escape_value));
735 const std::vector<IntVar*>& second_vars) {
736 return RevAlloc(
new NullIntersectArrayExcept(
this, first_vars, second_vars));
740 const std::vector<IntVar*>& first_vars,
741 const std::vector<IntVar*>& second_vars, int64_t escape_value) {
742 int first_escape_candidates = 0;
743 for (
int i = 0; i < first_vars.size(); ++i) {
744 first_escape_candidates += (first_vars[i]->Contains(escape_value));
746 int second_escape_candidates = 0;
747 for (
int i = 0; i < second_vars.size(); ++i) {
748 second_escape_candidates += (second_vars[i]->Contains(escape_value));
750 if (first_escape_candidates == 0 || second_escape_candidates == 0) {
752 new NullIntersectArrayExcept(
this, first_vars, second_vars));
754 return RevAlloc(
new NullIntersectArrayExcept(
this, first_vars, second_vars,
static const char kRangeArgument[]
static const char kAllDifferent[]
static const char kVarsArgument[]
void Switch(Solver *const solver)
Constraint * MakeSortingConstraint(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &sorted)
Constraint * MakeNonEquality(IntExpr *left, IntExpr *right)
left != right
void Fail()
Abandon the current branch in the search tree. A backtrack will follow.
Constraint * MakeAllDifferentExcept(const std::vector< IntVar * > &vars, int64_t escape_value)
Constraint * MakeNullIntersectExcept(const std::vector< IntVar * > &first_vars, const std::vector< IntVar * > &second_vars, int64_t escape_value)
Constraint * MakeTrueConstraint()
This constraint always succeeds.
Constraint * MakeAllDifferent(const std::vector< IntVar * > &vars)
Constraint * MakeNullIntersect(const std::vector< IntVar * > &first_vars, const std::vector< IntVar * > &second_vars)
For infeasible and unbounded see Not checked if options check_solutions_if_inf_or_unbounded and the If options first_solution_only is false
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
Demon * MakeDelayedConstraintDemon0(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)
trees with all degrees equal w the current value of w
trees with all degrees equal to