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());
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_;
149class 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_;
200void 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);
221void 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);
251void 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()) {
274void 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()) {
291void 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]) {
304void 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]);
312void 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]);
322class 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_;
376FastDistribute::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);
391std::string FastDistribute::DebugString()
const {
392 return absl::StrFormat(
"FastDistribute(vars = [%s], cards = [%s])",
397void 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);
418void 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);
439void 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);
452void 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);
478void 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) {
490void 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);
498void 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);
508class 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_;
571BoundedDistribute::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);
590std::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_,
", "));
598void 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);
612void 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);
653void 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);
667void BoundedDistribute::OneDomain(
int index) {
669 for (
int card_index = 0; card_index < card_size(); ++card_index) {
672 SetRevCannotContribute(
index, card_index);
678void 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) {
693void 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]);
701void 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]);
711class 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_;
771BoundedFastDistribute::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);
788std::string BoundedFastDistribute::DebugString()
const {
789 return absl::StrFormat(
790 "BoundedFastDistribute([%s], card_min = [%s], card_max = [%s]",
792 absl::StrJoin(card_max_,
", "));
795void 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",
811void 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);
851void 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);
865void 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);
891void 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) {
906void 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);
914void 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);
924class 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) {
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 Max() const =0
virtual int64 Min() const =0
The class IntVar is a subset of IntExpr.
virtual int64 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 bool Contains(int64 v) const =0
This method returns whether the value 'v' is in the domain of the variable.
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 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 Incr(Solver *const s)
bool IsSet(int64 row, int64 column) const
Returns whether the 'column' bit in the 'row' row is set.
void SetToOne(Solver *const solver, int64 row, int64 column)
Sets the 'column' bit in the 'row' row.
void SetToZero(Solver *const solver, int64 row, int64 column)
Erases the 'column' bit in the 'row' row.
Constraint * MakeFalseConstraint()
This constraint always fails.
IntVar * MakeIsEqualCstVar(IntExpr *const var, int64 value)
status var of (var == value)
Constraint * MakeTrueConstraint()
This constraint always succeeds.
Constraint * MakeDistribute(const std::vector< IntVar * > &vars, const std::vector< int64 > &values, const std::vector< IntVar * > &cards)
Aggregated version of count: |{i | v[i] == values[j]}| == cards[j].
Constraint * MakeAtMost(std::vector< IntVar * > vars, int64 value, int64 max_count)
|{i | vars[i] == value}| <= max_count
Constraint * MakeSumEquality(const std::vector< IntVar * > &vars, int64 cst)
Constraint * MakeCount(const std::vector< IntVar * > &vars, int64 value, int64 max_count)
|{i | vars[i] == value}| == max_count
Constraint * MakeAllDifferent(const std::vector< IntVar * > &vars)
All variables are pairwise different.
IntExpr * MakeSum(IntExpr *const left, IntExpr *const right)
left + right.
T * RevAlloc(T *object)
Registers the given object as being reversible.
std::vector< IntVarIterator * > holes_
static const int64 kint64max
static const int64 kint64min
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
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 IsIncreasingContiguous(const std::vector< T > &values)
std::string JoinDebugStringPtr(const std::vector< T > &v, const std::string &separator)
std::vector< int64 > ToInt64Vector(const std::vector< int > &input)
bool AreAllOnes(const std::vector< T > &values)