24#include "absl/strings/str_format.h"
25#include "absl/strings/str_join.h"
35 std::vector<IntVar*> tmp_sum;
36 for (
int i = 0; i < vars.size(); ++i) {
37 if (vars[i]->Contains(
value)) {
38 if (vars[i]->Bound()) {
50 if (max_count->
Bound()) {
53 std::vector<IntVar*> tmp_sum;
54 int64_t num_vars_bound_to_v = 0;
55 for (
int i = 0; i < vars.size(); ++i) {
56 if (vars[i]->Contains(
value)) {
57 if (vars[i]->Bound()) {
58 ++num_vars_bound_to_v;
65 MakeSum(max_count, -num_vars_bound_to_v)->Var());
74 AtMost(
Solver*
const s, std::vector<IntVar*> vars, int64_t
value,
79 max_count_(max_count),
84 void Post()
override {
85 for (IntVar*
var : vars_) {
86 if (!
var->Bound() &&
var->Contains(value_)) {
94 void InitialPropagate()
override {
95 for (IntVar*
var : vars_) {
96 if (
var->Bound() &&
var->Min() == value_) {
97 current_count_.Incr(solver());
103 void OneBound(IntVar*
var) {
104 if (
var->Min() == value_) {
105 current_count_.Incr(solver());
111 if (current_count_.Value() < max_count_) {
117 for (IntVar*
var : vars_) {
119 if (
var->Min() == value_) {
123 var->RemoveValue(value_);
126 if (forced > max_count_) {
131 std::string DebugString()
const override {
132 return absl::StrFormat(
"AtMost(%s, %d, %d)",
136 void Accept(ModelVisitor*
const visitor)
const override {
146 const std::vector<IntVar*>
vars_;
147 const int64_t value_;
148 const int64_t max_count_;
149 NumericalRev<int> current_count_;
152class Distribute :
public Constraint {
154 Distribute(Solver*
const s,
const std::vector<IntVar*>& vars,
155 const std::vector<int64_t>& values,
156 const std::vector<IntVar*>& cards)
161 undecided_(vars.
size(), cards.
size()),
162 min_(cards.
size(), 0),
163 max_(cards.
size(), 0) {}
165 ~Distribute()
override {}
167 void Post()
override;
168 void InitialPropagate()
override;
169 void OneBound(
int index);
170 void OneDomain(
int index);
171 void CountVar(
int cindex);
172 void CardMin(
int cindex);
173 void CardMax(
int cindex);
174 std::string DebugString()
const override {
175 return absl::StrFormat(
176 "Distribute(vars = [%s], values = [%s], cards = [%s])",
181 void Accept(ModelVisitor*
const visitor)
const override {
192 int64_t var_size()
const {
return vars_.size(); }
193 int64_t card_size()
const {
return cards_.size(); }
195 const std::vector<IntVar*>
vars_;
196 const std::vector<int64_t> values_;
197 const std::vector<IntVar*> cards_;
198 RevBitMatrix undecided_;
199 NumericalRevArray<int> min_;
200 NumericalRevArray<int> max_;
203void Distribute::Post() {
204 for (
int i = 0;
i < var_size(); ++
i) {
215 for (
int i = 0;
i < card_size(); ++
i) {
216 if (!cards_[i]->Bound()) {
219 cards_[
i]->WhenRange(d);
224void Distribute::InitialPropagate() {
225 Solver*
const s = solver();
226 for (
int j = 0; j < card_size(); ++j) {
229 for (
int i = 0;
i < var_size(); ++
i) {
232 if (
var->Min() == values_[j]) {
237 if (
var->Contains(values_[j])) {
243 cards_[j]->SetRange(
min,
max);
244 if (cards_[j]->Max() ==
min) {
246 }
else if (cards_[j]->Min() ==
max) {
249 min_.SetValue(s, j,
min);
250 max_.SetValue(s, j,
max);
254void Distribute::OneBound(
int index) {
256 Solver*
const s = solver();
257 for (
int j = 0; j < card_size(); ++j) {
260 if (
var->Min() == values_[j]) {
262 cards_[j]->SetMin(min_[j]);
263 if (min_[j] == cards_[j]->Max()) {
268 cards_[j]->SetMax(max_[j]);
269 if (max_[j] == cards_[j]->Min()) {
277void Distribute::OneDomain(
int index) {
279 Solver*
const s = solver();
280 for (
int j = 0; j < card_size(); ++j) {
282 if (!
var->Contains(values_[j])) {
285 cards_[j]->SetMax(max_[j]);
286 if (max_[j] == cards_[j]->Min()) {
294void Distribute::CountVar(
int cindex) {
295 if (cards_[cindex]->Min() > max_[cindex] ||
296 cards_[cindex]->Max() < min_[cindex]) {
299 if (cards_[cindex]->Min() == max_[cindex]) {
302 if (cards_[cindex]->Max() == min_[cindex]) {
307void Distribute::CardMin(
int cindex) {
308 for (
int i = 0;
i < var_size(); ++
i) {
309 if (undecided_.
IsSet(i, cindex)) {
310 vars_[
i]->RemoveValue(values_[cindex]);
315void Distribute::CardMax(
int cindex) {
316 for (
int i = 0;
i < var_size(); ++
i) {
317 if (undecided_.
IsSet(i, cindex)) {
318 vars_[
i]->SetValue(values_[cindex]);
325class FastDistribute :
public Constraint {
327 FastDistribute(Solver* s,
const std::vector<IntVar*>& vars,
328 const std::vector<IntVar*>& cards);
329 ~FastDistribute()
override {}
331 void Post()
override;
332 void InitialPropagate()
override;
333 void OneBound(
int index);
334 void OneDomain(
int index);
335 void CountVar(
int card_index);
336 void CardMin(
int card_index);
337 void CardMax(
int card_index);
338 std::string DebugString()
const override;
339 void SetRevCannotContribute(int64_t
var_index, int64_t card_index) {
340 Solver*
const s = solver();
342 max_.Decr(s, card_index);
343 cards_[card_index]->SetMax(max_[card_index]);
344 if (max_[card_index] == cards_[card_index]->Min()) {
348 void SetRevDoContribute(int64_t
var_index, int64_t card_index) {
349 Solver*
const s = solver();
351 min_.Incr(s, card_index);
352 cards_[card_index]->SetMin(min_[card_index]);
353 if (min_[card_index] == cards_[card_index]->Max()) {
358 void Accept(ModelVisitor*
const visitor)
const override {
359 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
360 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
362 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
364 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
368 int64_t var_size()
const {
return vars_.size(); }
369 int64_t card_size()
const {
return cards_.size(); }
371 const std::vector<IntVar*>
vars_;
372 const std::vector<IntVar*> cards_;
373 RevBitMatrix undecided_;
374 NumericalRevArray<int> min_;
375 NumericalRevArray<int> max_;
376 std::vector<IntVarIterator*> holes_;
379FastDistribute::FastDistribute(Solver*
const s,
380 const std::vector<IntVar*>& vars,
381 const std::vector<IntVar*>& cards)
385 undecided_(vars.
size(), cards.
size()),
386 min_(cards.
size(), 0),
387 max_(cards.
size(), 0),
388 holes_(vars.
size()) {
394std::string FastDistribute::DebugString()
const {
395 return absl::StrFormat(
"FastDistribute(vars = [%s], cards = [%s])",
400void FastDistribute::Post() {
412 for (
int card_index = 0; card_index < card_size(); ++card_index) {
413 if (!cards_[card_index]->Bound()) {
416 cards_[card_index]->WhenRange(d);
421void FastDistribute::InitialPropagate() {
422 Solver*
const s = solver();
423 for (
int card_index = 0; card_index < card_size(); ++card_index) {
428 if (
var->Bound() &&
var->Min() == card_index) {
431 }
else if (
var->Contains(card_index)) {
436 min_.SetValue(s, card_index,
min);
437 max_.SetValue(s, card_index,
max);
438 CountVar(card_index);
442void FastDistribute::OneBound(
int index) {
444 for (
int card_index = 0; card_index < card_size(); ++card_index) {
446 if (
var->Min() == card_index) {
447 SetRevDoContribute(
index, card_index);
449 SetRevCannotContribute(
index, card_index);
455void FastDistribute::OneDomain(
int index) {
457 const int64_t oldmin =
var->OldMin();
458 const int64_t oldmax =
var->OldMax();
459 const int64_t vmin =
var->Min();
460 const int64_t vmax =
var->Max();
461 for (int64_t card_index = std::max(oldmin, int64_t{0});
462 card_index < std::min(vmin, card_size()); ++card_index) {
464 SetRevCannotContribute(
index, card_index);
467 for (
const int64_t card_index : InitAndGetValues(holes_[
index])) {
468 if (card_index >= 0 && card_index < card_size() &&
470 SetRevCannotContribute(
index, card_index);
473 for (int64_t card_index = std::max(vmax + 1, int64_t{0});
474 card_index <= std::min(oldmax, card_size() - 1); ++card_index) {
476 SetRevCannotContribute(
index, card_index);
481void FastDistribute::CountVar(
int card_index) {
482 const int64_t stored_min = min_[card_index];
483 const int64_t stored_max = max_[card_index];
484 cards_[card_index]->SetRange(min_[card_index], max_[card_index]);
485 if (cards_[card_index]->Min() == stored_max) {
488 if (cards_[card_index]->Max() == stored_min) {
493void FastDistribute::CardMin(
int card_index) {
501void FastDistribute::CardMax(
int card_index) {
511class BoundedDistribute :
public Constraint {
513 BoundedDistribute(Solver* s,
const std::vector<IntVar*>& vars,
514 const std::vector<int64_t>& values,
515 const std::vector<int64_t>& card_min,
516 const std::vector<int64_t>& card_max);
517 ~BoundedDistribute()
override {}
519 void Post()
override;
520 void InitialPropagate()
override;
521 void OneBound(
int index);
522 void OneDomain(
int index);
523 void CountVar(
int card_index);
524 void CardMin(
int card_index);
525 void CardMax(
int card_index);
526 std::string DebugString()
const override;
527 void SetRevCannotContribute(int64_t
var_index, int64_t card_index) {
528 Solver*
const s = solver();
530 max_.Decr(s, card_index);
531 if (max_[card_index] < card_min_[card_index]) {
534 if (max_[card_index] == card_min_[card_index]) {
538 void SetRevDoContribute(int64_t
var_index, int64_t card_index) {
539 Solver*
const s = solver();
541 min_.Incr(s, card_index);
542 if (min_[card_index] > card_max_[card_index]) {
545 if (min_[card_index] == card_max_[card_index]) {
550 void Accept(ModelVisitor*
const visitor)
const override {
551 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
552 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
554 visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument, values_);
555 visitor->VisitIntegerArrayArgument(ModelVisitor::kMinArgument, card_min_);
556 visitor->VisitIntegerArrayArgument(ModelVisitor::kMaxArgument, card_max_);
557 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
561 int64_t var_size()
const {
return vars_.size(); }
562 int64_t card_size()
const {
return values_.size(); }
564 const std::vector<IntVar*>
vars_;
565 const std::vector<int64_t> values_;
566 const std::vector<int64_t> card_min_;
567 const std::vector<int64_t> card_max_;
568 RevBitMatrix undecided_;
569 NumericalRevArray<int> min_;
570 NumericalRevArray<int> max_;
571 std::vector<IntVarIterator*> holes_;
574BoundedDistribute::BoundedDistribute(Solver*
const s,
575 const std::vector<IntVar*>& vars,
576 const std::vector<int64_t>& values,
577 const std::vector<int64_t>& card_min,
578 const std::vector<int64_t>& card_max)
584 undecided_(vars.
size(), values.
size()),
585 min_(values.
size(), 0),
586 max_(values.
size(), 0),
587 holes_(vars.
size()) {
593std::string BoundedDistribute::DebugString()
const {
594 return absl::StrFormat(
595 "BoundedDistribute([%s], values = [%s], card_min = [%s], card_max = "
598 absl::StrJoin(card_min_,
", "), absl::StrJoin(card_max_,
", "));
601void BoundedDistribute::Post() {
606 solver(),
this, &BoundedDistribute::OneBound,
"OneBound",
var_index);
615void BoundedDistribute::InitialPropagate() {
616 Solver*
const s = solver();
618 int64_t sum_card_min = 0;
619 for (
int i = 0;
i < card_size(); ++
i) {
620 if (card_max_[i] < card_min_[i]) {
623 sum_card_min += card_min_[
i];
625 if (sum_card_min > var_size()) {
628 if (sum_card_min == var_size()) {
629 for (
int i = 0;
i < var_size(); ++
i) {
630 vars_[
i]->SetValues(values_);
634 for (
int card_index = 0; card_index < card_size(); ++card_index) {
635 const int64_t
value = values_[card_index];
638 for (
int i = 0;
i < var_size(); ++
i) {
647 undecided_.
SetToOne(s, i, card_index);
650 min_.SetValue(s, card_index,
min);
651 max_.SetValue(s, card_index,
max);
652 CountVar(card_index);
656void BoundedDistribute::OneBound(
int index) {
658 const int64_t var_min =
var->Min();
659 for (
int card_index = 0; card_index < card_size(); ++card_index) {
661 if (var_min == values_[card_index]) {
662 SetRevDoContribute(
index, card_index);
664 SetRevCannotContribute(
index, card_index);
670void BoundedDistribute::OneDomain(
int index) {
672 for (
int card_index = 0; card_index < card_size(); ++card_index) {
674 if (!
var->Contains(values_[card_index])) {
675 SetRevCannotContribute(
index, card_index);
681void BoundedDistribute::CountVar(
int card_index) {
682 const int64_t stored_min = min_[card_index];
683 const int64_t stored_max = max_[card_index];
684 if (card_min_[card_index] > stored_max ||
685 card_max_[card_index] < stored_min) {
688 if (card_min_[card_index] == stored_max) {
691 if (card_max_[card_index] == stored_min) {
696void BoundedDistribute::CardMin(
int card_index) {
704void BoundedDistribute::CardMax(
int card_index) {
714class BoundedFastDistribute :
public Constraint {
716 BoundedFastDistribute(Solver* s,
const std::vector<IntVar*>& vars,
717 const std::vector<int64_t>& card_min,
718 const std::vector<int64_t>& card_max);
719 ~BoundedFastDistribute()
override {}
721 void Post()
override;
722 void InitialPropagate()
override;
723 void OneBound(
int index);
724 void OneDomain(
int index);
725 void CountVar(
int card_index);
726 void CardMin(
int card_index);
727 void CardMax(
int card_index);
728 std::string DebugString()
const override;
729 void SetRevCannotContribute(int64_t
var_index, int64_t card_index) {
730 Solver*
const s = solver();
732 max_.Decr(s, card_index);
733 if (max_[card_index] < card_min_[card_index]) {
736 if (max_[card_index] == card_min_[card_index]) {
740 void SetRevDoContribute(int64_t
var_index, int64_t card_index) {
741 Solver*
const s = solver();
743 min_.Incr(s, card_index);
744 if (min_[card_index] > card_max_[card_index]) {
747 if (min_[card_index] == card_max_[card_index]) {
752 void Accept(ModelVisitor*
const visitor)
const override {
753 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
754 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
756 visitor->VisitIntegerArrayArgument(ModelVisitor::kMinArgument, card_min_);
757 visitor->VisitIntegerArrayArgument(ModelVisitor::kMaxArgument, card_max_);
758 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
762 int64_t var_size()
const {
return vars_.size(); }
763 int64_t card_size()
const {
return card_min_.size(); }
765 const std::vector<IntVar*>
vars_;
766 const std::vector<int64_t> card_min_;
767 const std::vector<int64_t> card_max_;
768 RevBitMatrix undecided_;
769 NumericalRevArray<int> min_;
770 NumericalRevArray<int> max_;
771 std::vector<IntVarIterator*> holes_;
774BoundedFastDistribute::BoundedFastDistribute(
775 Solver*
const s,
const std::vector<IntVar*>& vars,
776 const std::vector<int64_t>& card_min,
const std::vector<int64_t>& card_max)
781 undecided_(vars.
size(), card_min.
size()),
782 min_(card_min.
size(), 0),
783 max_(card_max.
size(), 0),
784 holes_(vars.
size()) {
790std::string BoundedFastDistribute::DebugString()
const {
791 return absl::StrFormat(
792 "BoundedFastDistribute([%s], card_min = [%s], card_max = [%s]",
794 absl::StrJoin(card_max_,
", "));
797void BoundedFastDistribute::Post() {
806 &BoundedFastDistribute::OneDomain,
"OneDomain",
813void BoundedFastDistribute::InitialPropagate() {
814 Solver*
const s = solver();
816 int64_t sum_card_min = 0;
817 for (
int i = 0;
i < card_size(); ++
i) {
818 if (card_max_[i] < card_min_[i]) {
821 sum_card_min += card_min_[
i];
823 if (sum_card_min > var_size()) {
826 if (sum_card_min == var_size()) {
827 for (
int i = 0;
i < var_size(); ++
i) {
828 vars_[
i]->SetRange(0, card_size() - 1);
832 for (
int card_index = 0; card_index < card_size(); ++card_index) {
835 for (
int i = 0;
i < var_size(); ++
i) {
838 if (
var->Min() == card_index) {
842 }
else if (
var->Contains(card_index)) {
844 undecided_.
SetToOne(s, i, card_index);
847 min_.SetValue(s, card_index,
min);
848 max_.SetValue(s, card_index,
max);
849 CountVar(card_index);
853void BoundedFastDistribute::OneBound(
int index) {
855 const int64_t var_min =
var->Min();
856 for (
int card_index = 0; card_index < card_size(); ++card_index) {
858 if (var_min == card_index) {
859 SetRevDoContribute(
index, card_index);
861 SetRevCannotContribute(
index, card_index);
867void BoundedFastDistribute::OneDomain(
int index) {
869 const int64_t oldmin =
var->OldMin();
870 const int64_t oldmax =
var->OldMax();
871 const int64_t vmin =
var->Min();
872 const int64_t vmax =
var->Max();
873 for (int64_t card_index = std::max(oldmin, int64_t{0});
874 card_index < std::min(vmin, card_size()); ++card_index) {
876 SetRevCannotContribute(
index, card_index);
879 for (
const int64_t card_index : InitAndGetValues(holes_[
index])) {
880 if (card_index >= 0 && card_index < card_size() &&
882 SetRevCannotContribute(
index, card_index);
885 for (int64_t card_index = std::max(vmax + 1, int64_t{0});
886 card_index <= std::min(oldmax, card_size() - 1); ++card_index) {
888 SetRevCannotContribute(
index, card_index);
893void BoundedFastDistribute::CountVar(
int card_index) {
894 const int64_t stored_min = min_[card_index];
895 const int64_t stored_max = max_[card_index];
896 if (card_min_[card_index] > stored_max ||
897 card_max_[card_index] < stored_min) {
900 if (card_min_[card_index] == stored_max) {
903 if (card_max_[card_index] == stored_min) {
908void BoundedFastDistribute::CardMin(
int card_index) {
916void BoundedFastDistribute::CardMax(
int card_index) {
926class SetAllToZero :
public Constraint {
928 SetAllToZero(Solver*
const s,
const std::vector<IntVar*>& vars)
929 : Constraint(s),
vars_(vars) {}
931 ~SetAllToZero()
override {}
933 void Post()
override {}
935 void InitialPropagate()
override {
936 for (
int i = 0;
i <
vars_.size(); ++
i) {
941 std::string DebugString()
const override {
return "SetAllToZero()"; }
943 void Accept(ModelVisitor*
const visitor)
const override {
944 visitor->BeginVisitConstraint(ModelVisitor::kDistribute,
this);
945 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kCardsArgument,
947 visitor->EndVisitConstraint(ModelVisitor::kDistribute,
this);
951 const std::vector<IntVar*>
vars_;
959 CHECK_GE(max_count, 0);
960 if (max_count >= vars.size()) {
961 return MakeTrueConstraint();
963 return RevAlloc(
new AtMost(
this, std::move(vars),
value, max_count));
967 const std::vector<int64_t>& values,
968 const std::vector<IntVar*>& cards) {
970 return RevAlloc(
new SetAllToZero(
this, cards));
972 CHECK_EQ(values.size(), cards.size());
974 CHECK_EQ(
this,
var->solver());
979 for (
int i = 0; i < values.size(); ++i) {
980 if (values[i] != i) {
985 for (
IntVar*
const card : cards) {
986 CHECK_EQ(
this, card->solver());
989 return RevAlloc(
new FastDistribute(
this, vars, cards));
991 return RevAlloc(
new Distribute(
this, vars, values, cards));
996 const std::vector<int>& values,
997 const std::vector<IntVar*>& cards) {
1002 const std::vector<IntVar*>& cards) {
1004 return RevAlloc(
new SetAllToZero(
this, cards));
1007 CHECK_EQ(
this,
var->solver());
1009 for (
IntVar*
const card : cards) {
1010 CHECK_EQ(
this, card->solver());
1012 return RevAlloc(
new FastDistribute(
this, vars, cards));
1016 int64_t card_min, int64_t card_max,
1017 int64_t card_size) {
1018 const int vsize = vars.size();
1021 CHECK_EQ(
this,
var->solver());
1023 if (card_min == 0 && card_max >= vsize) {
1024 return MakeTrueConstraint();
1025 }
else if (card_min > vsize || card_max < 0 || card_max < card_min) {
1026 return MakeFalseConstraint();
1028 std::vector<int64_t> mins(card_size, card_min);
1029 std::vector<int64_t> maxes(card_size, card_max);
1030 return RevAlloc(
new BoundedFastDistribute(
this, vars, mins, maxes));
1035 const std::vector<int64_t>& card_min,
1036 const std::vector<int64_t>& card_max) {
1037 const int vsize = vars.size();
1039 int64_t cmax = std::numeric_limits<int64_t>::max();
1040 int64_t cmin = std::numeric_limits<int64_t>::min();
1041 for (
int i = 0; i < card_max.size(); ++i) {
1042 cmax = std::min(cmax, card_max[i]);
1043 cmin = std::max(cmin, card_min[i]);
1045 if (cmax < 0 || cmin > vsize) {
1046 return MakeFalseConstraint();
1047 }
else if (cmax >= vsize && cmin == 0) {
1048 return MakeTrueConstraint();
1050 return RevAlloc(
new BoundedFastDistribute(
this, vars, card_min, card_max));
1055 const std::vector<int>& card_min,
1056 const std::vector<int>& card_max) {
1061 const std::vector<int64_t>& values,
1062 const std::vector<int64_t>& card_min,
1063 const std::vector<int64_t>& card_max) {
1064 CHECK_NE(vars.size(), 0);
1065 CHECK_EQ(card_min.size(), values.size());
1066 CHECK_EQ(card_min.size(), card_max.size());
1070 return MakeAllDifferent(vars);
1073 new BoundedDistribute(
this, vars, values, card_min, card_max));
1078 const std::vector<int>& values,
1079 const std::vector<int>& card_min,
1080 const std::vector<int>& card_max) {
const std::vector< IntVar * > vars_
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.
For the time being, Solver is neither MT_SAFE nor MT_HOT.
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)
--— Integer Expressions --—
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
In SWIG mode, we don't want anything besides these top-level includes.
std::string JoinDebugStringPtr(const std::vector< T > &v, absl::string_view separator)
Join v[i]->DebugString().
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
--— Vector manipulations --—
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)