Java Reference

Java Reference

CpModelTest.java
Go to the documentation of this file.
1 // Copyright 2010-2022 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 
14 package com.google.ortools.sat;
15 
16 import static com.google.common.truth.Truth.assertThat;
17 import static org.junit.jupiter.api.Assertions.assertNotNull;
18 
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;
30 
32 public final class CpModelTest {
33  @BeforeEach
34  public void setUp() {
36  }
37 
38  @Test
39  public void testCpModelNewIntVar() throws Exception {
40  final CpModel model = new CpModel();
41  assertNotNull(model);
42  final IntVar x = model.newIntVar(0, 10, "x");
43  final IntVar y = model.newIntVarFromDomain(Domain.fromValues(new long[] {0, 1, 2, 5}), "y");
44  final IntVar z =
45  model.newIntVarFromDomain(Domain.fromIntervals(new long[][] {{0, 2}, {5}}), "");
46  final BoolVar t = model.newBoolVar("t");
47  final IntVar u = model.newConstant(5);
48 
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});
55 
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");
61  }
62 
63  @Test
64  public void testCpModelNewIntervalVar() throws Exception {
65  final CpModel model = new CpModel();
66  assertNotNull(model);
67  final int horizon = 100;
68 
69  final IntVar startVar = model.newIntVar(0, horizon, "start");
70  final int duration = 10;
71  final IntervalVar interval = model.newFixedSizeIntervalVar(startVar, duration, "interval");
72 
73  final LinearExpr startExpr = interval.getStartExpr();
74  assertThat(startExpr.numElements()).isEqualTo(1);
75  assertThat(startExpr.getOffset()).isEqualTo(0);
76  assertThat(startExpr.getVariableIndex(0)).isEqualTo(startVar.getIndex());
77  assertThat(startExpr.getCoefficient(0)).isEqualTo(1);
78 
79  final LinearExpr sizeExpr = interval.getSizeExpr();
80  assertThat(sizeExpr.numElements()).isEqualTo(0);
81  assertThat(sizeExpr.getOffset()).isEqualTo(duration);
82 
83  final LinearExpr endExpr = interval.getEndExpr();
84  assertThat(endExpr.numElements()).isEqualTo(1);
85  assertThat(endExpr.getOffset()).isEqualTo(duration);
86  assertThat(endExpr.getVariableIndex(0)).isEqualTo(startVar.getIndex());
87  assertThat(endExpr.getCoefficient(0)).isEqualTo(1);
88  }
89 
90  @Test
91  public void testCpModelAddBoolOr() throws Exception {
92  final CpModel model = new CpModel();
93  assertNotNull(model);
94  final BoolVar x = model.newBoolVar("x");
95  final BoolVar y = model.newBoolVar("y");
96  final BoolVar z = model.newBoolVar("z");
97  model.addBoolOr(new Literal[] {x, y.not(), z});
98 
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);
102  }
103 
104  @Test
105  public void testCpModelAddAtLeastOne() throws Exception {
106  final CpModel model = new CpModel();
107  assertNotNull(model);
108  final BoolVar x = model.newBoolVar("x");
109  final BoolVar y = model.newBoolVar("y");
110  final BoolVar z = model.newBoolVar("z");
111  model.addAtLeastOne(new Literal[] {x, y.not(), z});
112 
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);
116  }
117 
118  @Test
119  public void testCpModelAddAtMostOne() throws Exception {
120  final CpModel model = new CpModel();
121  assertNotNull(model);
122  final BoolVar x = model.newBoolVar("x");
123  final BoolVar y = model.newBoolVar("y");
124  final BoolVar z = model.newBoolVar("z");
125  model.addAtMostOne(new Literal[] {x, y.not(), z});
126 
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);
130  }
131 
132  @Test
133  public void testCpModelAddExactlyOne() throws Exception {
134  final CpModel model = new CpModel();
135  assertNotNull(model);
136  final BoolVar x = model.newBoolVar("x");
137  final BoolVar y = model.newBoolVar("y");
138  final BoolVar z = model.newBoolVar("z");
139  model.addExactlyOne(new Literal[] {x, y.not(), z});
140 
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);
144  }
145 
146  @Test
147  public void testCpModelAddBoolAnd() throws Exception {
148  final CpModel model = new CpModel();
149  assertNotNull(model);
150  final BoolVar x = model.newBoolVar("x");
151  final BoolVar y = model.newBoolVar("y");
152  final BoolVar z = model.newBoolVar("z");
153  model.addBoolAnd(new Literal[] {x, y.not(), z});
154 
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);
158  }
159 
160  @Test
161  public void testCpModelAddBoolXor() throws Exception {
162  final CpModel model = new CpModel();
163  assertNotNull(model);
164  final BoolVar x = model.newBoolVar("x");
165  final BoolVar y = model.newBoolVar("y");
166  final BoolVar z = model.newBoolVar("z");
167  model.addBoolXor(new Literal[] {x, y.not(), z});
168 
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);
172  }
173 
174  @Test
175  public void testCpModelAddImplication() throws Exception {
176  final CpModel model = new CpModel();
177  assertNotNull(model);
178  final BoolVar x = model.newBoolVar("x");
179  final BoolVar y = model.newBoolVar("y");
180  model.addImplication(x, y);
181 
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);
185  }
186 
187  @Test
188  public void testCpModelAddLinear() throws Exception {
189  final CpModel model = new CpModel();
190  assertNotNull(model);
191  final BoolVar x = model.newBoolVar("x");
192  final BoolVar y = model.newBoolVar("y");
193 
194  model.addEquality(LinearExpr.newBuilder().add(x).add(y), 1);
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);
198 
199  final BoolVar b = model.newBoolVar("b");
200  model.addEquality(LinearExpr.newBuilder().add(x).add(y), 2).onlyEnforceIf(b.not());
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);
205 
206  final BoolVar c = model.newBoolVar("c");
207  model.addEquality(LinearExpr.newBuilder().add(x).add(y), 3).onlyEnforceIf(new Literal[] {b, c});
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);
213  }
214 
215  @Test
217  final CpModel model = new CpModel();
218  assertNotNull(model);
219  final Literal x = model.newBoolVar("x");
220  final Literal y = model.newBoolVar("y").not();
221 
222  model.addEquality(x, y);
223  }
224 
225  @Test
226  public void testCpModelAddMinEquality() throws Exception {
227  final CpModel model = new CpModel();
228  assertNotNull(model);
229  final BoolVar x = model.newBoolVar("x");
230  final BoolVar y = model.newBoolVar("y");
231  final BoolVar t = model.newBoolVar("t");
232 
233  model.addMinEquality(t, new IntVar[] {x, y});
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);
247  }
248 
249  @Test
250  public void testCpModelAddMaxEquality() throws Exception {
251  final CpModel model = new CpModel();
252  assertNotNull(model);
253  final BoolVar x = model.newBoolVar("x");
254  final BoolVar y = model.newBoolVar("y");
255  final BoolVar t = model.newBoolVar("t");
256 
257  model.addMaxEquality(t, new IntVar[] {x, y});
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);
271  }
272 
273  @Test
274  public void testCpModelAddMinExprEquality() throws Exception {
275  final CpModel model = new CpModel();
276  assertNotNull(model);
277  final IntVar x = model.newBoolVar("x");
278  final IntVar t = model.newBoolVar("t");
279 
281  new LinearExpr[] {
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);
296  }
297 
298  @Test
299  public void testCpModelAddAbsEquality() throws Exception {
300  final CpModel model = new CpModel();
301  assertNotNull(model);
302  final IntVar x = model.newBoolVar("x");
303  final IntVar t = model.newBoolVar("t");
304 
305  model.addAbsEquality(
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);
322  }
323 
324  @Test
325  public void testCpModelAddCircuit() throws Exception {
326  final CpModel model = new CpModel();
327  assertNotNull(model);
328 
329  final Literal x1 = model.newBoolVar("x1");
330  final Literal x2 = model.newBoolVar("x2");
331  final Literal x3 = model.newBoolVar("x3");
332 
333  CircuitConstraint circuit = model.addCircuit();
334  circuit.addArc(0, 1, x1);
335  circuit.addArc(1, 2, x2.not());
336  circuit.addArc(2, 0, x3);
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);
342  }
343 
344  @Test
345  public void testCpModelAddMultipleCircuit() throws Exception {
346  final CpModel model = new CpModel();
347  assertNotNull(model);
348 
349  final Literal x1 = model.newBoolVar("x1");
350  final Literal x2 = model.newBoolVar("x2");
351  final Literal x3 = model.newBoolVar("x3");
352 
354  circuit.addArc(0, 1, x1);
355  circuit.addArc(1, 2, x2.not());
356  circuit.addArc(2, 0, x3);
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);
362  }
363 
364  @Test
365  public void testCpModelAddAutomaton() throws Exception {
366  final CpModel model = new CpModel();
367  assertNotNull(model);
368 
369  final IntVar x1 = model.newIntVar(0, 5, "x1");
370  final IntVar x2 = model.newIntVar(0, 5, "x2");
371  final IntVar x3 = model.newIntVar(0, 5, "x3");
372 
373  AutomatonConstraint automaton =
374  model.addAutomaton(new IntVar[] {x1, x2, x3}, 0, new long[] {1, 2});
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())
382  .isEqualTo(3);
383  assertThat(model.model().getConstraints(0).getAutomaton().getTransitionHeadCount())
384  .isEqualTo(3);
385  assertThat(model.model().getConstraints(0).getAutomaton().getTransitionLabelCount())
386  .isEqualTo(3);
387  assertThat(model.model().getConstraints(0).getAutomaton().getStartingState()).isEqualTo(0);
388  assertThat(model.model().getConstraints(0).getAutomaton().getFinalStatesCount()).isEqualTo(2);
389  }
390 
391  @Test
392  public void testCpModelAddNoOverlap() throws Exception {
393  final CpModel model = new CpModel();
394  assertNotNull(model);
395  final int horizon = 100;
396 
397  final IntVar startVar1 = model.newIntVar(0, horizon, "start1");
398  final int duration1 = 10;
399  final IntervalVar interval1 = model.newFixedSizeIntervalVar(startVar1, duration1, "interval1");
400 
401  final IntVar startVar2 = model.newIntVar(0, horizon, "start2");
402  final int duration2 = 15;
403  final IntervalVar interval2 = model.newFixedSizeIntervalVar(startVar2, duration2, "interval2");
404 
405  model.addNoOverlap(new IntervalVar[] {interval1, interval2});
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);
411  }
412 
413  @Test
414  public void testCpModelAddCumulative() throws Exception {
415  final CpModel model = new CpModel();
416  assertNotNull(model);
417  final int horizon = 100;
418 
419  final IntVar startVar1 = model.newIntVar(0, horizon, "start1");
420  final int duration1 = 10;
421  final int demand1 = 20;
422  final IntervalVar interval1 = model.newFixedSizeIntervalVar(startVar1, duration1, "interval1");
423 
424  final IntVar startVar2 = model.newIntVar(0, horizon, "start2");
425  final IntVar demandVar2 = model.newIntVar(2, 5, "demand2");
426  final int duration2 = 15;
427  final IntervalVar interval2 = model.newFixedSizeIntervalVar(startVar2, duration2, "interval2");
428 
429  CumulativeConstraint cumul = model.addCumulative(13);
430  cumul.addDemand(interval1, demand1);
431  cumul.addDemand(interval2, demandVar2);
432 
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);
438 
439  cumul.addDemands(new IntervalVar[] {interval1}, new int[] {2});
440  cumul.addDemands(new IntervalVar[] {interval1}, new long[] {2});
441  cumul.addDemands(
442  new IntervalVar[] {interval2}, new LinearArgument[] {LinearExpr.affine(demandVar2, 1, 2)});
443  cumul.addDemands(
444  new IntervalVar[] {interval2}, new LinearExpr[] {LinearExpr.affine(demandVar2, 1, 3)});
445  assertThat(model.model().getConstraints(2).getCumulative().getIntervalsCount()).isEqualTo(6);
446  }
447 
448  @Test
449  public void testCpModelAddNoOverlap2D() throws Exception {
450  final CpModel model = new CpModel();
451  assertNotNull(model);
452  final int horizon = 100;
453 
454  final IntVar startVar1 = model.newIntVar(0, horizon, "start1");
455  final int duration1 = 10;
456  final IntervalVar interval1 = model.newFixedSizeIntervalVar(startVar1, duration1, "interval1");
457 
458  final IntVar startVar2 = model.newIntVar(0, horizon, "start2");
459  final int duration2 = 15;
460  final IntervalVar interval2 = model.newFixedSizeIntervalVar(startVar2, duration2, "interval2");
461 
463  ct.addRectangle(interval1, interval1);
464  ct.addRectangle(interval2, interval2);
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);
471  }
472 
473  @Test
474  public void testCpModelModelStats() throws Exception {
475  final CpModel model = new CpModel();
476  assertNotNull(model);
477  final BoolVar x = model.newBoolVar("x");
478  final BoolVar y = model.newBoolVar("y");
479  model.addImplication(x, y);
480 
481  String stats = model.modelStats();
482  assertThat(stats).isNotEmpty();
483  }
484 
485  @Test
486  public void testCpModelValidateOk() throws Exception {
487  final CpModel model = new CpModel();
488  assertNotNull(model);
489  final BoolVar x = model.newBoolVar("x");
490  final BoolVar y = model.newBoolVar("y");
491  model.addImplication(x, y);
492 
493  String stats = model.validate();
494  assertThat(stats).isEmpty();
495  }
496 
497  @Test
498  public void testCpModelValidateNotOk() throws Exception {
499  final CpModel model = new CpModel();
500  assertNotNull(model);
501  final IntVar x = model.newIntVar(0, 9223372036854775807L, "x");
502  final IntVar y = model.newIntVar(0, 10, "y");
504  Domain.fromFlatIntervals(new long[] {6, 9223372036854775807L}));
505 
506  String stats = model.validate();
507  assertThat(stats).isNotEmpty();
508  }
509 
510  @Test
511  public void testCpModelExceptionVisibility() throws Exception {
512  CpModel.MismatchedArrayLengths ex1 = new CpModel.MismatchedArrayLengths("test1", "ar1", "ar2");
513  CpModel.WrongLength ex2 = new CpModel.WrongLength("test2", "ar");
514  assertThat(ex1).hasMessageThat().isEqualTo("test1: ar1 and ar2 have mismatched lengths");
515  assertThat(ex2).hasMessageThat().isEqualTo("test2: ar");
516  }
517 
518  @Test
519  public void testCpModelClearConstraint() throws Exception {
520  final CpModel model = new CpModel();
521  assertNotNull(model);
522  final IntVar x = model.newIntVar(0, 92, "x");
523  final IntVar y = model.newIntVar(0, 10, "y");
524  List<Constraint> constraints = new ArrayList<>();
525  for (int i = 0; i < 10; ++i) {
527  Domain.fromFlatIntervals(new long[] {6 + i, 92 - i}));
528  constraints.add(ct);
529  }
530 
531  for (int i = 0; i < 10; ++i) {
532  Constraint ct = constraints.get(i);
533  assertThat(ct.getBuilder().toString())
534  .isEqualTo(model.getBuilder().getConstraintsBuilder(i).toString());
535  assertThat(ct.getBuilder().hasLinear()).isTrue();
536  assertThat(model.getBuilder().getConstraintsBuilder(i).hasLinear()).isTrue();
537  assertThat(ct.getBuilder().toString())
538  .isEqualTo(model.getBuilder().getConstraintsBuilder(i).toString());
539  }
540 
541  for (int i = 0; i < 10; ++i) {
542  Constraint ct = constraints.get(i);
543  ct.getBuilder().clear();
544  }
545 
546  for (int i = 0; i < 10; ++i) {
547  Constraint ct = constraints.get(i);
548  assertThat(ct.getBuilder().hasLinear()).isFalse();
549  assertThat(model.getBuilder().getConstraintsBuilder(i).hasLinear()).isFalse();
550  }
551  }
552 
553  @Test
554  public void testCpModelMinimize() throws Exception {
555  final CpModel model = new CpModel();
556  assertNotNull(model);
557 
558  final IntVar x1 = model.newIntVar(0, 5, "x1");
559  final IntVar x2 = model.newIntVar(0, 5, "x2");
560  final IntVar x3 = model.newIntVar(0, 5, "x3");
561 
562  model.minimize(LinearExpr.sum(new IntVar[] {x1, x2}));
563  assertThat(model.getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(2);
564  assertThat(model.getBuilder().hasFloatingPointObjective()).isFalse();
565 
566  model.minimize(x3);
567  assertThat(model.getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(1);
568  assertThat(model.getBuilder().hasFloatingPointObjective()).isFalse();
569 
570  model.minimize(LinearExpr.sum(new IntVar[] {x1, x2}));
571  assertThat(model.getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(2);
572  assertThat(model.getBuilder().hasFloatingPointObjective()).isFalse();
573 
574  model.minimize(DoubleLinearExpr.weightedSum(new IntVar[] {x1, x2}, new double[] {2.5, 3.5}));
575  assertThat(model.getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(2);
576  assertThat(model.getBuilder().hasObjective()).isFalse();
577 
578  model.minimize(DoubleLinearExpr.affine(x3, 1.4, 1.2));
579  assertThat(model.getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(1);
580  assertThat(model.getBuilder().hasObjective()).isFalse();
581 
582  model.maximize(LinearExpr.sum(new IntVar[] {x1, x2}));
583  assertThat(model.getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(2);
584  assertThat(model.getBuilder().hasFloatingPointObjective()).isFalse();
585 
586  model.maximize(x3);
587  assertThat(model.getBuilder().getObjectiveBuilder().getVarsCount()).isEqualTo(1);
588  assertThat(model.getBuilder().hasFloatingPointObjective()).isFalse();
589 
590  model.maximize(DoubleLinearExpr.weightedSum(new IntVar[] {x1, x2}, new double[] {2.5, 3.5}));
591  assertThat(model.getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(2);
592  assertThat(model.getBuilder().hasObjective()).isFalse();
593 
594  model.maximize(DoubleLinearExpr.affine(x3, 1.4, 1.2));
595  assertThat(model.getBuilder().getFloatingPointObjectiveBuilder().getVarsCount()).isEqualTo(1);
596  assertThat(model.getBuilder().hasObjective()).isFalse();
597  }
598 
599  @Test
600  public void testDomainGetter() {
601  System.out.println("testDomainGetter");
602  CpModel model = new CpModel();
603 
604  // Create decision variables
605  IntVar x = model.newIntVar(0, 5, "x");
606 
607  Domain d = x.getDomain();
608  long[] flat = d.flattenedIntervals();
609  if (flat.length != 2 || flat[0] != 0 || flat[1] != 5) {
610  throw new RuntimeException("Wrong domain");
611  }
612  }
613 
614  @Test
615  public void testCrashInPresolve() {
616  System.out.println("testCrashInPresolve");
617  CpModel model = new CpModel();
618 
619  // Create decision variables
620  IntVar x = model.newIntVar(0, 5, "x");
621  IntVar y = model.newIntVar(0, 5, "y");
622 
623  // Create a linear constraint which enforces that only x or y can be greater
624  // than 0.
625  model.addLinearConstraint(LinearExpr.sum(new IntVar[] {x, y}), 0, 1);
626 
627  // Create the objective variable
628  IntVar obj = model.newIntVar(0, 3, "obj");
629 
630  // Cut the domain of the objective variable
631  model.addGreaterOrEqual(obj, 2);
632 
633  // Set a constraint that makes the problem infeasible
634  model.addMaxEquality(obj, new IntVar[] {x, y});
635 
636  // Optimize objective
637  model.minimize(obj);
638 
639  // Create a solver and solve the model.
640  CpSolver solver = new CpSolver();
641  CpSolverStatus status = solver.solve(model);
642 
643  if (status != CpSolverStatus.INFEASIBLE) {
644  throw new IllegalStateException("Wrong status in testCrashInPresolve");
645  }
646  }
647 
648  @Test
650  System.out.println("testCrashInSolveWithAllowedAssignment");
651  final CpModel model = new CpModel();
652  final int numEntityOne = 50000;
653  final int numEntityTwo = 100;
654  final IntVar[] entitiesOne = new IntVar[numEntityOne];
655  for (int i = 0; i < entitiesOne.length; i++) {
656  entitiesOne[i] = model.newIntVar(1, numEntityTwo, "E" + i);
657  }
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;
662  }
663  }
664  TableConstraint table = model.addAllowedAssignments(entitiesOne);
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++) {
668  oneTuple[j] = i;
669  }
670  table.addTuple(oneTuple);
671  }
672  final Random r = new Random();
673  for (int i = 0; i < entitiesOne.length; i++) {
674  model.addEquality(entitiesOne[i], r.nextInt(numEntityTwo));
675  }
676  final CpSolver solver = new CpSolver();
677  CpSolverStatus unused = solver.solve(model);
678  }
679 
680  @Test
681  public void testCrashEquality() {
682  System.out.println("testCrashInSolveWithAllowedAssignment");
683  final CpModel model = new CpModel();
684 
685  final IntVar[] entities = new IntVar[20];
686  Arrays.setAll(entities, i -> model.newIntVar(1, 5, "E" + i));
687 
688  final int[] equalities = new int[] {18, 4, 19, 3, 12};
689  addEqualities(model, entities, equalities);
690 
691  final int[] allowedAssignments = new int[] {12, 8, 15};
692  final int[] allowedAssignmentValues = new int[] {1, 3};
693  addAllowedAssignMents(model, entities, allowedAssignments, allowedAssignmentValues);
694 
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};
709 
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);
717 
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++) {
721  model.addEquality(entities[i], configuration[i]);
722  }
723 
724  final CpSolver solver = new CpSolver();
725  CpSolverStatus unused = solver.solve(model);
726  }
727 
728  @Test
729  public void testLogCapture() {
730  System.out.println("testLogCapture");
731 
732  // Creates the model.
733  CpModel model = new CpModel();
734  // Creates the variables.
735  int numVals = 3;
736 
737  IntVar x = model.newIntVar(0, numVals - 1, "x");
738  IntVar y = model.newIntVar(0, numVals - 1, "y");
739  // Creates the constraints.
740  model.addDifferent(x, y);
741 
742  // Creates a solver and solves the model.
743  final CpSolver solver = new CpSolver();
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');
749  };
750  solver.setLogCallback(appendToLog);
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");
755  }
756 
757  String log = logBuilder.toString();
758  if (log.isEmpty()) {
759  throw new IllegalStateException("Log should not be empty");
760  }
761  }
762 
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]]);
766  }
767  }
768 
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);
776  }
777  final IntVar[] specificEntities = new IntVar[allowedAssignments.length];
778  for (int i = 0; i < allowedAssignments.length; i++) {
779  specificEntities[i] = entities[allowedAssignments[i]];
780  }
781  TableConstraint table = model.addAllowedAssignments(specificEntities);
782  for (int[] tuple : allAllowedValues) {
783  table.addTuple(tuple);
784  }
785  }
786 
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]];
792  }
793 
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);
799  }
800  TableConstraint table = model.addForbiddenAssignments(specificEntities);
801  for (int[] tuple : notAllowedValues) {
802  table.addTuple(tuple);
803  }
804  }
805 }
Load native libraries needed for using ortools-java.
Definition: Loader.java:33
static synchronized void loadNativeLibraries()
Definition: Loader.java:104
An Boolean variable.
Definition: BoolVar.java:20
Literal not()
Returns the negation of a boolean variable.
Definition: BoolVar.java:33
CircuitConstraint addArc(int tail, int head, Literal literal)
Add an arc to the graph of the circuit constraint.
Wrapper around a ConstraintProto.
Definition: Constraint.java:25
ConstraintProto.Builder getBuilder()
Returns the constraint builder.
Definition: Constraint.java:49
void onlyEnforceIf(Literal lit)
Adds a literal to the constraint.
Definition: Constraint.java:32
Tests the CpSolver java interface.
Exception thrown when parallel arrays have mismatched lengths.
Definition: CpModel.java:51
Exception thrown when an array has a wrong length.
Definition: CpModel.java:58
Main modeling class.
Definition: CpModel.java:42
Constraint addLinearExpressionInDomain(LinearArgument expr, Domain domain)
Adds.
Definition: CpModel.java:217
Constraint addEquality(LinearArgument expr, long value)
Adds.
Definition: CpModel.java:241
CumulativeConstraint addCumulative(LinearArgument capacity)
Adds.
Definition: CpModel.java:863
NoOverlap2dConstraint addNoOverlap2D()
Adds.
Definition: CpModel.java:846
Constraint addAbsEquality(LinearArgument target, LinearArgument expr)
Adds.
Definition: CpModel.java:643
BoolVar newBoolVar(String name)
Creates a Boolean variable with the given name.
Definition: CpModel.java:88
TableConstraint addAllowedAssignments(IntVar[] variables)
Adds.
Definition: CpModel.java:423
CircuitConstraint addCircuit()
Adds.
Definition: CpModel.java:394
Constraint addExactlyOne(Literal[] literals)
Adds.
Definition: CpModel.java:165
Constraint addAtLeastOne(Literal[] literals)
Same as addBoolOr.
Definition: CpModel.java:140
void maximize(LinearArgument expr)
Adds a maximization objective of a linear expression.
Definition: CpModel.java:934
IntervalVar newFixedSizeIntervalVar(LinearArgument start, long size, String name)
Creates an interval variable from an affine expression start, and a fixed size.
Definition: CpModel.java:733
Constraint addAtMostOne(Literal[] literals)
Adds.
Definition: CpModel.java:150
String modelStats()
Returns some statistics on model as a string.
Definition: CpModel.java:980
Constraint addImplication(Literal a, Literal b)
Adds.
Definition: CpModel.java:210
Constraint addBoolXor(Literal[] literals)
Adds.
Definition: CpModel.java:195
Constraint addMaxEquality(LinearArgument target, LinearArgument[] exprs)
Adds.
Definition: CpModel.java:608
Constraint addGreaterOrEqual(LinearArgument expr, long value)
Adds.
Definition: CpModel.java:280
IntVar newIntVar(long lb, long ub, String name)
Creates an integer variable with domain [lb, ub].
Definition: CpModel.java:72
MultipleCircuitConstraint addMultipleCircuit()
Adds.
Definition: CpModel.java:408
Constraint addDifferent(LinearArgument expr, long value)
Adds.
Definition: CpModel.java:306
AutomatonConstraint addAutomaton(IntVar[] transitionVariables, long startingState, long[] finalStates)
Adds an automaton constraint.
Definition: CpModel.java:500
Constraint addNoOverlap(IntervalVar[] intervalVars)
Adds.
Definition: CpModel.java:816
String validate()
Returns a non empty string explaining the issue if the model is invalid.
Definition: CpModel.java:985
void minimize(LinearArgument expr)
Adds a minimization objective of a linear expression.
Definition: CpModel.java:913
Constraint addBoolOr(Literal[] literals)
Adds.
Definition: CpModel.java:125
IntVar newIntVarFromDomain(Domain domain, String name)
Creates an integer variable with given domain.
Definition: CpModel.java:83
Constraint addLinearConstraint(LinearArgument expr, long lb, long ub)
Adds.
Definition: CpModel.java:236
Constraint addBoolAnd(Literal[] literals)
Adds.
Definition: CpModel.java:180
CpModelProto.Builder getBuilder()
Returns the model builder.
Definition: CpModel.java:1033
Constraint addMinEquality(LinearArgument target, LinearArgument[] exprs)
Adds.
Definition: CpModel.java:585
Wrapper around the SAT solver.
Definition: CpSolver.java:28
CpSolverStatus solve(CpModel model)
Solves the given model, and returns the solve status.
Definition: CpSolver.java:37
SatParameters.Builder getParameters()
Returns the builder of the parameters of the SAT solver for modification.
Definition: CpSolver.java:179
void setLogCallback(Consumer< String > cb)
Sets the log callback for the solver.
Definition: CpSolver.java:184
CumulativeConstraint addDemands(IntervalVar[] intervals, LinearArgument[] demands)
Adds all pairs (intervals[i], demands[i]) to the constraint.
CumulativeConstraint addDemand(IntervalVar interval, LinearArgument demand)
Adds a pair (interval, demand) to the constraint.
A linear expression interface that can be parsed.
An integer variable.
Definition: IntVar.java:21
int getIndex()
Returns the index of the variable in the underlying CpModelProto.
Definition: IntVar.java:44
Domain getDomain()
Returns the domain of the variable.
Definition: IntVar.java:76
String getName()
Returns the name of the variable given upon creation.
Definition: IntVar.java:39
LinearExpr getStartExpr()
Returns the start expression.
LinearExpr getEndExpr()
Returns the end expression.
LinearExpr getSizeExpr()
Returns the size expression.
LinearExprBuilder add(LinearArgument expr)
LinearExprBuilder addTerm(LinearArgument expr, long coeff)
MultipleCircuitConstraint addArc(int tail, int head, Literal literal)
Add an arc to the graph of the multiple circuit constraint.
NoOverlap2dConstraint addRectangle(IntervalVar xInterval, IntervalVar yInterval)
Adds a rectangle (xInterval, yInterval) to the constraint.
Specialized assignment constraint.
TableConstraint addTuple(int[] tuple)
Adds a tuple of possible/forbidden values to the constraint.
A object that can build a LinearExpr object.
A linear expression (sum (ai * xi) + b).
long getCoefficient(int index)
Returns the ith coefficient.
int numElements()
Returns the number of terms (excluding the constant one) in this expression.
static LinearExpr affine(LinearArgument expr, long coeff, long offset)
Shortcut for newBuilder().addTerm(expr, coeff).add(offset).build()
static LinearExprBuilder newBuilder()
Returns a builder.
long getOffset()
Returns the constant part of the expression.
int getVariableIndex(int index)
Returns the index of the ith variable.
static LinearExpr sum(LinearArgument[] exprs)
Shortcut for newBuilder().addSum(exprs).build()
Interface to describe a boolean variable or its negation.
Definition: Literal.java:17
Literal not()
Returns the Boolean negation of the current literal.