Google OR-Tools v9.15
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 <iterator>
21#include <limits>
22#include <string>
23#include <utility>
24#include <vector>
25
26#include "absl/container/flat_hash_map.h"
27#include "absl/container/flat_hash_set.h"
28#include "absl/log/check.h"
29#include "absl/log/log.h"
32
33namespace operations_research {
34namespace fz {
35namespace {
36
37// Helpers
38
39int64_t Eval(const Argument& arg,
40 const std::function<int64_t(Variable*)>& evaluator) {
41 switch (arg.type) {
43 return arg.Value();
44 }
45 case Argument::VAR_REF: {
46 return evaluator(arg.Var());
47 }
48 default: {
49 LOG(FATAL) << "Cannot evaluate " << arg.DebugString();
50 return 0;
51 }
52 }
53}
54
55int Length(const Argument& arg) {
56 return std::max(arg.values.size(), arg.variables.size());
57}
58
59int64_t EvalAt(const Argument& arg, int pos,
60 const std::function<int64_t(Variable*)>& evaluator) {
61 switch (arg.type) {
62 case Argument::INT_LIST: {
63 return arg.ValueAt(pos);
64 }
66 return evaluator(arg.VarAt(pos));
67 }
68 default: {
69 LOG(FATAL) << "Cannot evaluate " << arg.DebugString();
70 return 0;
71 }
72 }
73}
74
75std::vector<int64_t> SetEval(
76 const Argument& arg,
77 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
78 switch (arg.type) {
80 return {arg.Value()};
81 }
83 std::vector<int64_t> result;
84 result.reserve(arg.values[1] - arg.values[0] + 1);
85 for (int64_t i = arg.values[0]; i <= arg.values[1]; ++i) {
86 result.push_back(i);
87 }
88 return result;
89 }
90 case Argument::INT_LIST: {
91 return arg.values;
92 }
93 case Argument::VAR_REF: {
94 return set_evaluator(arg.Var());
95 }
96 default: {
97 LOG(FATAL) << "Cannot evaluate " << arg.DebugString();
98 return {};
99 }
100 }
101}
102
103std::vector<int64_t> SetEvalAt(
104 const Argument& arg, int pos,
105 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
106 switch (arg.type) {
108 const Domain& domain = arg.domains[pos];
109 if (domain.empty()) {
110 return {};
111 } else if (domain.is_interval) {
112 std::vector<int64_t> result;
113 result.reserve(domain.Max() - domain.Min() + 1);
114 for (int64_t i = domain.Min(); i <= domain.Max(); ++i) {
115 result.push_back(i);
116 }
117 return result;
118 } else {
119 return domain.values;
120 }
121 }
123 return set_evaluator(arg.variables[pos]);
124 }
125 default: {
126 LOG(FATAL) << "Cannot evaluate " << arg.DebugString();
127 return {};
128 }
129 }
130}
131
132int64_t SetSize(
133 const Argument& arg,
134 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
135 switch (arg.type) {
136 case Argument::INT_VALUE: {
137 return 1;
138 }
140 return arg.values[1] - arg.values[0] + 1;
141 }
142 case Argument::INT_LIST: {
143 return arg.values.size();
144 }
145 case Argument::VAR_REF: {
146 return set_evaluator(arg.Var()).size();
147 }
148 default: {
149 LOG(FATAL) << "Cannot get the size of " << arg.DebugString();
150 return {};
151 }
152 }
153}
154
155// Checkers
156
157bool CheckAllDifferentInt(
158 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
159 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
160 absl::flat_hash_set<int64_t> visited;
161 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
162 const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
163 if (visited.contains(value)) {
164 return false;
165 }
166 visited.insert(value);
167 }
168
169 return true;
170}
171
172bool CheckAllDifferentSet(
173 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
174 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
175 std::vector<std::vector<int64_t>> values;
176 values.reserve(Length(ct.arguments[0]));
177 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
178 values.push_back(SetEvalAt(ct.arguments[0], i, set_evaluator));
179 }
180 for (int i = 0; i + 1 < values.size(); ++i) {
181 for (int j = i + 1; j < values.size(); ++j) {
182 if (values[i] == values[j]) {
183 return false;
184 }
185 }
186 }
187 return true;
188}
189
190bool CheckAlldifferentExcept0(
191 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
192 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
193 absl::flat_hash_set<int64_t> visited;
194 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
195 const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
196 if (value != 0 && visited.contains(value)) {
197 return false;
198 }
199 visited.insert(value);
200 }
201
202 return true;
203}
204
205bool CheckAllDisjoint(
206 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
207 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
208 absl::flat_hash_set<int64_t> visited;
209 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
210 for (const int64_t value : SetEvalAt(ct.arguments[0], i, set_evaluator)) {
211 if (visited.contains(value)) {
212 return false;
213 }
214 visited.insert(value);
215 }
216 }
217 return true;
218}
219
220bool CheckAmong(
221 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
222 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
223 const int64_t expected = Eval(ct.arguments[0], evaluator);
224 int64_t count = 0;
225 for (int i = 0; i < Length(ct.arguments[1]); ++i) {
226 const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
227 count += ct.arguments[2].Contains(value);
228 }
229
230 return count == expected;
231}
232
233bool CheckArrayBoolAnd(
234 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
235 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
236 int64_t result = 1;
237
238 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
239 const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
240 result = std::min(result, value);
241 }
242
243 return result == Eval(ct.arguments[1], evaluator);
244}
245
246bool CheckArrayBoolOr(
247 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
248 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
249 int64_t result = 0;
250
251 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
252 const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
253 result = std::max(result, value);
254 }
255
256 return result == Eval(ct.arguments[1], evaluator);
257}
258
259bool CheckArrayBoolXor(
260 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
261 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
262 int64_t result = 0;
263
264 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
265 result += EvalAt(ct.arguments[0], i, evaluator);
266 }
267
268 return result % 2 == 1;
269}
270
271bool CheckArrayIntElement(
272 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
273 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
274 // Flatzinc arrays are 1 based.
275 const int64_t shifted_index = Eval(ct.arguments[0], evaluator) - 1;
276 const int64_t element = EvalAt(ct.arguments[1], shifted_index, evaluator);
277 const int64_t target = Eval(ct.arguments[2], evaluator);
278 return element == target;
279}
280
281bool CheckArrayIntElementNonShifted(
282 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
283 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
284 CHECK_EQ(ct.arguments[0].variables.size(), 1);
285 const int64_t index = Eval(ct.arguments[0], evaluator);
286 const int64_t element = EvalAt(ct.arguments[1], index, evaluator);
287 const int64_t target = Eval(ct.arguments[2], evaluator);
288 return element == target;
289}
290
291bool CheckArrayVarIntElement(
292 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
293 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
294 // Flatzinc arrays are 1 based.
295 const int64_t shifted_index = Eval(ct.arguments[0], evaluator) - 1;
296 const int64_t element = EvalAt(ct.arguments[1], shifted_index, evaluator);
297 const int64_t target = Eval(ct.arguments[2], evaluator);
298 return element == target;
299}
300
301bool CheckOrToolsArgMaxInt(
302 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
303 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
304 const int rank = evaluator(ct.arguments[1].Var());
305 const int min_index = ct.arguments[2].Value();
306 const int multiplier = ct.arguments[3].Value();
307 int index = -1;
308 int64_t max_value = std::numeric_limits<int64_t>::min();
309 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
310 const int64_t value = EvalAt(ct.arguments[0], i, evaluator) * multiplier;
311 if (value > max_value) {
312 max_value = value;
313 index = i;
314 }
315 }
316 return index + min_index == rank;
317}
318
319bool CheckOrToolsArrayIntElement(
320 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
321 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
322 const int64_t min_index = ct.arguments[1].values[0];
323 const int64_t index = Eval(ct.arguments[0], evaluator) - min_index;
324 const int64_t element = EvalAt(ct.arguments[2], index, evaluator);
325 const int64_t target = Eval(ct.arguments[3], evaluator);
326 return element == target;
327}
328
329bool CheckAtMostInt(
330 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
331 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
332 const int64_t expected = Eval(ct.arguments[0], evaluator);
333 const int64_t value = Eval(ct.arguments[2], evaluator);
334
335 int64_t count = 0;
336 for (int i = 0; i < Length(ct.arguments[1]); ++i) {
337 count += EvalAt(ct.arguments[1], i, evaluator) == value;
338 }
339 return count <= expected;
340}
341
342bool CheckBoolAnd(
343 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
344 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
345 const int64_t left = Eval(ct.arguments[0], evaluator);
346 const int64_t right = Eval(ct.arguments[1], evaluator);
347 const int64_t status = Eval(ct.arguments[2], evaluator);
348 return status == std::min(left, right);
349}
350
351bool CheckBoolClause(
352 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
353 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
354 int64_t result = 0;
355
356 // Positive variables.
357 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
358 const int64_t value = EvalAt(ct.arguments[0], i, evaluator);
359 result = std::max(result, value);
360 }
361 // Negative variables.
362 for (int i = 0; i < Length(ct.arguments[1]); ++i) {
363 const int64_t value = EvalAt(ct.arguments[1], i, evaluator);
364 result = std::max(result, 1 - value);
365 }
366
367 return result;
368}
369
370bool CheckBoolNot(
371 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
372 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
373 const int64_t left = Eval(ct.arguments[0], evaluator);
374 const int64_t right = Eval(ct.arguments[1], evaluator);
375 return left == 1 - right;
376}
377
378bool CheckBoolOr(
379 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
380 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
381 const int64_t left = Eval(ct.arguments[0], evaluator);
382 const int64_t right = Eval(ct.arguments[1], evaluator);
383 const int64_t status = Eval(ct.arguments[2], evaluator);
384 return status == std::max(left, right);
385}
386
387bool CheckBoolXor(
388 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
389 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
390 const int64_t left = Eval(ct.arguments[0], evaluator);
391 const int64_t right = Eval(ct.arguments[1], evaluator);
392 const int64_t target = Eval(ct.arguments[2], evaluator);
393 return target == (left + right == 1);
394}
395
396bool CheckDisjoint(
397 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
398 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
399 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
400 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
401 std::vector<int64_t> computed_intersection;
402 std::set_intersection(values_x.begin(), values_x.end(), values_y.begin(),
403 values_y.end(),
404 std::back_inserter(computed_intersection));
405 return computed_intersection.empty();
406}
407
408bool CheckOrToolsCircuit(
409 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
410 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
411 const int size = Length(ct.arguments[0]);
412 const int base = ct.arguments[1].Value();
413
414 absl::flat_hash_set<int64_t> visited;
415 int64_t current = 0;
416 for (int i = 0; i < size; ++i) {
417 const int64_t next = EvalAt(ct.arguments[0], current, evaluator) - base;
418 visited.insert(next);
419 current = next;
420 }
421 return visited.size() == size;
422}
423
424bool CheckOrToolsBinPacking(
425 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
426 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
427 const int64_t capacity = ct.arguments[0].Value();
428 const int num_positions = Length(ct.arguments[1]);
429 const std::vector<int64_t>& weights = ct.arguments[2].values;
430 absl::flat_hash_map<int64_t, int64_t> loads;
431 for (int i = 0; i < num_positions; ++i) {
432 const int64_t selected_bin = EvalAt(ct.arguments[1], i, evaluator);
433 loads[selected_bin] += weights[i];
434 }
435 for (const auto& [pos, load] : loads) {
436 if (load > capacity) {
437 return false;
438 }
439 }
440 return true;
441}
442
443bool CheckOrToolsBinPackingCapa(
444 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
445 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
446 const std::vector<int64_t>& capacities = ct.arguments[0].values;
447 const int num_positions = Length(ct.arguments[1]);
448 const int64_t first_bin = ct.arguments[2].values[0];
449 const int64_t last_bin = ct.arguments[2].values[1];
450 const std::vector<int64_t>& weights = ct.arguments[3].values;
451 std::vector<int64_t> actual_loads(last_bin - first_bin + 1, 0);
452 for (int i = 0; i < num_positions; ++i) {
453 const int64_t selected_bin = EvalAt(ct.arguments[1], i, evaluator);
454 actual_loads[selected_bin - first_bin] += weights[i];
455 }
456 for (int i = first_bin; i <= last_bin; ++i) {
457 if (actual_loads[i - first_bin] > capacities[i - first_bin]) {
458 return false;
459 }
460 }
461 return true;
462}
463
464bool CheckOrToolsBinPackingLoad(
465 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
466 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
467 const int num_positions = Length(ct.arguments[1]);
468 const int64_t first_bin = ct.arguments[2].values[0];
469 const int64_t last_bin = ct.arguments[2].values[1];
470 const std::vector<int64_t>& weights = ct.arguments[3].values;
471 std::vector<int64_t> actual_loads(last_bin - first_bin + 1, 0);
472 for (int p = 0; p < num_positions; ++p) {
473 const int64_t pos = EvalAt(ct.arguments[1], p, evaluator);
474 actual_loads[pos - first_bin] += weights[p];
475 }
476 for (int b = first_bin; b <= last_bin; ++b) {
477 const int64_t expected_load =
478 EvalAt(ct.arguments[0], b - first_bin, evaluator);
479 if (actual_loads[b - first_bin] != expected_load) {
480 return false;
481 }
482 }
483 return true;
484}
485
486bool CheckOrToolsNValue(
487 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
488 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
489 const int64_t card = Eval(ct.arguments[0], evaluator);
490 absl::flat_hash_set<int64_t> values;
491 for (int i = 0; i < Length(ct.arguments[1]); ++i) {
492 values.insert(EvalAt(ct.arguments[1], i, evaluator));
493 }
494 return card == values.size();
495}
496
497int64_t ComputeCount(const Constraint& ct,
498 const std::function<int64_t(Variable*)>& evaluator) {
499 int64_t result = 0;
500 const int64_t value = Eval(ct.arguments[1], evaluator);
501 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
502 result += EvalAt(ct.arguments[0], i, evaluator) == value;
503 }
504 return result;
505}
506
507bool CheckOrToolsCountEq(
508 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
509 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
510 const int64_t count = ComputeCount(ct, evaluator);
511 const int64_t expected = Eval(ct.arguments[2], evaluator);
512 return count == expected;
513}
514
515bool CheckCountGeq(
516 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
517 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
518 const int64_t count = ComputeCount(ct, evaluator);
519 const int64_t expected = Eval(ct.arguments[2], evaluator);
520 return count >= expected;
521}
522
523bool CheckCountGt(
524 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
525 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
526 const int64_t count = ComputeCount(ct, evaluator);
527 const int64_t expected = Eval(ct.arguments[2], evaluator);
528 return count > expected;
529}
530
531bool CheckCountLeq(
532 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
533 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
534 const int64_t count = ComputeCount(ct, evaluator);
535 const int64_t expected = Eval(ct.arguments[2], evaluator);
536 return count <= expected;
537}
538
539bool CheckCountLt(
540 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
541 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
542 const int64_t count = ComputeCount(ct, evaluator);
543 const int64_t expected = Eval(ct.arguments[2], evaluator);
544 return count < expected;
545}
546
547bool CheckCountNeq(
548 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
549 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
550 const int64_t count = ComputeCount(ct, evaluator);
551 const int64_t expected = Eval(ct.arguments[2], evaluator);
552 return count != expected;
553}
554
555bool CheckCountReif(
556 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
557 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
558 const int64_t count = ComputeCount(ct, evaluator);
559 const int64_t expected = Eval(ct.arguments[2], evaluator);
560 const int64_t status = Eval(ct.arguments[3], evaluator);
561 return status == (expected == count);
562}
563
564bool CheckCumulative(
565 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
566 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
567 // TODO(user): Improve complexity for large durations.
568 const int64_t capacity = Eval(ct.arguments[3], evaluator);
569 const int size = Length(ct.arguments[0]);
570 CHECK_EQ(size, Length(ct.arguments[1]));
571 CHECK_EQ(size, Length(ct.arguments[2]));
572 absl::flat_hash_map<int64_t, int64_t> usage;
573 for (int i = 0; i < size; ++i) {
574 const int64_t start = EvalAt(ct.arguments[0], i, evaluator);
575 const int64_t duration = EvalAt(ct.arguments[1], i, evaluator);
576 const int64_t requirement = EvalAt(ct.arguments[2], i, evaluator);
577 for (int64_t t = start; t < start + duration; ++t) {
578 usage[t] += requirement;
579 if (usage[t] > capacity) {
580 return false;
581 }
582 }
583 }
584 return true;
585}
586
587bool CheckOrToolsCumulativeOpt(
588 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
589 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
590 // TODO: Improve complexity for large durations.
591 const int64_t capacity = Eval(ct.arguments[4], evaluator);
592 const int size = Length(ct.arguments[0]);
593 CHECK_EQ(size, Length(ct.arguments[1]));
594 CHECK_EQ(size, Length(ct.arguments[2]));
595 CHECK_EQ(size, Length(ct.arguments[3]));
596 absl::flat_hash_map<int64_t, int64_t> usage;
597 for (int i = 0; i < size; ++i) {
598 if (EvalAt(ct.arguments[0], i, evaluator) == 0) continue;
599 const int64_t start = EvalAt(ct.arguments[1], i, evaluator);
600 const int64_t duration = EvalAt(ct.arguments[2], i, evaluator);
601 const int64_t requirement = EvalAt(ct.arguments[3], i, evaluator);
602 for (int64_t t = start; t < start + duration; ++t) {
603 usage[t] += requirement;
604 if (usage[t] > capacity) {
605 return false;
606 }
607 }
608 }
609 return true;
610}
611
612bool CheckDiffn(
613 const Constraint& /*ct*/,
614 const std::function<int64_t(Variable*)>& /*evaluator*/,
615 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
616 return true;
617}
618
619bool CheckDiffnK(
620 const Constraint& /*ct*/,
621 const std::function<int64_t(Variable*)>& /*evaluator*/,
622 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
623 return true;
624}
625
626bool CheckDiffnNonStrict(
627 const Constraint& /*ct*/,
628 const std::function<int64_t(Variable*)>& /*evaluator*/,
629 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
630 return true;
631}
632
633bool CheckDiffnNonStrictK(
634 const Constraint& /*ct*/,
635 const std::function<int64_t(Variable*)>& /*evaluator*/,
636 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
637 return true;
638}
639
640bool CheckDisjunctive(
641 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
642 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
643 const int size = Length(ct.arguments[0]);
644 CHECK_EQ(size, Length(ct.arguments[1]));
645 std::vector<std::pair<int64_t, int64_t>> start_durations_pairs;
646 start_durations_pairs.reserve(size);
647 for (int i = 0; i + 1 < size; ++i) {
648 const int64_t duration = EvalAt(ct.arguments[1], i, evaluator);
649 if (duration == 0) continue;
650 const int64_t start = EvalAt(ct.arguments[0], i, evaluator);
651 start_durations_pairs.push_back({start, duration});
652 }
653 std::sort(start_durations_pairs.begin(), start_durations_pairs.end());
654 int64_t previous_end = std::numeric_limits<int64_t>::min();
655 for (const auto& pair : start_durations_pairs) {
656 if (pair.first < previous_end) return false;
657 previous_end = pair.first + pair.second;
658 }
659 return true;
660}
661
662bool CheckDisjunctiveStrict(
663 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
664 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
665 const int size = Length(ct.arguments[0]);
666 CHECK_EQ(size, Length(ct.arguments[1]));
667 std::vector<std::pair<int64_t, int64_t>> start_durations_pairs;
668 start_durations_pairs.reserve(size);
669 for (int i = 0; i + 1 < size; ++i) {
670 const int64_t start = EvalAt(ct.arguments[0], i, evaluator);
671 const int64_t duration = EvalAt(ct.arguments[1], i, evaluator);
672 start_durations_pairs.push_back({start, duration});
673 }
674 std::sort(start_durations_pairs.begin(), start_durations_pairs.end());
675 int64_t previous_end = std::numeric_limits<int64_t>::min();
676 for (const auto& pair : start_durations_pairs) {
677 if (pair.first < previous_end) return false;
678 previous_end = pair.first + pair.second;
679 }
680 return true;
681}
682
683bool CheckOrToolsDisjunctiveStrictOpt(
684 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
685 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
686 const int size = Length(ct.arguments[0]);
687 CHECK_EQ(size, Length(ct.arguments[1]));
688 CHECK_EQ(size, Length(ct.arguments[2]));
689 std::vector<std::pair<int64_t, int64_t>> start_durations_pairs;
690 start_durations_pairs.reserve(size);
691 for (int i = 0; i + 1 < size; ++i) {
692 if (EvalAt(ct.arguments[0], i, evaluator) == 0) continue;
693 const int64_t start = EvalAt(ct.arguments[1], i, evaluator);
694 const int64_t duration = EvalAt(ct.arguments[2], i, evaluator);
695 start_durations_pairs.push_back({start, duration});
696 }
697 std::sort(start_durations_pairs.begin(), start_durations_pairs.end());
698 int64_t previous_end = std::numeric_limits<int64_t>::min();
699 for (const auto& pair : start_durations_pairs) {
700 if (pair.first < previous_end) return false;
701 previous_end = pair.first + pair.second;
702 }
703 return true;
704}
705
706bool CheckPartitionSet(
707 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
708 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
709 absl::flat_hash_set<int64_t> visited;
710 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
711 for (const int64_t value : SetEvalAt(ct.arguments[0], i, set_evaluator)) {
712 if (visited.contains(value)) {
713 return false;
714 }
715 visited.insert(value);
716 }
717 }
718 const std::vector<int64_t> universe = SetEval(ct.arguments[1], set_evaluator);
719 if (universe.size() != visited.size()) return false;
720 for (const int64_t value : universe) {
721 if (!visited.contains(value)) {
722 return false;
723 }
724 }
725
726 return true;
727}
728
729bool CheckFalseConstraint(
730 const Constraint& /*ct*/,
731 const std::function<int64_t(Variable*)>& /*evaluator*/,
732 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
733 return false;
734}
735
736std::vector<int64_t> ComputeGlobalCardinalityCards(
737 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator) {
738 std::vector<int64_t> cards(Length(ct.arguments[1]), 0);
739 absl::flat_hash_map<int64_t, int> positions;
740 for (int i = 0; i < ct.arguments[1].values.size(); ++i) {
741 const int64_t value = ct.arguments[1].values[i];
742 CHECK(!positions.contains(value));
743 positions[value] = i;
744 }
745 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
746 const int value = EvalAt(ct.arguments[0], i, evaluator);
747 if (positions.contains(value)) {
748 cards[positions[value]]++;
749 }
750 }
751 return cards;
752}
753
754bool CheckOrToolsGlobalCardinality(
755 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
756 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
757 const std::vector<int64_t> cards =
758 ComputeGlobalCardinalityCards(ct, evaluator);
759 CHECK_EQ(cards.size(), Length(ct.arguments[2]));
760 const bool is_closed = Eval(ct.arguments[3], evaluator) != 0;
761 for (int i = 0; i < Length(ct.arguments[2]); ++i) {
762 const int64_t card = EvalAt(ct.arguments[2], i, evaluator);
763 if (card != cards[i]) {
764 return false;
765 }
766 }
767
768 if (is_closed) {
769 int64_t sum_of_cards = 0;
770 for (int64_t card : cards) {
771 sum_of_cards += card;
772 }
773 return sum_of_cards == Length(ct.arguments[0]);
774 }
775 return true;
776}
777
778bool CheckOrToolsGlobalCardinalityLowUp(
779 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
780 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
781 const std::vector<int64_t> cards =
782 ComputeGlobalCardinalityCards(ct, evaluator);
783 CHECK_EQ(cards.size(), ct.arguments[2].values.size());
784 CHECK_EQ(cards.size(), ct.arguments[3].values.size());
785 const bool is_closed = Eval(ct.arguments[4], evaluator) != 0;
786 for (int i = 0; i < cards.size(); ++i) {
787 const int64_t card = cards[i];
788 if (card < ct.arguments[2].values[i] || card > ct.arguments[3].values[i]) {
789 return false;
790 }
791 }
792
793 if (is_closed) {
794 int64_t sum_of_cards = 0;
795 for (int64_t card : cards) {
796 sum_of_cards += card;
797 }
798 return sum_of_cards == Length(ct.arguments[0]);
799 }
800 return true;
801}
802
803bool CheckIntAbs(
804 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
805 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
806 const int64_t left = Eval(ct.arguments[0], evaluator);
807 const int64_t right = Eval(ct.arguments[1], evaluator);
808 return std::abs(left) == right;
809}
810
811bool CheckIntDiv(
812 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
813 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
814 const int64_t left = Eval(ct.arguments[0], evaluator);
815 const int64_t right = Eval(ct.arguments[1], evaluator);
816 const int64_t target = Eval(ct.arguments[2], evaluator);
817 return target == left / right;
818}
819
820bool CheckIntEq(
821 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
822 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
823 const int64_t left = Eval(ct.arguments[0], evaluator);
824 const int64_t right = Eval(ct.arguments[1], evaluator);
825 return left == right;
826}
827
828bool CheckIntEqImp(
829 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
830 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
831 const int64_t left = Eval(ct.arguments[0], evaluator);
832 const int64_t right = Eval(ct.arguments[1], evaluator);
833 const bool status = Eval(ct.arguments[2], evaluator) != 0;
834 return (status && (left == right)) || !status;
835}
836
837bool CheckIntEqReif(
838 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
839 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
840 const int64_t left = Eval(ct.arguments[0], evaluator);
841 const int64_t right = Eval(ct.arguments[1], evaluator);
842 const bool status = Eval(ct.arguments[2], evaluator) != 0;
843 return status == (left == right);
844}
845
846bool CheckIntGe(
847 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
848 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
849 const int64_t left = Eval(ct.arguments[0], evaluator);
850 const int64_t right = Eval(ct.arguments[1], evaluator);
851 return left >= right;
852}
853
854bool CheckIntGeImp(
855 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
856 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
857 const int64_t left = Eval(ct.arguments[0], evaluator);
858 const int64_t right = Eval(ct.arguments[1], evaluator);
859 const bool status = Eval(ct.arguments[2], evaluator) != 0;
860 return (status && (left >= right)) || !status;
861}
862
863bool CheckIntGeReif(
864 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
865 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
866 const int64_t left = Eval(ct.arguments[0], evaluator);
867 const int64_t right = Eval(ct.arguments[1], evaluator);
868 const bool status = Eval(ct.arguments[2], evaluator) != 0;
869 return status == (left >= right);
870}
871
872bool CheckIntGt(
873 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
874 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
875 const int64_t left = Eval(ct.arguments[0], evaluator);
876 const int64_t right = Eval(ct.arguments[1], evaluator);
877 return left > right;
878}
879
880bool CheckIntGtImp(
881 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
882 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
883 const int64_t left = Eval(ct.arguments[0], evaluator);
884 const int64_t right = Eval(ct.arguments[1], evaluator);
885 const bool status = Eval(ct.arguments[2], evaluator) != 0;
886 return (status && (left > right)) || !status;
887}
888
889bool CheckIntGtReif(
890 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
891 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
892 const int64_t left = Eval(ct.arguments[0], evaluator);
893 const int64_t right = Eval(ct.arguments[1], evaluator);
894 const bool status = Eval(ct.arguments[2], evaluator) != 0;
895 return status == (left > right);
896}
897
898bool CheckIntLe(
899 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
900 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
901 const int64_t left = Eval(ct.arguments[0], evaluator);
902 const int64_t right = Eval(ct.arguments[1], evaluator);
903 return left <= right;
904}
905
906bool CheckIntLeImp(
907 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
908 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
909 const int64_t left = Eval(ct.arguments[0], evaluator);
910 const int64_t right = Eval(ct.arguments[1], evaluator);
911 const bool status = Eval(ct.arguments[2], evaluator) != 0;
912 return (status && (left <= right)) || !status;
913}
914
915bool CheckIntLeReif(
916 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
917 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
918 const int64_t left = Eval(ct.arguments[0], evaluator);
919 const int64_t right = Eval(ct.arguments[1], evaluator);
920 const bool status = Eval(ct.arguments[2], evaluator) != 0;
921 return status == (left <= right);
922}
923
924bool CheckIntLt(
925 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
926 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
927 const int64_t left = Eval(ct.arguments[0], evaluator);
928 const int64_t right = Eval(ct.arguments[1], evaluator);
929 return left < right;
930}
931
932bool CheckIntLtImp(
933 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
934 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
935 const int64_t left = Eval(ct.arguments[0], evaluator);
936 const int64_t right = Eval(ct.arguments[1], evaluator);
937 const bool status = Eval(ct.arguments[2], evaluator) != 0;
938 return (status && (left < right)) || !status;
939}
940
941bool CheckIntLtReif(
942 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
943 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
944 const int64_t left = Eval(ct.arguments[0], evaluator);
945 const int64_t right = Eval(ct.arguments[1], evaluator);
946 const bool status = Eval(ct.arguments[2], evaluator) != 0;
947 return status == (left < right);
948}
949
950int64_t ComputeIntLin(const Constraint& ct,
951 const std::function<int64_t(Variable*)>& evaluator) {
952 int64_t result = 0;
953 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
954 result += EvalAt(ct.arguments[0], i, evaluator) *
955 EvalAt(ct.arguments[1], i, evaluator);
956 }
957 return result;
958}
959
960bool CheckIntLinEq(
961 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
962 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
963 const int64_t left = ComputeIntLin(ct, evaluator);
964 const int64_t right = Eval(ct.arguments[2], evaluator);
965 return left == right;
966}
967
968bool CheckIntLinEqImp(
969 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
970 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
971 const int64_t left = ComputeIntLin(ct, evaluator);
972 const int64_t right = Eval(ct.arguments[2], evaluator);
973 const bool status = Eval(ct.arguments[3], evaluator) != 0;
974 return (status && (left == right)) || !status;
975}
976
977bool CheckIntLinEqReif(
978 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
979 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
980 const int64_t left = ComputeIntLin(ct, evaluator);
981 const int64_t right = Eval(ct.arguments[2], evaluator);
982 const bool status = Eval(ct.arguments[3], evaluator) != 0;
983 return status == (left == right);
984}
985
986bool CheckIntLinGe(
987 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
988 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
989 const int64_t left = ComputeIntLin(ct, evaluator);
990 const int64_t right = Eval(ct.arguments[2], evaluator);
991 return left >= right;
992}
993
994bool CheckIntLinGeImp(
995 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
996 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
997 const int64_t left = ComputeIntLin(ct, evaluator);
998 const int64_t right = Eval(ct.arguments[2], evaluator);
999 const bool status = Eval(ct.arguments[3], evaluator) != 0;
1000 return (status && (left >= right)) || !status;
1001}
1002
1003bool CheckIntLinGeReif(
1004 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1005 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1006 const int64_t left = ComputeIntLin(ct, evaluator);
1007 const int64_t right = Eval(ct.arguments[2], evaluator);
1008 const bool status = Eval(ct.arguments[3], evaluator) != 0;
1009 return status == (left >= right);
1010}
1011
1012bool CheckIntLinLe(
1013 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1014 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1015 const int64_t left = ComputeIntLin(ct, evaluator);
1016 const int64_t right = Eval(ct.arguments[2], evaluator);
1017 return left <= right;
1018}
1019
1020bool CheckIntLinLeImp(
1021 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1022 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1023 const int64_t left = ComputeIntLin(ct, evaluator);
1024 const int64_t right = Eval(ct.arguments[2], evaluator);
1025 const bool status = Eval(ct.arguments[3], evaluator) != 0;
1026 return (status && (left <= right)) || !status;
1027}
1028
1029bool CheckIntLinLeReif(
1030 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1031 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1032 const int64_t left = ComputeIntLin(ct, evaluator);
1033 const int64_t right = Eval(ct.arguments[2], evaluator);
1034 const bool status = Eval(ct.arguments[3], evaluator) != 0;
1035 return status == (left <= right);
1036}
1037
1038bool CheckIntLinNe(
1039 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1040 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1041 const int64_t left = ComputeIntLin(ct, evaluator);
1042 const int64_t right = Eval(ct.arguments[2], evaluator);
1043 return left != right;
1044}
1045
1046bool CheckIntLinNeImp(
1047 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1048 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1049 const int64_t left = ComputeIntLin(ct, evaluator);
1050 const int64_t right = Eval(ct.arguments[2], evaluator);
1051 const bool status = Eval(ct.arguments[3], evaluator) != 0;
1052 return (status && (left != right)) || !status;
1053}
1054
1055bool CheckIntLinNeReif(
1056 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1057 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1058 const int64_t left = ComputeIntLin(ct, evaluator);
1059 const int64_t right = Eval(ct.arguments[2], evaluator);
1060 const bool status = Eval(ct.arguments[3], evaluator) != 0;
1061 return status == (left != right);
1062}
1063
1064bool CheckIntMax(
1065 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1066 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1067 const int64_t left = Eval(ct.arguments[0], evaluator);
1068 const int64_t right = Eval(ct.arguments[1], evaluator);
1069 const int64_t status = Eval(ct.arguments[2], evaluator);
1070 return status == std::max(left, right);
1071}
1072
1073bool CheckIntMin(
1074 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1075 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1076 const int64_t left = Eval(ct.arguments[0], evaluator);
1077 const int64_t right = Eval(ct.arguments[1], evaluator);
1078 const int64_t status = Eval(ct.arguments[2], evaluator);
1079 return status == std::min(left, right);
1080}
1081
1082bool CheckIntMinus(
1083 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1084 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1085 const int64_t left = Eval(ct.arguments[0], evaluator);
1086 const int64_t right = Eval(ct.arguments[1], evaluator);
1087 const int64_t target = Eval(ct.arguments[2], evaluator);
1088 return target == left - right;
1089}
1090
1091bool CheckIntMod(
1092 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1093 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1094 const int64_t left = Eval(ct.arguments[0], evaluator);
1095 const int64_t right = Eval(ct.arguments[1], evaluator);
1096 const int64_t target = Eval(ct.arguments[2], evaluator);
1097 return target == left % right;
1098}
1099
1100bool CheckIntNe(
1101 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1102 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1103 const int64_t left = Eval(ct.arguments[0], evaluator);
1104 const int64_t right = Eval(ct.arguments[1], evaluator);
1105 return left != right;
1106}
1107
1108bool CheckIntNeImp(
1109 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1110 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1111 const int64_t left = Eval(ct.arguments[0], evaluator);
1112 const int64_t right = Eval(ct.arguments[1], evaluator);
1113 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1114 return (status && (left != right)) || !status;
1115}
1116
1117bool CheckIntNeReif(
1118 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1119 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1120 const int64_t left = Eval(ct.arguments[0], evaluator);
1121 const int64_t right = Eval(ct.arguments[1], evaluator);
1122 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1123 return status == (left != right);
1124}
1125
1126bool CheckIntNegate(
1127 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1128 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1129 const int64_t left = Eval(ct.arguments[0], evaluator);
1130 const int64_t right = Eval(ct.arguments[1], evaluator);
1131 return left == -right;
1132}
1133
1134bool CheckIntPlus(
1135 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1136 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1137 const int64_t left = Eval(ct.arguments[0], evaluator);
1138 const int64_t right = Eval(ct.arguments[1], evaluator);
1139 const int64_t target = Eval(ct.arguments[2], evaluator);
1140 return target == left + right;
1141}
1142
1143bool CheckIntTimes(
1144 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1145 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1146 const int64_t left = Eval(ct.arguments[0], evaluator);
1147 const int64_t right = Eval(ct.arguments[1], evaluator);
1148 const int64_t target = Eval(ct.arguments[2], evaluator);
1149 return target == left * right;
1150}
1151
1152bool CheckOrToolsInverse(
1153 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1154 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1155 CHECK_EQ(Length(ct.arguments[0]), Length(ct.arguments[1]));
1156 const int size = Length(ct.arguments[0]);
1157 const int f_base = ct.arguments[2].Value();
1158 const int invf_base = ct.arguments[3].Value();
1159 // Check all bounds.
1160 for (int i = 0; i < size; ++i) {
1161 const int64_t x = EvalAt(ct.arguments[0], i, evaluator) - invf_base;
1162 const int64_t y = EvalAt(ct.arguments[1], i, evaluator) - f_base;
1163 if (x < 0 || x >= size || y < 0 || y >= size) {
1164 return false;
1165 }
1166 }
1167
1168 // Check f-1(f(i)) = i.
1169 for (int i = 0; i < size; ++i) {
1170 const int64_t fi = EvalAt(ct.arguments[0], i, evaluator) - invf_base;
1171 const int64_t invf_fi = EvalAt(ct.arguments[1], fi, evaluator) - f_base;
1172 if (invf_fi != i) {
1173 return false;
1174 }
1175 }
1176
1177 return true;
1178}
1179
1180bool CheckOrToolsLexLessInt(
1181 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1182 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1183 const int min_size =
1184 std::min(Length(ct.arguments[0]), Length(ct.arguments[1]));
1185 for (int i = 0; i < min_size; ++i) {
1186 const int64_t x = EvalAt(ct.arguments[0], i, evaluator);
1187 const int64_t y = EvalAt(ct.arguments[1], i, evaluator);
1188 if (x < y) {
1189 return true;
1190 }
1191 if (x > y) {
1192 return false;
1193 }
1194 }
1195 // We are at the end of the common list. We compare the lengths of the lists.
1196 return Length(ct.arguments[1]) > Length(ct.arguments[0]);
1197}
1198
1199bool CheckOrToolsLexLesseqInt(
1200 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1201 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1202 const int min_size =
1203 std::min(Length(ct.arguments[0]), Length(ct.arguments[1]));
1204 for (int i = 0; i < min_size; ++i) {
1205 const int64_t x = EvalAt(ct.arguments[0], i, evaluator);
1206 const int64_t y = EvalAt(ct.arguments[1], i, evaluator);
1207 if (x < y) {
1208 return true;
1209 }
1210 if (x > y) {
1211 return false;
1212 }
1213 }
1214 // We are at the end of the common list. We compare the lengths of the lists.
1215 return Length(ct.arguments[1]) >= Length(ct.arguments[0]);
1216}
1217
1218bool CheckMaximumArgInt(
1219 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1220 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1221 const int64_t max_index = Eval(ct.arguments[1], evaluator) - 1;
1222 const int64_t max_value = EvalAt(ct.arguments[0], max_index, evaluator);
1223 // Checks that all value before max_index are < max_value.
1224 for (int i = 0; i < max_index; ++i) {
1225 if (EvalAt(ct.arguments[0], i, evaluator) >= max_value) {
1226 return false;
1227 }
1228 }
1229 // Checks that all value after max_index are <= max_value.
1230 for (int i = max_index + 1; i < Length(ct.arguments[0]); i++) {
1231 if (EvalAt(ct.arguments[0], i, evaluator) > max_value) {
1232 return false;
1233 }
1234 }
1235
1236 return true;
1237}
1238
1239bool CheckMaximumInt(
1240 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1241 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1242 int64_t max_value = std::numeric_limits<int64_t>::min();
1243 for (int i = 0; i < Length(ct.arguments[1]); ++i) {
1244 max_value = std::max(max_value, EvalAt(ct.arguments[1], i, evaluator));
1245 }
1246 return max_value == Eval(ct.arguments[0], evaluator);
1247}
1248
1249bool CheckMinimumArgInt(
1250 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1251 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1252 const int64_t min_index = Eval(ct.arguments[1], evaluator) - 1;
1253 const int64_t min_value = EvalAt(ct.arguments[0], min_index, evaluator);
1254 // Checks that all value before min_index are > min_value.
1255 for (int i = 0; i < min_index; ++i) {
1256 if (EvalAt(ct.arguments[0], i, evaluator) <= min_value) {
1257 return false;
1258 }
1259 }
1260 // Checks that all value after min_index are >= min_value.
1261 for (int i = min_index + 1; i < Length(ct.arguments[0]); i++) {
1262 if (EvalAt(ct.arguments[0], i, evaluator) < min_value) {
1263 return false;
1264 }
1265 }
1266
1267 return true;
1268}
1269
1270bool CheckMinimumInt(
1271 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1272 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1273 int64_t min_value = std::numeric_limits<int64_t>::max();
1274 for (int i = 0; i < Length(ct.arguments[1]); ++i) {
1275 min_value = std::min(min_value, EvalAt(ct.arguments[1], i, evaluator));
1276 }
1277 return min_value == Eval(ct.arguments[0], evaluator);
1278}
1279
1280bool CheckNetworkFlowConservation(
1281 const Argument& arcs, const Argument& balance_input, int base_node,
1282 const Argument& flow_vars,
1283 const std::function<int64_t(Variable*)>& evaluator) {
1284 std::vector<int64_t> balance(balance_input.values);
1285 const int num_arcs = Length(arcs) / 2;
1286 for (int arc = 0; arc < num_arcs; arc++) {
1287 const int tail = arcs.values[arc * 2] - base_node;
1288 const int head = arcs.values[arc * 2 + 1] - base_node;
1289 const int64_t flow = EvalAt(flow_vars, arc, evaluator);
1290 balance[tail] -= flow;
1291 balance[head] += flow;
1292 }
1293
1294 for (const int64_t value : balance) {
1295 if (value != 0) return false;
1296 }
1297
1298 return true;
1299}
1300
1301bool CheckOrToolsNetworkFlow(
1302 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1303 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1304 return CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1],
1305 ct.arguments[2].Value(), ct.arguments[3],
1306 evaluator);
1307}
1308
1309bool CheckOrToolsNetworkFlowCost(
1310 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1311 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1312 if (!CheckNetworkFlowConservation(ct.arguments[0], ct.arguments[1],
1313 ct.arguments[2].Value(), ct.arguments[3],
1314 evaluator)) {
1315 return false;
1316 }
1317
1318 int64_t total_cost = 0;
1319 const int num_arcs = Length(ct.arguments[3]);
1320 for (int arc = 0; arc < num_arcs; arc++) {
1321 const int64_t flow = EvalAt(ct.arguments[3], arc, evaluator);
1322 const int64_t unit_cost = ct.arguments[4].ValueAt(arc);
1323 total_cost += flow * unit_cost;
1324 }
1325
1326 return total_cost == Eval(ct.arguments[5], evaluator);
1327}
1328
1329bool CheckOrToolsRegular(
1330 const Constraint& /*ct*/,
1331 const std::function<int64_t(Variable*)>& /*evaluator*/,
1332 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
1333 return true;
1334}
1335
1336bool CheckRegularNfa(
1337 const Constraint& /*ct*/,
1338 const std::function<int64_t(Variable*)>& /*evaluator*/,
1339 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
1340 return true;
1341}
1342
1343bool CheckSetCard(
1344 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1345 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1346 const int64_t set_size = SetSize(ct.arguments[0], set_evaluator);
1347 const int64_t cardinality = Eval(ct.arguments[1], evaluator);
1348 return set_size == cardinality;
1349}
1350
1351bool CheckArraySetElement(
1352 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1353 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1354 const int64_t index = Eval(ct.arguments[0], evaluator);
1355 const int64_t min_index = ct.arguments[0].Var()->domain.Min();
1356 const std::vector<int64_t> element =
1357 SetEvalAt(ct.arguments[1], index - min_index, set_evaluator);
1358 const std::vector<int64_t> target = SetEval(ct.arguments[2], set_evaluator);
1359 return element == target;
1360}
1361
1362bool CheckSetIn(
1363 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1364 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1365 const int64_t value = Eval(ct.arguments[0], evaluator);
1366 const std::vector<int64_t> set = SetEval(ct.arguments[1], set_evaluator);
1367 return std::find(set.begin(), set.end(), value) != set.end();
1368}
1369
1370bool CheckSetNotIn(
1371 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1372 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1373 const int64_t value = Eval(ct.arguments[0], evaluator);
1374 const std::vector<int64_t> set = SetEval(ct.arguments[1], set_evaluator);
1375 return std::find(set.begin(), set.end(), value) == set.end();
1376}
1377
1378bool CheckSetInReif(
1379 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1380 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1381 const int64_t value = Eval(ct.arguments[0], evaluator);
1382 const std::vector<int64_t> set = SetEval(ct.arguments[1], set_evaluator);
1383 const bool contain = std::find(set.begin(), set.end(), value) != set.end();
1384 const int64_t status = Eval(ct.arguments[2], evaluator);
1385 return contain == (status == 1);
1386}
1387
1388bool CheckSetIntersect(
1389 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1390 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1391 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1392 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1393 const std::vector<int64_t> values_r = SetEval(ct.arguments[2], set_evaluator);
1394 absl::flat_hash_set<int64_t> set_r(values_r.begin(), values_r.end());
1395 absl::flat_hash_set<int64_t> computed_intersection;
1396 std::set_intersection(
1397 values_x.begin(), values_x.end(), values_y.begin(), values_y.end(),
1398 std::inserter(computed_intersection, computed_intersection.begin()));
1399 return computed_intersection == set_r;
1400}
1401
1402bool CheckSetUnion(
1403 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1404 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1405 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1406 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1407 const std::vector<int64_t> values_r = SetEval(ct.arguments[2], set_evaluator);
1408 absl::flat_hash_set<int64_t> set_r(values_r.begin(), values_r.end());
1409 absl::flat_hash_set<int64_t> computed_intersection;
1410 std::set_union(
1411 values_x.begin(), values_x.end(), values_y.begin(), values_y.end(),
1412 std::inserter(computed_intersection, computed_intersection.begin()));
1413 return computed_intersection == set_r;
1414}
1415
1416bool CheckSetSubset(
1417 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1418 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1419 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1420 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1421 return std::includes(values_y.begin(), values_y.end(), values_x.begin(),
1422 values_x.end());
1423}
1424
1425bool CheckSetSubsetReif(
1426 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1427 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1428 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1429 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1430 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1431 return std::includes(values_y.begin(), values_y.end(), values_x.begin(),
1432 values_x.end()) == status;
1433}
1434
1435bool CheckSetSuperset(
1436 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1437 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1438 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1439 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1440 return std::includes(values_x.begin(), values_x.end(), values_y.begin(),
1441 values_y.end());
1442}
1443
1444bool CheckSetSupersetReif(
1445 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1446 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1447 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1448 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1449 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1450 return std::includes(values_x.begin(), values_x.end(), values_y.begin(),
1451 values_y.end()) == status;
1452}
1453
1454bool CheckSetDiff(
1455 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1456 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1457 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1458 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1459 const std::vector<int64_t> values_r = SetEval(ct.arguments[2], set_evaluator);
1460 absl::flat_hash_set<int64_t> set_r(values_r.begin(), values_r.end());
1461 absl::flat_hash_set<int64_t> computed_diff;
1462 std::set_difference(values_x.begin(), values_x.end(), values_y.begin(),
1463 values_y.end(),
1464 std::inserter(computed_diff, computed_diff.begin()));
1465 return computed_diff == set_r;
1466}
1467
1468bool CheckSetSymDiff(
1469 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1470 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1471 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1472 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1473 const std::vector<int64_t> values_r = SetEval(ct.arguments[2], set_evaluator);
1474 absl::flat_hash_set<int64_t> set_r(values_r.begin(), values_r.end());
1475 absl::flat_hash_set<int64_t> computed_sym_diff;
1476 std::set_symmetric_difference(
1477 values_x.begin(), values_x.end(), values_y.begin(), values_y.end(),
1478 std::inserter(computed_sym_diff, computed_sym_diff.begin()));
1479 return computed_sym_diff == set_r;
1480}
1481
1482bool CheckSetEq(
1483 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1484 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1485 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1486 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1487 return values_x == values_y;
1488}
1489
1490bool CheckSetEqReif(
1491 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1492 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1493 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1494 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1495 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1496 return (values_x == values_y) == status;
1497}
1498
1499bool CheckSetNe(
1500 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1501 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1502 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1503 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1504 return values_x != values_y;
1505}
1506
1507bool CheckSetLe(
1508 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1509 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1510 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1511 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1512 const int min_size = std::min(values_x.size(), values_y.size());
1513 for (int i = 0; i < min_size; ++i) {
1514 if (values_x[i] < values_y[i]) return true;
1515 if (values_x[i] > values_y[i]) return false;
1516 }
1517 return values_y.size() >= values_x.size();
1518}
1519
1520bool CheckSetLeReif(
1521 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1522 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1523 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1524 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1525 const int min_size = std::min(values_x.size(), values_y.size());
1526 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1527
1528 const bool expected_status = [&]() {
1529 for (int i = 0; i < min_size; ++i) {
1530 if (values_x[i] < values_y[i]) return true;
1531 if (values_x[i] > values_y[i]) return false;
1532 }
1533 return values_y.size() >= values_x.size();
1534 }();
1535
1536 return expected_status == status;
1537}
1538
1539bool CheckSetLt(
1540 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1541 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1542 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1543 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1544 const int min_size = std::min(values_x.size(), values_y.size());
1545 for (int i = 0; i < min_size; ++i) {
1546 if (values_x[i] < values_y[i]) return true;
1547 if (values_x[i] > values_y[i]) return false;
1548 }
1549 return values_y.size() > values_x.size();
1550}
1551
1552bool CheckSetLtReif(
1553 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1554 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1555 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1556 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1557 const int min_size = std::min(values_x.size(), values_y.size());
1558 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1559
1560 const bool expected_status = [&]() {
1561 for (int i = 0; i < min_size; ++i) {
1562 if (values_x[i] < values_y[i]) return true;
1563 if (values_x[i] > values_y[i]) return false;
1564 }
1565 return values_y.size() > values_x.size();
1566 }();
1567
1568 return expected_status == status;
1569}
1570
1571bool CheckSetNeReif(
1572 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1573 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1574 const std::vector<int64_t> values_x = SetEval(ct.arguments[0], set_evaluator);
1575 const std::vector<int64_t> values_y = SetEval(ct.arguments[1], set_evaluator);
1576 const bool status = Eval(ct.arguments[2], evaluator) != 0;
1577 return (values_x != values_y) == status;
1578}
1579
1580bool CheckSlidingSum(
1581 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1582 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1583 const int64_t low = Eval(ct.arguments[0], evaluator);
1584 const int64_t up = Eval(ct.arguments[1], evaluator);
1585 const int64_t length = Eval(ct.arguments[2], evaluator);
1586 // Compute initial sum.
1587 int64_t sliding_sum = 0;
1588 for (int i = 0; i < std::min<int64_t>(length, Length(ct.arguments[3])); ++i) {
1589 sliding_sum += EvalAt(ct.arguments[3], i, evaluator);
1590 }
1591 if (sliding_sum < low || sliding_sum > up) {
1592 return false;
1593 }
1594 for (int i = length; i < Length(ct.arguments[3]); ++i) {
1595 sliding_sum += EvalAt(ct.arguments[3], i, evaluator) -
1596 EvalAt(ct.arguments[3], i - length, evaluator);
1597 if (sliding_sum < low || sliding_sum > up) {
1598 return false;
1599 }
1600 }
1601 return true;
1602}
1603
1604bool CheckSort(
1605 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1606 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1607 CHECK_EQ(Length(ct.arguments[0]), Length(ct.arguments[1]));
1608 absl::flat_hash_map<int64_t, int> init_count;
1609 absl::flat_hash_map<int64_t, int> sorted_count;
1610 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
1611 init_count[EvalAt(ct.arguments[0], i, evaluator)]++;
1612 sorted_count[EvalAt(ct.arguments[1], i, evaluator)]++;
1613 }
1614 if (init_count != sorted_count) {
1615 return false;
1616 }
1617 for (int i = 0; i < Length(ct.arguments[1]) - 1; ++i) {
1618 if (EvalAt(ct.arguments[1], i, evaluator) >
1619 EvalAt(ct.arguments[1], i, evaluator)) {
1620 return false;
1621 }
1622 }
1623 return true;
1624}
1625
1626bool CheckOrToolsSubCircuit(
1627 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1628 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1629 absl::flat_hash_set<int64_t> visited;
1630 const int base = ct.arguments[1].Value();
1631 // Find inactive nodes (pointing to themselves).
1632 int64_t current = -1;
1633 for (int i = 0; i < Length(ct.arguments[0]); ++i) {
1634 const int64_t next = EvalAt(ct.arguments[0], i, evaluator) - base;
1635 if (next != i && current == -1) {
1636 current = next;
1637 } else if (next == i) {
1638 visited.insert(next);
1639 }
1640 }
1641
1642 // Try to find a path of length 'residual_size'.
1643 const int residual_size = Length(ct.arguments[0]) - visited.size();
1644 for (int i = 0; i < residual_size; ++i) {
1645 const int64_t next = EvalAt(ct.arguments[0], current, evaluator) - base;
1646 visited.insert(next);
1647 if (next == current) {
1648 return false;
1649 }
1650 current = next;
1651 }
1652
1653 // Have we visited all nodes?
1654 return visited.size() == Length(ct.arguments[0]);
1655}
1656
1657bool CheckOrToolsTableInt(
1658 const Constraint& /*ct*/,
1659 const std::function<int64_t(Variable*)>& /*evaluator*/,
1660 const std::function<std::vector<int64_t>(Variable*)>& /*set_evaluator*/) {
1661 return true;
1662}
1663
1664bool CheckSymmetricAllDifferent(
1665 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1666 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1667 const int size = Length(ct.arguments[0]);
1668 for (int i = 0; i < size; ++i) {
1669 const int64_t value = EvalAt(ct.arguments[0], i, evaluator) - 1;
1670 if (value < 0 || value >= size) {
1671 return false;
1672 }
1673 const int64_t reverse_value = EvalAt(ct.arguments[0], value, evaluator) - 1;
1674 if (reverse_value != i) {
1675 return false;
1676 }
1677 }
1678 return true;
1679}
1680
1681bool CheckValuePrecedeInt(
1682 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1683 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1684 const int64_t before = ct.arguments[0].Value();
1685 const int64_t after = ct.arguments[1].Value();
1686 const int64_t length = Length(ct.arguments[2]);
1687 bool before_found = false;
1688 for (int i = 0; i < length; ++i) {
1689 const int64_t current = EvalAt(ct.arguments[2], i, evaluator);
1690 if (current == before) before_found = true;
1691 if (current == after && !before_found) return false;
1692 }
1693 return true;
1694}
1695
1696bool CheckOrToolsPrecedeChainInt(
1697 const Constraint& ct, const std::function<int64_t(Variable*)>& evaluator,
1698 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator) {
1699 absl::flat_hash_map<int64_t, int> value_to_index;
1700 if (ct.arguments[0].type == fz::Argument::INT_INTERVAL) {
1701 for (int64_t v = ct.arguments[0].values[0]; v <= ct.arguments[0].values[1];
1702 ++v) {
1703 value_to_index[v] = value_to_index.size();
1704 ;
1705 }
1706 } else if (ct.arguments[0].type == fz::Argument::INT_LIST) {
1707 for (int64_t v : ct.arguments[0].values) {
1708 value_to_index[v] = value_to_index.size();
1709 }
1710 } else {
1711 LOG(FATAL) << "Unsupported argument type: " << ct.arguments[0].type;
1712 }
1713
1714 int max_visited_index = -1;
1715 const int64_t length = Length(ct.arguments[1]);
1716 for (int i = 0; i < length; ++i) {
1717 const int64_t current = EvalAt(ct.arguments[1], i, evaluator);
1718 const auto it = value_to_index.find(current);
1719 if (it == value_to_index.end()) continue;
1720 if (it->second > max_visited_index + 1) return false;
1721 if (it->second == max_visited_index + 1) ++max_visited_index;
1722 }
1723 return true;
1724}
1725
1726using CallMap = absl::flat_hash_map<
1727 std::string,
1728 std::function<bool(const Constraint& ct, std::function<int64_t(Variable*)>,
1729 const std::function<std::vector<int64_t>(Variable*)>&)>>;
1730
1731// Creates a map between flatzinc predicates and CP-SAT builders.
1732//
1733// Predicates starting with fzn_ are predicates with the same name in flatzinc
1734// and in minizinc. The fzn_ prefix is added to differentiate them.
1735//
1736// Predicates starting with ortools_ are predicates defined only in or-tools.
1737// They are created at compilation time when using the or-tools mzn library.
1738CallMap CreateCallMap() {
1739 CallMap m;
1740 m["alldifferent_except_0"] = CheckAlldifferentExcept0;
1741 m["among"] = CheckAmong;
1742 m["array_bool_and"] = CheckArrayBoolAnd;
1743 m["array_bool_element"] = CheckArrayIntElement;
1744 m["array_bool_or"] = CheckArrayBoolOr;
1745 m["array_bool_xor"] = CheckArrayBoolXor;
1746 m["array_int_element"] = CheckArrayIntElement;
1747 m["array_int_element_nonshifted"] = CheckArrayIntElementNonShifted;
1748 m["array_int_maximum"] = CheckMaximumInt;
1749 m["array_int_minimum"] = CheckMinimumInt;
1750 m["array_set_element"] = CheckArraySetElement;
1751 m["array_var_bool_element"] = CheckArrayVarIntElement;
1752 m["array_var_int_element"] = CheckArrayVarIntElement;
1753 m["array_var_set_element"] = CheckArraySetElement;
1754 m["at_most_int"] = CheckAtMostInt;
1755 m["bool_and"] = CheckBoolAnd;
1756 m["bool_clause"] = CheckBoolClause;
1757 m["bool_eq_imp"] = CheckIntEqImp;
1758 m["bool_eq_reif"] = CheckIntEqReif;
1759 m["bool_eq"] = CheckIntEq;
1760 m["bool_ge_imp"] = CheckIntGeImp;
1761 m["bool_ge_reif"] = CheckIntGeReif;
1762 m["bool_ge"] = CheckIntGe;
1763 m["bool_gt_imp"] = CheckIntGtImp;
1764 m["bool_gt_reif"] = CheckIntGtReif;
1765 m["bool_gt"] = CheckIntGt;
1766 m["bool_le_imp"] = CheckIntLeImp;
1767 m["bool_le_reif"] = CheckIntLeReif;
1768 m["bool_le"] = CheckIntLe;
1769 m["bool_left_imp"] = CheckIntLe;
1770 m["bool_lin_eq"] = CheckIntLinEq;
1771 m["bool_lin_le"] = CheckIntLinLe;
1772 m["bool_lt_imp"] = CheckIntLtImp;
1773 m["bool_lt_reif"] = CheckIntLtReif;
1774 m["bool_lt"] = CheckIntLt;
1775 m["bool_ne_imp"] = CheckIntNeImp;
1776 m["bool_ne_reif"] = CheckIntNeReif;
1777 m["bool_ne"] = CheckIntNe;
1778 m["bool_not"] = CheckBoolNot;
1779 m["bool_or"] = CheckBoolOr;
1780 m["bool_right_imp"] = CheckIntGe;
1781 m["bool_xor"] = CheckBoolXor;
1782 m["bool2int"] = CheckIntEq;
1783 m["count_eq"] = CheckOrToolsCountEq;
1784 m["count_geq"] = CheckCountGeq;
1785 m["count_gt"] = CheckCountGt;
1786 m["count_leq"] = CheckCountLeq;
1787 m["count_lt"] = CheckCountLt;
1788 m["count_neq"] = CheckCountNeq;
1789 m["count_reif"] = CheckCountReif;
1790 m["count"] = CheckOrToolsCountEq;
1791 m["diffn_k_with_sizes"] = CheckDiffnK;
1792 m["diffn_nonstrict_k_with_sizes"] = CheckDiffnNonStrictK;
1793 m["false_constraint"] = CheckFalseConstraint;
1794 m["fixed_cumulative"] = CheckCumulative;
1795 m["fzn_all_different_int"] = CheckAllDifferentInt;
1796 m["fzn_all_different_set"] = CheckAllDifferentSet;
1797 m["fzn_all_disjoint"] = CheckAllDisjoint;
1798 m["fzn_cumulative"] = CheckCumulative;
1799 m["fzn_diffn_nonstrict"] = CheckDiffnNonStrict;
1800 m["fzn_diffn"] = CheckDiffn;
1801 m["fzn_disjoint"] = CheckDisjoint;
1802 m["fzn_disjunctive_strict"] = CheckDisjunctiveStrict;
1803 m["fzn_disjunctive"] = CheckDisjunctive;
1804 m["fzn_partition_set"] = CheckPartitionSet;
1805 m["fzn_value_precede_int"] = CheckValuePrecedeInt;
1806 m["int_abs"] = CheckIntAbs;
1807 m["int_div"] = CheckIntDiv;
1808 m["int_eq_imp"] = CheckIntEqImp;
1809 m["int_eq_reif"] = CheckIntEqReif;
1810 m["int_eq"] = CheckIntEq;
1811 m["int_ge_imp"] = CheckIntGeImp;
1812 m["int_ge_reif"] = CheckIntGeReif;
1813 m["int_ge"] = CheckIntGe;
1814 m["int_gt_imp"] = CheckIntGtImp;
1815 m["int_gt_reif"] = CheckIntGtReif;
1816 m["int_gt"] = CheckIntGt;
1817 m["int_in"] = CheckSetIn;
1818 m["int_le_imp"] = CheckIntLeImp;
1819 m["int_le_reif"] = CheckIntLeReif;
1820 m["int_le"] = CheckIntLe;
1821 m["int_lin_eq_imp"] = CheckIntLinEqImp;
1822 m["int_lin_eq_reif"] = CheckIntLinEqReif;
1823 m["int_lin_eq"] = CheckIntLinEq;
1824 m["int_lin_ge_imp"] = CheckIntLinGeImp;
1825 m["int_lin_ge_reif"] = CheckIntLinGeReif;
1826 m["int_lin_ge"] = CheckIntLinGe;
1827 m["int_lin_le_imp"] = CheckIntLinLeImp;
1828 m["int_lin_le_reif"] = CheckIntLinLeReif;
1829 m["int_lin_le"] = CheckIntLinLe;
1830 m["int_lin_ne_imp"] = CheckIntLinNeImp;
1831 m["int_lin_ne_reif"] = CheckIntLinNeReif;
1832 m["int_lin_ne"] = CheckIntLinNe;
1833 m["int_lt_imp"] = CheckIntLtImp;
1834 m["int_lt_reif"] = CheckIntLtReif;
1835 m["int_lt"] = CheckIntLt;
1836 m["int_max"] = CheckIntMax;
1837 m["int_min"] = CheckIntMin;
1838 m["int_minus"] = CheckIntMinus;
1839 m["int_mod"] = CheckIntMod;
1840 m["int_ne_imp"] = CheckIntNeImp;
1841 m["int_ne_reif"] = CheckIntNeReif;
1842 m["int_ne"] = CheckIntNe;
1843 m["int_negate"] = CheckIntNegate;
1844 m["int_not_in"] = CheckSetNotIn;
1845 m["int_plus"] = CheckIntPlus;
1846 m["int_times"] = CheckIntTimes;
1847 m["maximum_arg_int"] = CheckMaximumArgInt;
1848 m["maximum_int"] = CheckMaximumInt;
1849 m["minimum_arg_int"] = CheckMinimumArgInt;
1850 m["minimum_int"] = CheckMinimumInt;
1851 m["ortools_arg_max_bool"] = CheckOrToolsArgMaxInt;
1852 m["ortools_arg_max_int"] = CheckOrToolsArgMaxInt;
1853 m["ortools_array_bool_element"] = CheckOrToolsArrayIntElement;
1854 m["ortools_array_int_element"] = CheckOrToolsArrayIntElement;
1855 m["ortools_array_var_bool_element"] = CheckOrToolsArrayIntElement;
1856 m["ortools_array_var_int_element"] = CheckOrToolsArrayIntElement;
1857 m["ortools_bin_packing_capa"] = CheckOrToolsBinPackingCapa;
1858 m["ortools_bin_packing_load"] = CheckOrToolsBinPackingLoad;
1859 m["ortools_bin_packing"] = CheckOrToolsBinPacking;
1860 m["ortools_circuit"] = CheckOrToolsCircuit;
1861 m["ortools_count_eq_cst"] = CheckOrToolsCountEq;
1862 m["ortools_count_eq"] = CheckOrToolsCountEq;
1863 m["ortools_cumulative_opt"] = CheckOrToolsCumulativeOpt;
1864 m["ortools_disjunctive_strict_opt"] = CheckOrToolsDisjunctiveStrictOpt;
1865 m["ortools_global_cardinality_low_up"] = CheckOrToolsGlobalCardinalityLowUp;
1866 m["ortools_global_cardinality"] = CheckOrToolsGlobalCardinality;
1867 m["ortools_inverse"] = CheckOrToolsInverse;
1868 m["ortools_lex_less_bool"] = CheckOrToolsLexLessInt;
1869 m["ortools_lex_less_int"] = CheckOrToolsLexLessInt;
1870 m["ortools_lex_lesseq_bool"] = CheckOrToolsLexLesseqInt;
1871 m["ortools_lex_lesseq_int"] = CheckOrToolsLexLesseqInt;
1872 m["ortools_network_flow_cost"] = CheckOrToolsNetworkFlowCost;
1873 m["ortools_network_flow"] = CheckOrToolsNetworkFlow;
1874 m["ortools_nvalue"] = CheckOrToolsNValue;
1875 m["ortools_precede_chain_int"] = CheckOrToolsPrecedeChainInt;
1876 m["ortools_regular"] = CheckOrToolsRegular;
1877 m["ortools_subcircuit"] = CheckOrToolsSubCircuit;
1878 m["ortools_table_bool"] = CheckOrToolsTableInt;
1879 m["ortools_table_int"] = CheckOrToolsTableInt;
1880 m["regular_nfa"] = CheckRegularNfa;
1881 m["set_card"] = CheckSetCard;
1882 m["set_diff"] = CheckSetDiff;
1883 m["set_eq_reif"] = CheckSetEqReif;
1884 m["set_eq"] = CheckSetEq;
1885 m["set_in_reif"] = CheckSetInReif;
1886 m["set_in"] = CheckSetIn;
1887 m["set_intersect"] = CheckSetIntersect;
1888 m["set_le"] = CheckSetLe;
1889 m["set_lt"] = CheckSetLt;
1890 m["set_le_reif"] = CheckSetLeReif;
1891 m["set_lt_reif"] = CheckSetLtReif;
1892 m["set_ne_reif"] = CheckSetNeReif;
1893 m["set_ne"] = CheckSetNe;
1894 m["set_not_in"] = CheckSetNotIn;
1895 m["set_subset_reif"] = CheckSetSubsetReif;
1896 m["set_subset"] = CheckSetSubset;
1897 m["set_superset_reif"] = CheckSetSupersetReif;
1898 m["set_superset"] = CheckSetSuperset;
1899 m["set_symdiff"] = CheckSetSymDiff;
1900 m["set_union"] = CheckSetUnion;
1901 m["sliding_sum"] = CheckSlidingSum;
1902 m["sort"] = CheckSort;
1903 m["symmetric_all_different"] = CheckSymmetricAllDifferent;
1904 m["var_cumulative"] = CheckCumulative;
1905 m["variable_cumulative"] = CheckCumulative;
1906 return m;
1907}
1908
1909} // namespace
1910
1912 const Model& model, const std::function<int64_t(Variable*)>& evaluator,
1913 const std::function<std::vector<int64_t>(Variable*)>& set_evaluator,
1914 SolverLogger* logger) {
1915 bool ok = true;
1916 const CallMap call_map = CreateCallMap();
1917 for (Constraint* ct : model.constraints()) {
1918 if (!ct->active) continue;
1919 DCHECK(call_map.contains(ct->type)) << ct->type;
1920 const auto& checker = call_map.at(ct->type);
1921 if (!checker(*ct, evaluator, set_evaluator)) {
1922 SOLVER_LOG(logger, "Failing constraint ", ct->DebugString());
1923 ok = false;
1924 }
1925 }
1926 return ok;
1927}
1928
1929} // namespace fz
1930} // namespace operations_research
const std::vector< Constraint * > & constraints() const
Definition model.h:377
bool CheckSolution(const Model &model, const std::function< int64_t(Variable *)> &evaluator, const std::function< std::vector< int64_t >(Variable *)> &set_evaluator, SolverLogger *logger)
Definition checker.cc:1911
OR-Tools root namespace.
std::vector< Variable * > variables
Definition model.h:212
std::vector< Domain > domains
Definition model.h:213
Variable * VarAt(int pos) const
Definition model.cc:747
std::string DebugString() const
Definition model.cc:589
int64_t ValueAt(int pos) const
Definition model.cc:699
std::vector< int64_t > values
Definition model.h:211
std::vector< Argument > arguments
Definition model.h:241
std::vector< int64_t > values
Definition model.h:106
#define SOLVER_LOG(logger,...)
Definition logging.h:114