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