18 #include "absl/container/flat_hash_map.h"
19 #include "absl/container/flat_hash_set.h"
37 return evaluator(arg.
Var());
57 return evaluator(arg.
VarAt(pos));
68 bool CheckAllDifferentInt(
71 absl::flat_hash_set<int64> visited;
77 visited.insert(
value);
83 bool CheckAlldifferentExcept0(
86 absl::flat_hash_set<int64> visited;
92 visited.insert(
value);
107 return count == expected;
110 bool CheckArrayBoolAnd(
135 bool CheckArrayBoolXor(
144 return result % 2 == 1;
147 bool CheckArrayIntElement(
158 return element == target;
161 bool CheckArrayIntElementNonShifted(
168 return element == target;
171 bool CheckArrayVarIntElement(
182 return element == target;
194 return count <= expected;
202 return status ==
std::min(left, right);
227 return left == 1 - right;
235 return status ==
std::max(left, right);
243 return target == (left + right == 1);
252 for (
int i = 0; i < size; ++i) {
257 }
else if (
next == size) {
263 absl::flat_hash_set<int64> visited;
267 visited.insert(
next);
285 const int64 count = ComputeCount(
ct, evaluator);
287 return count == expected;
292 const int64 count = ComputeCount(
ct, evaluator);
294 return count >= expected;
299 const int64 count = ComputeCount(
ct, evaluator);
301 return count > expected;
306 const int64 count = ComputeCount(
ct, evaluator);
308 return count <= expected;
313 const int64 count = ComputeCount(
ct, evaluator);
315 return count < expected;
320 const int64 count = ComputeCount(
ct, evaluator);
322 return count != expected;
327 const int64 count = ComputeCount(
ct, evaluator);
330 return status == (expected == count);
340 absl::flat_hash_map<int64, int64> usage;
341 for (
int i = 0; i < size; ++i) {
345 for (
int64 t = start; t < start + duration; ++t) {
346 usage[t] += requirement;
365 bool CheckDiffnNonStrict(
371 bool CheckDiffnNonStrictK(
382 bool CheckDisjunctiveStrict(
388 bool CheckFalseConstraint(
394 std::vector<int64> ComputeGlobalCardinalityCards(
397 std::vector<int64> cards(Size(
ct.
arguments[1]), 0);
398 absl::flat_hash_map<int64, int> positions;
399 for (
int i = 0; i <
ct.
arguments[1].values.size(); ++i) {
402 positions[
value] = i;
407 cards[positions[
value]]++;
413 bool CheckGlobalCardinality(
416 const std::vector<int64> cards = ComputeGlobalCardinalityCards(
ct, evaluator);
420 if (card != cards[i]) {
427 bool CheckGlobalCardinalityClosed(
430 const std::vector<int64> cards = ComputeGlobalCardinalityCards(
ct, evaluator);
434 if (card != cards[i]) {
438 int64 sum_of_cards = 0;
439 for (
int64 card : cards) {
440 sum_of_cards += card;
445 bool CheckGlobalCardinalityLowUp(
448 const std::vector<int64> cards = ComputeGlobalCardinalityCards(
ct, evaluator);
451 for (
int i = 0; i < cards.size(); ++i) {
452 const int64 card = cards[i];
460 bool CheckGlobalCardinalityLowUpClosed(
463 const std::vector<int64> cards = ComputeGlobalCardinalityCards(
ct, evaluator);
466 for (
int i = 0; i < cards.size(); ++i) {
467 const int64 card = cards[i];
472 int64 sum_of_cards = 0;
473 for (
int64 card : cards) {
474 sum_of_cards += card;
479 bool CheckGlobalCardinalityOld(
483 std::vector<int64> cards(size, 0);
490 for (
int i = 0; i < size; ++i) {
492 if (card != cards[i]) {
503 return std::abs(left) == right;
511 return target == left / right;
518 return left == right;
525 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
526 return (status && (left == right)) || !status;
533 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
534 return status == (left == right);
541 return left >= right;
548 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
549 return (status && (left >= right)) || !status;
556 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
557 return status == (left >= right);
571 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
572 return (status && (left > right)) || !status;
579 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
580 return status == (left > right);
587 return left <= right;
594 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
595 return (status && (left <= right)) || !status;
602 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
603 return status == (left <= right);
617 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
618 return (status && (left < right)) || !status;
625 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
626 return status == (left < right);
641 const int64 left = ComputeIntLin(
ct, evaluator);
643 return left == right;
648 const int64 left = ComputeIntLin(
ct, evaluator);
650 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
651 return (status && (left == right)) || !status;
654 bool CheckIntLinEqReif(
657 const int64 left = ComputeIntLin(
ct, evaluator);
659 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
660 return status == (left == right);
665 const int64 left = ComputeIntLin(
ct, evaluator);
667 return left >= right;
672 const int64 left = ComputeIntLin(
ct, evaluator);
674 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
675 return (status && (left >= right)) || !status;
678 bool CheckIntLinGeReif(
681 const int64 left = ComputeIntLin(
ct, evaluator);
683 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
684 return status == (left >= right);
689 const int64 left = ComputeIntLin(
ct, evaluator);
691 return left <= right;
696 const int64 left = ComputeIntLin(
ct, evaluator);
698 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
699 return (status && (left <= right)) || !status;
702 bool CheckIntLinLeReif(
705 const int64 left = ComputeIntLin(
ct, evaluator);
707 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
708 return status == (left <= right);
713 const int64 left = ComputeIntLin(
ct, evaluator);
715 return left != right;
720 const int64 left = ComputeIntLin(
ct, evaluator);
722 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
723 return (status && (left != right)) || !status;
726 bool CheckIntLinNeReif(
729 const int64 left = ComputeIntLin(
ct, evaluator);
731 const bool status = Eval(
ct.
arguments[3], evaluator) != 0;
732 return status == (left != right);
740 return status ==
std::max(left, right);
748 return status ==
std::min(left, right);
756 return target == left - right;
764 return target == left % right;
771 return left != right;
778 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
779 return (status && (left != right)) || !status;
786 const bool status = Eval(
ct.
arguments[2], evaluator) != 0;
787 return status == (left != right);
794 return left == -right;
802 return target == left + right;
810 return target == left * right;
818 for (
int i = 0; i < size; ++i) {
821 if (x < 0 || x >= size || y < 0 || y >= size) {
826 for (
int i = 0; i < size; ++i) {
854 bool CheckLexLesseqInt(
872 bool CheckMaximumArgInt(
878 for (
int i = 0; i < max_index; ++i) {
879 if (EvalAt(
ct.
arguments[0], i, evaluator) >= max_value) {
884 for (
int i = max_index + 1; i < Size(
ct.
arguments[0]); i++) {
885 if (EvalAt(
ct.
arguments[0], i, evaluator) > max_value) {
899 return max_value == Eval(
ct.
arguments[0], evaluator);
902 bool CheckMinimumArgInt(
908 for (
int i = 0; i < min_index; ++i) {
909 if (EvalAt(
ct.
arguments[0], i, evaluator) <= min_value) {
914 for (
int i = min_index + 1; i < Size(
ct.
arguments[0]); i++) {
915 if (EvalAt(
ct.
arguments[0], i, evaluator) < min_value) {
929 return min_value == Eval(
ct.
arguments[0], evaluator);
932 bool CheckNetworkFlowConservation(
936 std::vector<int64> balance(balance_input.
values);
938 const int num_arcs = Size(arcs) / 2;
939 for (
int arc = 0; arc < num_arcs; arc++) {
941 const int head = arcs.
values[arc * 2 + 1] - 1;
942 const int64 flow = EvalAt(flow_vars, arc, evaluator);
943 balance[
tail] -= flow;
944 balance[
head] += flow;
948 if (
value != 0)
return false;
960 bool CheckNetworkFlowCost(
968 int64 total_cost = 0;
970 for (
int arc = 0; arc < num_arcs; arc++) {
973 total_cost += flow *
cost;
976 return total_cost == Eval(
ct.
arguments[4], evaluator);
982 absl::flat_hash_set<int64> all_values;
984 all_values.insert(EvalAt(
ct.
arguments[1], i, evaluator));
987 return count == all_values.size();
1025 int64 sliding_sum = 0;
1026 for (
int i = 0; i < std::min<int64>(length, Size(
ct.
arguments[3])); ++i) {
1027 sliding_sum += EvalAt(
ct.
arguments[3], i, evaluator);
1029 if (sliding_sum < low || sliding_sum > up) {
1032 for (
int i = length; i < Size(
ct.
arguments[3]); ++i) {
1033 sliding_sum += EvalAt(
ct.
arguments[3], i, evaluator) -
1035 if (sliding_sum < low || sliding_sum > up) {
1045 absl::flat_hash_map<int64, int> init_count;
1046 absl::flat_hash_map<int64, int> sorted_count;
1048 init_count[EvalAt(
ct.
arguments[0], i, evaluator)]++;
1049 sorted_count[EvalAt(
ct.
arguments[1], i, evaluator)]++;
1051 if (init_count != sorted_count) {
1054 for (
int i = 0; i < Size(
ct.
arguments[1]) - 1; ++i) {
1065 absl::flat_hash_set<int64> visited;
1070 if (
next != i && current == -1) {
1072 }
else if (
next == i) {
1073 visited.insert(
next);
1078 const int residual_size = Size(
ct.
arguments[0]) - visited.size();
1079 for (
int i = 0; i < residual_size; ++i) {
1081 visited.insert(
next);
1082 if (
next == current) {
1097 bool CheckSymmetricAllDifferent(
1101 for (
int i = 0; i < size; ++i) {
1103 if (value < 0 || value >= size) {
1107 if (reverse_value != i) {
1114 using CallMap = absl::flat_hash_map<
1125 CallMap CreateCallMap() {
1127 m[
"fzn_all_different_int"] = CheckAllDifferentInt;
1128 m[
"alldifferent_except_0"] = CheckAlldifferentExcept0;
1129 m[
"among"] = CheckAmong;
1130 m[
"array_bool_and"] = CheckArrayBoolAnd;
1131 m[
"array_bool_element"] = CheckArrayIntElement;
1132 m[
"array_bool_or"] = CheckArrayBoolOr;
1133 m[
"array_bool_xor"] = CheckArrayBoolXor;
1134 m[
"array_int_element"] = CheckArrayIntElement;
1135 m[
"array_int_element_nonshifted"] = CheckArrayIntElementNonShifted;
1136 m[
"array_var_bool_element"] = CheckArrayVarIntElement;
1137 m[
"array_var_int_element"] = CheckArrayVarIntElement;
1138 m[
"at_most_int"] = CheckAtMostInt;
1139 m[
"bool_and"] = CheckBoolAnd;
1140 m[
"bool_clause"] = CheckBoolClause;
1141 m[
"bool_eq"] = CheckIntEq;
1142 m[
"bool2int"] = CheckIntEq;
1143 m[
"bool_eq_imp"] = CheckIntEqImp;
1144 m[
"bool_eq_reif"] = CheckIntEqReif;
1145 m[
"bool_ge"] = CheckIntGe;
1146 m[
"bool_ge_imp"] = CheckIntGeImp;
1147 m[
"bool_ge_reif"] = CheckIntGeReif;
1148 m[
"bool_gt"] = CheckIntGt;
1149 m[
"bool_gt_imp"] = CheckIntGtImp;
1150 m[
"bool_gt_reif"] = CheckIntGtReif;
1151 m[
"bool_le"] = CheckIntLe;
1152 m[
"bool_le_imp"] = CheckIntLeImp;
1153 m[
"bool_le_reif"] = CheckIntLeReif;
1154 m[
"bool_left_imp"] = CheckIntLe;
1155 m[
"bool_lin_eq"] = CheckIntLinEq;
1156 m[
"bool_lin_le"] = CheckIntLinLe;
1157 m[
"bool_lt"] = CheckIntLt;
1158 m[
"bool_lt_imp"] = CheckIntLtImp;
1159 m[
"bool_lt_reif"] = CheckIntLtReif;
1160 m[
"bool_ne"] = CheckIntNe;
1161 m[
"bool_ne_imp"] = CheckIntNeImp;
1162 m[
"bool_ne_reif"] = CheckIntNeReif;
1163 m[
"bool_not"] = CheckBoolNot;
1164 m[
"bool_or"] = CheckBoolOr;
1165 m[
"bool_right_imp"] = CheckIntGe;
1166 m[
"bool_xor"] = CheckBoolXor;
1167 m[
"fzn_circuit"] = CheckCircuit;
1168 m[
"count_eq"] = CheckCountEq;
1169 m[
"count"] = CheckCountEq;
1170 m[
"count_geq"] = CheckCountGeq;
1171 m[
"count_gt"] = CheckCountGt;
1172 m[
"count_leq"] = CheckCountLeq;
1173 m[
"count_lt"] = CheckCountLt;
1174 m[
"count_neq"] = CheckCountNeq;
1175 m[
"count_reif"] = CheckCountReif;
1176 m[
"fzn_cumulative"] = CheckCumulative;
1177 m[
"var_cumulative"] = CheckCumulative;
1178 m[
"variable_cumulative"] = CheckCumulative;
1179 m[
"fixed_cumulative"] = CheckCumulative;
1180 m[
"fzn_diffn"] = CheckDiffn;
1181 m[
"diffn_k_with_sizes"] = CheckDiffnK;
1182 m[
"fzn_diffn_nonstrict"] = CheckDiffnNonStrict;
1183 m[
"diffn_nonstrict_k_with_sizes"] = CheckDiffnNonStrictK;
1184 m[
"disjunctive"] = CheckDisjunctive;
1185 m[
"disjunctive_strict"] = CheckDisjunctiveStrict;
1186 m[
"false_constraint"] = CheckFalseConstraint;
1187 m[
"global_cardinality"] = CheckGlobalCardinality;
1188 m[
"global_cardinality_closed"] = CheckGlobalCardinalityClosed;
1189 m[
"global_cardinality_low_up"] = CheckGlobalCardinalityLowUp;
1190 m[
"global_cardinality_low_up_closed"] = CheckGlobalCardinalityLowUpClosed;
1191 m[
"global_cardinality_old"] = CheckGlobalCardinalityOld;
1192 m[
"int_abs"] = CheckIntAbs;
1193 m[
"int_div"] = CheckIntDiv;
1194 m[
"int_eq"] = CheckIntEq;
1195 m[
"int_eq_imp"] = CheckIntEqImp;
1196 m[
"int_eq_reif"] = CheckIntEqReif;
1197 m[
"int_ge"] = CheckIntGe;
1198 m[
"int_ge_imp"] = CheckIntGeImp;
1199 m[
"int_ge_reif"] = CheckIntGeReif;
1200 m[
"int_gt"] = CheckIntGt;
1201 m[
"int_gt_imp"] = CheckIntGtImp;
1202 m[
"int_gt_reif"] = CheckIntGtReif;
1203 m[
"int_le"] = CheckIntLe;
1204 m[
"int_le_imp"] = CheckIntLeImp;
1205 m[
"int_le_reif"] = CheckIntLeReif;
1206 m[
"int_lin_eq"] = CheckIntLinEq;
1207 m[
"int_lin_eq_imp"] = CheckIntLinEqImp;
1208 m[
"int_lin_eq_reif"] = CheckIntLinEqReif;
1209 m[
"int_lin_ge"] = CheckIntLinGe;
1210 m[
"int_lin_ge_imp"] = CheckIntLinGeImp;
1211 m[
"int_lin_ge_reif"] = CheckIntLinGeReif;
1212 m[
"int_lin_le"] = CheckIntLinLe;
1213 m[
"int_lin_le_imp"] = CheckIntLinLeImp;
1214 m[
"int_lin_le_reif"] = CheckIntLinLeReif;
1215 m[
"int_lin_ne"] = CheckIntLinNe;
1216 m[
"int_lin_ne_imp"] = CheckIntLinNeImp;
1217 m[
"int_lin_ne_reif"] = CheckIntLinNeReif;
1218 m[
"int_lt"] = CheckIntLt;
1219 m[
"int_lt_imp"] = CheckIntLtImp;
1220 m[
"int_lt_reif"] = CheckIntLtReif;
1221 m[
"int_max"] = CheckIntMax;
1222 m[
"int_min"] = CheckIntMin;
1223 m[
"int_minus"] = CheckIntMinus;
1224 m[
"int_mod"] = CheckIntMod;
1225 m[
"int_ne"] = CheckIntNe;
1226 m[
"int_ne_imp"] = CheckIntNeImp;
1227 m[
"int_ne_reif"] = CheckIntNeReif;
1228 m[
"int_negate"] = CheckIntNegate;
1229 m[
"int_plus"] = CheckIntPlus;
1230 m[
"int_times"] = CheckIntTimes;
1231 m[
"fzn_inverse"] = CheckInverse;
1232 m[
"lex_less_bool"] = CheckLexLessInt;
1233 m[
"lex_less_int"] = CheckLexLessInt;
1234 m[
"lex_lesseq_bool"] = CheckLexLesseqInt;
1235 m[
"lex_lesseq_int"] = CheckLexLesseqInt;
1236 m[
"maximum_arg_int"] = CheckMaximumArgInt;
1237 m[
"maximum_int"] = CheckMaximumInt;
1238 m[
"array_int_maximum"] = CheckMaximumInt;
1239 m[
"minimum_arg_int"] = CheckMinimumArgInt;
1240 m[
"minimum_int"] = CheckMinimumInt;
1241 m[
"array_int_minimum"] = CheckMinimumInt;
1242 m[
"ortools_network_flow"] = CheckNetworkFlow;
1243 m[
"ortools_network_flow_cost"] = CheckNetworkFlowCost;
1244 m[
"nvalue"] = CheckNvalue;
1245 m[
"ortools_regular"] = CheckRegular;
1246 m[
"regular_nfa"] = CheckRegularNfa;
1247 m[
"set_in"] = CheckSetIn;
1248 m[
"int_in"] = CheckSetIn;
1249 m[
"set_not_in"] = CheckSetNotIn;
1250 m[
"int_not_in"] = CheckSetNotIn;
1251 m[
"set_in_reif"] = CheckSetInReif;
1252 m[
"sliding_sum"] = CheckSlidingSum;
1253 m[
"sort"] = CheckSort;
1254 m[
"fzn_subcircuit"] = CheckSubCircuit;
1255 m[
"symmetric_all_different"] = CheckSymmetricAllDifferent;
1256 m[
"ortools_table_bool"] = CheckTableInt;
1257 m[
"ortools_table_int"] = CheckTableInt;
1266 const CallMap call_map = CreateCallMap();
1270 if (!checker(*
ct, evaluator)) {