14 package com.google.ortools.sat;
16 import static com.google.common.truth.Truth.assertThat;
17 import static org.junit.jupiter.api.Assertions.assertNotNull;
19 import com.google.ortools.Loader;
20 import com.google.ortools.sat.CpSolverStatus;
21 import com.google.ortools.sat.LinearArgumentProto;
22 import com.google.ortools.util.Domain;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.Random;
27 import java.util.function.Consumer;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
46 final BoolVar t = model.newBoolVar(
"t");
47 final IntVar u = model.newConstant(5);
49 assertThat(x.getName()).isEqualTo(
"x");
50 assertThat(y.getName()).isEqualTo(
"y");
51 assertThat(z.getName()).isEmpty();
52 assertThat(t.
getName()).isEqualTo(
"t");
53 assertThat(u.
getName()).isEmpty();
54 assertThat(x.getDomain().flattenedIntervals()).isEqualTo(
new long[] {0, 10});
56 assertThat(x.toString()).isEqualTo(
"x(0..10)");
57 assertThat(y.toString()).isEqualTo(
"y(0..2, 5)");
58 assertThat(z.toString()).isEqualTo(
"var_2(0..2, 5)");
59 assertThat(t.
toString()).isEqualTo(
"t(0..1)");
60 assertThat(u.
toString()).isEqualTo(
"5");
67 final int horizon = 100;
70 final int duration = 10;
75 assertThat(startExpr.
getOffset()).isEqualTo(0);
81 assertThat(sizeExpr.
getOffset()).isEqualTo(duration);
85 assertThat(endExpr.
getOffset()).isEqualTo(duration);
99 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
100 assertThat(model.
model().getConstraints(0).hasBoolOr()).isTrue();
101 assertThat(model.
model().getConstraints(0).getBoolOr().getLiteralsCount()).isEqualTo(3);
107 assertNotNull(model);
113 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
114 assertThat(model.
model().getConstraints(0).hasBoolOr()).isTrue();
115 assertThat(model.
model().getConstraints(0).getBoolOr().getLiteralsCount()).isEqualTo(3);
121 assertNotNull(model);
127 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
128 assertThat(model.
model().getConstraints(0).hasAtMostOne()).isTrue();
129 assertThat(model.
model().getConstraints(0).getAtMostOne().getLiteralsCount()).isEqualTo(3);
135 assertNotNull(model);
141 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
142 assertThat(model.
model().getConstraints(0).hasExactlyOne()).isTrue();
143 assertThat(model.
model().getConstraints(0).getExactlyOne().getLiteralsCount()).isEqualTo(3);
149 assertNotNull(model);
155 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
156 assertThat(model.
model().getConstraints(0).hasBoolAnd()).isTrue();
157 assertThat(model.
model().getConstraints(0).getBoolAnd().getLiteralsCount()).isEqualTo(3);
163 assertNotNull(model);
169 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
170 assertThat(model.
model().getConstraints(0).hasBoolXor()).isTrue();
171 assertThat(model.
model().getConstraints(0).getBoolXor().getLiteralsCount()).isEqualTo(3);
177 assertNotNull(model);
182 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
183 assertThat(model.
model().getConstraints(0).hasBoolOr()).isTrue();
184 assertThat(model.
model().getConstraints(0).getBoolOr().getLiteralsCount()).isEqualTo(2);
190 assertNotNull(model);
195 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
196 assertThat(model.
model().getConstraints(0).hasLinear()).isTrue();
197 assertThat(model.
model().getConstraints(0).getLinear().getVarsCount()).isEqualTo(2);
201 assertThat(model.
model().getConstraintsCount()).isEqualTo(2);
202 assertThat(model.
model().getConstraints(1).hasLinear()).isTrue();
203 assertThat(model.
model().getConstraints(1).getEnforcementLiteralCount()).isEqualTo(1);
204 assertThat(model.
model().getConstraints(1).getEnforcementLiteral(0)).isEqualTo(-3);
208 assertThat(model.
model().getConstraintsCount()).isEqualTo(3);
209 assertThat(model.
model().getConstraints(2).hasLinear()).isTrue();
210 assertThat(model.
model().getConstraints(2).getEnforcementLiteralCount()).isEqualTo(2);
211 assertThat(model.
model().getConstraints(2).getEnforcementLiteral(0)).isEqualTo(2);
212 assertThat(model.
model().getConstraints(2).getEnforcementLiteral(1)).isEqualTo(3);
218 assertNotNull(model);
228 assertNotNull(model);
234 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
235 assertThat(model.
model().getConstraints(0).hasLinMax()).isTrue();
236 LinearArgumentProto ct = model.
model().getConstraints(0).getLinMax();
237 assertThat(ct.getTarget().getVarsCount()).isEqualTo(1);
238 assertThat(ct.getTarget().getVars(0)).isEqualTo(2);
239 assertThat(ct.getTarget().getCoeffs(0)).isEqualTo(-1);
240 assertThat(ct.getExprsCount()).isEqualTo(2);
241 assertThat(ct.getExprs(0).getVarsCount()).isEqualTo(1);
242 assertThat(ct.getExprs(0).getVars(0)).isEqualTo(0);
243 assertThat(ct.getExprs(0).getCoeffs(0)).isEqualTo(-1);
244 assertThat(ct.getExprs(1).getVarsCount()).isEqualTo(1);
245 assertThat(ct.getExprs(1).getVars(0)).isEqualTo(1);
246 assertThat(ct.getExprs(1).getCoeffs(0)).isEqualTo(-1);
252 assertNotNull(model);
258 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
259 assertThat(model.
model().getConstraints(0).hasLinMax()).isTrue();
260 LinearArgumentProto ct = model.
model().getConstraints(0).getLinMax();
261 assertThat(ct.getTarget().getVarsCount()).isEqualTo(1);
262 assertThat(ct.getTarget().getVars(0)).isEqualTo(2);
263 assertThat(ct.getTarget().getCoeffs(0)).isEqualTo(1);
264 assertThat(ct.getExprsCount()).isEqualTo(2);
265 assertThat(ct.getExprs(0).getVarsCount()).isEqualTo(1);
266 assertThat(ct.getExprs(0).getVars(0)).isEqualTo(0);
267 assertThat(ct.getExprs(0).getCoeffs(0)).isEqualTo(1);
268 assertThat(ct.getExprs(1).getVarsCount()).isEqualTo(1);
269 assertThat(ct.getExprs(1).getVars(0)).isEqualTo(1);
270 assertThat(ct.getExprs(1).getCoeffs(0)).isEqualTo(1);
276 assertNotNull(model);
282 LinearExpr.newBuilder().addTerm(x, 2).add(1).build(), LinearExpr.constant(5)});
283 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
284 assertThat(model.
model().getConstraints(0).hasLinMax()).isTrue();
285 LinearArgumentProto ct = model.
model().getConstraints(0).getLinMax();
286 assertThat(ct.getTarget().getVarsCount()).isEqualTo(1);
287 assertThat(ct.getTarget().getVars(0)).isEqualTo(1);
288 assertThat(ct.getTarget().getCoeffs(0)).isEqualTo(3);
289 assertThat(ct.getExprsCount()).isEqualTo(2);
290 assertThat(ct.getExprs(0).getVarsCount()).isEqualTo(1);
291 assertThat(ct.getExprs(0).getVars(0)).isEqualTo(0);
292 assertThat(ct.getExprs(0).getCoeffs(0)).isEqualTo(-2);
293 assertThat(ct.getExprs(0).getOffset()).isEqualTo(-1);
294 assertThat(ct.getExprs(1).getVarsCount()).isEqualTo(0);
295 assertThat(ct.getExprs(1).getOffset()).isEqualTo(-5);
301 assertNotNull(model);
307 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
308 assertThat(model.
model().getConstraints(0).hasLinMax()).isTrue();
309 LinearArgumentProto ct = model.
model().getConstraints(0).getLinMax();
310 assertThat(ct.getTarget().getVarsCount()).isEqualTo(1);
311 assertThat(ct.getTarget().getVars(0)).isEqualTo(1);
312 assertThat(ct.getTarget().getCoeffs(0)).isEqualTo(-3);
313 assertThat(ct.getExprsCount()).isEqualTo(2);
314 assertThat(ct.getExprs(0).getVarsCount()).isEqualTo(1);
315 assertThat(ct.getExprs(0).getVars(0)).isEqualTo(0);
316 assertThat(ct.getExprs(0).getCoeffs(0)).isEqualTo(2);
317 assertThat(ct.getExprs(0).getOffset()).isEqualTo(1);
318 assertThat(ct.getExprs(1).getVarsCount()).isEqualTo(1);
319 assertThat(ct.getExprs(1).getVars(0)).isEqualTo(0);
320 assertThat(ct.getExprs(1).getCoeffs(0)).isEqualTo(-2);
321 assertThat(ct.getExprs(1).getOffset()).isEqualTo(-1);
327 assertNotNull(model);
337 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
338 assertThat(model.
model().getConstraints(0).hasCircuit()).isTrue();
339 assertThat(model.
model().getConstraints(0).getCircuit().getTailsCount()).isEqualTo(3);
340 assertThat(model.
model().getConstraints(0).getCircuit().getHeadsCount()).isEqualTo(3);
341 assertThat(model.
model().getConstraints(0).getCircuit().getLiteralsCount()).isEqualTo(3);
347 assertNotNull(model);
357 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
358 assertThat(model.
model().getConstraints(0).hasRoutes()).isTrue();
359 assertThat(model.
model().getConstraints(0).getRoutes().getTailsCount()).isEqualTo(3);
360 assertThat(model.
model().getConstraints(0).getRoutes().getHeadsCount()).isEqualTo(3);
361 assertThat(model.
model().getConstraints(0).getRoutes().getLiteralsCount()).isEqualTo(3);
367 assertNotNull(model);
375 automaton.addTransition(0, 1, 0);
376 automaton.addTransition(1, 1, 1);
377 automaton.addTransition(1, 2, 2);
378 assertThat(model.
model().getConstraintsCount()).isEqualTo(1);
379 assertThat(model.
model().getConstraints(0).hasAutomaton()).isTrue();
380 assertThat(model.
model().getConstraints(0).hasAutomaton()).isTrue();
381 assertThat(model.
model().getConstraints(0).getAutomaton().getTransitionTailCount())
383 assertThat(model.
model().getConstraints(0).getAutomaton().getTransitionHeadCount())
385 assertThat(model.
model().getConstraints(0).getAutomaton().getTransitionLabelCount())
387 assertThat(model.
model().getConstraints(0).getAutomaton().getStartingState()).isEqualTo(0);
388 assertThat(model.
model().getConstraints(0).getAutomaton().getFinalStatesCount()).isEqualTo(2);
394 assertNotNull(model);
395 final int horizon = 100;
398 final int duration1 = 10;
402 final int duration2 = 15;
406 assertThat(model.
model().getConstraintsCount()).isEqualTo(3);
407 assertThat(model.
model().getConstraints(0).hasInterval()).isTrue();
408 assertThat(model.
model().getConstraints(1).hasInterval()).isTrue();
409 assertThat(model.
model().getConstraints(2).hasNoOverlap()).isTrue();
410 assertThat(model.
model().getConstraints(2).getNoOverlap().getIntervalsCount()).isEqualTo(2);
416 assertNotNull(model);
417 final int horizon = 100;
420 final int duration1 = 10;
421 final int demand1 = 20;
426 final int duration2 = 15;
433 assertThat(model.
model().getConstraintsCount()).isEqualTo(3);
434 assertThat(model.
model().getConstraints(0).hasInterval()).isTrue();
435 assertThat(model.
model().getConstraints(1).hasInterval()).isTrue();
436 assertThat(model.
model().getConstraints(2).hasCumulative()).isTrue();
437 assertThat(model.
model().getConstraints(2).getCumulative().getIntervalsCount()).isEqualTo(2);
445 assertThat(model.
model().getConstraints(2).getCumulative().getIntervalsCount()).isEqualTo(6);
451 assertNotNull(model);
452 final int horizon = 100;
455 final int duration1 = 10;
459 final int duration2 = 15;
465 assertThat(model.
model().getConstraintsCount()).isEqualTo(3);
466 assertThat(model.
model().getConstraints(0).hasInterval()).isTrue();
467 assertThat(model.
model().getConstraints(1).hasInterval()).isTrue();
468 assertThat(model.
model().getConstraints(2).hasNoOverlap2D()).isTrue();
469 assertThat(model.
model().getConstraints(2).getNoOverlap2D().getXIntervalsCount()).isEqualTo(2);
470 assertThat(model.
model().getConstraints(2).getNoOverlap2D().getYIntervalsCount()).isEqualTo(2);
476 assertNotNull(model);
482 assertThat(stats).isNotEmpty();
488 assertNotNull(model);
494 assertThat(stats).isEmpty();
500 assertNotNull(model);
504 Domain.fromFlatIntervals(
new long[] {6, 9223372036854775807L}));
507 assertThat(stats).isNotEmpty();
514 assertThat(ex1).hasMessageThat().isEqualTo(
"test1: ar1 and ar2 have mismatched lengths");
515 assertThat(ex2).hasMessageThat().isEqualTo(
"test2: ar");
521 assertNotNull(model);
524 List<Constraint> constraints =
new ArrayList<>();
525 for (
int i = 0; i < 10; ++i) {
527 Domain.fromFlatIntervals(
new long[] {6 + i, 92 - i}));
531 for (
int i = 0; i < 10; ++i) {
534 .isEqualTo(model.
getBuilder().getConstraintsBuilder(i).toString());
535 assertThat(ct.
getBuilder().hasLinear()).isTrue();
536 assertThat(model.
getBuilder().getConstraintsBuilder(i).hasLinear()).isTrue();
538 .isEqualTo(model.
getBuilder().getConstraintsBuilder(i).toString());
541 for (
int i = 0; i < 10; ++i) {
546 for (
int i = 0; i < 10; ++i) {
548 assertThat(ct.
getBuilder().hasLinear()).isFalse();
549 assertThat(model.
getBuilder().getConstraintsBuilder(i).hasLinear()).isFalse();
556 assertNotNull(model);
563 assertThat(model.
getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(2);
564 assertThat(model.
getBuilder().hasFloatingPointObjective()).isFalse();
567 assertThat(model.
getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(1);
568 assertThat(model.
getBuilder().hasFloatingPointObjective()).isFalse();
571 assertThat(model.
getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(2);
572 assertThat(model.
getBuilder().hasFloatingPointObjective()).isFalse();
575 assertThat(model.
getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(2);
576 assertThat(model.
getBuilder().hasObjective()).isFalse();
579 assertThat(model.
getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(1);
580 assertThat(model.
getBuilder().hasObjective()).isFalse();
583 assertThat(model.
getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(2);
584 assertThat(model.
getBuilder().hasFloatingPointObjective()).isFalse();
587 assertThat(model.
getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(1);
588 assertThat(model.
getBuilder().hasFloatingPointObjective()).isFalse();
591 assertThat(model.
getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(2);
592 assertThat(model.
getBuilder().hasObjective()).isFalse();
595 assertThat(model.
getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(1);
596 assertThat(model.
getBuilder().hasObjective()).isFalse();
601 System.out.println(
"testDomainGetter");
608 long[] flat = d.flattenedIntervals();
609 if (flat.length != 2 || flat[0] != 0 || flat[1] != 5) {
610 throw new RuntimeException(
"Wrong domain");
616 System.out.println(
"testCrashInPresolve");
641 CpSolverStatus status = solver.
solve(model);
643 if (status != CpSolverStatus.INFEASIBLE) {
644 throw new IllegalStateException(
"Wrong status in testCrashInPresolve");
650 System.out.println(
"testCrashInSolveWithAllowedAssignment");
652 final int numEntityOne = 50000;
653 final int numEntityTwo = 100;
655 for (
int i = 0; i < entitiesOne.length; i++) {
656 entitiesOne[i] = model.
newIntVar(1, numEntityTwo,
"E" + i);
658 final int[][] allAllowedValues =
new int[numEntityTwo][entitiesOne.length];
659 for (
int i = 0; i < numEntityTwo; i++) {
660 for (
int j = 0; j < entitiesOne.length; j++) {
661 allAllowedValues[i][j] = i;
665 final int[] oneTuple =
new int[entitiesOne.length];
666 for (
int i = 0; i < numEntityTwo; i++) {
667 for (
int j = 0; j < entitiesOne.length; j++) {
672 final Random r =
new Random();
673 for (
int i = 0; i < entitiesOne.length; i++) {
674 model.
addEquality(entitiesOne[i], r.nextInt(numEntityTwo));
677 CpSolverStatus unused = solver.
solve(model);
682 System.out.println(
"testCrashInSolveWithAllowedAssignment");
686 Arrays.setAll(entities, i -> model.
newIntVar(1, 5,
"E" + i));
688 final int[] equalities =
new int[] {18, 4, 19, 3, 12};
689 addEqualities(model, entities, equalities);
691 final int[] allowedAssignments =
new int[] {12, 8, 15};
692 final int[] allowedAssignmentValues =
new int[] {1, 3};
693 addAllowedAssignMents(model, entities, allowedAssignments, allowedAssignmentValues);
695 final int[] forbiddenAssignments1 =
new int[] {6, 15, 19};
696 final int[] forbiddenAssignments1Values =
new int[] {3};
697 final int[] forbiddenAssignments2 =
new int[] {10, 19};
698 final int[] forbiddenAssignments2Values =
new int[] {4};
699 final int[] forbiddenAssignments3 =
new int[] {18, 0, 9, 7};
700 final int[] forbiddenAssignments3Values =
new int[] {4};
701 final int[] forbiddenAssignments4 =
new int[] {14, 11};
702 final int[] forbiddenAssignments4Values =
new int[] {1, 2, 3, 4, 5};
703 final int[] forbiddenAssignments5 =
new int[] {5, 16, 1, 3};
704 final int[] forbiddenAssignments5Values =
new int[] {1, 2, 3, 4, 5};
705 final int[] forbiddenAssignments6 =
new int[] {2, 6, 11, 4};
706 final int[] forbiddenAssignments6Values =
new int[] {1, 2, 3, 4, 5};
707 final int[] forbiddenAssignments7 =
new int[] {6, 18, 12, 2, 9, 14};
708 final int[] forbiddenAssignments7Values =
new int[] {1, 2, 3, 4, 5};
710 addForbiddenAssignments(forbiddenAssignments1Values, forbiddenAssignments1, entities, model);
711 addForbiddenAssignments(forbiddenAssignments2Values, forbiddenAssignments2, entities, model);
712 addForbiddenAssignments(forbiddenAssignments3Values, forbiddenAssignments3, entities, model);
713 addForbiddenAssignments(forbiddenAssignments4Values, forbiddenAssignments4, entities, model);
714 addForbiddenAssignments(forbiddenAssignments5Values, forbiddenAssignments5, entities, model);
715 addForbiddenAssignments(forbiddenAssignments6Values, forbiddenAssignments6, entities, model);
716 addForbiddenAssignments(forbiddenAssignments7Values, forbiddenAssignments7, entities, model);
718 final int[] configuration =
719 new int[] {5, 4, 2, 3, 3, 3, 4, 3, 3, 1, 4, 4, 3, 1, 4, 1, 4, 4, 3, 3};
720 for (
int i = 0; i < configuration.length; i++) {
725 CpSolverStatus unused = solver.
solve(model);
730 System.out.println(
"testLogCapture");
744 StringBuilder logBuilder =
new StringBuilder();
745 Consumer<String> appendToLog = (String message) -> {
746 System.out.println(
"Current Thread Name:" + Thread.currentThread().getName()
747 +
" Id:" + Thread.currentThread().getId() +
" msg:" + message);
748 logBuilder.append(message).append(
'\n');
751 solver.
getParameters().setLogToStdout(
false).setLogSearchProgress(
true);
752 CpSolverStatus status = solver.
solve(model);
753 if (status != CpSolverStatus.OPTIMAL) {
754 throw new IllegalStateException(
"Wrong status in testCrashInPresolve");
757 String log = logBuilder.toString();
759 throw new IllegalStateException(
"Log should not be empty");
763 private void addEqualities(
final CpModel model,
final IntVar[] entities,
final int[] equalities) {
764 for (
int i = 0; i < (equalities.length - 1); i++) {
765 model.
addEquality(entities[equalities[i]], entities[equalities[i + 1]]);
769 private void addAllowedAssignMents(
final CpModel model,
final IntVar[] entities,
770 final int[] allowedAssignments,
final int[] allowedAssignmentValues) {
771 final int[][] allAllowedValues =
772 new int[allowedAssignmentValues.length][allowedAssignments.length];
773 for (
int i = 0; i < allowedAssignmentValues.length; i++) {
774 final int value = allowedAssignmentValues[i];
775 Arrays.fill(allAllowedValues[i], 0, allowedAssignments.length, value);
777 final IntVar[] specificEntities =
new IntVar[allowedAssignments.length];
778 for (
int i = 0; i < allowedAssignments.length; i++) {
779 specificEntities[i] = entities[allowedAssignments[i]];
781 TableConstraint table = model.addAllowedAssignments(specificEntities);
782 for (
int[] tuple : allAllowedValues) {
783 table.addTuple(tuple);
787 private void addForbiddenAssignments(
final int[] forbiddenAssignmentsValues,
788 final int[] forbiddenAssignments,
final IntVar[] entities,
final CpModel model) {
789 final IntVar[] specificEntities =
new IntVar[forbiddenAssignments.length];
790 for (
int i = 0; i < forbiddenAssignments.length; i++) {
791 specificEntities[i] = entities[forbiddenAssignments[i]];
794 final int[][] notAllowedValues =
795 new int[forbiddenAssignmentsValues.length][forbiddenAssignments.length];
796 for (
int i = 0; i < forbiddenAssignmentsValues.length; i++) {
797 final int value = forbiddenAssignmentsValues[i];
798 Arrays.fill(notAllowedValues[i], 0, forbiddenAssignments.length, value);
800 TableConstraint table = model.addForbiddenAssignments(specificEntities);
801 for (
int[] tuple : notAllowedValues) {
802 table.addTuple(tuple);