21 #include "absl/strings/str_format.h"
22 #include "absl/strings/str_join.h"
32 std::vector<IntVar*> tmp_sum;
33 for (
int i = 0; i < vars.size(); ++i) {
34 if (vars[i]->Contains(
value)) {
35 if (vars[i]->Bound()) {
47 if (max_count->
Bound()) {
50 std::vector<IntVar*> tmp_sum;
51 int64 num_vars_bound_to_v = 0;
52 for (
int i = 0; i < vars.size(); ++i) {
53 if (vars[i]->Contains(
value)) {
54 if (vars[i]->Bound()) {
55 ++num_vars_bound_to_v;
62 MakeSum(max_count, -num_vars_bound_to_v)->Var());
74 vars_(std::move(vars)),
76 max_count_(max_count),
81 void Post()
override {
82 for (IntVar*
var : vars_) {
83 if (!
var->Bound() &&
var->Contains(value_)) {
91 void InitialPropagate()
override {
92 for (IntVar*
var : vars_) {
93 if (
var->Bound() &&
var->Min() == value_) {
94 current_count_.
Incr(solver());
100 void OneBound(IntVar*
var) {
101 if (
var->Min() == value_) {
102 current_count_.
Incr(solver());
108 if (current_count_.
Value() < max_count_) {
114 for (IntVar*
var : vars_) {
116 if (
var->Min() == value_) {
120 var->RemoveValue(value_);
123 if (forced > max_count_) {
128 std::string DebugString()
const override {
129 return absl::StrFormat(
"AtMost(%s, %d, %d)",
133 void Accept(ModelVisitor*
const visitor)
const override {
143 const std::vector<IntVar*>
vars_;
145 const int64 max_count_;
146 NumericalRev<int> current_count_;
149 class Distribute :
public Constraint {
151 Distribute(Solver*
const s,
const std::vector<IntVar*>& vars,
152 const std::vector<int64>& values,
153 const std::vector<IntVar*>& cards)
158 undecided_(vars.size(), cards.size()),
159 min_(cards.size(), 0),
160 max_(cards.size(), 0) {}
162 ~Distribute()
override {}
164 void Post()
override;
165 void InitialPropagate()
override;
166 void OneBound(
int index);
167 void OneDomain(
int index);
168 void CountVar(
int cindex);
169 void CardMin(
int cindex);
170 void CardMax(
int cindex);
171 std::string DebugString()
const override {
172 return absl::StrFormat(
173 "Distribute(vars = [%s], values = [%s], cards = [%s])",
178 void Accept(ModelVisitor*
const visitor)
const override {
189 int64 var_size()
const {
return vars_.size(); }
190 int64 card_size()
const {
return cards_.size(); }
192 const std::vector<IntVar*>
vars_;
193 const std::vector<int64> values_;
194 const std::vector<IntVar*> cards_;
195 RevBitMatrix undecided_;
196 NumericalRevArray<int> min_;
197 NumericalRevArray<int> max_;
200 void Distribute::Post() {
201 for (
int i = 0; i < var_size(); ++i) {
212 for (
int i = 0; i < card_size(); ++i) {
213 if (!cards_[i]->Bound()) {
216 cards_[i]->WhenRange(d);
221 void Distribute::InitialPropagate() {
222 Solver*
const s = solver();
223 for (
int j = 0; j < card_size(); ++j) {
226 for (
int i = 0; i < var_size(); ++i) {
229 if (
var->
Min() == values_[j]) {
240 cards_[j]->SetRange(
min,
max);
241 if (cards_[j]->Max() ==
min) {
243 }
else if (cards_[j]->Min() ==
max) {
246 min_.SetValue(s, j,
min);
247 max_.SetValue(s, j,
max);
251 void Distribute::OneBound(
int index) {
253 Solver*
const s = solver();
254 for (
int j = 0; j < card_size(); ++j) {
257 if (
var->
Min() == values_[j]) {
259 cards_[j]->SetMin(min_[j]);
260 if (min_[j] == cards_[j]->Max()) {
265 cards_[j]->SetMax(max_[j]);
266 if (max_[j] == cards_[j]->Min()) {
274 void Distribute::OneDomain(
int index) {
276 Solver*
const s = solver();
277 for (
int j = 0; j < card_size(); ++j) {
282 cards_[j]->SetMax(max_[j]);
283 if (max_[j] == cards_[j]->Min()) {
291 void Distribute::CountVar(
int cindex) {
292 if (cards_[cindex]->Min() > max_[cindex] ||
293 cards_[cindex]->Max() < min_[cindex]) {
296 if (cards_[cindex]->Min() == max_[cindex]) {
299 if (cards_[cindex]->Max() == min_[cindex]) {
304 void Distribute::CardMin(
int cindex) {
305 for (
int i = 0; i < var_size(); ++i) {
306 if (undecided_.
IsSet(i, cindex)) {
307 vars_[i]->RemoveValue(values_[cindex]);
312 void Distribute::CardMax(
int cindex) {
313 for (
int i = 0; i < var_size(); ++i) {
314 if (undecided_.
IsSet(i, cindex)) {
315 vars_[i]->SetValue(values_[cindex]);
322 class FastDistribute :
public Constraint {
324 FastDistribute(Solver*
const s,
const std::vector<IntVar*>& vars,
325 const std::vector<IntVar*>& cards);
326 ~FastDistribute()
override {}
328 void Post()
override;
329 void InitialPropagate()
override;
330 void OneBound(
int index);
331 void OneDomain(
int index);
332 void CountVar(
int card_index);
333 void CardMin(
int card_index);
334 void CardMax(
int card_index);
335 std::string DebugString()
const override;
336 void SetRevCannotContribute(
int64 var_index,
int64 card_index) {
337 Solver*
const s = solver();
338 undecided_.SetToZero(s, var_index, card_index);
339 max_.Decr(s, card_index);
340 cards_[card_index]->SetMax(max_[card_index]);
341 if (max_[card_index] == cards_[card_index]->Min()) {
345 void SetRevDoContribute(
int64 var_index,
int64 card_index) {
346 Solver*
const s = solver();
347 undecided_.SetToZero(s, var_index, card_index);
348 min_.Incr(s, card_index);
349 cards_[card_index]->SetMin(min_[card_index]);
350 if (min_[card_index] == cards_[card_index]->Max()) {
355 void Accept(ModelVisitor*
const visitor)
const override {
365 int64 var_size()
const {
return vars_.size(); }
366 int64 card_size()
const {
return cards_.size(); }
368 const std::vector<IntVar*>
vars_;
369 const std::vector<IntVar*> cards_;
370 RevBitMatrix undecided_;
371 NumericalRevArray<int> min_;
372 NumericalRevArray<int> max_;
373 std::vector<IntVarIterator*>
holes_;
376 FastDistribute::FastDistribute(Solver*
const s,
377 const std::vector<IntVar*>& vars,
378 const std::vector<IntVar*>& cards)
382 undecided_(vars.size(), cards.size()),
383 min_(cards.size(), 0),
384 max_(cards.size(), 0),
386 for (
int var_index = 0; var_index < var_size(); ++var_index) {
387 holes_[var_index] =
vars_[var_index]->MakeHoleIterator(
true);
391 std::string FastDistribute::DebugString()
const {
392 return absl::StrFormat(
"FastDistribute(vars = [%s], cards = [%s])",
397 void FastDistribute::Post() {
398 for (
int var_index = 0; var_index < var_size(); ++var_index) {
399 IntVar*
const var =
vars_[var_index];
402 "OneBound", var_index);
405 "OneDomain", var_index);
409 for (
int card_index = 0; card_index < card_size(); ++card_index) {
410 if (!cards_[card_index]->Bound()) {
413 cards_[card_index]->WhenRange(d);
418 void FastDistribute::InitialPropagate() {
419 Solver*
const s = solver();
420 for (
int card_index = 0; card_index < card_size(); ++card_index) {
423 for (
int var_index = 0; var_index < var_size(); ++var_index) {
424 IntVar*
const var =
vars_[var_index];
430 undecided_.
SetToOne(s, var_index, card_index);
433 min_.SetValue(s, card_index,
min);
434 max_.SetValue(s, card_index,
max);
435 CountVar(card_index);
439 void FastDistribute::OneBound(
int index) {
441 for (
int card_index = 0; card_index < card_size(); ++card_index) {
443 if (
var->
Min() == card_index) {
444 SetRevDoContribute(
index, card_index);
446 SetRevCannotContribute(
index, card_index);
452 void FastDistribute::OneDomain(
int index) {
459 card_index <
std::min(vmin, card_size()); ++card_index) {
461 SetRevCannotContribute(
index, card_index);
465 if (card_index >= 0 && card_index < card_size() &&
467 SetRevCannotContribute(
index, card_index);
471 card_index <=
std::min(oldmax, card_size() - 1); ++card_index) {
473 SetRevCannotContribute(
index, card_index);
478 void FastDistribute::CountVar(
int card_index) {
479 const int64 stored_min = min_[card_index];
480 const int64 stored_max = max_[card_index];
481 cards_[card_index]->SetRange(min_[card_index], max_[card_index]);
482 if (cards_[card_index]->Min() == stored_max) {
485 if (cards_[card_index]->Max() == stored_min) {
490 void FastDistribute::CardMin(
int card_index) {
491 for (
int var_index = 0; var_index < var_size(); ++var_index) {
492 if (undecided_.
IsSet(var_index, card_index)) {
493 vars_[var_index]->RemoveValue(card_index);
498 void FastDistribute::CardMax(
int card_index) {
499 for (
int var_index = 0; var_index < var_size(); ++var_index) {
500 if (undecided_.
IsSet(var_index, card_index)) {
501 vars_[var_index]->SetValue(card_index);
508 class BoundedDistribute :
public Constraint {
510 BoundedDistribute(Solver*
const s,
const std::vector<IntVar*>& vars,
511 const std::vector<int64>& values,
512 const std::vector<int64>& card_min,
513 const std::vector<int64>& card_max);
514 ~BoundedDistribute()
override {}
516 void Post()
override;
517 void InitialPropagate()
override;
518 void OneBound(
int index);
519 void OneDomain(
int index);
520 void CountVar(
int card_index);
521 void CardMin(
int card_index);
522 void CardMax(
int card_index);
523 std::string DebugString()
const override;
524 void SetRevCannotContribute(
int64 var_index,
int64 card_index) {
525 Solver*
const s = solver();
526 undecided_.SetToZero(s, var_index, card_index);
527 max_.Decr(s, card_index);
528 if (max_[card_index] < card_min_[card_index]) {
531 if (max_[card_index] == card_min_[card_index]) {
535 void SetRevDoContribute(
int64 var_index,
int64 card_index) {
536 Solver*
const s = solver();
537 undecided_.SetToZero(s, var_index, card_index);
538 min_.Incr(s, card_index);
539 if (min_[card_index] > card_max_[card_index]) {
542 if (min_[card_index] == card_max_[card_index]) {
547 void Accept(ModelVisitor*
const visitor)
const override {
558 int64 var_size()
const {
return vars_.size(); }
559 int64 card_size()
const {
return values_.size(); }
561 const std::vector<IntVar*>
vars_;
562 const std::vector<int64> values_;
563 const std::vector<int64> card_min_;
564 const std::vector<int64> card_max_;
565 RevBitMatrix undecided_;
566 NumericalRevArray<int> min_;
567 NumericalRevArray<int> max_;
568 std::vector<IntVarIterator*>
holes_;
571 BoundedDistribute::BoundedDistribute(Solver*
const s,
572 const std::vector<IntVar*>& vars,
573 const std::vector<int64>& values,
574 const std::vector<int64>& card_min,
575 const std::vector<int64>& card_max)
581 undecided_(vars.size(), values.size()),
582 min_(values.size(), 0),
583 max_(values.size(), 0),
585 for (
int var_index = 0; var_index < var_size(); ++var_index) {
586 holes_[var_index] =
vars_[var_index]->MakeHoleIterator(
true);
590 std::string BoundedDistribute::DebugString()
const {
591 return absl::StrFormat(
592 "BoundedDistribute([%s], values = [%s], card_min = [%s], card_max = "
595 absl::StrJoin(card_min_,
", "), absl::StrJoin(card_max_,
", "));
598 void BoundedDistribute::Post() {
599 for (
int var_index = 0; var_index < var_size(); ++var_index) {
600 IntVar*
const var =
vars_[var_index];
603 solver(),
this, &BoundedDistribute::OneBound,
"OneBound", var_index);
606 "OneDomain", var_index);
612 void BoundedDistribute::InitialPropagate() {
613 Solver*
const s = solver();
615 int64 sum_card_min = 0;
616 for (
int i = 0; i < card_size(); ++i) {
617 if (card_max_[i] < card_min_[i]) {
620 sum_card_min += card_min_[i];
622 if (sum_card_min > var_size()) {
625 if (sum_card_min == var_size()) {
626 for (
int i = 0; i < var_size(); ++i) {
627 vars_[i]->SetValues(values_);
631 for (
int card_index = 0; card_index < card_size(); ++card_index) {
635 for (
int i = 0; i < var_size(); ++i) {
644 undecided_.
SetToOne(s, i, card_index);
647 min_.SetValue(s, card_index,
min);
648 max_.SetValue(s, card_index,
max);
649 CountVar(card_index);
653 void BoundedDistribute::OneBound(
int index) {
656 for (
int card_index = 0; card_index < card_size(); ++card_index) {
658 if (var_min == values_[card_index]) {
659 SetRevDoContribute(
index, card_index);
661 SetRevCannotContribute(
index, card_index);
667 void BoundedDistribute::OneDomain(
int index) {
669 for (
int card_index = 0; card_index < card_size(); ++card_index) {
672 SetRevCannotContribute(
index, card_index);
678 void BoundedDistribute::CountVar(
int card_index) {
679 const int64 stored_min = min_[card_index];
680 const int64 stored_max = max_[card_index];
681 if (card_min_[card_index] > stored_max ||
682 card_max_[card_index] < stored_min) {
685 if (card_min_[card_index] == stored_max) {
688 if (card_max_[card_index] == stored_min) {
693 void BoundedDistribute::CardMin(
int card_index) {
694 for (
int var_index = 0; var_index < var_size(); ++var_index) {
695 if (undecided_.
IsSet(var_index, card_index)) {
696 vars_[var_index]->RemoveValue(values_[card_index]);
701 void BoundedDistribute::CardMax(
int card_index) {
702 for (
int var_index = 0; var_index < var_size(); ++var_index) {
703 if (undecided_.
IsSet(var_index, card_index)) {
704 vars_[var_index]->SetValue(values_[card_index]);
711 class BoundedFastDistribute :
public Constraint {
713 BoundedFastDistribute(Solver*
const s,
const std::vector<IntVar*>& vars,
714 const std::vector<int64>& card_min,
715 const std::vector<int64>& card_max);
716 ~BoundedFastDistribute()
override {}
718 void Post()
override;
719 void InitialPropagate()
override;
720 void OneBound(
int index);
721 void OneDomain(
int index);
722 void CountVar(
int card_index);
723 void CardMin(
int card_index);
724 void CardMax(
int card_index);
725 std::string DebugString()
const override;
726 void SetRevCannotContribute(
int64 var_index,
int64 card_index) {
727 Solver*
const s = solver();
728 undecided_.SetToZero(s, var_index, card_index);
729 max_.Decr(s, card_index);
730 if (max_[card_index] < card_min_[card_index]) {
733 if (max_[card_index] == card_min_[card_index]) {
737 void SetRevDoContribute(
int64 var_index,
int64 card_index) {
738 Solver*
const s = solver();
739 undecided_.SetToZero(s, var_index, card_index);
740 min_.Incr(s, card_index);
741 if (min_[card_index] > card_max_[card_index]) {
744 if (min_[card_index] == card_max_[card_index]) {
749 void Accept(ModelVisitor*
const visitor)
const override {
759 int64 var_size()
const {
return vars_.size(); }
760 int64 card_size()
const {
return card_min_.size(); }
762 const std::vector<IntVar*>
vars_;
763 const std::vector<int64> card_min_;
764 const std::vector<int64> card_max_;
765 RevBitMatrix undecided_;
766 NumericalRevArray<int> min_;
767 NumericalRevArray<int> max_;
768 std::vector<IntVarIterator*>
holes_;
771 BoundedFastDistribute::BoundedFastDistribute(Solver*
const s,
772 const std::vector<IntVar*>& vars,
773 const std::vector<int64>& card_min,
774 const std::vector<int64>& card_max)
779 undecided_(vars.size(), card_min.size()),
780 min_(card_min.size(), 0),
781 max_(card_max.size(), 0),
783 for (
int var_index = 0; var_index < var_size(); ++var_index) {
784 holes_[var_index] =
vars_[var_index]->MakeHoleIterator(
true);
788 std::string BoundedFastDistribute::DebugString()
const {
789 return absl::StrFormat(
790 "BoundedFastDistribute([%s], card_min = [%s], card_max = [%s]",
792 absl::StrJoin(card_max_,
", "));
795 void BoundedFastDistribute::Post() {
796 for (
int var_index = 0; var_index < var_size(); ++var_index) {
797 IntVar*
const var =
vars_[var_index];
801 "OneBound", var_index);
804 &BoundedFastDistribute::OneDomain,
"OneDomain",
811 void BoundedFastDistribute::InitialPropagate() {
812 Solver*
const s = solver();
814 int64 sum_card_min = 0;
815 for (
int i = 0; i < card_size(); ++i) {
816 if (card_max_[i] < card_min_[i]) {
819 sum_card_min += card_min_[i];
821 if (sum_card_min > var_size()) {
824 if (sum_card_min == var_size()) {
825 for (
int i = 0; i < var_size(); ++i) {
826 vars_[i]->SetRange(0, card_size() - 1);
830 for (
int card_index = 0; card_index < card_size(); ++card_index) {
833 for (
int i = 0; i < var_size(); ++i) {
836 if (
var->
Min() == card_index) {
842 undecided_.
SetToOne(s, i, card_index);
845 min_.SetValue(s, card_index,
min);
846 max_.SetValue(s, card_index,
max);
847 CountVar(card_index);
851 void BoundedFastDistribute::OneBound(
int index) {
854 for (
int card_index = 0; card_index < card_size(); ++card_index) {
856 if (var_min == card_index) {
857 SetRevDoContribute(
index, card_index);
859 SetRevCannotContribute(
index, card_index);
865 void BoundedFastDistribute::OneDomain(
int index) {
872 card_index <
std::min(vmin, card_size()); ++card_index) {
874 SetRevCannotContribute(
index, card_index);
878 if (card_index >= 0 && card_index < card_size() &&
880 SetRevCannotContribute(
index, card_index);
884 card_index <=
std::min(oldmax, card_size() - 1); ++card_index) {
886 SetRevCannotContribute(
index, card_index);
891 void BoundedFastDistribute::CountVar(
int card_index) {
892 const int64 stored_min = min_[card_index];
893 const int64 stored_max = max_[card_index];
894 if (card_min_[card_index] > stored_max ||
895 card_max_[card_index] < stored_min) {
898 if (card_min_[card_index] == stored_max) {
901 if (card_max_[card_index] == stored_min) {
906 void BoundedFastDistribute::CardMin(
int card_index) {
907 for (
int var_index = 0; var_index < var_size(); ++var_index) {
908 if (undecided_.
IsSet(var_index, card_index)) {
909 vars_[var_index]->RemoveValue(card_index);
914 void BoundedFastDistribute::CardMax(
int card_index) {
915 for (
int var_index = 0; var_index < var_size(); ++var_index) {
916 if (undecided_.
IsSet(var_index, card_index)) {
917 vars_[var_index]->SetValue(card_index);
924 class SetAllToZero :
public Constraint {
926 SetAllToZero(Solver*
const s,
const std::vector<IntVar*>& vars)
927 : Constraint(s),
vars_(vars) {}
929 ~SetAllToZero()
override {}
931 void Post()
override {}
933 void InitialPropagate()
override {
934 for (
int i = 0; i <
vars_.size(); ++i) {
935 vars_[i]->SetValue(0);
939 std::string DebugString()
const override {
return "SetAllToZero()"; }
941 void Accept(ModelVisitor*
const visitor)
const override {
949 const std::vector<IntVar*>
vars_;
958 if (max_count >= vars.size()) {
961 return RevAlloc(
new AtMost(
this, std::move(vars),
value, max_count));
965 const std::vector<int64>& values,
966 const std::vector<IntVar*>& cards) {
968 return RevAlloc(
new SetAllToZero(
this, cards));
970 CHECK_EQ(values.size(), cards.size());
977 for (
int i = 0; i < values.size(); ++i) {
978 if (values[i] != i) {
983 for (
IntVar*
const card : cards) {
987 return RevAlloc(
new FastDistribute(
this, vars, cards));
989 return RevAlloc(
new Distribute(
this, vars, values, cards));
994 const std::vector<int>& values,
995 const std::vector<IntVar*>& cards) {
1000 const std::vector<IntVar*>& cards) {
1002 return RevAlloc(
new SetAllToZero(
this, cards));
1007 for (
IntVar*
const card : cards) {
1010 return RevAlloc(
new FastDistribute(
this, vars, cards));
1016 const int vsize = vars.size();
1021 if (card_min == 0 && card_max >= vsize) {
1023 }
else if (card_min > vsize || card_max < 0 || card_max < card_min) {
1026 std::vector<int64> mins(card_size, card_min);
1027 std::vector<int64> maxes(card_size, card_max);
1028 return RevAlloc(
new BoundedFastDistribute(
this, vars, mins, maxes));
1033 const std::vector<int64>& card_min,
1034 const std::vector<int64>& card_max) {
1035 const int vsize = vars.size();
1039 for (
int i = 0; i < card_max.size(); ++i) {
1040 cmax =
std::min(cmax, card_max[i]);
1041 cmin =
std::max(cmin, card_min[i]);
1043 if (cmax < 0 || cmin > vsize) {
1045 }
else if (cmax >= vsize && cmin == 0) {
1048 return RevAlloc(
new BoundedFastDistribute(
this, vars, card_min, card_max));
1053 const std::vector<int>& card_min,
1054 const std::vector<int>& card_max) {
1059 const std::vector<int64>& values,
1060 const std::vector<int64>& card_min,
1061 const std::vector<int64>& card_max) {
1063 CHECK_EQ(card_min.size(), values.size());
1064 CHECK_EQ(card_min.size(), card_max.size());
1071 new BoundedDistribute(
this, vars, values, card_min, card_max));
1076 const std::vector<int>& values,
1077 const std::vector<int>& card_min,
1078 const std::vector<int>& card_max) {