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