39 const std::function<int64_t(
Variable*)>& evaluator) {
45 return evaluator(arg.
Var());
48 LOG(FATAL) <<
"Cannot evaluate " << arg.
DebugString();
58int64_t EvalAt(
const Argument& arg,
int pos,
59 const std::function<int64_t(
Variable*)>& evaluator) {
65 return evaluator(arg.
VarAt(pos));
68 LOG(FATAL) <<
"Cannot evaluate " << arg.
DebugString();
77 const std::function<int64_t(
Variable*)>& evaluator) {
78 absl::flat_hash_set<int64_t> visited;
79 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
80 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
81 if (visited.contains(value)) {
84 visited.insert(value);
90bool CheckAlldifferentExcept0(
92 absl::flat_hash_set<int64_t> visited;
93 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
94 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
95 if (value != 0 && visited.contains(value)) {
98 visited.insert(value);
105 const std::function<int64_t(
Variable*)>& evaluator) {
106 const int64_t expected = Eval(ct.
arguments[0], evaluator);
108 for (
int i = 0; i < Size(ct.
arguments[1]); ++i) {
109 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
110 count += ct.
arguments[2].Contains(value);
113 return count == expected;
117 const std::function<int64_t(
Variable*)>& evaluator) {
120 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
121 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
122 result = std::min(result, value);
125 return result == Eval(ct.
arguments[1], evaluator);
129 const std::function<int64_t(
Variable*)>& evaluator) {
132 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
133 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
134 result = std::max(result, value);
137 return result == Eval(ct.
arguments[1], evaluator);
141 const std::function<int64_t(
Variable*)>& evaluator) {
144 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
145 result += EvalAt(ct.
arguments[0], i, evaluator);
148 return result % 2 == 1;
151bool CheckArrayIntElement(
const Constraint& ct,
152 const std::function<int64_t(
Variable*)>& evaluator) {
154 const int64_t shifted_index = Eval(ct.
arguments[0], evaluator) - 1;
155 const int64_t element = EvalAt(ct.
arguments[1], shifted_index, evaluator);
156 const int64_t target = Eval(ct.
arguments[2], evaluator);
157 return element == target;
160bool CheckArrayIntElementNonShifted(
162 CHECK_EQ(ct.
arguments[0].variables.size(), 1);
163 const int64_t index = Eval(ct.
arguments[0], evaluator);
164 const int64_t element = EvalAt(ct.
arguments[1], index, evaluator);
165 const int64_t target = Eval(ct.
arguments[2], evaluator);
166 return element == target;
169bool CheckArrayVarIntElement(
172 const int64_t shifted_index = Eval(ct.
arguments[0], evaluator) - 1;
173 const int64_t element = EvalAt(ct.
arguments[1], shifted_index, evaluator);
174 const int64_t target = Eval(ct.
arguments[2], evaluator);
175 return element == target;
178bool CheckOrtoolsArrayIntElement(
180 const int64_t min_index = ct.
arguments[1].values[0];
181 const int64_t index = Eval(ct.
arguments[0], evaluator) - min_index;
182 const int64_t element = EvalAt(ct.
arguments[2], index, evaluator);
183 const int64_t target = Eval(ct.
arguments[3], evaluator);
184 return element == target;
188 const std::function<int64_t(
Variable*)>& evaluator) {
189 const int64_t expected = Eval(ct.
arguments[0], evaluator);
190 const int64_t value = Eval(ct.
arguments[2], evaluator);
193 for (
int i = 0; i < Size(ct.
arguments[1]); ++i) {
194 count += EvalAt(ct.
arguments[1], i, evaluator) == value;
196 return count <= expected;
200 const std::function<int64_t(
Variable*)>& evaluator) {
201 const int64_t left = Eval(ct.
arguments[0], evaluator);
202 const int64_t right = Eval(ct.
arguments[1], evaluator);
203 const int64_t status = Eval(ct.
arguments[2], evaluator);
204 return status == std::min(left, right);
208 const std::function<int64_t(
Variable*)>& evaluator) {
212 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
213 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
214 result = std::max(result, value);
217 for (
int i = 0; i < Size(ct.
arguments[1]); ++i) {
218 const int64_t value = EvalAt(ct.
arguments[1], i, evaluator);
219 result = std::max(result, 1 - value);
226 const std::function<int64_t(
Variable*)>& evaluator) {
227 const int64_t left = Eval(ct.
arguments[0], evaluator);
228 const int64_t right = Eval(ct.
arguments[1], evaluator);
229 return left == 1 - right;
233 const std::function<int64_t(
Variable*)>& evaluator) {
234 const int64_t left = Eval(ct.
arguments[0], evaluator);
235 const int64_t right = Eval(ct.
arguments[1], evaluator);
236 const int64_t status = Eval(ct.
arguments[2], evaluator);
237 return status == std::max(left, right);
241 const std::function<int64_t(
Variable*)>& evaluator) {
242 const int64_t left = Eval(ct.
arguments[0], evaluator);
243 const int64_t right = Eval(ct.
arguments[1], evaluator);
244 const int64_t target = Eval(ct.
arguments[2], evaluator);
245 return target == (left + right == 1);
249 const std::function<int64_t(
Variable*)>& evaluator) {
253 absl::flat_hash_set<int64_t> visited;
255 for (
int i = 0; i < size; ++i) {
256 const int64_t next = EvalAt(ct.
arguments[0], current, evaluator) -
base;
257 visited.insert(next);
260 return visited.size() == size;
264 const std::function<int64_t(
Variable*)>& evaluator) {
266 const int64_t value = Eval(ct.
arguments[1], evaluator);
267 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
268 result += EvalAt(ct.
arguments[0], i, evaluator) == value;
274 const std::function<int64_t(
Variable*)>& evaluator) {
275 const int64_t count = ComputeCount(ct, evaluator);
276 const int64_t expected = Eval(ct.
arguments[2], evaluator);
277 return count == expected;
281 const std::function<int64_t(
Variable*)>& evaluator) {
282 const int64_t count = ComputeCount(ct, evaluator);
283 const int64_t expected = Eval(ct.
arguments[2], evaluator);
284 return count >= expected;
288 const std::function<int64_t(
Variable*)>& evaluator) {
289 const int64_t count = ComputeCount(ct, evaluator);
290 const int64_t expected = Eval(ct.
arguments[2], evaluator);
291 return count > expected;
295 const std::function<int64_t(
Variable*)>& evaluator) {
296 const int64_t count = ComputeCount(ct, evaluator);
297 const int64_t expected = Eval(ct.
arguments[2], evaluator);
298 return count <= expected;
302 const std::function<int64_t(
Variable*)>& evaluator) {
303 const int64_t count = ComputeCount(ct, evaluator);
304 const int64_t expected = Eval(ct.
arguments[2], evaluator);
305 return count < expected;
309 const std::function<int64_t(
Variable*)>& evaluator) {
310 const int64_t count = ComputeCount(ct, evaluator);
311 const int64_t expected = Eval(ct.
arguments[2], evaluator);
312 return count != expected;
316 const std::function<int64_t(
Variable*)>& evaluator) {
317 const int64_t count = ComputeCount(ct, evaluator);
318 const int64_t expected = Eval(ct.
arguments[2], evaluator);
319 const int64_t status = Eval(ct.
arguments[3], evaluator);
320 return status == (expected == count);
324 const std::function<int64_t(
Variable*)>& evaluator) {
326 const int64_t capacity = Eval(ct.
arguments[3], evaluator);
330 absl::flat_hash_map<int64_t, int64_t> usage;
331 for (
int i = 0; i < size; ++i) {
332 const int64_t start = EvalAt(ct.
arguments[0], i, evaluator);
333 const int64_t duration = EvalAt(ct.
arguments[1], i, evaluator);
334 const int64_t requirement = EvalAt(ct.
arguments[2], i, evaluator);
335 for (int64_t t = start; t < start + duration; ++t) {
336 usage[t] += requirement;
337 if (usage[t] > capacity) {
346 const std::function<int64_t(
Variable*)>& evaluator) {
348 const int64_t capacity = Eval(ct.
arguments[4], evaluator);
353 absl::flat_hash_map<int64_t, int64_t> usage;
354 for (
int i = 0; i < size; ++i) {
355 if (EvalAt(ct.
arguments[0], i, evaluator) == 0)
continue;
356 const int64_t start = EvalAt(ct.
arguments[1], i, evaluator);
357 const int64_t duration = EvalAt(ct.
arguments[2], i, evaluator);
358 const int64_t requirement = EvalAt(ct.
arguments[3], i, evaluator);
359 for (int64_t t = start; t < start + duration; ++t) {
360 usage[t] += requirement;
361 if (usage[t] > capacity) {
370 const std::function<int64_t(
Variable*)>& ) {
375 const std::function<int64_t(
Variable*)>& ) {
379bool CheckDiffnNonStrict(
381 const std::function<int64_t(
Variable*)>& ) {
385bool CheckDiffnNonStrictK(
387 const std::function<int64_t(
Variable*)>& ) {
392 const std::function<int64_t(
Variable*)>& evaluator) {
395 std::vector<std::pair<int64_t, int64_t>> start_durations_pairs;
396 start_durations_pairs.reserve(size);
397 for (
int i = 0; i + 1 < size; ++i) {
398 const int64_t duration = EvalAt(ct.
arguments[1], i, evaluator);
399 if (duration == 0)
continue;
400 const int64_t start = EvalAt(ct.
arguments[0], i, evaluator);
401 start_durations_pairs.push_back({start, duration});
403 std::sort(start_durations_pairs.begin(), start_durations_pairs.end());
404 int64_t previous_end = std::numeric_limits<int64_t>::min();
405 for (
const auto& pair : start_durations_pairs) {
406 if (pair.first < previous_end)
return false;
407 previous_end = pair.first + pair.second;
412bool CheckDisjunctiveStrict(
416 std::vector<std::pair<int64_t, int64_t>> start_durations_pairs;
417 start_durations_pairs.reserve(size);
418 for (
int i = 0; i + 1 < size; ++i) {
419 const int64_t start = EvalAt(ct.
arguments[0], i, evaluator);
420 const int64_t duration = EvalAt(ct.
arguments[1], i, evaluator);
421 start_durations_pairs.push_back({start, duration});
423 std::sort(start_durations_pairs.begin(), start_durations_pairs.end());
424 int64_t previous_end = std::numeric_limits<int64_t>::min();
425 for (
const auto& pair : start_durations_pairs) {
426 if (pair.first < previous_end)
return false;
427 previous_end = pair.first + pair.second;
432bool CheckDisjunctiveStrictOpt(
437 std::vector<std::pair<int64_t, int64_t>> start_durations_pairs;
438 start_durations_pairs.reserve(size);
439 for (
int i = 0; i + 1 < size; ++i) {
440 if (EvalAt(ct.
arguments[0], i, evaluator) == 0)
continue;
441 const int64_t start = EvalAt(ct.
arguments[1], i, evaluator);
442 const int64_t duration = EvalAt(ct.
arguments[2], i, evaluator);
443 start_durations_pairs.push_back({start, duration});
445 std::sort(start_durations_pairs.begin(), start_durations_pairs.end());
446 int64_t previous_end = std::numeric_limits<int64_t>::min();
447 for (
const auto& pair : start_durations_pairs) {
448 if (pair.first < previous_end)
return false;
449 previous_end = pair.first + pair.second;
454bool CheckFalseConstraint(
456 const std::function<int64_t(
Variable*)>& ) {
460std::vector<int64_t> ComputeGlobalCardinalityCards(
462 std::vector<int64_t> cards(Size(ct.
arguments[1]), 0);
463 absl::flat_hash_map<int64_t, int> positions;
464 for (
int i = 0; i < ct.
arguments[1].values.size(); ++i) {
465 const int64_t value = ct.
arguments[1].values[i];
466 CHECK(!positions.contains(value));
467 positions[value] = i;
469 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
470 const int value = EvalAt(ct.
arguments[0], i, evaluator);
471 if (positions.contains(value)) {
472 cards[positions[value]]++;
478bool CheckGlobalCardinality(
480 const std::vector<int64_t> cards =
481 ComputeGlobalCardinalityCards(ct, evaluator);
482 CHECK_EQ(cards.size(), Size(ct.
arguments[2]));
483 for (
int i = 0; i < Size(ct.
arguments[2]); ++i) {
484 const int64_t card = EvalAt(ct.
arguments[2], i, evaluator);
485 if (card != cards[i]) {
492bool CheckGlobalCardinalityClosed(
494 const std::vector<int64_t> cards =
495 ComputeGlobalCardinalityCards(ct, evaluator);
496 CHECK_EQ(cards.size(), Size(ct.
arguments[2]));
497 for (
int i = 0; i < Size(ct.
arguments[2]); ++i) {
498 const int64_t card = EvalAt(ct.
arguments[2], i, evaluator);
499 if (card != cards[i]) {
503 int64_t sum_of_cards = 0;
504 for (int64_t card : cards) {
505 sum_of_cards += card;
507 return sum_of_cards == Size(ct.
arguments[0]);
510bool CheckGlobalCardinalityLowUp(
512 const std::vector<int64_t> cards =
513 ComputeGlobalCardinalityCards(ct, evaluator);
514 CHECK_EQ(cards.size(), ct.
arguments[2].values.size());
515 CHECK_EQ(cards.size(), ct.
arguments[3].values.size());
516 for (
int i = 0; i < cards.size(); ++i) {
517 const int64_t card = cards[i];
525bool CheckGlobalCardinalityLowUpClosed(
527 const std::vector<int64_t> cards =
528 ComputeGlobalCardinalityCards(ct, evaluator);
529 CHECK_EQ(cards.size(), ct.
arguments[2].values.size());
530 CHECK_EQ(cards.size(), ct.
arguments[3].values.size());
531 for (
int i = 0; i < cards.size(); ++i) {
532 const int64_t card = cards[i];
537 int64_t sum_of_cards = 0;
538 for (int64_t card : cards) {
539 sum_of_cards += card;
541 return sum_of_cards == Size(ct.
arguments[0]);
544bool CheckGlobalCardinalityOld(
547 std::vector<int64_t> cards(size, 0);
548 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
549 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator);
550 if (value >= 0 && value < size) {
554 for (
int i = 0; i < size; ++i) {
555 const int64_t card = EvalAt(ct.
arguments[1], i, evaluator);
556 if (card != cards[i]) {
564 const std::function<int64_t(
Variable*)>& evaluator) {
565 const int64_t left = Eval(ct.
arguments[0], evaluator);
566 const int64_t right = Eval(ct.
arguments[1], evaluator);
567 return std::abs(left) == right;
571 const std::function<int64_t(
Variable*)>& evaluator) {
572 const int64_t left = Eval(ct.
arguments[0], evaluator);
573 const int64_t right = Eval(ct.
arguments[1], evaluator);
574 const int64_t target = Eval(ct.
arguments[2], evaluator);
575 return target == left / right;
579 const std::function<int64_t(
Variable*)>& evaluator) {
580 const int64_t left = Eval(ct.
arguments[0], evaluator);
581 const int64_t right = Eval(ct.
arguments[1], evaluator);
582 return left == right;
586 const std::function<int64_t(
Variable*)>& evaluator) {
587 const int64_t left = Eval(ct.
arguments[0], evaluator);
588 const int64_t right = Eval(ct.
arguments[1], evaluator);
589 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
590 return (status && (left == right)) || !status;
594 const std::function<int64_t(
Variable*)>& evaluator) {
595 const int64_t left = Eval(ct.
arguments[0], evaluator);
596 const int64_t right = Eval(ct.
arguments[1], evaluator);
597 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
598 return status == (left == right);
602 const std::function<int64_t(
Variable*)>& evaluator) {
603 const int64_t left = Eval(ct.
arguments[0], evaluator);
604 const int64_t right = Eval(ct.
arguments[1], evaluator);
605 return left >= right;
609 const std::function<int64_t(
Variable*)>& evaluator) {
610 const int64_t left = Eval(ct.
arguments[0], evaluator);
611 const int64_t right = Eval(ct.
arguments[1], evaluator);
612 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
613 return (status && (left >= right)) || !status;
617 const std::function<int64_t(
Variable*)>& evaluator) {
618 const int64_t left = Eval(ct.
arguments[0], evaluator);
619 const int64_t right = Eval(ct.
arguments[1], evaluator);
620 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
621 return status == (left >= right);
625 const std::function<int64_t(
Variable*)>& evaluator) {
626 const int64_t left = Eval(ct.
arguments[0], evaluator);
627 const int64_t right = Eval(ct.
arguments[1], evaluator);
632 const std::function<int64_t(
Variable*)>& evaluator) {
633 const int64_t left = Eval(ct.
arguments[0], evaluator);
634 const int64_t right = Eval(ct.
arguments[1], evaluator);
635 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
636 return (status && (left > right)) || !status;
640 const std::function<int64_t(
Variable*)>& evaluator) {
641 const int64_t left = Eval(ct.
arguments[0], evaluator);
642 const int64_t right = Eval(ct.
arguments[1], evaluator);
643 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
644 return status == (left > right);
648 const std::function<int64_t(
Variable*)>& evaluator) {
649 const int64_t left = Eval(ct.
arguments[0], evaluator);
650 const int64_t right = Eval(ct.
arguments[1], evaluator);
651 return left <= right;
655 const std::function<int64_t(
Variable*)>& evaluator) {
656 const int64_t left = Eval(ct.
arguments[0], evaluator);
657 const int64_t right = Eval(ct.
arguments[1], evaluator);
658 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
659 return (status && (left <= right)) || !status;
663 const std::function<int64_t(
Variable*)>& evaluator) {
664 const int64_t left = Eval(ct.
arguments[0], evaluator);
665 const int64_t right = Eval(ct.
arguments[1], evaluator);
666 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
667 return status == (left <= right);
671 const std::function<int64_t(
Variable*)>& evaluator) {
672 const int64_t left = Eval(ct.
arguments[0], evaluator);
673 const int64_t right = Eval(ct.
arguments[1], evaluator);
678 const std::function<int64_t(
Variable*)>& evaluator) {
679 const int64_t left = Eval(ct.
arguments[0], evaluator);
680 const int64_t right = Eval(ct.
arguments[1], evaluator);
681 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
682 return (status && (left < right)) || !status;
686 const std::function<int64_t(
Variable*)>& evaluator) {
687 const int64_t left = Eval(ct.
arguments[0], evaluator);
688 const int64_t right = Eval(ct.
arguments[1], evaluator);
689 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
690 return status == (left < right);
694 const std::function<int64_t(
Variable*)>& evaluator) {
696 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
697 result += EvalAt(ct.
arguments[0], i, evaluator) *
704 const std::function<int64_t(
Variable*)>& evaluator) {
705 const int64_t left = ComputeIntLin(ct, evaluator);
706 const int64_t right = Eval(ct.
arguments[2], evaluator);
707 return left == right;
711 const std::function<int64_t(
Variable*)>& evaluator) {
712 const int64_t left = ComputeIntLin(ct, evaluator);
713 const int64_t right = Eval(ct.
arguments[2], evaluator);
714 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
715 return (status && (left == right)) || !status;
719 const std::function<int64_t(
Variable*)>& evaluator) {
720 const int64_t left = ComputeIntLin(ct, evaluator);
721 const int64_t right = Eval(ct.
arguments[2], evaluator);
722 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
723 return status == (left == right);
727 const std::function<int64_t(
Variable*)>& evaluator) {
728 const int64_t left = ComputeIntLin(ct, evaluator);
729 const int64_t right = Eval(ct.
arguments[2], evaluator);
730 return left >= right;
734 const std::function<int64_t(
Variable*)>& evaluator) {
735 const int64_t left = ComputeIntLin(ct, evaluator);
736 const int64_t right = Eval(ct.
arguments[2], evaluator);
737 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
738 return (status && (left >= right)) || !status;
742 const std::function<int64_t(
Variable*)>& evaluator) {
743 const int64_t left = ComputeIntLin(ct, evaluator);
744 const int64_t right = Eval(ct.
arguments[2], evaluator);
745 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
746 return status == (left >= right);
750 const std::function<int64_t(
Variable*)>& evaluator) {
751 const int64_t left = ComputeIntLin(ct, evaluator);
752 const int64_t right = Eval(ct.
arguments[2], evaluator);
753 return left <= right;
757 const std::function<int64_t(
Variable*)>& evaluator) {
758 const int64_t left = ComputeIntLin(ct, evaluator);
759 const int64_t right = Eval(ct.
arguments[2], evaluator);
760 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
761 return (status && (left <= right)) || !status;
765 const std::function<int64_t(
Variable*)>& evaluator) {
766 const int64_t left = ComputeIntLin(ct, evaluator);
767 const int64_t right = Eval(ct.
arguments[2], evaluator);
768 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
769 return status == (left <= right);
773 const std::function<int64_t(
Variable*)>& evaluator) {
774 const int64_t left = ComputeIntLin(ct, evaluator);
775 const int64_t right = Eval(ct.
arguments[2], evaluator);
776 return left != right;
780 const std::function<int64_t(
Variable*)>& evaluator) {
781 const int64_t left = ComputeIntLin(ct, evaluator);
782 const int64_t right = Eval(ct.
arguments[2], evaluator);
783 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
784 return (status && (left != right)) || !status;
788 const std::function<int64_t(
Variable*)>& evaluator) {
789 const int64_t left = ComputeIntLin(ct, evaluator);
790 const int64_t right = Eval(ct.
arguments[2], evaluator);
791 const bool status = Eval(ct.
arguments[3], evaluator) != 0;
792 return status == (left != right);
796 const std::function<int64_t(
Variable*)>& evaluator) {
797 const int64_t left = Eval(ct.
arguments[0], evaluator);
798 const int64_t right = Eval(ct.
arguments[1], evaluator);
799 const int64_t status = Eval(ct.
arguments[2], evaluator);
800 return status == std::max(left, right);
804 const std::function<int64_t(
Variable*)>& evaluator) {
805 const int64_t left = Eval(ct.
arguments[0], evaluator);
806 const int64_t right = Eval(ct.
arguments[1], evaluator);
807 const int64_t status = Eval(ct.
arguments[2], evaluator);
808 return status == std::min(left, right);
812 const std::function<int64_t(
Variable*)>& evaluator) {
813 const int64_t left = Eval(ct.
arguments[0], evaluator);
814 const int64_t right = Eval(ct.
arguments[1], evaluator);
815 const int64_t target = Eval(ct.
arguments[2], evaluator);
816 return target == left - right;
820 const std::function<int64_t(
Variable*)>& evaluator) {
821 const int64_t left = Eval(ct.
arguments[0], evaluator);
822 const int64_t right = Eval(ct.
arguments[1], evaluator);
823 const int64_t target = Eval(ct.
arguments[2], evaluator);
824 return target == left % right;
828 const std::function<int64_t(
Variable*)>& evaluator) {
829 const int64_t left = Eval(ct.
arguments[0], evaluator);
830 const int64_t right = Eval(ct.
arguments[1], evaluator);
831 return left != right;
835 const std::function<int64_t(
Variable*)>& evaluator) {
836 const int64_t left = Eval(ct.
arguments[0], evaluator);
837 const int64_t right = Eval(ct.
arguments[1], evaluator);
838 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
839 return (status && (left != right)) || !status;
843 const std::function<int64_t(
Variable*)>& evaluator) {
844 const int64_t left = Eval(ct.
arguments[0], evaluator);
845 const int64_t right = Eval(ct.
arguments[1], evaluator);
846 const bool status = Eval(ct.
arguments[2], evaluator) != 0;
847 return status == (left != right);
851 const std::function<int64_t(
Variable*)>& evaluator) {
852 const int64_t left = Eval(ct.
arguments[0], evaluator);
853 const int64_t right = Eval(ct.
arguments[1], evaluator);
854 return left == -right;
858 const std::function<int64_t(
Variable*)>& evaluator) {
859 const int64_t left = Eval(ct.
arguments[0], evaluator);
860 const int64_t right = Eval(ct.
arguments[1], evaluator);
861 const int64_t target = Eval(ct.
arguments[2], evaluator);
862 return target == left + right;
866 const std::function<int64_t(
Variable*)>& evaluator) {
867 const int64_t left = Eval(ct.
arguments[0], evaluator);
868 const int64_t right = Eval(ct.
arguments[1], evaluator);
869 const int64_t target = Eval(ct.
arguments[2], evaluator);
870 return target == left * right;
874 const std::function<int64_t(
Variable*)>& evaluator) {
877 const int f_base = ct.
arguments[2].Value();
878 const int invf_base = ct.
arguments[3].Value();
880 for (
int i = 0; i < size; ++i) {
881 const int64_t x = EvalAt(ct.
arguments[0], i, evaluator) - invf_base;
882 const int64_t y = EvalAt(ct.
arguments[1], i, evaluator) - f_base;
883 if (x < 0 || x >= size || y < 0 || y >= size) {
889 for (
int i = 0; i < size; ++i) {
890 const int64_t fi = EvalAt(ct.
arguments[0], i, evaluator) - invf_base;
891 const int64_t invf_fi = EvalAt(ct.
arguments[1], fi, evaluator) - f_base;
901 const std::function<int64_t(
Variable*)>& evaluator) {
903 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
904 const int64_t x = EvalAt(ct.
arguments[0], i, evaluator);
905 const int64_t y = EvalAt(ct.
arguments[1], i, evaluator);
918 const std::function<int64_t(
Variable*)>& evaluator) {
920 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
921 const int64_t x = EvalAt(ct.
arguments[0], i, evaluator);
922 const int64_t y = EvalAt(ct.
arguments[1], i, evaluator);
935 const std::function<int64_t(
Variable*)>& evaluator) {
936 const int64_t max_index = Eval(ct.
arguments[1], evaluator) - 1;
937 const int64_t max_value = EvalAt(ct.
arguments[0], max_index, evaluator);
939 for (
int i = 0; i < max_index; ++i) {
940 if (EvalAt(ct.
arguments[0], i, evaluator) >= max_value) {
945 for (
int i = max_index + 1; i < Size(ct.
arguments[0]); i++) {
946 if (EvalAt(ct.
arguments[0], i, evaluator) > max_value) {
955 const std::function<int64_t(
Variable*)>& evaluator) {
956 int64_t max_value = std::numeric_limits<int64_t>::min();
957 for (
int i = 0; i < Size(ct.
arguments[1]); ++i) {
958 max_value = std::max(max_value, EvalAt(ct.
arguments[1], i, evaluator));
960 return max_value == Eval(ct.
arguments[0], evaluator);
964 const std::function<int64_t(
Variable*)>& evaluator) {
965 const int64_t min_index = Eval(ct.
arguments[1], evaluator) - 1;
966 const int64_t min_value = EvalAt(ct.
arguments[0], min_index, evaluator);
968 for (
int i = 0; i < min_index; ++i) {
969 if (EvalAt(ct.
arguments[0], i, evaluator) <= min_value) {
974 for (
int i = min_index + 1; i < Size(ct.
arguments[0]); i++) {
975 if (EvalAt(ct.
arguments[0], i, evaluator) < min_value) {
984 const std::function<int64_t(
Variable*)>& evaluator) {
985 int64_t min_value = std::numeric_limits<int64_t>::max();
986 for (
int i = 0; i < Size(ct.
arguments[1]); ++i) {
987 min_value = std::min(min_value, EvalAt(ct.
arguments[1], i, evaluator));
989 return min_value == Eval(ct.
arguments[0], evaluator);
992bool CheckNetworkFlowConservation(
995 const std::function<int64_t(
Variable*)>& evaluator) {
996 std::vector<int64_t> balance(balance_input.
values);
997 const int num_arcs = Size(arcs) / 2;
998 for (
int arc = 0; arc < num_arcs; arc++) {
999 const int tail = arcs.
values[arc * 2] - base_node;
1000 const int head = arcs.
values[arc * 2 + 1] - base_node;
1001 const int64_t flow = EvalAt(flow_vars, arc, evaluator);
1002 balance[tail] -= flow;
1003 balance[head] += flow;
1006 for (
const int64_t value : balance) {
1007 if (value != 0)
return false;
1014 const std::function<int64_t(
Variable*)>& evaluator) {
1020bool CheckNetworkFlowCost(
const Constraint& ct,
1021 const std::function<int64_t(
Variable*)>& evaluator) {
1028 int64_t total_cost = 0;
1029 const int num_arcs = Size(ct.
arguments[3]);
1030 for (
int arc = 0; arc < num_arcs; arc++) {
1031 const int64_t flow = EvalAt(ct.
arguments[3], arc, evaluator);
1032 const int64_t unit_cost = ct.
arguments[4].ValueAt(arc);
1033 total_cost += flow * unit_cost;
1036 return total_cost == Eval(ct.
arguments[5], evaluator);
1040 const std::function<int64_t(
Variable*)>& evaluator) {
1041 const int64_t count = Eval(ct.
arguments[0], evaluator);
1042 absl::flat_hash_set<int64_t> all_values;
1043 for (
int i = 0; i < Size(ct.
arguments[1]); ++i) {
1044 all_values.insert(EvalAt(ct.
arguments[1], i, evaluator));
1047 return count == all_values.size();
1051 const std::function<int64_t(
Variable*)>& ) {
1056 const std::function<int64_t(
Variable*)>& ) {
1061 const std::function<int64_t(
Variable*)>& evaluator) {
1062 const int64_t value = Eval(ct.
arguments[0], evaluator);
1067 const std::function<int64_t(
Variable*)>& evaluator) {
1068 const int64_t value = Eval(ct.
arguments[0], evaluator);
1069 return !ct.
arguments[1].Contains(value);
1073 const std::function<int64_t(
Variable*)>& evaluator) {
1074 const int64_t value = Eval(ct.
arguments[0], evaluator);
1075 const int64_t status = Eval(ct.
arguments[2], evaluator);
1076 return status == ct.
arguments[1].Contains(value);
1080 const std::function<int64_t(
Variable*)>& evaluator) {
1081 const int64_t low = Eval(ct.
arguments[0], evaluator);
1082 const int64_t up = Eval(ct.
arguments[1], evaluator);
1083 const int64_t length = Eval(ct.
arguments[2], evaluator);
1085 int64_t sliding_sum = 0;
1086 for (
int i = 0; i < std::min<int64_t>(length, Size(ct.
arguments[3])); ++i) {
1087 sliding_sum += EvalAt(ct.
arguments[3], i, evaluator);
1089 if (sliding_sum < low || sliding_sum > up) {
1092 for (
int i = length; i < Size(ct.
arguments[3]); ++i) {
1093 sliding_sum += EvalAt(ct.
arguments[3], i, evaluator) -
1094 EvalAt(ct.
arguments[3], i - length, evaluator);
1095 if (sliding_sum < low || sliding_sum > up) {
1103 const std::function<int64_t(
Variable*)>& evaluator) {
1105 absl::flat_hash_map<int64_t, int> init_count;
1106 absl::flat_hash_map<int64_t, int> sorted_count;
1107 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
1108 init_count[EvalAt(ct.
arguments[0], i, evaluator)]++;
1109 sorted_count[EvalAt(ct.
arguments[1], i, evaluator)]++;
1111 if (init_count != sorted_count) {
1114 for (
int i = 0; i < Size(ct.
arguments[1]) - 1; ++i) {
1115 if (EvalAt(ct.
arguments[1], i, evaluator) >
1116 EvalAt(ct.
arguments[1], i, evaluator)) {
1124 const std::function<int64_t(
Variable*)>& evaluator) {
1125 absl::flat_hash_set<int64_t> visited;
1128 int64_t current = -1;
1129 for (
int i = 0; i < Size(ct.
arguments[0]); ++i) {
1130 const int64_t next = EvalAt(ct.
arguments[0], i, evaluator) -
base;
1131 if (next != i && current == -1) {
1133 }
else if (next == i) {
1134 visited.insert(next);
1139 const int residual_size = Size(ct.
arguments[0]) - visited.size();
1140 for (
int i = 0; i < residual_size; ++i) {
1141 const int64_t next = EvalAt(ct.
arguments[0], current, evaluator) -
base;
1142 visited.insert(next);
1143 if (next == current) {
1150 return visited.size() == Size(ct.
arguments[0]);
1154 const std::function<int64_t(
Variable*)>& ) {
1158bool CheckSymmetricAllDifferent(
1161 for (
int i = 0; i < size; ++i) {
1162 const int64_t value = EvalAt(ct.
arguments[0], i, evaluator) - 1;
1163 if (value < 0 || value >= size) {
1166 const int64_t reverse_value = EvalAt(ct.
arguments[0], value, evaluator) - 1;
1167 if (reverse_value != i) {
1175 absl::flat_hash_map<std::string,
1177 std::function<int64_t(
Variable*)>)>>;
1186CallMap CreateCallMap() {
1188 m[
"alldifferent_except_0"] = CheckAlldifferentExcept0;
1189 m[
"among"] = CheckAmong;
1190 m[
"array_bool_and"] = CheckArrayBoolAnd;
1191 m[
"array_bool_element"] = CheckArrayIntElement;
1192 m[
"array_bool_or"] = CheckArrayBoolOr;
1193 m[
"array_bool_xor"] = CheckArrayBoolXor;
1194 m[
"array_int_element"] = CheckArrayIntElement;
1195 m[
"array_int_element_nonshifted"] = CheckArrayIntElementNonShifted;
1196 m[
"array_int_maximum"] = CheckMaximumInt;
1197 m[
"array_int_minimum"] = CheckMinimumInt;
1198 m[
"array_var_bool_element"] = CheckArrayVarIntElement;
1199 m[
"array_var_int_element"] = CheckArrayVarIntElement;
1200 m[
"at_most_int"] = CheckAtMostInt;
1201 m[
"bool_and"] = CheckBoolAnd;
1202 m[
"bool_clause"] = CheckBoolClause;
1203 m[
"bool_eq_imp"] = CheckIntEqImp;
1204 m[
"bool_eq_reif"] = CheckIntEqReif;
1205 m[
"bool_eq"] = CheckIntEq;
1206 m[
"bool_ge_imp"] = CheckIntGeImp;
1207 m[
"bool_ge_reif"] = CheckIntGeReif;
1208 m[
"bool_ge"] = CheckIntGe;
1209 m[
"bool_gt_imp"] = CheckIntGtImp;
1210 m[
"bool_gt_reif"] = CheckIntGtReif;
1211 m[
"bool_gt"] = CheckIntGt;
1212 m[
"bool_le_imp"] = CheckIntLeImp;
1213 m[
"bool_le_reif"] = CheckIntLeReif;
1214 m[
"bool_le"] = CheckIntLe;
1215 m[
"bool_left_imp"] = CheckIntLe;
1216 m[
"bool_lin_eq"] = CheckIntLinEq;
1217 m[
"bool_lin_le"] = CheckIntLinLe;
1218 m[
"bool_lt_imp"] = CheckIntLtImp;
1219 m[
"bool_lt_reif"] = CheckIntLtReif;
1220 m[
"bool_lt"] = CheckIntLt;
1221 m[
"bool_ne_imp"] = CheckIntNeImp;
1222 m[
"bool_ne_reif"] = CheckIntNeReif;
1223 m[
"bool_ne"] = CheckIntNe;
1224 m[
"bool_not"] = CheckBoolNot;
1225 m[
"bool_or"] = CheckBoolOr;
1226 m[
"bool_right_imp"] = CheckIntGe;
1227 m[
"bool_xor"] = CheckBoolXor;
1228 m[
"bool2int"] = CheckIntEq;
1229 m[
"count_eq"] = CheckCountEq;
1230 m[
"count_geq"] = CheckCountGeq;
1231 m[
"count_gt"] = CheckCountGt;
1232 m[
"count_leq"] = CheckCountLeq;
1233 m[
"count_lt"] = CheckCountLt;
1234 m[
"count_neq"] = CheckCountNeq;
1235 m[
"count_reif"] = CheckCountReif;
1236 m[
"count"] = CheckCountEq;
1237 m[
"diffn_k_with_sizes"] = CheckDiffnK;
1238 m[
"diffn_nonstrict_k_with_sizes"] = CheckDiffnNonStrictK;
1239 m[
"false_constraint"] = CheckFalseConstraint;
1240 m[
"fixed_cumulative"] = CheckCumulative;
1241 m[
"fzn_all_different_int"] = CheckAllDifferentInt;
1242 m[
"fzn_cumulative"] = CheckCumulative;
1243 m[
"fzn_diffn_nonstrict"] = CheckDiffnNonStrict;
1244 m[
"fzn_diffn"] = CheckDiffn;
1245 m[
"fzn_disjunctive_strict"] = CheckDisjunctiveStrict;
1246 m[
"fzn_disjunctive"] = CheckDisjunctive;
1247 m[
"global_cardinality_closed"] = CheckGlobalCardinalityClosed;
1248 m[
"global_cardinality_low_up_closed"] = CheckGlobalCardinalityLowUpClosed;
1249 m[
"global_cardinality_low_up"] = CheckGlobalCardinalityLowUp;
1250 m[
"global_cardinality_old"] = CheckGlobalCardinalityOld;
1251 m[
"global_cardinality"] = CheckGlobalCardinality;
1252 m[
"int_abs"] = CheckIntAbs;
1253 m[
"int_div"] = CheckIntDiv;
1254 m[
"int_eq_imp"] = CheckIntEqImp;
1255 m[
"int_eq_reif"] = CheckIntEqReif;
1256 m[
"int_eq"] = CheckIntEq;
1257 m[
"int_ge_imp"] = CheckIntGeImp;
1258 m[
"int_ge_reif"] = CheckIntGeReif;
1259 m[
"int_ge"] = CheckIntGe;
1260 m[
"int_gt_imp"] = CheckIntGtImp;
1261 m[
"int_gt_reif"] = CheckIntGtReif;
1262 m[
"int_gt"] = CheckIntGt;
1263 m[
"int_in"] = CheckSetIn;
1264 m[
"int_le_imp"] = CheckIntLeImp;
1265 m[
"int_le_reif"] = CheckIntLeReif;
1266 m[
"int_le"] = CheckIntLe;
1267 m[
"int_lin_eq_imp"] = CheckIntLinEqImp;
1268 m[
"int_lin_eq_reif"] = CheckIntLinEqReif;
1269 m[
"int_lin_eq"] = CheckIntLinEq;
1270 m[
"int_lin_ge_imp"] = CheckIntLinGeImp;
1271 m[
"int_lin_ge_reif"] = CheckIntLinGeReif;
1272 m[
"int_lin_ge"] = CheckIntLinGe;
1273 m[
"int_lin_le_imp"] = CheckIntLinLeImp;
1274 m[
"int_lin_le_reif"] = CheckIntLinLeReif;
1275 m[
"int_lin_le"] = CheckIntLinLe;
1276 m[
"int_lin_ne_imp"] = CheckIntLinNeImp;
1277 m[
"int_lin_ne_reif"] = CheckIntLinNeReif;
1278 m[
"int_lin_ne"] = CheckIntLinNe;
1279 m[
"int_lt_imp"] = CheckIntLtImp;
1280 m[
"int_lt_reif"] = CheckIntLtReif;
1281 m[
"int_lt"] = CheckIntLt;
1282 m[
"int_max"] = CheckIntMax;
1283 m[
"int_min"] = CheckIntMin;
1284 m[
"int_minus"] = CheckIntMinus;
1285 m[
"int_mod"] = CheckIntMod;
1286 m[
"int_ne_imp"] = CheckIntNeImp;
1287 m[
"int_ne_reif"] = CheckIntNeReif;
1288 m[
"int_ne"] = CheckIntNe;
1289 m[
"int_negate"] = CheckIntNegate;
1290 m[
"int_not_in"] = CheckSetNotIn;
1291 m[
"int_plus"] = CheckIntPlus;
1292 m[
"int_times"] = CheckIntTimes;
1293 m[
"lex_less_bool"] = CheckLexLessInt;
1294 m[
"lex_less_int"] = CheckLexLessInt;
1295 m[
"lex_lesseq_bool"] = CheckLexLesseqInt;
1296 m[
"lex_lesseq_int"] = CheckLexLesseqInt;
1297 m[
"maximum_arg_int"] = CheckMaximumArgInt;
1298 m[
"maximum_int"] = CheckMaximumInt;
1299 m[
"minimum_arg_int"] = CheckMinimumArgInt;
1300 m[
"minimum_int"] = CheckMinimumInt;
1301 m[
"nvalue"] = CheckNvalue;
1302 m[
"ortools_array_bool_element"] = CheckOrtoolsArrayIntElement;
1303 m[
"ortools_array_int_element"] = CheckOrtoolsArrayIntElement;
1304 m[
"ortools_array_var_bool_element"] = CheckOrtoolsArrayIntElement;
1305 m[
"ortools_array_var_int_element"] = CheckOrtoolsArrayIntElement;
1306 m[
"ortools_circuit"] = CheckCircuit;
1307 m[
"ortools_cumulative_opt"] = CheckCumulativeOpt;
1308 m[
"ortools_disjunctive_strict_opt"] = CheckDisjunctiveStrictOpt;
1309 m[
"ortools_inverse"] = CheckInverse;
1310 m[
"ortools_network_flow_cost"] = CheckNetworkFlowCost;
1311 m[
"ortools_network_flow"] = CheckNetworkFlow;
1312 m[
"ortools_regular"] = CheckRegular;
1313 m[
"ortools_subcircuit"] = CheckSubCircuit;
1314 m[
"ortools_table_bool"] = CheckTableInt;
1315 m[
"ortools_table_int"] = CheckTableInt;
1316 m[
"regular_nfa"] = CheckRegularNfa;
1317 m[
"set_in_reif"] = CheckSetInReif;
1318 m[
"set_in"] = CheckSetIn;
1319 m[
"set_not_in"] = CheckSetNotIn;
1320 m[
"sliding_sum"] = CheckSlidingSum;
1321 m[
"sort"] = CheckSort;
1322 m[
"symmetric_all_different"] = CheckSymmetricAllDifferent;
1323 m[
"var_cumulative"] = CheckCumulative;
1324 m[
"variable_cumulative"] = CheckCumulative;
1331 const std::function<int64_t(
Variable*)>& evaluator,
1334 const CallMap call_map = CreateCallMap();
1336 if (!ct->active)
continue;
1337 const auto& checker = call_map.at(ct->type);
1338 if (!checker(*ct, evaluator)) {
1339 SOLVER_LOG(logger,
"Failing constraint ", ct->DebugString());