23#include "absl/strings/str_format.h"
24#include "absl/strings/str_join.h"
34 std::vector<IntVar*> tmp_sum;
35 for (
int i = 0; i < vars.size(); ++i) {
36 if (vars[i]->Contains(value)) {
37 if (vars[i]->Bound()) {
49 if (max_count->
Bound()) {
52 std::vector<IntVar*> tmp_sum;
53 int64_t num_vars_bound_to_v = 0;
54 for (
int i = 0; i < vars.size(); ++i) {
55 if (vars[i]->Contains(value)) {
56 if (vars[i]->Bound()) {
57 ++num_vars_bound_to_v;
64 MakeSum(max_count, -num_vars_bound_to_v)->Var());
73 AtMost(
Solver*
const s, std::vector<IntVar*> vars, int64_t value,
76 vars_(
std::move(vars)),
78 max_count_(max_count),
83 void Post()
override {
84 for (IntVar* var : vars_) {
85 if (!var->Bound() && var->Contains(value_)) {
93 void InitialPropagate()
override {
94 for (IntVar* var : vars_) {
95 if (var->Bound() && var->Min() == value_) {
96 current_count_.Incr(solver());
102 void OneBound(IntVar* var) {
103 if (var->Min() == value_) {
104 current_count_.Incr(solver());
110 if (current_count_.Value() < max_count_) {
116 for (IntVar* var : vars_) {
118 if (var->Min() == value_) {
122 var->RemoveValue(value_);
125 if (forced > max_count_) {
130 std::string DebugString()
const override {
131 return absl::StrFormat(
"AtMost(%s, %d, %d)",
135 void Accept(ModelVisitor*
const visitor)
const override {
145 const std::vector<IntVar*> vars_;
146 const int64_t value_;
147 const int64_t max_count_;
148 NumericalRev<int> current_count_;
153 Distribute(Solver*
const s,
const std::vector<IntVar*>& vars,
154 const std::vector<int64_t>& values,
155 const std::vector<IntVar*>& cards)
160 undecided_(vars.size(), cards.size()),
161 min_(cards.size(), 0),
162 max_(cards.size(), 0) {}
164 ~Distribute()
override {}
166 void Post()
override;
167 void InitialPropagate()
override;
168 void OneBound(
int index);
169 void OneDomain(
int index);
170 void CountVar(
int cindex);
171 void CardMin(
int cindex);
172 void CardMax(
int cindex);
173 std::string DebugString()
const override {
174 return absl::StrFormat(
175 "Distribute(vars = [%s], values = [%s], cards = [%s])",
180 void Accept(ModelVisitor*
const visitor)
const override {
191 int64_t var_size()
const {
return vars_.size(); }
192 int64_t card_size()
const {
return cards_.size(); }
194 const std::vector<IntVar*> vars_;
195 const std::vector<int64_t> values_;
196 const std::vector<IntVar*> cards_;
197 RevBitMatrix undecided_;
198 NumericalRevArray<int> min_;
199 NumericalRevArray<int> max_;
202void Distribute::Post() {
203 for (
int i = 0;
i < var_size(); ++
i) {
204 IntVar*
const var = vars_[
i];
214 for (
int i = 0;
i < card_size(); ++
i) {
215 if (!cards_[i]->Bound()) {
218 cards_[
i]->WhenRange(d);
223void Distribute::InitialPropagate() {
224 Solver*
const s = solver();
225 for (
int j = 0; j < card_size(); ++j) {
228 for (
int i = 0;
i < var_size(); ++
i) {
229 IntVar*
const var = vars_[
i];
231 if (var->Min() == values_[j]) {
236 if (var->Contains(values_[j])) {
242 cards_[j]->SetRange(min, max);
243 if (cards_[j]->Max() == min) {
245 }
else if (cards_[j]->Min() == max) {
248 min_.SetValue(s, j, min);
249 max_.SetValue(s, j, max);
253void Distribute::OneBound(
int index) {
254 IntVar*
const var = vars_[index];
255 Solver*
const s = solver();
256 for (
int j = 0; j < card_size(); ++j) {
257 if (undecided_.
IsSet(index, j)) {
259 if (var->Min() == values_[j]) {
261 cards_[j]->SetMin(min_[j]);
262 if (min_[j] == cards_[j]->Max()) {
267 cards_[j]->SetMax(max_[j]);
268 if (max_[j] == cards_[j]->Min()) {
276void Distribute::OneDomain(
int index) {
277 IntVar*
const var = vars_[index];
278 Solver*
const s = solver();
279 for (
int j = 0; j < card_size(); ++j) {
280 if (undecided_.
IsSet(index, j)) {
281 if (!var->Contains(values_[j])) {
284 cards_[j]->SetMax(max_[j]);
285 if (max_[j] == cards_[j]->Min()) {
293void Distribute::CountVar(
int cindex) {
294 if (cards_[cindex]->Min() > max_[cindex] ||
295 cards_[cindex]->Max() < min_[cindex]) {
298 if (cards_[cindex]->Min() == max_[cindex]) {
301 if (cards_[cindex]->Max() == min_[cindex]) {
306void Distribute::CardMin(
int cindex) {
307 for (
int i = 0;
i < var_size(); ++
i) {
308 if (undecided_.
IsSet(i, cindex)) {
309 vars_[
i]->RemoveValue(values_[cindex]);
314void Distribute::CardMax(
int cindex) {
315 for (
int i = 0;
i < var_size(); ++
i) {
316 if (undecided_.
IsSet(i, cindex)) {
317 vars_[
i]->SetValue(values_[cindex]);
324class FastDistribute :
public Constraint {
326 FastDistribute(Solver* s,
const std::vector<IntVar*>& vars,
327 const std::vector<IntVar*>& cards);
328 ~FastDistribute()
override {}
330 void Post()
override;
331 void InitialPropagate()
override;
332 void OneBound(
int index);
333 void OneDomain(
int index);
334 void CountVar(
int card_index);
335 void CardMin(
int card_index);
336 void CardMax(
int card_index);
337 std::string DebugString()
const override;
338 void SetRevCannotContribute(int64_t var_index, int64_t card_index) {
339 Solver*
const s = solver();
340 undecided_.
SetToZero(s, var_index, card_index);
341 max_.Decr(s, card_index);
342 cards_[card_index]->SetMax(max_[card_index]);
343 if (max_[card_index] == cards_[card_index]->Min()) {
347 void SetRevDoContribute(int64_t var_index, int64_t card_index) {
348 Solver*
const s = solver();
349 undecided_.
SetToZero(s, var_index, card_index);
350 min_.Incr(s, card_index);
351 cards_[card_index]->SetMin(min_[card_index]);
352 if (min_[card_index] == cards_[card_index]->Max()) {
357 void Accept(ModelVisitor*
const visitor)
const override {
358 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
359 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
361 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
363 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
367 int64_t var_size()
const {
return vars_.size(); }
368 int64_t card_size()
const {
return cards_.size(); }
370 const std::vector<IntVar*> vars_;
371 const std::vector<IntVar*> cards_;
372 RevBitMatrix undecided_;
373 NumericalRevArray<int> min_;
374 NumericalRevArray<int> max_;
375 std::vector<IntVarIterator*> holes_;
378FastDistribute::FastDistribute(Solver*
const s,
379 const std::vector<IntVar*>& vars,
380 const std::vector<IntVar*>& cards)
384 undecided_(vars.size(), cards.size()),
385 min_(cards.size(), 0),
386 max_(cards.size(), 0),
387 holes_(vars.size()) {
388 for (
int var_index = 0; var_index < var_size(); ++var_index) {
389 holes_[var_index] = vars_[var_index]->MakeHoleIterator(
true);
393std::string FastDistribute::DebugString()
const {
394 return absl::StrFormat(
"FastDistribute(vars = [%s], cards = [%s])",
399void FastDistribute::Post() {
400 for (
int var_index = 0; var_index < var_size(); ++var_index) {
401 IntVar*
const var = vars_[var_index];
404 "OneBound", var_index);
407 "OneDomain", var_index);
411 for (
int card_index = 0; card_index < card_size(); ++card_index) {
412 if (!cards_[card_index]->Bound()) {
415 cards_[card_index]->WhenRange(d);
420void FastDistribute::InitialPropagate() {
421 Solver*
const s = solver();
422 for (
int card_index = 0; card_index < card_size(); ++card_index) {
425 for (
int var_index = 0; var_index < var_size(); ++var_index) {
426 IntVar*
const var = vars_[var_index];
427 if (var->Bound() && var->Min() == card_index) {
430 }
else if (var->Contains(card_index)) {
432 undecided_.
SetToOne(s, var_index, card_index);
435 min_.SetValue(s, card_index, min);
436 max_.SetValue(s, card_index, max);
437 CountVar(card_index);
441void FastDistribute::OneBound(
int index) {
442 IntVar*
const var = vars_[index];
443 for (
int card_index = 0; card_index < card_size(); ++card_index) {
444 if (undecided_.
IsSet(index, card_index)) {
445 if (var->Min() == card_index) {
446 SetRevDoContribute(index, card_index);
448 SetRevCannotContribute(index, card_index);
454void FastDistribute::OneDomain(
int index) {
455 IntVar*
const var = vars_[index];
456 const int64_t oldmin = var->OldMin();
457 const int64_t oldmax = var->OldMax();
458 const int64_t vmin = var->Min();
459 const int64_t vmax = var->Max();
460 for (int64_t card_index = std::max(oldmin, int64_t{0});
461 card_index < std::min(vmin, card_size()); ++card_index) {
462 if (undecided_.
IsSet(index, card_index)) {
463 SetRevCannotContribute(index, card_index);
466 for (
const int64_t card_index : InitAndGetValues(holes_[index])) {
467 if (card_index >= 0 && card_index < card_size() &&
468 undecided_.
IsSet(index, card_index)) {
469 SetRevCannotContribute(index, card_index);
472 for (int64_t card_index = std::max(vmax + 1, int64_t{0});
473 card_index <= std::min(oldmax, card_size() - 1); ++card_index) {
474 if (undecided_.
IsSet(index, card_index)) {
475 SetRevCannotContribute(index, card_index);
480void FastDistribute::CountVar(
int card_index) {
481 const int64_t stored_min = min_[card_index];
482 const int64_t stored_max = max_[card_index];
483 cards_[card_index]->SetRange(min_[card_index], max_[card_index]);
484 if (cards_[card_index]->Min() == stored_max) {
487 if (cards_[card_index]->Max() == stored_min) {
492void FastDistribute::CardMin(
int card_index) {
493 for (
int var_index = 0; var_index < var_size(); ++var_index) {
494 if (undecided_.
IsSet(var_index, card_index)) {
495 vars_[var_index]->RemoveValue(card_index);
500void FastDistribute::CardMax(
int card_index) {
501 for (
int var_index = 0; var_index < var_size(); ++var_index) {
502 if (undecided_.
IsSet(var_index, card_index)) {
503 vars_[var_index]->SetValue(card_index);
510class BoundedDistribute :
public Constraint {
512 BoundedDistribute(Solver* s,
const std::vector<IntVar*>& vars,
513 const std::vector<int64_t>& values,
514 const std::vector<int64_t>& card_min,
515 const std::vector<int64_t>& card_max);
516 ~BoundedDistribute()
override {}
518 void Post()
override;
519 void InitialPropagate()
override;
520 void OneBound(
int index);
521 void OneDomain(
int index);
522 void CountVar(
int card_index);
523 void CardMin(
int card_index);
524 void CardMax(
int card_index);
525 std::string DebugString()
const override;
526 void SetRevCannotContribute(int64_t var_index, int64_t card_index) {
527 Solver*
const s = solver();
528 undecided_.
SetToZero(s, var_index, card_index);
529 max_.Decr(s, card_index);
530 if (max_[card_index] < card_min_[card_index]) {
533 if (max_[card_index] == card_min_[card_index]) {
537 void SetRevDoContribute(int64_t var_index, int64_t card_index) {
538 Solver*
const s = solver();
539 undecided_.
SetToZero(s, var_index, card_index);
540 min_.Incr(s, card_index);
541 if (min_[card_index] > card_max_[card_index]) {
544 if (min_[card_index] == card_max_[card_index]) {
549 void Accept(ModelVisitor*
const visitor)
const override {
550 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
551 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
553 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument, values_);
554 visitor->VisitIntegerArrayArgument(ModelVisitor::kMinArgument, card_min_);
555 visitor->VisitIntegerArrayArgument(ModelVisitor::kMaxArgument, card_max_);
556 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
560 int64_t var_size()
const {
return vars_.size(); }
561 int64_t card_size()
const {
return values_.size(); }
563 const std::vector<IntVar*> vars_;
564 const std::vector<int64_t> values_;
565 const std::vector<int64_t> card_min_;
566 const std::vector<int64_t> card_max_;
567 RevBitMatrix undecided_;
568 NumericalRevArray<int> min_;
569 NumericalRevArray<int> max_;
570 std::vector<IntVarIterator*> holes_;
573BoundedDistribute::BoundedDistribute(Solver*
const s,
574 const std::vector<IntVar*>& vars,
575 const std::vector<int64_t>& values,
576 const std::vector<int64_t>& card_min,
577 const std::vector<int64_t>& card_max)
583 undecided_(vars.size(), values.size()),
584 min_(values.size(), 0),
585 max_(values.size(), 0),
586 holes_(vars.size()) {
587 for (
int var_index = 0; var_index < var_size(); ++var_index) {
588 holes_[var_index] = vars_[var_index]->MakeHoleIterator(
true);
592std::string BoundedDistribute::DebugString()
const {
593 return absl::StrFormat(
594 "BoundedDistribute([%s], values = [%s], card_min = [%s], card_max = "
597 absl::StrJoin(card_min_,
", "), absl::StrJoin(card_max_,
", "));
600void BoundedDistribute::Post() {
601 for (
int var_index = 0; var_index < var_size(); ++var_index) {
602 IntVar*
const var = vars_[var_index];
605 solver(),
this, &BoundedDistribute::OneBound,
"OneBound", var_index);
608 "OneDomain", var_index);
614void BoundedDistribute::InitialPropagate() {
615 Solver*
const s = solver();
617 int64_t sum_card_min = 0;
618 for (
int i = 0;
i < card_size(); ++
i) {
619 if (card_max_[i] < card_min_[i]) {
622 sum_card_min += card_min_[
i];
624 if (sum_card_min > var_size()) {
627 if (sum_card_min == var_size()) {
628 for (
int i = 0;
i < var_size(); ++
i) {
629 vars_[
i]->SetValues(values_);
633 for (
int card_index = 0; card_index < card_size(); ++card_index) {
634 const int64_t value = values_[card_index];
637 for (
int i = 0;
i < var_size(); ++
i) {
638 IntVar*
const var = vars_[
i];
640 if (var->Min() == value) {
644 }
else if (var->Contains(value)) {
646 undecided_.
SetToOne(s, i, card_index);
649 min_.SetValue(s, card_index, min);
650 max_.SetValue(s, card_index, max);
651 CountVar(card_index);
655void BoundedDistribute::OneBound(
int index) {
656 IntVar*
const var = vars_[index];
657 const int64_t var_min = var->Min();
658 for (
int card_index = 0; card_index < card_size(); ++card_index) {
659 if (undecided_.
IsSet(index, card_index)) {
660 if (var_min == values_[card_index]) {
661 SetRevDoContribute(index, card_index);
663 SetRevCannotContribute(index, card_index);
669void BoundedDistribute::OneDomain(
int index) {
670 IntVar*
const var = vars_[index];
671 for (
int card_index = 0; card_index < card_size(); ++card_index) {
672 if (undecided_.
IsSet(index, card_index)) {
673 if (!var->Contains(values_[card_index])) {
674 SetRevCannotContribute(index, card_index);
680void BoundedDistribute::CountVar(
int card_index) {
681 const int64_t stored_min = min_[card_index];
682 const int64_t stored_max = max_[card_index];
683 if (card_min_[card_index] > stored_max ||
684 card_max_[card_index] < stored_min) {
687 if (card_min_[card_index] == stored_max) {
690 if (card_max_[card_index] == stored_min) {
695void BoundedDistribute::CardMin(
int card_index) {
696 for (
int var_index = 0; var_index < var_size(); ++var_index) {
697 if (undecided_.
IsSet(var_index, card_index)) {
698 vars_[var_index]->RemoveValue(values_[card_index]);
703void BoundedDistribute::CardMax(
int card_index) {
704 for (
int var_index = 0; var_index < var_size(); ++var_index) {
705 if (undecided_.
IsSet(var_index, card_index)) {
706 vars_[var_index]->SetValue(values_[card_index]);
713class BoundedFastDistribute :
public Constraint {
715 BoundedFastDistribute(Solver* s,
const std::vector<IntVar*>& vars,
716 const std::vector<int64_t>& card_min,
717 const std::vector<int64_t>& card_max);
718 ~BoundedFastDistribute()
override {}
720 void Post()
override;
721 void InitialPropagate()
override;
722 void OneBound(
int index);
723 void OneDomain(
int index);
724 void CountVar(
int card_index);
725 void CardMin(
int card_index);
726 void CardMax(
int card_index);
727 std::string DebugString()
const override;
728 void SetRevCannotContribute(int64_t var_index, int64_t card_index) {
729 Solver*
const s = solver();
730 undecided_.
SetToZero(s, var_index, card_index);
731 max_.Decr(s, card_index);
732 if (max_[card_index] < card_min_[card_index]) {
735 if (max_[card_index] == card_min_[card_index]) {
739 void SetRevDoContribute(int64_t var_index, int64_t card_index) {
740 Solver*
const s = solver();
741 undecided_.
SetToZero(s, var_index, card_index);
742 min_.Incr(s, card_index);
743 if (min_[card_index] > card_max_[card_index]) {
746 if (min_[card_index] == card_max_[card_index]) {
751 void Accept(ModelVisitor*
const visitor)
const override {
752 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
753 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
755 visitor->VisitIntegerArrayArgument(ModelVisitor::kMinArgument, card_min_);
756 visitor->VisitIntegerArrayArgument(ModelVisitor::kMaxArgument, card_max_);
757 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
761 int64_t var_size()
const {
return vars_.size(); }
762 int64_t card_size()
const {
return card_min_.size(); }
764 const std::vector<IntVar*> vars_;
765 const std::vector<int64_t> card_min_;
766 const std::vector<int64_t> card_max_;
767 RevBitMatrix undecided_;
768 NumericalRevArray<int> min_;
769 NumericalRevArray<int> max_;
770 std::vector<IntVarIterator*> holes_;
773BoundedFastDistribute::BoundedFastDistribute(
774 Solver*
const s,
const std::vector<IntVar*>& vars,
775 const std::vector<int64_t>& card_min,
const std::vector<int64_t>& card_max)
780 undecided_(vars.size(), card_min.size()),
781 min_(card_min.size(), 0),
782 max_(card_max.size(), 0),
783 holes_(vars.size()) {
784 for (
int var_index = 0; var_index < var_size(); ++var_index) {
785 holes_[var_index] = vars_[var_index]->MakeHoleIterator(
true);
789std::string BoundedFastDistribute::DebugString()
const {
790 return absl::StrFormat(
791 "BoundedFastDistribute([%s], card_min = [%s], card_max = [%s]",
793 absl::StrJoin(card_max_,
", "));
796void BoundedFastDistribute::Post() {
797 for (
int var_index = 0; var_index < var_size(); ++var_index) {
798 IntVar*
const var = vars_[var_index];
802 "OneBound", var_index);
805 &BoundedFastDistribute::OneDomain,
"OneDomain",
812void BoundedFastDistribute::InitialPropagate() {
813 Solver*
const s = solver();
815 int64_t sum_card_min = 0;
816 for (
int i = 0;
i < card_size(); ++
i) {
817 if (card_max_[i] < card_min_[i]) {
820 sum_card_min += card_min_[
i];
822 if (sum_card_min > var_size()) {
825 if (sum_card_min == var_size()) {
826 for (
int i = 0;
i < var_size(); ++
i) {
827 vars_[
i]->SetRange(0, card_size() - 1);
831 for (
int card_index = 0; card_index < card_size(); ++card_index) {
834 for (
int i = 0;
i < var_size(); ++
i) {
835 IntVar*
const var = vars_[
i];
837 if (var->Min() == card_index) {
841 }
else if (var->Contains(card_index)) {
843 undecided_.
SetToOne(s, i, card_index);
846 min_.SetValue(s, card_index, min);
847 max_.SetValue(s, card_index, max);
848 CountVar(card_index);
852void BoundedFastDistribute::OneBound(
int index) {
853 IntVar*
const var = vars_[index];
854 const int64_t var_min = var->Min();
855 for (
int card_index = 0; card_index < card_size(); ++card_index) {
856 if (undecided_.
IsSet(index, card_index)) {
857 if (var_min == card_index) {
858 SetRevDoContribute(index, card_index);
860 SetRevCannotContribute(index, card_index);
866void BoundedFastDistribute::OneDomain(
int index) {
867 IntVar*
const var = vars_[index];
868 const int64_t oldmin = var->OldMin();
869 const int64_t oldmax = var->OldMax();
870 const int64_t vmin = var->Min();
871 const int64_t vmax = var->Max();
872 for (int64_t card_index = std::max(oldmin, int64_t{0});
873 card_index < std::min(vmin, card_size()); ++card_index) {
874 if (undecided_.
IsSet(index, card_index)) {
875 SetRevCannotContribute(index, card_index);
878 for (
const int64_t card_index : InitAndGetValues(holes_[index])) {
879 if (card_index >= 0 && card_index < card_size() &&
880 undecided_.
IsSet(index, card_index)) {
881 SetRevCannotContribute(index, card_index);
884 for (int64_t card_index = std::max(vmax + 1, int64_t{0});
885 card_index <= std::min(oldmax, card_size() - 1); ++card_index) {
886 if (undecided_.
IsSet(index, card_index)) {
887 SetRevCannotContribute(index, card_index);
892void BoundedFastDistribute::CountVar(
int card_index) {
893 const int64_t stored_min = min_[card_index];
894 const int64_t stored_max = max_[card_index];
895 if (card_min_[card_index] > stored_max ||
896 card_max_[card_index] < stored_min) {
899 if (card_min_[card_index] == stored_max) {
902 if (card_max_[card_index] == stored_min) {
907void BoundedFastDistribute::CardMin(
int card_index) {
908 for (
int var_index = 0; var_index < var_size(); ++var_index) {
909 if (undecided_.
IsSet(var_index, card_index)) {
910 vars_[var_index]->RemoveValue(card_index);
915void BoundedFastDistribute::CardMax(
int card_index) {
916 for (
int var_index = 0; var_index < var_size(); ++var_index) {
917 if (undecided_.
IsSet(var_index, card_index)) {
918 vars_[var_index]->SetValue(card_index);
925class SetAllToZero :
public Constraint {
927 SetAllToZero(Solver*
const s,
const std::vector<IntVar*>& vars)
928 : Constraint(s), vars_(vars) {}
930 ~SetAllToZero()
override {}
932 void Post()
override {}
934 void InitialPropagate()
override {
935 for (
int i = 0;
i < vars_.size(); ++
i) {
936 vars_[
i]->SetValue(0);
940 std::string DebugString()
const override {
return "SetAllToZero()"; }
942 void Accept(ModelVisitor*
const visitor)
const override {
943 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
944 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
946 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
950 const std::vector<IntVar*> vars_;
958 CHECK_GE(max_count, 0);
959 if (max_count >= vars.size()) {
962 return RevAlloc(
new AtMost(
this, std::move(vars), value, max_count));
966 const std::vector<int64_t>& values,
967 const std::vector<IntVar*>& cards) {
969 return RevAlloc(
new SetAllToZero(
this, cards));
971 CHECK_EQ(values.size(), cards.size());
972 for (
IntVar*
const var : vars) {
973 CHECK_EQ(
this, var->solver());
978 for (
int i = 0; i < values.size(); ++i) {
979 if (values[i] != i) {
984 for (
IntVar*
const card : cards) {
985 CHECK_EQ(
this, card->solver());
988 return RevAlloc(
new FastDistribute(
this, vars, cards));
990 return RevAlloc(
new Distribute(
this, vars, values, cards));
995 const std::vector<int>& values,
996 const std::vector<IntVar*>& cards) {
1001 const std::vector<IntVar*>& cards) {
1003 return RevAlloc(
new SetAllToZero(
this, cards));
1005 for (
IntVar*
const var : vars) {
1006 CHECK_EQ(
this, var->solver());
1008 for (
IntVar*
const card : cards) {
1009 CHECK_EQ(
this, card->solver());
1011 return RevAlloc(
new FastDistribute(
this, vars, cards));
1015 int64_t card_min, int64_t card_max,
1016 int64_t card_size) {
1017 const int vsize = vars.size();
1019 for (
IntVar*
const var : vars) {
1020 CHECK_EQ(
this, var->solver());
1022 if (card_min == 0 && card_max >= vsize) {
1024 }
else if (card_min > vsize || card_max < 0 || card_max < card_min) {
1027 std::vector<int64_t> mins(card_size, card_min);
1028 std::vector<int64_t> maxes(card_size, card_max);
1029 return RevAlloc(
new BoundedFastDistribute(
this, vars, mins, maxes));
1034 const std::vector<int64_t>& card_min,
1035 const std::vector<int64_t>& card_max) {
1036 const int vsize = vars.size();
1038 int64_t cmax = std::numeric_limits<int64_t>::max();
1039 int64_t cmin = std::numeric_limits<int64_t>::min();
1040 for (
int i = 0; i < card_max.size(); ++i) {
1041 cmax = std::min(cmax, card_max[i]);
1042 cmin = std::max(cmin, card_min[i]);
1044 if (cmax < 0 || cmin > vsize) {
1046 }
else if (cmax >= vsize && cmin == 0) {
1049 return RevAlloc(
new BoundedFastDistribute(
this, vars, card_min, card_max));
1054 const std::vector<int>& card_min,
1055 const std::vector<int>& card_max) {
1060 const std::vector<int64_t>& values,
1061 const std::vector<int64_t>& card_min,
1062 const std::vector<int64_t>& card_max) {
1063 CHECK_NE(vars.size(), 0);
1064 CHECK_EQ(card_min.size(), values.size());
1065 CHECK_EQ(card_min.size(), card_max.size());
1072 new BoundedDistribute(
this, vars, values, card_min, card_max));
1077 const std::vector<int>& values,
1078 const std::vector<int>& card_min,
1079 const std::vector<int>& card_max) {
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual int64_t Min() const =0
static const char kDistribute[]
static const char kValueArgument[]
static const char kValuesArgument[]
static const char kAtMost[]
static const char kVarsArgument[]
static const char kCountArgument[]
static const char kCardsArgument[]
bool IsSet(int64_t row, int64_t column) const
Returns whether the 'column' bit in the 'row' row is set.
void SetToZero(Solver *solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
void SetToOne(Solver *solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Constraint * MakeDistribute(const std::vector< IntVar * > &vars, const std::vector< int64_t > &values, const std::vector< IntVar * > &cards)
Aggregated version of count: |{i | v[i] == values[j]}| == cards[j].
Constraint * MakeSumEquality(const std::vector< IntVar * > &vars, int64_t cst)
IntVar * MakeIsEqualCstVar(IntExpr *var, int64_t value)
status var of (var == value)
IntExpr * MakeSum(IntExpr *left, IntExpr *right)
left + right.
Constraint * MakeAtMost(std::vector< IntVar * > vars, int64_t value, int64_t max_count)
|{i | vars[i] == value}| <= max_count
Constraint * MakeCount(const std::vector< IntVar * > &vars, int64_t value, int64_t max_count)
|{i | vars[i] == value}| == max_count
Constraint * MakeTrueConstraint()
This constraint always succeeds.
Constraint * MakeAllDifferent(const std::vector< IntVar * > &vars)
Constraint * MakeFalseConstraint()
This constraint always fails.
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
bool IsIncreasingContiguous(const std::vector< T > &values)
bool IsArrayInRange(const std::vector< IntVar * > &vars, T range_min, T range_max)
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
bool AreAllOnes(const std::vector< T > &values)