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