Google OR-Tools: ortools/constraint_solver/count_cst.cc Source File
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) {
49 if (max_count->Bound()) {
50 return MakeCount(vars, value, max_count->Min());
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)) {
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)),
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_) {
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_;
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()),
167 void InitialPropagate() override;
169 void OneDomain(int index);
170 void CountVar(int cindex);
173 std::string DebugString() const override {
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_;
198 NumericalRevArray<int> min_;
199 NumericalRevArray<int> max_;
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])) {
238 undecided_.SetToOne(s, i, j);
242 cards_[j]->SetRange(min, max);
243 if (cards_[j]->Max() == min) {
245 } else if (cards_[j]->Min() == 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)) {
258 undecided_.SetToZero(s, 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])) {
282 undecided_.SetToZero(s, index, 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 {}
331 void InitialPropagate() override;
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);
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);
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_;
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()),
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];
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);
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 {}
519 void InitialPropagate() override;
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);
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);
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_;
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()),
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 {
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);
614void BoundedDistribute::InitialPropagate() {
615 Solver* const s = solver();
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);
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 {}
721 void InitialPropagate() override;
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);
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);
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_;
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()),
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 {
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];
805 &BoundedFastDistribute::OneDomain, "OneDomain",
812void BoundedFastDistribute::InitialPropagate() {
813 Solver* const s = solver();
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);
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 {}
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_;
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) {
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));
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,
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));
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());
1068 IsArrayInRange(vars, values.front(), values.back())) {
1072 new BoundedDistribute(this, vars, values, card_min, card_max));
1077 const std::vector<int>& values,
1078 const std::vector<int>& card_min,
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].
Definition count_cst.cc:965
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
Definition count_cst.cc:956
Constraint * MakeCount(const std::vector< IntVar * > &vars, int64_t value, int64_t max_count)
|{i | vars[i] == value}| == max_count
Definition count_cst.cc:32
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)