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,
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_;
151class Distribute :
public Constraint {
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) {
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) {
231 if (
var->
Min() == 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) {
255 Solver*
const s = solver();
256 for (
int j = 0; j < card_size(); ++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) {
278 Solver*
const s = solver();
279 for (
int j = 0; j < card_size(); ++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*
const 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 {
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),
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];
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) {
443 for (
int card_index = 0; card_index < card_size(); ++card_index) {
445 if (
var->
Min() == card_index) {
446 SetRevDoContribute(
index, card_index);
448 SetRevCannotContribute(
index, card_index);
454void FastDistribute::OneDomain(
int index) {
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) {
463 SetRevCannotContribute(
index, card_index);
466 for (
const int64_t card_index : InitAndGetValues(
holes_[
index])) {
467 if (card_index >= 0 && card_index < card_size() &&
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) {
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*
const 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 {
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),
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) {
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) {
657 const int64_t var_min =
var->
Min();
658 for (
int card_index = 0; card_index < card_size(); ++card_index) {
660 if (var_min == values_[card_index]) {
661 SetRevDoContribute(
index, card_index);
663 SetRevCannotContribute(
index, card_index);
669void BoundedDistribute::OneDomain(
int index) {
671 for (
int card_index = 0; card_index < card_size(); ++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*
const 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 {
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),
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) {
837 if (
var->
Min() == 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) {
854 const int64_t var_min =
var->
Min();
855 for (
int card_index = 0; card_index < card_size(); ++card_index) {
857 if (var_min == card_index) {
858 SetRevDoContribute(
index, card_index);
860 SetRevCannotContribute(
index, card_index);
866void BoundedFastDistribute::OneDomain(
int index) {
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) {
875 SetRevCannotContribute(
index, card_index);
878 for (
const int64_t card_index : InitAndGetValues(
holes_[
index])) {
879 if (card_index >= 0 && card_index < card_size() &&
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) {
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 {
950 const std::vector<IntVar*>
vars_;
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());
978 for (
int i = 0; i < values.size(); ++i) {
979 if (values[i] != i) {
984 for (
IntVar*
const card : cards) {
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));
1008 for (
IntVar*
const card : cards) {
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();
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();
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) {
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) {
const std::vector< IntVar * > vars_
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
A constraint is the main modeling object.
virtual bool Bound() const
Returns true if the min and the max of the expression are equal.
virtual int64_t Min() const =0
virtual int64_t Max() const =0
The class IntVar is a subset of IntExpr.
virtual bool Contains(int64_t v) const =0
This method returns whether the value 'v' is in the domain of the variable.
virtual int64_t OldMax() const =0
Returns the previous max.
virtual void WhenBound(Demon *d)=0
This method attaches a demon that will be awakened when the variable is bound.
virtual void WhenDomain(Demon *d)=0
This method attaches a demon that will watch any domain modification of the domain of the variable.
virtual int64_t OldMin() const =0
Returns the previous min.
static const char kMinArgument[]
static const char kAtMost[]
static const char kMaxArgument[]
static const char kValueArgument[]
static const char kCountArgument[]
static const char kVarsArgument[]
static const char kDistribute[]
static const char kCardsArgument[]
static const char kValuesArgument[]
void SetToZero(Solver *const solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
bool IsSet(int64_t row, int64_t column) const
Returns whether the 'column' bit in the 'row' row is set.
void SetToOne(Solver *const solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Constraint * MakeCount(const std::vector< IntVar * > &vars, int64_t value, int64_t max_count)
|{i | vars[i] == value}| == max_count
Constraint * MakeSumEquality(const std::vector< IntVar * > &vars, int64_t cst)
Constraint * MakeFalseConstraint()
This constraint always fails.
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 * MakeTrueConstraint()
This constraint always succeeds.
Constraint * MakeAllDifferent(const std::vector< IntVar * > &vars)
All variables are pairwise different.
IntExpr * MakeSum(IntExpr *const left, IntExpr *const right)
left + right.
IntVar * MakeIsEqualCstVar(IntExpr *const var, int64_t value)
status var of (var == value)
Constraint * MakeAtMost(std::vector< IntVar * > vars, int64_t value, int64_t max_count)
|{i | vars[i] == value}| <= max_count
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.
std::string JoinDebugStringPtr(const std::vector< T > &v, const std::string &separator)
bool IsIncreasingContiguous(const std::vector< T > &values)
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
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)