OR-Tools  9.0
checker.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <algorithm>
17 #include <cstdint>
18 #include <limits>
19 
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/container/flat_hash_set.h"
22 #include "ortools/base/map_util.h"
23 #include "ortools/flatzinc/model.h"
24 #include "ortools/util/logging.h"
25 
26 namespace operations_research {
27 namespace fz {
28 namespace {
29 
30 // Helpers
31 
32 int64_t Eval(const Argument& arg,
33  const std::function<int64_t(IntegerVariable*)>& evaluator) {
34  switch (arg.type) {
35  case Argument::INT_VALUE: {
36  return arg.Value();
37  }
38  case Argument::INT_VAR_REF: {
39  return evaluator(arg.Var());
40  }
41  default: {
42  LOG(FATAL) << "Cannot evaluate " << arg.DebugString();
43  return 0;
44  }
45  }
46 }
47 
48 int Size(const Argument& arg) {
49  return std::max(arg.values.size(), arg.variables.size());
50 }
51 
52 int64_t EvalAt(const Argument& arg, int pos,
53  const std::function<int64_t(IntegerVariable*)>& evaluator) {
54  switch (arg.type) {
55  case Argument::INT_LIST: {
56  return arg.ValueAt(pos);
57  }
59  return evaluator(arg.VarAt(pos));
60  }
61  default: {
62  LOG(FATAL) << "Cannot evaluate " << arg.DebugString();
63  return 0;
64  }
65  }
66 }
67 
68 // Checkers
69 
70 bool CheckAllDifferentInt(
71  const Constraint& ct,
72  const std::function<int64_t(IntegerVariable*)>& evaluator) {
73  absl::flat_hash_set<int64_t> visited;
74  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
75  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
76  if (gtl::ContainsKey(visited, value)) {
77  return false;
78  }
79  visited.insert(value);
80  }
81 
82  return true;
83 }
84 
85 bool CheckAlldifferentExcept0(
86  const Constraint& ct,
87  const std::function<int64_t(IntegerVariable*)>& evaluator) {
88  absl::flat_hash_set<int64_t> visited;
89  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
90  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
91  if (value != 0 && gtl::ContainsKey(visited, value)) {
92  return false;
93  }
94  visited.insert(value);
95  }
96 
97  return true;
98 }
99 
100 bool CheckAmong(const Constraint& ct,
101  const std::function<int64_t(IntegerVariable*)>& evaluator) {
102  const int64_t expected = Eval(ct.arguments[0], evaluator);
103  int64_t count = 0;
104  for (int i = 0; i < Size(ct.arguments[1]); ++i) {
105  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
106  count += ct.arguments[2].Contains(value);
107  }
108 
109  return count == expected;
110 }
111 
112 bool CheckArrayBoolAnd(
113  const Constraint& ct,
114  const std::function<int64_t(IntegerVariable*)>& evaluator) {
115  int64_t result = 1;
116 
117  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
118  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
119  result = std::min(result, value);
120  }
121 
122  return result == Eval(ct.arguments[1], evaluator);
123 }
124 
125 bool CheckArrayBoolOr(
126  const Constraint& ct,
127  const std::function<int64_t(IntegerVariable*)>& evaluator) {
128  int64_t result = 0;
129 
130  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
131  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
132  result = std::max(result, value);
133  }
134 
135  return result == Eval(ct.arguments[1], evaluator);
136 }
137 
138 bool CheckArrayBoolXor(
139  const Constraint& ct,
140  const std::function<int64_t(IntegerVariable*)>& evaluator) {
141  int64_t result = 0;
142 
143  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
144  result += EvalAt(ct.arguments[0], i, evaluator);
145  }
146 
147  return result % 2 == 1;
148 }
149 
150 bool CheckArrayIntElement(
151  const Constraint& ct,
152  const std::function<int64_t(IntegerVariable*)>& evaluator) {
153  if (ct.arguments[0].variables.size() == 2) {
154  // TODO(user): Check 2D element.
155  return true;
156  }
157  // Flatzinc arrays are 1 based.
158  const int64_t shifted_index = Eval(ct.arguments[0], evaluator) - 1;
159  const int64_t element = EvalAt(ct.arguments[1], shifted_index, evaluator);
160  const int64_t target = Eval(ct.arguments[2], evaluator);
161  return element == target;
162 }
163 
164 bool CheckArrayIntElementNonShifted(
165  const Constraint& ct,
166  const std::function<int64_t(IntegerVariable*)>& evaluator) {
167  CHECK_EQ(ct.arguments[0].variables.size(), 1);
168  const int64_t index = Eval(ct.arguments[0], evaluator);
169  const int64_t element = EvalAt(ct.arguments[1], index, evaluator);
170  const int64_t target = Eval(ct.arguments[2], evaluator);
171  return element == target;
172 }
173 
174 bool CheckArrayVarIntElement(
175  const Constraint& ct,
176  const std::function<int64_t(IntegerVariable*)>& evaluator) {
177  if (ct.arguments[0].variables.size() == 2) {
178  // TODO(user): Check 2D element.
179  return true;
180  }
181  // Flatzinc arrays are 1 based.
182  const int64_t shifted_index = Eval(ct.arguments[0], evaluator) - 1;
183  const int64_t element = EvalAt(ct.arguments[1], shifted_index, evaluator);
184  const int64_t target = Eval(ct.arguments[2], evaluator);
185  return element == target;
186 }
187 
188 bool CheckAtMostInt(const Constraint& ct,
189  const std::function<int64_t(IntegerVariable*)>& evaluator) {
190  const int64_t expected = Eval(ct.arguments[0], evaluator);
191  const int64_t value = Eval(ct.arguments[2], evaluator);
192 
193  int64_t count = 0;
194  for (int i = 0; i < Size(ct.arguments[1]); ++i) {
195  count += EvalAt(ct.arguments[1], i, evaluator) == value;
196  }
197  return count <= expected;
198 }
199 
200 bool CheckBoolAnd(const Constraint& ct,
201  const std::function<int64_t(IntegerVariable*)>& evaluator) {
202  const int64_t left = Eval(ct.arguments[0], evaluator);
203  const int64_t right = Eval(ct.arguments[1], evaluator);
204  const int64_t status = Eval(ct.arguments[2], evaluator);
205  return status == std::min(left, right);
206 }
207 
208 bool CheckBoolClause(
209  const Constraint& ct,
210  const std::function<int64_t(IntegerVariable*)>& evaluator) {
211  int64_t result = 0;
212 
213  // Positive variables.
214  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
215  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
216  result = std::max(result, value);
217  }
218  // Negative variables.
219  for (int i = 0; i < Size(ct.arguments[1]); ++i) {
220  const int64_t value = EvalAt(ct.arguments[1], i, evaluator);
221  result = std::max(result, 1 - value);
222  }
223 
224  return result;
225 }
226 
227 bool CheckBoolNot(const Constraint& ct,
228  const std::function<int64_t(IntegerVariable*)>& evaluator) {
229  const int64_t left = Eval(ct.arguments[0], evaluator);
230  const int64_t right = Eval(ct.arguments[1], evaluator);
231  return left == 1 - right;
232 }
233 
234 bool CheckBoolOr(const Constraint& ct,
235  const std::function<int64_t(IntegerVariable*)>& evaluator) {
236  const int64_t left = Eval(ct.arguments[0], evaluator);
237  const int64_t right = Eval(ct.arguments[1], evaluator);
238  const int64_t status = Eval(ct.arguments[2], evaluator);
239  return status == std::max(left, right);
240 }
241 
242 bool CheckBoolXor(const Constraint& ct,
243  const std::function<int64_t(IntegerVariable*)>& evaluator) {
244  const int64_t left = Eval(ct.arguments[0], evaluator);
245  const int64_t right = Eval(ct.arguments[1], evaluator);
246  const int64_t target = Eval(ct.arguments[2], evaluator);
247  return target == (left + right == 1);
248 }
249 
250 bool CheckCircuit(const Constraint& ct,
251  const std::function<int64_t(IntegerVariable*)>& evaluator) {
252  // There are two versions of the constraint. 0 based and 1 based.
253  // Let's try to detect which one we have.
254  const int size = Size(ct.arguments[0]);
255  int shift = 0;
256  for (int i = 0; i < size; ++i) {
257  const int64_t next = EvalAt(ct.arguments[0], i, evaluator);
258  if (next == 0) { // 0 based.
259  shift = 0;
260  break;
261  } else if (next == size) { // 1 based.
262  shift = -1;
263  break;
264  }
265  }
266 
267  absl::flat_hash_set<int64_t> visited;
268  int64_t current = 0;
269  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
270  const int64_t next = EvalAt(ct.arguments[0], current, evaluator) + shift;
271  visited.insert(next);
272  current = next;
273  }
274  return visited.size() == Size(ct.arguments[0]);
275 }
276 
277 int64_t ComputeCount(
278  const Constraint& ct,
279  const std::function<int64_t(IntegerVariable*)>& evaluator) {
280  int64_t result = 0;
281  const int64_t value = Eval(ct.arguments[1], evaluator);
282  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
283  result += EvalAt(ct.arguments[0], i, evaluator) == value;
284  }
285  return result;
286 }
287 
288 bool CheckCountEq(const Constraint& ct,
289  const std::function<int64_t(IntegerVariable*)>& evaluator) {
290  const int64_t count = ComputeCount(ct, evaluator);
291  const int64_t expected = Eval(ct.arguments[2], evaluator);
292  return count == expected;
293 }
294 
295 bool CheckCountGeq(const Constraint& ct,
296  const std::function<int64_t(IntegerVariable*)>& evaluator) {
297  const int64_t count = ComputeCount(ct, evaluator);
298  const int64_t expected = Eval(ct.arguments[2], evaluator);
299  return count >= expected;
300 }
301 
302 bool CheckCountGt(const Constraint& ct,
303  const std::function<int64_t(IntegerVariable*)>& evaluator) {
304  const int64_t count = ComputeCount(ct, evaluator);
305  const int64_t expected = Eval(ct.arguments[2], evaluator);
306  return count > expected;
307 }
308 
309 bool CheckCountLeq(const Constraint& ct,
310  const std::function<int64_t(IntegerVariable*)>& evaluator) {
311  const int64_t count = ComputeCount(ct, evaluator);
312  const int64_t expected = Eval(ct.arguments[2], evaluator);
313  return count <= expected;
314 }
315 
316 bool CheckCountLt(const Constraint& ct,
317  const std::function<int64_t(IntegerVariable*)>& evaluator) {
318  const int64_t count = ComputeCount(ct, evaluator);
319  const int64_t expected = Eval(ct.arguments[2], evaluator);
320  return count < expected;
321 }
322 
323 bool CheckCountNeq(const Constraint& ct,
324  const std::function<int64_t(IntegerVariable*)>& evaluator) {
325  const int64_t count = ComputeCount(ct, evaluator);
326  const int64_t expected = Eval(ct.arguments[2], evaluator);
327  return count != expected;
328 }
329 
330 bool CheckCountReif(const Constraint& ct,
331  const std::function<int64_t(IntegerVariable*)>& evaluator) {
332  const int64_t count = ComputeCount(ct, evaluator);
333  const int64_t expected = Eval(ct.arguments[2], evaluator);
334  const int64_t status = Eval(ct.arguments[3], evaluator);
335  return status == (expected == count);
336 }
337 
338 bool CheckCumulative(
339  const Constraint& ct,
340  const std::function<int64_t(IntegerVariable*)>& evaluator) {
341  // TODO(user): Improve complexity for large durations.
342  const int64_t capacity = Eval(ct.arguments[3], evaluator);
343  const int size = Size(ct.arguments[0]);
344  CHECK_EQ(size, Size(ct.arguments[1]));
345  CHECK_EQ(size, Size(ct.arguments[2]));
346  absl::flat_hash_map<int64_t, int64_t> usage;
347  for (int i = 0; i < size; ++i) {
348  const int64_t start = EvalAt(ct.arguments[0], i, evaluator);
349  const int64_t duration = EvalAt(ct.arguments[1], i, evaluator);
350  const int64_t requirement = EvalAt(ct.arguments[2], i, evaluator);
351  for (int64_t t = start; t < start + duration; ++t) {
352  usage[t] += requirement;
353  if (usage[t] > capacity) {
354  return false;
355  }
356  }
357  }
358  return true;
359 }
360 
361 bool CheckDiffn(const Constraint& ct,
362  const std::function<int64_t(IntegerVariable*)>& evaluator) {
363  return true;
364 }
365 
366 bool CheckDiffnK(const Constraint& ct,
367  const std::function<int64_t(IntegerVariable*)>& evaluator) {
368  return true;
369 }
370 
371 bool CheckDiffnNonStrict(
372  const Constraint& ct,
373  const std::function<int64_t(IntegerVariable*)>& evaluator) {
374  return true;
375 }
376 
377 bool CheckDiffnNonStrictK(
378  const Constraint& ct,
379  const std::function<int64_t(IntegerVariable*)>& evaluator) {
380  return true;
381 }
382 
383 bool CheckDisjunctive(
384  const Constraint& ct,
385  const std::function<int64_t(IntegerVariable*)>& evaluator) {
386  return true;
387 }
388 
389 bool CheckDisjunctiveStrict(
390  const Constraint& ct,
391  const std::function<int64_t(IntegerVariable*)>& evaluator) {
392  return true;
393 }
394 
395 bool CheckFalseConstraint(
396  const Constraint& ct,
397  const std::function<int64_t(IntegerVariable*)>& evaluator) {
398  return false;
399 }
400 
401 std::vector<int64_t> ComputeGlobalCardinalityCards(
402  const Constraint& ct,
403  const std::function<int64_t(IntegerVariable*)>& evaluator) {
404  std::vector<int64_t> cards(Size(ct.arguments[1]), 0);
405  absl::flat_hash_map<int64_t, int> positions;
406  for (int i = 0; i < ct.arguments[1].values.size(); ++i) {
407  const int64_t value = ct.arguments[1].values[i];
408  CHECK(!gtl::ContainsKey(positions, value));
409  positions[value] = i;
410  }
411  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
412  const int value = EvalAt(ct.arguments[0], i, evaluator);
413  if (gtl::ContainsKey(positions, value)) {
414  cards[positions[value]]++;
415  }
416  }
417  return cards;
418 }
419 
420 bool CheckGlobalCardinality(
421  const Constraint& ct,
422  const std::function<int64_t(IntegerVariable*)>& evaluator) {
423  const std::vector<int64_t> cards =
424  ComputeGlobalCardinalityCards(ct, evaluator);
425  CHECK_EQ(cards.size(), Size(ct.arguments[2]));
426  for (int i = 0; i < Size(ct.arguments[2]); ++i) {
427  const int64_t card = EvalAt(ct.arguments[2], i, evaluator);
428  if (card != cards[i]) {
429  return false;
430  }
431  }
432  return true;
433 }
434 
435 bool CheckGlobalCardinalityClosed(
436  const Constraint& ct,
437  const std::function<int64_t(IntegerVariable*)>& evaluator) {
438  const std::vector<int64_t> cards =
439  ComputeGlobalCardinalityCards(ct, evaluator);
440  CHECK_EQ(cards.size(), Size(ct.arguments[2]));
441  for (int i = 0; i < Size(ct.arguments[2]); ++i) {
442  const int64_t card = EvalAt(ct.arguments[2], i, evaluator);
443  if (card != cards[i]) {
444  return false;
445  }
446  }
447  int64_t sum_of_cards = 0;
448  for (int64_t card : cards) {
449  sum_of_cards += card;
450  }
451  return sum_of_cards == Size(ct.arguments[0]);
452 }
453 
454 bool CheckGlobalCardinalityLowUp(
455  const Constraint& ct,
456  const std::function<int64_t(IntegerVariable*)>& evaluator) {
457  const std::vector<int64_t> cards =
458  ComputeGlobalCardinalityCards(ct, evaluator);
459  CHECK_EQ(cards.size(), ct.arguments[2].values.size());
460  CHECK_EQ(cards.size(), ct.arguments[3].values.size());
461  for (int i = 0; i < cards.size(); ++i) {
462  const int64_t card = cards[i];
463  if (card < ct.arguments[2].values[i] || card > ct.arguments[3].values[i]) {
464  return false;
465  }
466  }
467  return true;
468 }
469 
470 bool CheckGlobalCardinalityLowUpClosed(
471  const Constraint& ct,
472  const std::function<int64_t(IntegerVariable*)>& evaluator) {
473  const std::vector<int64_t> cards =
474  ComputeGlobalCardinalityCards(ct, evaluator);
475  CHECK_EQ(cards.size(), ct.arguments[2].values.size());
476  CHECK_EQ(cards.size(), ct.arguments[3].values.size());
477  for (int i = 0; i < cards.size(); ++i) {
478  const int64_t card = cards[i];
479  if (card < ct.arguments[2].values[i] || card > ct.arguments[3].values[i]) {
480  return false;
481  }
482  }
483  int64_t sum_of_cards = 0;
484  for (int64_t card : cards) {
485  sum_of_cards += card;
486  }
487  return sum_of_cards == Size(ct.arguments[0]);
488 }
489 
490 bool CheckGlobalCardinalityOld(
491  const Constraint& ct,
492  const std::function<int64_t(IntegerVariable*)>& evaluator) {
493  const int size = Size(ct.arguments[1]);
494  std::vector<int64_t> cards(size, 0);
495  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
496  const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
497  if (value >= 0 && value < size) {
498  cards[value]++;
499  }
500  }
501  for (int i = 0; i < size; ++i) {
502  const int64_t card = EvalAt(ct.arguments[1], i, evaluator);
503  if (card != cards[i]) {
504  return false;
505  }
506  }
507  return true;
508 }
509 
510 bool CheckIntAbs(const Constraint& ct,
511  const std::function<int64_t(IntegerVariable*)>& evaluator) {
512  const int64_t left = Eval(ct.arguments[0], evaluator);
513  const int64_t right = Eval(ct.arguments[1], evaluator);
514  return std::abs(left) == right;
515 }
516 
517 bool CheckIntDiv(const Constraint& ct,
518  const std::function<int64_t(IntegerVariable*)>& evaluator) {
519  const int64_t left = Eval(ct.arguments[0], evaluator);
520  const int64_t right = Eval(ct.arguments[1], evaluator);
521  const int64_t target = Eval(ct.arguments[2], evaluator);
522  return target == left / right;
523 }
524 
525 bool CheckIntEq(const Constraint& ct,
526  const std::function<int64_t(IntegerVariable*)>& evaluator) {
527  const int64_t left = Eval(ct.arguments[0], evaluator);
528  const int64_t right = Eval(ct.arguments[1], evaluator);
529  return left == right;
530 }
531 
532 bool CheckIntEqImp(const Constraint& ct,
533  const std::function<int64_t(IntegerVariable*)>& evaluator) {
534  const int64_t left = Eval(ct.arguments[0], evaluator);
535  const int64_t right = Eval(ct.arguments[1], evaluator);
536  const bool status = Eval(ct.arguments[2], evaluator) != 0;
537  return (status && (left == right)) || !status;
538 }
539 
540 bool CheckIntEqReif(const Constraint& ct,
541  const std::function<int64_t(IntegerVariable*)>& evaluator) {
542  const int64_t left = Eval(ct.arguments[0], evaluator);
543  const int64_t right = Eval(ct.arguments[1], evaluator);
544  const bool status = Eval(ct.arguments[2], evaluator) != 0;
545  return status == (left == right);
546 }
547 
548 bool CheckIntGe(const Constraint& ct,
549  const std::function<int64_t(IntegerVariable*)>& evaluator) {
550  const int64_t left = Eval(ct.arguments[0], evaluator);
551  const int64_t right = Eval(ct.arguments[1], evaluator);
552  return left >= right;
553 }
554 
555 bool CheckIntGeImp(const Constraint& ct,
556  const std::function<int64_t(IntegerVariable*)>& evaluator) {
557  const int64_t left = Eval(ct.arguments[0], evaluator);
558  const int64_t right = Eval(ct.arguments[1], evaluator);
559  const bool status = Eval(ct.arguments[2], evaluator) != 0;
560  return (status && (left >= right)) || !status;
561 }
562 
563 bool CheckIntGeReif(const Constraint& ct,
564  const std::function<int64_t(IntegerVariable*)>& evaluator) {
565  const int64_t left = Eval(ct.arguments[0], evaluator);
566  const int64_t right = Eval(ct.arguments[1], evaluator);
567  const bool status = Eval(ct.arguments[2], evaluator) != 0;
568  return status == (left >= right);
569 }
570 
571 bool CheckIntGt(const Constraint& ct,
572  const std::function<int64_t(IntegerVariable*)>& evaluator) {
573  const int64_t left = Eval(ct.arguments[0], evaluator);
574  const int64_t right = Eval(ct.arguments[1], evaluator);
575  return left > right;
576 }
577 
578 bool CheckIntGtImp(const Constraint& ct,
579  const std::function<int64_t(IntegerVariable*)>& evaluator) {
580  const int64_t left = Eval(ct.arguments[0], evaluator);
581  const int64_t right = Eval(ct.arguments[1], evaluator);
582  const bool status = Eval(ct.arguments[2], evaluator) != 0;
583  return (status && (left > right)) || !status;
584 }
585 
586 bool CheckIntGtReif(const Constraint& ct,
587  const std::function<int64_t(IntegerVariable*)>& evaluator) {
588  const int64_t left = Eval(ct.arguments[0], evaluator);
589  const int64_t right = Eval(ct.arguments[1], evaluator);
590  const bool status = Eval(ct.arguments[2], evaluator) != 0;
591  return status == (left > right);
592 }
593 
594 bool CheckIntLe(const Constraint& ct,
595  const std::function<int64_t(IntegerVariable*)>& evaluator) {
596  const int64_t left = Eval(ct.arguments[0], evaluator);
597  const int64_t right = Eval(ct.arguments[1], evaluator);
598  return left <= right;
599 }
600 
601 bool CheckIntLeImp(const Constraint& ct,
602  const std::function<int64_t(IntegerVariable*)>& evaluator) {
603  const int64_t left = Eval(ct.arguments[0], evaluator);
604  const int64_t right = Eval(ct.arguments[1], evaluator);
605  const bool status = Eval(ct.arguments[2], evaluator) != 0;
606  return (status && (left <= right)) || !status;
607 }
608 
609 bool CheckIntLeReif(const Constraint& ct,
610  const std::function<int64_t(IntegerVariable*)>& evaluator) {
611  const int64_t left = Eval(ct.arguments[0], evaluator);
612  const int64_t right = Eval(ct.arguments[1], evaluator);
613  const bool status = Eval(ct.arguments[2], evaluator) != 0;
614  return status == (left <= right);
615 }
616 
617 bool CheckIntLt(const Constraint& ct,
618  const std::function<int64_t(IntegerVariable*)>& evaluator) {
619  const int64_t left = Eval(ct.arguments[0], evaluator);
620  const int64_t right = Eval(ct.arguments[1], evaluator);
621  return left < right;
622 }
623 
624 bool CheckIntLtImp(const Constraint& ct,
625  const std::function<int64_t(IntegerVariable*)>& evaluator) {
626  const int64_t left = Eval(ct.arguments[0], evaluator);
627  const int64_t right = Eval(ct.arguments[1], evaluator);
628  const bool status = Eval(ct.arguments[2], evaluator) != 0;
629  return (status && (left < right)) || !status;
630 }
631 
632 bool CheckIntLtReif(const Constraint& ct,
633  const std::function<int64_t(IntegerVariable*)>& evaluator) {
634  const int64_t left = Eval(ct.arguments[0], evaluator);
635  const int64_t right = Eval(ct.arguments[1], evaluator);
636  const bool status = Eval(ct.arguments[2], evaluator) != 0;
637  return status == (left < right);
638 }
639 
640 int64_t ComputeIntLin(
641  const Constraint& ct,
642  const std::function<int64_t(IntegerVariable*)>& evaluator) {
643  int64_t result = 0;
644  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
645  result += EvalAt(ct.arguments[0], i, evaluator) *
646  EvalAt(ct.arguments[1], i, evaluator);
647  }
648  return result;
649 }
650 
651 bool CheckIntLinEq(const Constraint& ct,
652  const std::function<int64_t(IntegerVariable*)>& evaluator) {
653  const int64_t left = ComputeIntLin(ct, evaluator);
654  const int64_t right = Eval(ct.arguments[2], evaluator);
655  return left == right;
656 }
657 
658 bool CheckIntLinEqImp(
659  const Constraint& ct,
660  const std::function<int64_t(IntegerVariable*)>& evaluator) {
661  const int64_t left = ComputeIntLin(ct, evaluator);
662  const int64_t right = Eval(ct.arguments[2], evaluator);
663  const bool status = Eval(ct.arguments[3], evaluator) != 0;
664  return (status && (left == right)) || !status;
665 }
666 
667 bool CheckIntLinEqReif(
668  const Constraint& ct,
669  const std::function<int64_t(IntegerVariable*)>& evaluator) {
670  const int64_t left = ComputeIntLin(ct, evaluator);
671  const int64_t right = Eval(ct.arguments[2], evaluator);
672  const bool status = Eval(ct.arguments[3], evaluator) != 0;
673  return status == (left == right);
674 }
675 
676 bool CheckIntLinGe(const Constraint& ct,
677  const std::function<int64_t(IntegerVariable*)>& evaluator) {
678  const int64_t left = ComputeIntLin(ct, evaluator);
679  const int64_t right = Eval(ct.arguments[2], evaluator);
680  return left >= right;
681 }
682 
683 bool CheckIntLinGeImp(
684  const Constraint& ct,
685  const std::function<int64_t(IntegerVariable*)>& evaluator) {
686  const int64_t left = ComputeIntLin(ct, evaluator);
687  const int64_t right = Eval(ct.arguments[2], evaluator);
688  const bool status = Eval(ct.arguments[3], evaluator) != 0;
689  return (status && (left >= right)) || !status;
690 }
691 
692 bool CheckIntLinGeReif(
693  const Constraint& ct,
694  const std::function<int64_t(IntegerVariable*)>& evaluator) {
695  const int64_t left = ComputeIntLin(ct, evaluator);
696  const int64_t right = Eval(ct.arguments[2], evaluator);
697  const bool status = Eval(ct.arguments[3], evaluator) != 0;
698  return status == (left >= right);
699 }
700 
701 bool CheckIntLinLe(const Constraint& ct,
702  const std::function<int64_t(IntegerVariable*)>& evaluator) {
703  const int64_t left = ComputeIntLin(ct, evaluator);
704  const int64_t right = Eval(ct.arguments[2], evaluator);
705  return left <= right;
706 }
707 
708 bool CheckIntLinLeImp(
709  const Constraint& ct,
710  const std::function<int64_t(IntegerVariable*)>& evaluator) {
711  const int64_t left = ComputeIntLin(ct, evaluator);
712  const int64_t right = Eval(ct.arguments[2], evaluator);
713  const bool status = Eval(ct.arguments[3], evaluator) != 0;
714  return (status && (left <= right)) || !status;
715 }
716 
717 bool CheckIntLinLeReif(
718  const Constraint& ct,
719  const std::function<int64_t(IntegerVariable*)>& 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);
724 }
725 
726 bool CheckIntLinNe(const Constraint& ct,
727  const std::function<int64_t(IntegerVariable*)>& evaluator) {
728  const int64_t left = ComputeIntLin(ct, evaluator);
729  const int64_t right = Eval(ct.arguments[2], evaluator);
730  return left != right;
731 }
732 
733 bool CheckIntLinNeImp(
734  const Constraint& ct,
735  const std::function<int64_t(IntegerVariable*)>& evaluator) {
736  const int64_t left = ComputeIntLin(ct, evaluator);
737  const int64_t right = Eval(ct.arguments[2], evaluator);
738  const bool status = Eval(ct.arguments[3], evaluator) != 0;
739  return (status && (left != right)) || !status;
740 }
741 
742 bool CheckIntLinNeReif(
743  const Constraint& ct,
744  const std::function<int64_t(IntegerVariable*)>& evaluator) {
745  const int64_t left = ComputeIntLin(ct, evaluator);
746  const int64_t right = Eval(ct.arguments[2], evaluator);
747  const bool status = Eval(ct.arguments[3], evaluator) != 0;
748  return status == (left != right);
749 }
750 
751 bool CheckIntMax(const Constraint& ct,
752  const std::function<int64_t(IntegerVariable*)>& evaluator) {
753  const int64_t left = Eval(ct.arguments[0], evaluator);
754  const int64_t right = Eval(ct.arguments[1], evaluator);
755  const int64_t status = Eval(ct.arguments[2], evaluator);
756  return status == std::max(left, right);
757 }
758 
759 bool CheckIntMin(const Constraint& ct,
760  const std::function<int64_t(IntegerVariable*)>& evaluator) {
761  const int64_t left = Eval(ct.arguments[0], evaluator);
762  const int64_t right = Eval(ct.arguments[1], evaluator);
763  const int64_t status = Eval(ct.arguments[2], evaluator);
764  return status == std::min(left, right);
765 }
766 
767 bool CheckIntMinus(const Constraint& ct,
768  const std::function<int64_t(IntegerVariable*)>& evaluator) {
769  const int64_t left = Eval(ct.arguments[0], evaluator);
770  const int64_t right = Eval(ct.arguments[1], evaluator);
771  const int64_t target = Eval(ct.arguments[2], evaluator);
772  return target == left - right;
773 }
774 
775 bool CheckIntMod(const Constraint& ct,
776  const std::function<int64_t(IntegerVariable*)>& evaluator) {
777  const int64_t left = Eval(ct.arguments[0], evaluator);
778  const int64_t right = Eval(ct.arguments[1], evaluator);
779  const int64_t target = Eval(ct.arguments[2], evaluator);
780  return target == left % right;
781 }
782 
783 bool CheckIntNe(const Constraint& ct,
784  const std::function<int64_t(IntegerVariable*)>& evaluator) {
785  const int64_t left = Eval(ct.arguments[0], evaluator);
786  const int64_t right = Eval(ct.arguments[1], evaluator);
787  return left != right;
788 }
789 
790 bool CheckIntNeImp(const Constraint& ct,
791  const std::function<int64_t(IntegerVariable*)>& evaluator) {
792  const int64_t left = Eval(ct.arguments[0], evaluator);
793  const int64_t right = Eval(ct.arguments[1], evaluator);
794  const bool status = Eval(ct.arguments[2], evaluator) != 0;
795  return (status && (left != right)) || !status;
796 }
797 
798 bool CheckIntNeReif(const Constraint& ct,
799  const std::function<int64_t(IntegerVariable*)>& evaluator) {
800  const int64_t left = Eval(ct.arguments[0], evaluator);
801  const int64_t right = Eval(ct.arguments[1], evaluator);
802  const bool status = Eval(ct.arguments[2], evaluator) != 0;
803  return status == (left != right);
804 }
805 
806 bool CheckIntNegate(const Constraint& ct,
807  const std::function<int64_t(IntegerVariable*)>& evaluator) {
808  const int64_t left = Eval(ct.arguments[0], evaluator);
809  const int64_t right = Eval(ct.arguments[1], evaluator);
810  return left == -right;
811 }
812 
813 bool CheckIntPlus(const Constraint& ct,
814  const std::function<int64_t(IntegerVariable*)>& evaluator) {
815  const int64_t left = Eval(ct.arguments[0], evaluator);
816  const int64_t right = Eval(ct.arguments[1], evaluator);
817  const int64_t target = Eval(ct.arguments[2], evaluator);
818  return target == left + right;
819 }
820 
821 bool CheckIntTimes(const Constraint& ct,
822  const std::function<int64_t(IntegerVariable*)>& evaluator) {
823  const int64_t left = Eval(ct.arguments[0], evaluator);
824  const int64_t right = Eval(ct.arguments[1], evaluator);
825  const int64_t target = Eval(ct.arguments[2], evaluator);
826  return target == left * right;
827 }
828 
829 bool CheckInverse(const Constraint& ct,
830  const std::function<int64_t(IntegerVariable*)>& evaluator) {
831  CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1]));
832  const int size = Size(ct.arguments[0]);
833  // Check all bounds.
834  for (int i = 0; i < size; ++i) {
835  const int64_t x = EvalAt(ct.arguments[0], i, evaluator) - 1;
836  const int64_t y = EvalAt(ct.arguments[1], i, evaluator) - 1;
837  if (x < 0 || x >= size || y < 0 || y >= size) {
838  return false;
839  }
840  }
841  // Check f-1(f(i)) = i.
842  for (int i = 0; i < size; ++i) {
843  const int64_t fi = EvalAt(ct.arguments[0], i, evaluator) - 1;
844  const int64_t invf_fi = EvalAt(ct.arguments[1], fi, evaluator) - 1;
845  if (invf_fi != i) {
846  return false;
847  }
848  }
849 
850  return true;
851 }
852 
853 bool CheckLexLessInt(
854  const Constraint& ct,
855  const std::function<int64_t(IntegerVariable*)>& evaluator) {
856  CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1]));
857  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
858  const int64_t x = EvalAt(ct.arguments[0], i, evaluator);
859  const int64_t y = EvalAt(ct.arguments[1], i, evaluator);
860  if (x < y) {
861  return true;
862  }
863  if (x > y) {
864  return false;
865  }
866  }
867  // We are at the end of the list. The two chains are equals.
868  return false;
869 }
870 
871 bool CheckLexLesseqInt(
872  const Constraint& ct,
873  const std::function<int64_t(IntegerVariable*)>& evaluator) {
874  CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1]));
875  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
876  const int64_t x = EvalAt(ct.arguments[0], i, evaluator);
877  const int64_t y = EvalAt(ct.arguments[1], i, evaluator);
878  if (x < y) {
879  return true;
880  }
881  if (x > y) {
882  return false;
883  }
884  }
885  // We are at the end of the list. The two chains are equals.
886  return true;
887 }
888 
889 bool CheckMaximumArgInt(
890  const Constraint& ct,
891  const std::function<int64_t(IntegerVariable*)>& evaluator) {
892  const int64_t max_index = Eval(ct.arguments[1], evaluator) - 1;
893  const int64_t max_value = EvalAt(ct.arguments[0], max_index, evaluator);
894  // Checks that all value before max_index are < max_value.
895  for (int i = 0; i < max_index; ++i) {
896  if (EvalAt(ct.arguments[0], i, evaluator) >= max_value) {
897  return false;
898  }
899  }
900  // Checks that all value after max_index are <= max_value.
901  for (int i = max_index + 1; i < Size(ct.arguments[0]); i++) {
902  if (EvalAt(ct.arguments[0], i, evaluator) > max_value) {
903  return false;
904  }
905  }
906 
907  return true;
908 }
909 
910 bool CheckMaximumInt(
911  const Constraint& ct,
912  const std::function<int64_t(IntegerVariable*)>& evaluator) {
913  int64_t max_value = std::numeric_limits<int64_t>::min();
914  for (int i = 0; i < Size(ct.arguments[1]); ++i) {
915  max_value = std::max(max_value, EvalAt(ct.arguments[1], i, evaluator));
916  }
917  return max_value == Eval(ct.arguments[0], evaluator);
918 }
919 
920 bool CheckMinimumArgInt(
921  const Constraint& ct,
922  const std::function<int64_t(IntegerVariable*)>& evaluator) {
923  const int64_t min_index = Eval(ct.arguments[1], evaluator) - 1;
924  const int64_t min_value = EvalAt(ct.arguments[0], min_index, evaluator);
925  // Checks that all value before min_index are > min_value.
926  for (int i = 0; i < min_index; ++i) {
927  if (EvalAt(ct.arguments[0], i, evaluator) <= min_value) {
928  return false;
929  }
930  }
931  // Checks that all value after min_index are >= min_value.
932  for (int i = min_index + 1; i < Size(ct.arguments[0]); i++) {
933  if (EvalAt(ct.arguments[0], i, evaluator) < min_value) {
934  return false;
935  }
936  }
937 
938  return true;
939 }
940 
941 bool CheckMinimumInt(
942  const Constraint& ct,
943  const std::function<int64_t(IntegerVariable*)>& evaluator) {
944  int64_t min_value = std::numeric_limits<int64_t>::max();
945  for (int i = 0; i < Size(ct.arguments[1]); ++i) {
946  min_value = std::min(min_value, EvalAt(ct.arguments[1], i, evaluator));
947  }
948  return min_value == Eval(ct.arguments[0], evaluator);
949 }
950 
951 bool CheckNetworkFlowConservation(
952  const Argument& arcs, const Argument& balance_input,
953  const Argument& flow_vars,
954  const std::function<int64_t(IntegerVariable*)>& evaluator) {
955  std::vector<int64_t> balance(balance_input.values);
956 
957  const int num_arcs = Size(arcs) / 2;
958  for (int arc = 0; arc < num_arcs; arc++) {
959  const int tail = arcs.values[arc * 2] - 1;
960  const int head = arcs.values[arc * 2 + 1] - 1;
961  const int64_t flow = EvalAt(flow_vars, arc, evaluator);
962  balance[tail] -= flow;
963  balance[head] += flow;
964  }
965 
966  for (const int64_t value : balance) {
967  if (value != 0) return false;
968  }
969 
970  return true;
971 }
972 
973 bool CheckNetworkFlow(
974  const Constraint& ct,
975  const std::function<int64_t(IntegerVariable*)>& evaluator) {
976  return CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1],
977  ct.arguments[2], evaluator);
978 }
979 
980 bool CheckNetworkFlowCost(
981  const Constraint& ct,
982  const std::function<int64_t(IntegerVariable*)>& evaluator) {
983  if (!CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1],
984  ct.arguments[3], evaluator)) {
985  return false;
986  }
987 
988  int64_t total_cost = 0;
989  const int num_arcs = Size(ct.arguments[3]);
990  for (int arc = 0; arc < num_arcs; arc++) {
991  const int64_t flow = EvalAt(ct.arguments[3], arc, evaluator);
992  const int64_t cost = EvalAt(ct.arguments[2], arc, evaluator);
993  total_cost += flow * cost;
994  }
995 
996  return total_cost == Eval(ct.arguments[4], evaluator);
997 }
998 
999 bool CheckNvalue(const Constraint& ct,
1000  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1001  const int64_t count = Eval(ct.arguments[0], evaluator);
1002  absl::flat_hash_set<int64_t> all_values;
1003  for (int i = 0; i < Size(ct.arguments[1]); ++i) {
1004  all_values.insert(EvalAt(ct.arguments[1], i, evaluator));
1005  }
1006 
1007  return count == all_values.size();
1008 }
1009 
1010 bool CheckRegular(const Constraint& ct,
1011  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1012  return true;
1013 }
1014 
1015 bool CheckRegularNfa(
1016  const Constraint& ct,
1017  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1018  return true;
1019 }
1020 
1021 bool CheckSetIn(const Constraint& ct,
1022  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1023  const int64_t value = Eval(ct.arguments[0], evaluator);
1024  return ct.arguments[1].Contains(value);
1025 }
1026 
1027 bool CheckSetNotIn(const Constraint& ct,
1028  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1029  const int64_t value = Eval(ct.arguments[0], evaluator);
1030  return !ct.arguments[1].Contains(value);
1031 }
1032 
1033 bool CheckSetInReif(const Constraint& ct,
1034  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1035  const int64_t value = Eval(ct.arguments[0], evaluator);
1036  const int64_t status = Eval(ct.arguments[2], evaluator);
1037  return status == ct.arguments[1].Contains(value);
1038 }
1039 
1040 bool CheckSlidingSum(
1041  const Constraint& ct,
1042  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1043  const int64_t low = Eval(ct.arguments[0], evaluator);
1044  const int64_t up = Eval(ct.arguments[1], evaluator);
1045  const int64_t length = Eval(ct.arguments[2], evaluator);
1046  // Compute initial sum.
1047  int64_t sliding_sum = 0;
1048  for (int i = 0; i < std::min<int64_t>(length, Size(ct.arguments[3])); ++i) {
1049  sliding_sum += EvalAt(ct.arguments[3], i, evaluator);
1050  }
1051  if (sliding_sum < low || sliding_sum > up) {
1052  return false;
1053  }
1054  for (int i = length; i < Size(ct.arguments[3]); ++i) {
1055  sliding_sum += EvalAt(ct.arguments[3], i, evaluator) -
1056  EvalAt(ct.arguments[3], i - length, evaluator);
1057  if (sliding_sum < low || sliding_sum > up) {
1058  return false;
1059  }
1060  }
1061  return true;
1062 }
1063 
1064 bool CheckSort(const Constraint& ct,
1065  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1066  CHECK_EQ(Size(ct.arguments[0]), Size(ct.arguments[1]));
1067  absl::flat_hash_map<int64_t, int> init_count;
1068  absl::flat_hash_map<int64_t, int> sorted_count;
1069  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
1070  init_count[EvalAt(ct.arguments[0], i, evaluator)]++;
1071  sorted_count[EvalAt(ct.arguments[1], i, evaluator)]++;
1072  }
1073  if (init_count != sorted_count) {
1074  return false;
1075  }
1076  for (int i = 0; i < Size(ct.arguments[1]) - 1; ++i) {
1077  if (EvalAt(ct.arguments[1], i, evaluator) >
1078  EvalAt(ct.arguments[1], i, evaluator)) {
1079  return false;
1080  }
1081  }
1082  return true;
1083 }
1084 
1085 bool CheckSubCircuit(
1086  const Constraint& ct,
1087  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1088  absl::flat_hash_set<int64_t> visited;
1089  // Find inactive nodes (pointing to themselves).
1090  int64_t current = -1;
1091  for (int i = 0; i < Size(ct.arguments[0]); ++i) {
1092  const int64_t next = EvalAt(ct.arguments[0], i, evaluator) - 1;
1093  if (next != i && current == -1) {
1094  current = next;
1095  } else if (next == i) {
1096  visited.insert(next);
1097  }
1098  }
1099 
1100  // Try to find a path of length 'residual_size'.
1101  const int residual_size = Size(ct.arguments[0]) - visited.size();
1102  for (int i = 0; i < residual_size; ++i) {
1103  const int64_t next = EvalAt(ct.arguments[0], current, evaluator) - 1;
1104  visited.insert(next);
1105  if (next == current) {
1106  return false;
1107  }
1108  current = next;
1109  }
1110 
1111  // Have we visited all nodes?
1112  return visited.size() == Size(ct.arguments[0]);
1113 }
1114 
1115 bool CheckTableInt(const Constraint& ct,
1116  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1117  return true;
1118 }
1119 
1120 bool CheckSymmetricAllDifferent(
1121  const Constraint& ct,
1122  const std::function<int64_t(IntegerVariable*)>& evaluator) {
1123  const int size = Size(ct.arguments[0]);
1124  for (int i = 0; i < size; ++i) {
1125  const int64_t value = EvalAt(ct.arguments[0], i, evaluator) - 1;
1126  if (value < 0 || value >= size) {
1127  return false;
1128  }
1129  const int64_t reverse_value = EvalAt(ct.arguments[0], value, evaluator) - 1;
1130  if (reverse_value != i) {
1131  return false;
1132  }
1133  }
1134  return true;
1135 }
1136 
1137 using CallMap = absl::flat_hash_map<
1138  std::string, std::function<bool(const Constraint& ct,
1139  std::function<int64_t(IntegerVariable*)>)>>;
1140 
1141 // Creates a map between flatzinc predicates and CP-SAT builders.
1142 //
1143 // Predicates starting with fzn_ are predicates with the same name in flatzinc
1144 // and in minizinc. The fzn_ prefix is added to differentiate them.
1145 //
1146 // Predicates starting with ortools_ are predicates defined only in or-tools.
1147 // They are created at compilation time when using the or-tools mzn library.
1148 CallMap CreateCallMap() {
1149  CallMap m;
1150  m["fzn_all_different_int"] = CheckAllDifferentInt;
1151  m["alldifferent_except_0"] = CheckAlldifferentExcept0;
1152  m["among"] = CheckAmong;
1153  m["array_bool_and"] = CheckArrayBoolAnd;
1154  m["array_bool_element"] = CheckArrayIntElement;
1155  m["array_bool_or"] = CheckArrayBoolOr;
1156  m["array_bool_xor"] = CheckArrayBoolXor;
1157  m["array_int_element"] = CheckArrayIntElement;
1158  m["array_int_element_nonshifted"] = CheckArrayIntElementNonShifted;
1159  m["array_var_bool_element"] = CheckArrayVarIntElement;
1160  m["array_var_int_element"] = CheckArrayVarIntElement;
1161  m["at_most_int"] = CheckAtMostInt;
1162  m["bool_and"] = CheckBoolAnd;
1163  m["bool_clause"] = CheckBoolClause;
1164  m["bool_eq"] = CheckIntEq;
1165  m["bool2int"] = CheckIntEq;
1166  m["bool_eq_imp"] = CheckIntEqImp;
1167  m["bool_eq_reif"] = CheckIntEqReif;
1168  m["bool_ge"] = CheckIntGe;
1169  m["bool_ge_imp"] = CheckIntGeImp;
1170  m["bool_ge_reif"] = CheckIntGeReif;
1171  m["bool_gt"] = CheckIntGt;
1172  m["bool_gt_imp"] = CheckIntGtImp;
1173  m["bool_gt_reif"] = CheckIntGtReif;
1174  m["bool_le"] = CheckIntLe;
1175  m["bool_le_imp"] = CheckIntLeImp;
1176  m["bool_le_reif"] = CheckIntLeReif;
1177  m["bool_left_imp"] = CheckIntLe;
1178  m["bool_lin_eq"] = CheckIntLinEq;
1179  m["bool_lin_le"] = CheckIntLinLe;
1180  m["bool_lt"] = CheckIntLt;
1181  m["bool_lt_imp"] = CheckIntLtImp;
1182  m["bool_lt_reif"] = CheckIntLtReif;
1183  m["bool_ne"] = CheckIntNe;
1184  m["bool_ne_imp"] = CheckIntNeImp;
1185  m["bool_ne_reif"] = CheckIntNeReif;
1186  m["bool_not"] = CheckBoolNot;
1187  m["bool_or"] = CheckBoolOr;
1188  m["bool_right_imp"] = CheckIntGe;
1189  m["bool_xor"] = CheckBoolXor;
1190  m["fzn_circuit"] = CheckCircuit;
1191  m["count_eq"] = CheckCountEq;
1192  m["count"] = CheckCountEq;
1193  m["count_geq"] = CheckCountGeq;
1194  m["count_gt"] = CheckCountGt;
1195  m["count_leq"] = CheckCountLeq;
1196  m["count_lt"] = CheckCountLt;
1197  m["count_neq"] = CheckCountNeq;
1198  m["count_reif"] = CheckCountReif;
1199  m["fzn_cumulative"] = CheckCumulative;
1200  m["var_cumulative"] = CheckCumulative;
1201  m["variable_cumulative"] = CheckCumulative;
1202  m["fixed_cumulative"] = CheckCumulative;
1203  m["fzn_diffn"] = CheckDiffn;
1204  m["diffn_k_with_sizes"] = CheckDiffnK;
1205  m["fzn_diffn_nonstrict"] = CheckDiffnNonStrict;
1206  m["diffn_nonstrict_k_with_sizes"] = CheckDiffnNonStrictK;
1207  m["disjunctive"] = CheckDisjunctive;
1208  m["disjunctive_strict"] = CheckDisjunctiveStrict;
1209  m["false_constraint"] = CheckFalseConstraint;
1210  m["global_cardinality"] = CheckGlobalCardinality;
1211  m["global_cardinality_closed"] = CheckGlobalCardinalityClosed;
1212  m["global_cardinality_low_up"] = CheckGlobalCardinalityLowUp;
1213  m["global_cardinality_low_up_closed"] = CheckGlobalCardinalityLowUpClosed;
1214  m["global_cardinality_old"] = CheckGlobalCardinalityOld;
1215  m["int_abs"] = CheckIntAbs;
1216  m["int_div"] = CheckIntDiv;
1217  m["int_eq"] = CheckIntEq;
1218  m["int_eq_imp"] = CheckIntEqImp;
1219  m["int_eq_reif"] = CheckIntEqReif;
1220  m["int_ge"] = CheckIntGe;
1221  m["int_ge_imp"] = CheckIntGeImp;
1222  m["int_ge_reif"] = CheckIntGeReif;
1223  m["int_gt"] = CheckIntGt;
1224  m["int_gt_imp"] = CheckIntGtImp;
1225  m["int_gt_reif"] = CheckIntGtReif;
1226  m["int_le"] = CheckIntLe;
1227  m["int_le_imp"] = CheckIntLeImp;
1228  m["int_le_reif"] = CheckIntLeReif;
1229  m["int_lin_eq"] = CheckIntLinEq;
1230  m["int_lin_eq_imp"] = CheckIntLinEqImp;
1231  m["int_lin_eq_reif"] = CheckIntLinEqReif;
1232  m["int_lin_ge"] = CheckIntLinGe;
1233  m["int_lin_ge_imp"] = CheckIntLinGeImp;
1234  m["int_lin_ge_reif"] = CheckIntLinGeReif;
1235  m["int_lin_le"] = CheckIntLinLe;
1236  m["int_lin_le_imp"] = CheckIntLinLeImp;
1237  m["int_lin_le_reif"] = CheckIntLinLeReif;
1238  m["int_lin_ne"] = CheckIntLinNe;
1239  m["int_lin_ne_imp"] = CheckIntLinNeImp;
1240  m["int_lin_ne_reif"] = CheckIntLinNeReif;
1241  m["int_lt"] = CheckIntLt;
1242  m["int_lt_imp"] = CheckIntLtImp;
1243  m["int_lt_reif"] = CheckIntLtReif;
1244  m["int_max"] = CheckIntMax;
1245  m["int_min"] = CheckIntMin;
1246  m["int_minus"] = CheckIntMinus;
1247  m["int_mod"] = CheckIntMod;
1248  m["int_ne"] = CheckIntNe;
1249  m["int_ne_imp"] = CheckIntNeImp;
1250  m["int_ne_reif"] = CheckIntNeReif;
1251  m["int_negate"] = CheckIntNegate;
1252  m["int_plus"] = CheckIntPlus;
1253  m["int_times"] = CheckIntTimes;
1254  m["fzn_inverse"] = CheckInverse;
1255  m["lex_less_bool"] = CheckLexLessInt;
1256  m["lex_less_int"] = CheckLexLessInt;
1257  m["lex_lesseq_bool"] = CheckLexLesseqInt;
1258  m["lex_lesseq_int"] = CheckLexLesseqInt;
1259  m["maximum_arg_int"] = CheckMaximumArgInt;
1260  m["maximum_int"] = CheckMaximumInt;
1261  m["array_int_maximum"] = CheckMaximumInt;
1262  m["minimum_arg_int"] = CheckMinimumArgInt;
1263  m["minimum_int"] = CheckMinimumInt;
1264  m["array_int_minimum"] = CheckMinimumInt;
1265  m["ortools_network_flow"] = CheckNetworkFlow;
1266  m["ortools_network_flow_cost"] = CheckNetworkFlowCost;
1267  m["nvalue"] = CheckNvalue;
1268  m["ortools_regular"] = CheckRegular;
1269  m["regular_nfa"] = CheckRegularNfa;
1270  m["set_in"] = CheckSetIn;
1271  m["int_in"] = CheckSetIn;
1272  m["set_not_in"] = CheckSetNotIn;
1273  m["int_not_in"] = CheckSetNotIn;
1274  m["set_in_reif"] = CheckSetInReif;
1275  m["sliding_sum"] = CheckSlidingSum;
1276  m["sort"] = CheckSort;
1277  m["fzn_subcircuit"] = CheckSubCircuit;
1278  m["symmetric_all_different"] = CheckSymmetricAllDifferent;
1279  m["ortools_table_bool"] = CheckTableInt;
1280  m["ortools_table_int"] = CheckTableInt;
1281  return m;
1282 }
1283 
1284 } // namespace
1285 
1287  const std::function<int64_t(IntegerVariable*)>& evaluator,
1288  SolverLogger* logger) {
1289  bool ok = true;
1290  const CallMap call_map = CreateCallMap();
1291  for (Constraint* ct : model.constraints()) {
1292  if (!ct->active) continue;
1293  const auto& checker = gtl::FindOrDie(call_map, ct->type);
1294  if (!checker(*ct, evaluator)) {
1295  SOLVER_LOG(logger, "Failing constraint ", ct->DebugString());
1296  ok = false;
1297  }
1298  }
1299  return ok;
1300 }
1301 
1302 } // namespace fz
1303 } // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:498
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:705
#define LOG(severity)
Definition: base/logging.h:423
Block * next
const Constraint * ct
int64_t value
GRBmodel * model
const int FATAL
Definition: log_severity.h:32
bool ContainsKey(const Collection &collection, const Key &key)
Definition: map_util.h:200
const Collection::value_type::second_type & FindOrDie(const Collection &collection, const typename Collection::value_type::first_type &key)
Definition: map_util.h:206
bool CheckSolution(const Model &model, const std::function< int64_t(IntegerVariable *)> &evaluator, SolverLogger *logger)
Definition: checker.cc:1286
Collection of objects used to extend the Constraint Solver library.
int index
Definition: pack.cc:509
int64_t capacity
int64_t tail
int64_t cost
int64_t head
IntegerVariable * Var() const
Definition: model.cc:582
std::vector< IntegerVariable * > variables
IntegerVariable * VarAt(int pos) const
Definition: model.cc:586
std::string DebugString() const
Definition: model.cc:455
std::vector< int64_t > values
int64_t ValueAt(int pos) const
Definition: model.cc:557
std::string DebugString() const
Definition: model.cc:622
std::vector< Argument > arguments
#define SOLVER_LOG(logger,...)
Definition: util/logging.h:63