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 package org.sat4j.tools.xplain;
29
30 import java.util.Map;
31 import java.util.Set;
32
33 import org.sat4j.core.VecInt;
34 import org.sat4j.specs.IConstr;
35 import org.sat4j.specs.ISolver;
36 import org.sat4j.specs.IVecInt;
37 import org.sat4j.specs.TimeoutException;
38
39
40
41
42 public class QuickXplainStrategy implements XplainStrategy {
43
44 private boolean computationCanceled;
45
46 public void cancelExplanationComputation() {
47 computationCanceled = true;
48 }
49
50 public IVecInt explain(ISolver solver, Map<Integer, IConstr> constrs,
51 IVecInt assumps) throws TimeoutException {
52 computationCanceled = false;
53 IVecInt encodingAssumptions = new VecInt(constrs.size()
54 + assumps.size());
55 assumps.copyTo(encodingAssumptions);
56 IVecInt firstExplanation = solver.unsatExplanation();
57 Set<Integer> constraintsVariables = constrs.keySet();
58 int p;
59 for (int i = 0; i < firstExplanation.size(); i++) {
60 if (constraintsVariables.contains(p = -firstExplanation.get(i))) {
61 encodingAssumptions.push(p);
62 }
63 }
64 IVecInt results = new VecInt(encodingAssumptions.size());
65 computeExplanation(solver, encodingAssumptions, assumps.size(),
66 encodingAssumptions.size() - 1, results);
67 return results;
68 }
69
70 private void computeExplanation(ISolver solver,
71 IVecInt encodingAssumptions, int start, int end, IVecInt result)
72 throws TimeoutException {
73 if (!solver.isSatisfiable(encodingAssumptions)) {
74 return;
75 }
76 int i = start;
77 encodingAssumptions.set(i, -encodingAssumptions.get(i));
78 assert encodingAssumptions.get(i) < 0;
79 while (!computationCanceled
80 && solver.isSatisfiable(encodingAssumptions)) {
81 if (i == end) {
82 for (int j = start; j <= end; j++) {
83 encodingAssumptions.set(j, -encodingAssumptions.get(j));
84 }
85 return;
86 }
87 i++;
88 assert encodingAssumptions.get(i) > 0;
89 encodingAssumptions.set(i, -encodingAssumptions.get(i));
90 }
91 result.push(-encodingAssumptions.get(i));
92 if (start == i) {
93 return;
94 }
95 int newend = i - 1;
96 int split = (newend + start) / 2;
97 if (split < newend) {
98 for (int j = split + 1; j < i; j++) {
99 encodingAssumptions.set(j, -encodingAssumptions.get(j));
100 }
101 computeExplanation(solver, encodingAssumptions, split + 1, newend,
102 result);
103 }
104 if (start <= split) {
105 for (int j = start; j <= split; j++) {
106 encodingAssumptions.set(j, -encodingAssumptions.get(j));
107 }
108 computeExplanation(solver, encodingAssumptions, start, split,
109 result);
110 }
111 if (computationCanceled) {
112 throw new TimeoutException();
113 }
114 }
115 }