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