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.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36
37 import org.sat4j.core.VecInt;
38 import org.sat4j.specs.ContradictionException;
39 import org.sat4j.specs.IConstr;
40 import org.sat4j.specs.ISolver;
41 import org.sat4j.specs.IVecInt;
42 import org.sat4j.specs.IteratorInt;
43 import org.sat4j.specs.TimeoutException;
44 import org.sat4j.tools.SolverDecorator;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class Xplain<T extends ISolver> extends SolverDecorator<T> implements
61 Explainer {
62
63 protected Map<Integer, IConstr> constrs = new HashMap<Integer, IConstr>();
64
65 protected IVecInt assump;
66
67 private int lastCreatedVar;
68 private boolean pooledVarId = false;
69 private final IVecInt lastClause = new VecInt();
70 private IConstr lastConstr;
71 private final boolean skipDuplicatedEntries;
72
73 private MinimizationStrategy xplainStrategy = new DeletionStrategy();
74
75 public Xplain(T solver, boolean skipDuplicatedEntries) {
76 super(solver);
77 this.skipDuplicatedEntries = skipDuplicatedEntries;
78 }
79
80 public Xplain(T solver) {
81 this(solver, true);
82 }
83
84 @Override
85 public IConstr addClause(IVecInt literals) throws ContradictionException {
86 if (skipDuplicatedEntries) {
87 if (literals.equals(lastClause)) {
88
89 return null;
90 }
91 lastClause.clear();
92 literals.copyTo(lastClause);
93 }
94 int newvar = createNewVar(literals);
95 literals.push(newvar);
96 lastConstr = super.addClause(literals);
97 if (lastConstr == null) {
98 discardLastestVar();
99 } else {
100 constrs.put(newvar, lastConstr);
101 }
102 return lastConstr;
103 }
104
105
106
107
108
109
110
111 protected int createNewVar(IVecInt literals) {
112 if (pooledVarId) {
113 pooledVarId = false;
114 return lastCreatedVar;
115 }
116 lastCreatedVar = nextFreeVarId(true);
117 return lastCreatedVar;
118 }
119
120 protected void discardLastestVar() {
121 pooledVarId = true;
122 }
123
124 @Override
125 public IConstr addExactly(IVecInt literals, int n)
126 throws ContradictionException {
127 throw new UnsupportedOperationException(
128 "Explanation requires Pseudo Boolean support. See XplainPB class instead.");
129 }
130
131 @Override
132 public IConstr addAtLeast(IVecInt literals, int degree)
133 throws ContradictionException {
134 throw new UnsupportedOperationException(
135 "Explanation requires Pseudo Boolean support. See XplainPB class instead.");
136 }
137
138 @Override
139 public IConstr addAtMost(IVecInt literals, int degree)
140 throws ContradictionException {
141 throw new UnsupportedOperationException(
142 "Explanation requires Pseudo Boolean support. See XplainPB class instead.");
143 }
144
145
146
147
148 private static final long serialVersionUID = 1L;
149
150
151
152
153
154
155 private IVecInt explanationKeys() throws TimeoutException {
156 assert !isSatisfiable(assump);
157 ISolver solver = decorated();
158 if (solver instanceof SolverDecorator<?>) {
159 solver = ((SolverDecorator<? extends ISolver>) solver).decorated();
160 }
161 return xplainStrategy.explain(solver, constrs, assump);
162 }
163
164 public int[] minimalExplanation() throws TimeoutException {
165 IVecInt keys = explanationKeys();
166 keys.sort();
167 List<Integer> allKeys = new ArrayList<Integer>(constrs.keySet());
168 Collections.sort(allKeys);
169 int[] model = new int[keys.size()];
170 int i = 0;
171 for (IteratorInt it = keys.iterator(); it.hasNext();) {
172 model[i++] = allKeys.indexOf(it.next()) + 1;
173 }
174 return model;
175 }
176
177
178
179
180
181
182 public Collection<IConstr> explain() throws TimeoutException {
183 IVecInt keys = explanationKeys();
184 Collection<IConstr> explanation = new ArrayList<IConstr>(keys.size());
185 for (IteratorInt it = keys.iterator(); it.hasNext();) {
186 explanation.add(constrs.get(it.next()));
187 }
188 return explanation;
189 }
190
191
192
193
194 public void cancelExplanation() {
195 xplainStrategy.cancelExplanationComputation();
196 }
197
198
199
200
201
202 public Collection<IConstr> getConstraints() {
203 return constrs.values();
204 }
205
206 @Override
207 public int[] findModel() throws TimeoutException {
208 assump = VecInt.EMPTY;
209 IVecInt extraVariables = new VecInt();
210 for (Integer p : constrs.keySet()) {
211 extraVariables.push(-p);
212 }
213 return super.findModel(extraVariables);
214 }
215
216 @Override
217 public int[] findModel(IVecInt assumps) throws TimeoutException {
218 assump = assumps;
219 IVecInt extraVariables = new VecInt();
220 assumps.copyTo(extraVariables);
221 for (Integer p : constrs.keySet()) {
222 extraVariables.push(-p);
223 }
224 return super.findModel(extraVariables);
225 }
226
227 @Override
228 public boolean isSatisfiable() throws TimeoutException {
229 assump = VecInt.EMPTY;
230 IVecInt extraVariables = new VecInt();
231 for (Integer p : constrs.keySet()) {
232 extraVariables.push(-p);
233 }
234 return super.isSatisfiable(extraVariables);
235 }
236
237 @Override
238 public boolean isSatisfiable(boolean global) throws TimeoutException {
239 assump = VecInt.EMPTY;
240 IVecInt extraVariables = new VecInt();
241 for (Integer p : constrs.keySet()) {
242 extraVariables.push(-p);
243 }
244 return super.isSatisfiable(extraVariables, global);
245 }
246
247 @Override
248 public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
249 assump = assumps;
250 IVecInt extraVariables = new VecInt();
251 assumps.copyTo(extraVariables);
252 for (Integer p : constrs.keySet()) {
253 extraVariables.push(-p);
254 }
255 return super.isSatisfiable(extraVariables);
256 }
257
258 @Override
259 public boolean isSatisfiable(IVecInt assumps, boolean global)
260 throws TimeoutException {
261 assump = assumps;
262 IVecInt extraVariables = new VecInt();
263 assumps.copyTo(extraVariables);
264 for (Integer p : constrs.keySet()) {
265 extraVariables.push(-p);
266 }
267 return super.isSatisfiable(extraVariables, global);
268 }
269
270 @Override
271 public int[] model() {
272 int[] fullmodel = super.modelWithInternalVariables();
273 if (fullmodel == null) {
274 return null;
275 }
276 int[] model = new int[fullmodel.length - constrs.size()];
277 int j = 0;
278 for (int i = 0; i < fullmodel.length; i++) {
279 if (constrs.get(Math.abs(fullmodel[i])) == null) {
280 model[j++] = fullmodel[i];
281 }
282 }
283 return model;
284 }
285
286 @Override
287 public String toString(String prefix) {
288 System.out.println(prefix + "Explanation (MUS) enabled solver");
289 System.out.println(prefix + xplainStrategy);
290 return super.toString(prefix);
291 }
292
293 public void setMinimizationStrategy(MinimizationStrategy strategy) {
294 xplainStrategy = strategy;
295 }
296
297 @Override
298 public boolean removeConstr(IConstr c) {
299 if (lastConstr == c) {
300 lastClause.clear();
301 lastConstr = null;
302 }
303 return super.removeConstr(c);
304 }
305
306 @Override
307 public boolean removeSubsumedConstr(IConstr c) {
308 if (lastConstr == c) {
309 lastClause.clear();
310 lastConstr = null;
311 }
312 return super.removeSubsumedConstr(c);
313 }
314
315 }