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