1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.sat4j.pb;
32
33 import static org.junit.Assert.assertEquals;
34 import static org.junit.Assert.assertFalse;
35 import static org.junit.Assert.assertTrue;
36 import static org.sat4j.pb.tools.WeightedObject.newWO;
37
38 import java.math.BigInteger;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Set;
45
46 import org.junit.Before;
47 import org.junit.Test;
48 import org.sat4j.pb.tools.DependencyHelper;
49 import org.sat4j.pb.tools.StringNegator;
50 import org.sat4j.pb.tools.WeightedObject;
51 import org.sat4j.specs.ContradictionException;
52 import org.sat4j.specs.IVec;
53 import org.sat4j.specs.TimeoutException;
54
55 public class TestDependencyHelper {
56 private static final String profile = "profile";
57 private static final String junit3 = "junit_3";
58 private static final String junit4 = "junit_4";
59
60 private DependencyHelper<String, String> helper;
61
62 @Before
63 public void setUp() {
64 this.helper = new DependencyHelper<String, String>(
65 SolverFactory.newEclipseP2());
66
67
68 }
69
70 @Test
71 public void testBasicRequirements() throws ContradictionException,
72 TimeoutException {
73 this.helper.implication("A").implies("B").and("C").and("D").named("I1");
74 this.helper.implication("B").impliesNot("C").named("I2");
75 this.helper.setTrue("A", "User selection");
76 assertFalse(this.helper.hasASolution());
77
78 Set<String> cause = this.helper.why();
79 assertEquals(3, cause.size());
80 Iterator<String> it = cause.iterator();
81 assertEquals("I1", it.next());
82 assertTrue(it.hasNext());
83 assertEquals("I2", it.next());
84 assertTrue(it.hasNext());
85 assertEquals("User selection", it.next());
86 }
87
88 @Test
89 public void testBasicRequirementsDetailedExplanation()
90 throws ContradictionException, TimeoutException {
91 this.helper.implication("A").implies("B").named("I1b");
92 this.helper.implication("A").implies("C").named("I1c");
93 this.helper.implication("A").implies("D").named("I1d");
94 this.helper.implication("B").impliesNot("C").named("I2");
95 this.helper.setTrue("A", "User selection");
96 assertFalse(this.helper.hasASolution());
97
98 Set<String> cause = this.helper.why();
99 assertEquals(4, cause.size());
100 Iterator<String> it = cause.iterator();
101 assertEquals("I1b", it.next());
102 assertEquals("I1c", it.next());
103 assertEquals("I2", it.next());
104 assertEquals("User selection", it.next());
105 }
106
107 @Test
108 public void testDisjunctions() throws ContradictionException,
109 TimeoutException {
110 this.helper.implication("A").implies("B").and("C").and("D").named("I1");
111 this.helper.implication("C").implies("C1", "C2", "C3")
112 .named("C versions");
113 this.helper.atMost(1, "C1", "C2", "C3").named("Singleton on C");
114 this.helper.setTrue("A", "User selection");
115 assertTrue(this.helper.hasASolution());
116 IVec<String> solution = this.helper.getSolution();
117 assertTrue(solution.contains("A"));
118 assertTrue(solution.contains("B"));
119 assertTrue(solution.contains("C"));
120 assertTrue(solution.contains("D"));
121 if (solution.contains("C1")) {
122 assertFalse(solution.contains("C2"));
123 assertFalse(solution.contains("C3"));
124 }
125 if (solution.contains("C2")) {
126 assertFalse(solution.contains("C1"));
127 assertFalse(solution.contains("C3"));
128 }
129 if (solution.contains("C3")) {
130 assertFalse(solution.contains("C1"));
131 assertFalse(solution.contains("C2"));
132 }
133 }
134
135 @Test
136 public void testDisjunctionExplanation() throws ContradictionException,
137 TimeoutException {
138 this.helper.implication("A").implies("B").and("C").and("D").named("I1");
139 this.helper.implication("B").impliesNot("C1").named("I2");
140 this.helper.implication("D").impliesNot("C2").named("I3");
141 this.helper.implication("C").implies("C1", "C2").named("C versions");
142 this.helper.atMost(1, "C1", "C2", "C3").named("Singleton on C");
143 this.helper.setTrue("A", "User selection");
144 assertFalse(this.helper.hasASolution());
145
146 Set<String> cause = this.helper.why();
147 assertEquals(5, cause.size());
148 Iterator<String> it = cause.iterator();
149 assertEquals("C versions", it.next());
150 assertEquals("I1", it.next());
151 assertEquals("I2", it.next());
152 assertEquals("I3", it.next());
153 assertEquals("User selection", it.next());
154 }
155
156 @Test
157 public void testExplanationForASolution() throws ContradictionException,
158 TimeoutException {
159 this.helper.implication("A").implies("B").and("C").and("D").named("I1");
160 this.helper.implication("C").implies("C1", "C2", "C3")
161 .named("C versions");
162 this.helper.atMost(1, "C1", "C2", "C3").named("Singleton on C");
163 this.helper.setTrue("A", "User selection");
164 assertTrue(this.helper.hasASolution());
165 IVec<String> solution = this.helper.getSolution();
166 assertTrue(solution.contains("A"));
167 assertTrue(solution.contains("B"));
168 assertTrue(solution.contains("C"));
169 assertTrue(solution.contains("D"));
170 Set<String> cause = this.helper.why("D");
171 assertEquals(2, cause.size());
172 Iterator<String> it = cause.iterator();
173 assertEquals("I1", it.next());
174 assertEquals("User selection", it.next());
175 }
176
177 @Test
178 public void testObjectiveFunction() throws ContradictionException,
179 TimeoutException {
180 this.helper.implication("A").implies("B").and("C").and("D").named("I1");
181 this.helper.implication("C").implies("C1", "C2", "C3")
182 .named("C versions");
183 this.helper.atMost(1, "C1", "C2", "C3").named("Singleton on C");
184 this.helper.setTrue("A", "User selection");
185 this.helper.setObjectiveFunction(newWO("C1", 4), newWO("C2", 2),
186 newWO("C3", 1));
187 assertTrue(this.helper.hasASolution());
188 IVec<String> solution = this.helper.getSolution();
189 assertTrue(solution.contains("A"));
190 assertTrue(solution.contains("B"));
191 assertTrue(solution.contains("C"));
192 assertTrue(solution.contains("C3"));
193 assertFalse(solution.contains("C2"));
194 assertFalse(solution.contains("C1"));
195 assertTrue(solution.contains("D"));
196 }
197
198 @Test
199 public void testJunitExample() throws ContradictionException,
200 TimeoutException {
201 this.helper.implication(profile).implies(junit3)
202 .named("profile->junit_3");
203 this.helper.implication(profile).implies(junit4)
204 .named("profile->junit_4");
205 this.helper.setObjectiveFunction(WeightedObject.newWO(junit4, 1),
206 WeightedObject.newWO(junit3, 2));
207 this.helper.setTrue(profile, "profile must exist");
208 assertTrue(this.helper.hasASolution());
209 List<String> expected = new ArrayList<String>(Arrays.asList(profile,
210 junit3, junit4));
211 IVec<String> solution = this.helper.getSolution();
212 for (Iterator<String> i = solution.iterator(); i.hasNext();) {
213 String variable = i.next();
214 assertTrue(variable + " was not part of the solution",
215 expected.remove(variable));
216 }
217 assertTrue("solution contained too many variables: " + expected,
218 expected.isEmpty());
219 }
220
221 @Test
222 public void testJunitSingletonObjectiveExample()
223 throws ContradictionException, TimeoutException {
224 this.helper.implication(profile).implies(junit3, junit4)
225 .named("profile->junit");
226 this.helper.atMost(1, junit4, junit3);
227 this.helper.setObjectiveFunction(WeightedObject.newWO(junit4, 1),
228 WeightedObject.newWO(junit3, 2));
229 this.helper.setTrue(profile, "profile must exist");
230 assertTrue(this.helper.hasASolution());
231 List<String> expected = new ArrayList<String>(Arrays.asList(profile,
232 junit4));
233 IVec<String> solution = this.helper.getSolution();
234 for (Iterator<String> i = solution.iterator(); i.hasNext();) {
235 String variable = i.next();
236 assertTrue(variable + " was not part of the solution",
237 expected.remove(variable));
238 }
239 assertTrue("solution contained too many variables: " + expected,
240 expected.isEmpty());
241 }
242
243 @Test
244 public void testEquivalency() throws ContradictionException,
245 TimeoutException {
246 this.helper.implication("A").implies("B").named("C1");
247 this.helper.iff("C2", "B", "C");
248 this.helper.setTrue("A", "C3");
249 assertTrue(this.helper.hasASolution());
250 this.helper.setFalse("C", "C4");
251 assertFalse(this.helper.hasASolution());
252 }
253
254 @Test
255 public void testDisjunction() throws ContradictionException,
256 TimeoutException {
257
258 this.helper.disjunction("A", "B").implies("C", "D").named("C1");
259
260 this.helper.implication().implies("A", "B").named("C2");
261 this.helper.setFalse("C", "C3");
262 assertTrue(this.helper.hasASolution());
263 this.helper.setFalse("D", "C4");
264 assertFalse(this.helper.hasASolution());
265
266 }
267
268 @Test
269 public void testCathyExamples() throws ContradictionException,
270 TimeoutException {
271 this.helper.setNegator(StringNegator.INSTANCE);
272
273 this.helper.and("C1", "A", "B", "C", "D");
274
275 this.helper.implication("-A", "B").implies("E").named("C2");
276 this.helper.setFalse("D", "InitState");
277 this.helper.setTrue("B", "InitState");
278 this.helper.setFalse("E", "InitState");
279 this.helper.atMost(1, "A", "B", "C", "D", "E").named("C5");
280 assertFalse(this.helper.hasASolution());
281 assertEquals(3, this.helper.why().size());
282 }
283
284 @Test
285 public void testCardinalityConstraints() throws ContradictionException,
286 TimeoutException {
287 this.helper.setNegator(StringNegator.INSTANCE);
288
289 this.helper.atMost("C1", 2, "A", "B", "C");
290 this.helper.atLeast("C2", 2, "A", "B", "C");
291 this.helper.setFalse("C3", "A");
292 assertTrue(this.helper.hasASolution());
293 IVec<String> solution = this.helper.getSolution();
294 assertTrue(solution.contains("B"));
295 assertTrue(solution.contains("C"));
296 }
297
298 @Test
299 public void testPseudoConstraints() throws ContradictionException,
300 TimeoutException {
301 this.helper.setNegator(StringNegator.INSTANCE);
302
303 this.helper.atMost("C1", BigInteger.valueOf(5),
304 WeightedObject.newWO("A", 3), WeightedObject.newWO("B", 2),
305 WeightedObject.newWO("C", 1));
306 this.helper.atLeast("C2", BigInteger.valueOf(7),
307 WeightedObject.newWO("A", 6), WeightedObject.newWO("B", 4),
308 WeightedObject.newWO("C", 2));
309 assertTrue(this.helper.hasASolution());
310 IVec<String> solution = this.helper.getSolution();
311 assertTrue(solution.contains("A"));
312 assertFalse(solution.contains("B") && solution.contains("C"));
313 }
314
315 @Test
316 public void testPseudoConstraintsNegativeLiterals()
317 throws ContradictionException, TimeoutException {
318 this.helper.setNegator(StringNegator.INSTANCE);
319
320 this.helper.atMost("C1", BigInteger.valueOf(5),
321 WeightedObject.newWO("A", 3), WeightedObject.newWO("B", 2),
322 WeightedObject.newWO("C", 1));
323 this.helper.atMost("C2", BigInteger.valueOf(1),
324 WeightedObject.newWO("-A", 3), WeightedObject.newWO("-B", 2),
325 WeightedObject.newWO("-C", 1));
326 assertTrue(this.helper.hasASolution());
327 IVec<String> solution = this.helper.getSolution();
328 assertTrue(solution.contains("A"));
329 assertTrue(solution.contains("B"));
330 assertFalse(solution.contains("C"));
331 }
332
333 @Test
334 public void testIgnoreContiguousDuplicatedEntry()
335 throws ContradictionException {
336 this.helper.setNegator(StringNegator.INSTANCE);
337 this.helper.clause("C1", "A", "-B", "C");
338 this.helper.clause("C2", "A", "-B", "C");
339 this.helper.clause("C3", "A", "-B", "C");
340 this.helper.clause("C4", "A", "-B", "C");
341 this.helper.clause("C5", "-A", "-B", "C");
342 this.helper.clause("C6", "A", "-B", "-C");
343 this.helper.clause("C7", "A", "B", "C");
344 assertEquals(4, this.helper.getNumberOfConstraints());
345 }
346
347 @Test
348 public void testNonDuplicatedEntryNotCatched()
349 throws ContradictionException {
350 this.helper.setNegator(StringNegator.INSTANCE);
351 this.helper.clause("C1", "A", "-B", "C");
352 this.helper.clause("C2", "A", "B", "C");
353 this.helper.clause("C3", "A", "-B", "C");
354 this.helper.clause("C4", "A", "B", "C");
355 this.helper.clause("C5", "-A", "-B", "C");
356 this.helper.clause("C6", "A", "-B", "-C");
357 this.helper.clause("C7", "A", "B", "C");
358 assertEquals(7, this.helper.getNumberOfConstraints());
359 }
360
361 @Test
362 public void testLimitofHashFunction() throws ContradictionException {
363 this.helper.setNegator(StringNegator.INSTANCE);
364 this.helper.clause("C0", "A", "B", "C", "D");
365 this.helper.clause("C1", "A", "-B", "C");
366 this.helper.clause("C2", "D", "-B");
367 this.helper.clause("C3", "A", "-B", "C");
368 this.helper.clause("C4", "A", "-B", "C");
369 this.helper.clause("C5", "A", "-B", "C");
370 this.helper.clause("C6", "A", "-B", "C");
371 this.helper.clause("C7", "A", "B", "C");
372 assertEquals(5, this.helper.getNumberOfConstraints());
373 }
374
375 @Test
376 public void testVariablesIntroducedInNegativeFormFirst()
377 throws ContradictionException, TimeoutException {
378 this.helper.setNegator(StringNegator.INSTANCE);
379 this.helper.clause("C0", "-A", "-B");
380 this.helper.clause("C1", "A", "-B");
381 this.helper.clause("C2", "-A", "B");
382 this.helper.clause("C3", "A", "B");
383 assertFalse(this.helper.hasASolution());
384 }
385
386 @Test
387 public void testVariablesIntroducedInNegativeFormFirstStoredCorrectly()
388 throws ContradictionException, TimeoutException {
389 this.helper.setNegator(StringNegator.INSTANCE);
390 this.helper.clause("C0", "-A", "-B");
391 this.helper.clause("C1", "A", "-B");
392 this.helper.clause("C3", "A", "B");
393 assertTrue(this.helper.hasASolution());
394 IVec<String> solution = this.helper.getSolution();
395 assertTrue(solution.contains("A"));
396 assertFalse(solution.contains("B"));
397 }
398
399 @Test
400
401 public void testThatWeCanRetrieveTheTruthValueOfNegatedObjects()
402 throws ContradictionException, TimeoutException {
403 this.helper.setNegator(StringNegator.INSTANCE);
404 this.helper.clause("C0", "-A", "-B");
405 this.helper.clause("C1", "A", "-B");
406 this.helper.clause("C3", "A", "B");
407 assertTrue(this.helper.hasASolution());
408 assertTrue(this.helper.getBooleanValueFor("A"));
409 assertTrue(this.helper.getBooleanValueFor("-B"));
410 }
411
412 @Test
413 public void testImpliedObjects() throws ContradictionException,
414 TimeoutException {
415 this.helper.setNegator(StringNegator.INSTANCE);
416 this.helper.clause("C0", "A", "B", "C");
417 this.helper.clause("C1", "-A", "-B");
418 this.helper.clause("C2", "-A", "-C");
419 this.helper.clause("C2", "-B", "-C");
420 assertTrue(this.helper.hasASolution());
421 Collection<String> assumptions = new ArrayList<String>();
422 assumptions.add("A");
423 Collection<String> satisfied = new ArrayList<String>();
424 Collection<String> falsified = new ArrayList<String>();
425 this.helper.impliedBy(assumptions, satisfied, falsified);
426 assertEquals(">>>" + satisfied, 1, satisfied.size());
427 assertTrue(satisfied.contains("A"));
428 assertEquals(2, falsified.size());
429 assertTrue(falsified.contains("B"));
430 assertTrue(falsified.contains("C"));
431 }
432
433 }