View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004-2008 Daniel Le Berre
3    *
4    * All rights reserved. This program and the accompanying materials
5    * are made available under the terms of the Eclipse Public License v1.0
6    * which accompanies this distribution, and is available at
7    * http://www.eclipse.org/legal/epl-v10.html
8    *
9    * Alternatively, the contents of this file may be used under the terms of
10   * either the GNU Lesser General Public License Version 2.1 or later (the
11   * "LGPL"), in which case the provisions of the LGPL are applicable instead
12   * of those above. If you wish to allow use of your version of this file only
13   * under the terms of the LGPL, and not to allow others to use your version of
14   * this file under the terms of the EPL, indicate your decision by deleting
15   * the provisions above and replace them with the notice and other provisions
16   * required by the LGPL. If you do not delete the provisions above, a recipient
17   * may use your version of this file under the terms of the EPL or the LGPL.
18   * 
19   * Based on the original MiniSat specification from:
20   * 
21   * An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the
22   * Sixth International Conference on Theory and Applications of Satisfiability
23   * Testing, LNCS 2919, pp 502-518, 2003.
24   *
25   * See www.minisat.se for the original solver in C++.
26   * 
27   *******************************************************************************/
28  package org.sat4j.tools.xplain;
29  
30  import java.util.Arrays;
31  import java.util.Collection;
32  import java.util.HashMap;
33  import java.util.HashSet;
34  import java.util.Map;
35  
36  import org.sat4j.core.VecInt;
37  import org.sat4j.specs.ContradictionException;
38  import org.sat4j.specs.IConstr;
39  import org.sat4j.specs.ISolver;
40  import org.sat4j.specs.IVecInt;
41  import org.sat4j.specs.IteratorInt;
42  import org.sat4j.specs.TimeoutException;
43  import org.sat4j.tools.SolverDecorator;
44  
45  /**
46   * Computation of MUS in a structured CNF, i.e. the clauses belong to
47   * components, the explanation is to be extracted in terms of components.
48   * 
49   * @author daniel
50   * 
51   * @param <T>
52   *            a subinterface to ISolver.
53   * @since 2.1
54   */
55  public class HighLevelXplain<T extends ISolver> extends SolverDecorator<T>
56  		implements Explainer {
57  
58  	protected Map<Integer, Integer> constrs = new HashMap<Integer, Integer>();
59  
60  	protected IVecInt assump;
61  
62  	private int lastCreatedVar;
63  	private boolean pooledVarId = false;
64  
65  	private MinimizationStrategy xplainStrategy = new DeletionStrategy();
66  	private final Map<Integer, Integer> highLevelToVar = new HashMap<Integer, Integer>();
67  
68  	public HighLevelXplain(T solver) {
69  		super(solver);
70  	}
71  
72  	/**
73  	 * 
74  	 * @param literals
75  	 *            a clause
76  	 * @param desc
77  	 *            the level of the clause set
78  	 * @return on object representing that clause in the solver.
79  	 * @throws ContradictionException
80  	 */
81  	public IConstr addClause(IVecInt literals, int desc)
82  			throws ContradictionException {
83  		if (desc == 0) {
84  			return addClause(literals);
85  		}
86  		Integer hlvar = highLevelToVar.get(desc);
87  		if (hlvar == null) {
88  			hlvar = createNewVar(literals);
89  			highLevelToVar.put(desc, hlvar);
90  			constrs.put(hlvar, desc);
91  		}
92  		literals.push(hlvar);
93  		IConstr constr = super.addClause(literals);
94  		return constr;
95  	}
96  
97  	/**
98  	 * 
99  	 * @param literals
100 	 * @return
101 	 * @since 2.1
102 	 */
103 	protected int createNewVar(IVecInt literals) {
104 		if (pooledVarId) {
105 			pooledVarId = false;
106 			return lastCreatedVar;
107 		}
108 		lastCreatedVar = nextFreeVarId(true);
109 		return lastCreatedVar;
110 	}
111 
112 	protected void discardLastestVar() {
113 		pooledVarId = true;
114 	}
115 
116 	@Override
117 	public IConstr addAtLeast(IVecInt literals, int degree)
118 			throws ContradictionException {
119 		throw new UnsupportedOperationException();
120 	}
121 
122 	@Override
123 	public IConstr addAtMost(IVecInt literals, int degree)
124 			throws ContradictionException {
125 		throw new UnsupportedOperationException();
126 	}
127 
128 	/**
129 	 * 
130 	 */
131 	private static final long serialVersionUID = 1L;
132 
133 	/**
134 	 * @since 2.2.4
135 	 * @return
136 	 * @throws TimeoutException
137 	 */
138 	private IVecInt explanationKeys() throws TimeoutException {
139 		assert !isSatisfiable(assump);
140 		ISolver solver = decorated();
141 		if (solver instanceof SolverDecorator<?>) {
142 			solver = ((SolverDecorator<? extends ISolver>) solver).decorated();
143 		}
144 		return xplainStrategy.explain(solver, constrs, assump);
145 	}
146 
147 	public int[] minimalExplanation() throws TimeoutException {
148 		Collection<Integer> components = explain();
149 		int[] model = new int[components.size()];
150 		int i = 0;
151 		for (int c : components) {
152 			model[i++] = c;
153 		}
154 		Arrays.sort(model);
155 		return model;
156 	}
157 
158 	/**
159 	 * @since 2.1
160 	 * @return
161 	 * @throws TimeoutException
162 	 */
163 	public Collection<Integer> explain() throws TimeoutException {
164 		IVecInt keys = explanationKeys();
165 		Collection<Integer> explanation = new HashSet<Integer>(keys.size());
166 		for (IteratorInt it = keys.iterator(); it.hasNext();) {
167 			explanation.add(constrs.get(it.next()));
168 		}
169 		return explanation;
170 	}
171 
172 	/**
173 	 * @since 2.1
174 	 */
175 	public void cancelExplanation() {
176 		xplainStrategy.cancelExplanationComputation();
177 	}
178 
179 	@Override
180 	public int[] findModel() throws TimeoutException {
181 		assump = VecInt.EMPTY;
182 		IVecInt extraVariables = new VecInt();
183 		for (Integer p : constrs.keySet()) {
184 			extraVariables.push(-p);
185 		}
186 		return super.findModel(extraVariables);
187 	}
188 
189 	@Override
190 	public int[] findModel(IVecInt assumps) throws TimeoutException {
191 		assump = assumps;
192 		IVecInt extraVariables = new VecInt();
193 		assumps.copyTo(extraVariables);
194 		for (Integer p : constrs.keySet()) {
195 			extraVariables.push(-p);
196 		}
197 		return super.findModel(extraVariables);
198 	}
199 
200 	@Override
201 	public boolean isSatisfiable() throws TimeoutException {
202 		assump = VecInt.EMPTY;
203 		IVecInt extraVariables = new VecInt();
204 		for (Integer p : constrs.keySet()) {
205 			extraVariables.push(-p);
206 		}
207 		return super.isSatisfiable(extraVariables);
208 	}
209 
210 	@Override
211 	public boolean isSatisfiable(boolean global) throws TimeoutException {
212 		assump = VecInt.EMPTY;
213 		IVecInt extraVariables = new VecInt();
214 		for (Integer p : constrs.keySet()) {
215 			extraVariables.push(-p);
216 		}
217 		return super.isSatisfiable(extraVariables, global);
218 	}
219 
220 	@Override
221 	public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
222 		assump = assumps;
223 		IVecInt extraVariables = new VecInt();
224 		assumps.copyTo(extraVariables);
225 		for (Integer p : constrs.keySet()) {
226 			extraVariables.push(-p);
227 		}
228 		return super.isSatisfiable(extraVariables);
229 	}
230 
231 	@Override
232 	public boolean isSatisfiable(IVecInt assumps, boolean global)
233 			throws TimeoutException {
234 		assump = assumps;
235 		IVecInt extraVariables = new VecInt();
236 		assumps.copyTo(extraVariables);
237 		for (Integer p : constrs.keySet()) {
238 			extraVariables.push(-p);
239 		}
240 		return super.isSatisfiable(extraVariables, global);
241 	}
242 
243 	@Override
244 	public int[] model() {
245 		int[] fullmodel = super.model();
246 		if (fullmodel == null) {
247 			return null;
248 		}
249 		int[] model = new int[fullmodel.length - constrs.size()];
250 		int j = 0;
251 		for (int i = 0; i < fullmodel.length; i++) {
252 			if (constrs.get(Math.abs(fullmodel[i])) == null) {
253 				model[j++] = fullmodel[i];
254 			}
255 		}
256 		return model;
257 	}
258 
259 	@Override
260 	public String toString(String prefix) {
261 		System.out.println(prefix
262 				+ "High Level Explanation (MUS) enabled solver");
263 		System.out.println(prefix + xplainStrategy);
264 		return super.toString(prefix);
265 	}
266 
267 	public void setMinimizationStrategy(MinimizationStrategy strategy) {
268 		xplainStrategy = strategy;
269 	}
270 
271 }