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