View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004, 2012 Artois University and CNRS
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   * Contributors:
28   *   CRIL - initial API and implementation
29   *******************************************************************************/
30  package org.sat4j.tools.xplain;
31  
32  import java.util.Arrays;
33  import java.util.Collection;
34  import java.util.HashMap;
35  import java.util.HashSet;
36  import java.util.Map;
37  
38  import org.sat4j.core.VecInt;
39  import org.sat4j.specs.ContradictionException;
40  import org.sat4j.specs.IConstr;
41  import org.sat4j.specs.ISolver;
42  import org.sat4j.specs.IVecInt;
43  import org.sat4j.specs.IteratorInt;
44  import org.sat4j.specs.TimeoutException;
45  import org.sat4j.tools.SolverDecorator;
46  
47  /**
48   * Computation of MUS in a structured CNF, i.e. the clauses belong to
49   * components, the explanation is to be extracted in terms of components.
50   * 
51   * @author daniel
52   * 
53   * @param <T>
54   *            a subinterface to ISolver.
55   * @since 2.1
56   */
57  public class HighLevelXplain<T extends ISolver> extends SolverDecorator<T>
58          implements Explainer {
59  
60      protected Map<Integer, Integer> constrs = new HashMap<Integer, Integer>();
61  
62      protected IVecInt assump;
63  
64      private int lastCreatedVar;
65      private boolean pooledVarId = false;
66  
67      private MinimizationStrategy xplainStrategy = new DeletionStrategy();
68      private final Map<Integer, Integer> highLevelToVar = new HashMap<Integer, Integer>();
69  
70      public HighLevelXplain(T solver) {
71          super(solver);
72      }
73  
74      /**
75       * 
76       * @param literals
77       *            a clause
78       * @param desc
79       *            the level of the clause set
80       * @return on object representing that clause in the solver.
81       * @throws ContradictionException
82       */
83      public IConstr addClause(IVecInt literals, int desc)
84              throws ContradictionException {
85          if (desc == 0) {
86              return addClause(literals);
87          }
88          Integer hlvar = this.highLevelToVar.get(desc);
89          if (hlvar == null) {
90              hlvar = createNewVar(literals);
91              this.highLevelToVar.put(desc, hlvar);
92              this.constrs.put(hlvar, desc);
93          }
94          literals.push(hlvar);
95          IConstr constr = super.addClause(literals);
96          return constr;
97      }
98  
99      /**
100      * 
101      * @param literals
102      * @return
103      * @since 2.1
104      */
105     protected int createNewVar(IVecInt literals) {
106         if (this.pooledVarId) {
107             this.pooledVarId = false;
108             return this.lastCreatedVar;
109         }
110         this.lastCreatedVar = nextFreeVarId(true);
111         return this.lastCreatedVar;
112     }
113 
114     protected void discardLastestVar() {
115         this.pooledVarId = true;
116     }
117 
118     @Override
119     public IConstr addAtLeast(IVecInt literals, int degree)
120             throws ContradictionException {
121         throw new UnsupportedOperationException();
122     }
123 
124     @Override
125     public IConstr addAtMost(IVecInt literals, int degree)
126             throws ContradictionException {
127         throw new UnsupportedOperationException();
128     }
129 
130     /**
131 	 * 
132 	 */
133     private static final long serialVersionUID = 1L;
134 
135     /**
136      * @since 2.2.4
137      * @return
138      * @throws TimeoutException
139      */
140     private IVecInt explanationKeys() throws TimeoutException {
141         assert !isSatisfiable(this.assump);
142         ISolver solver = decorated();
143         if (solver instanceof SolverDecorator<?>) {
144             solver = ((SolverDecorator<? extends ISolver>) solver).decorated();
145         }
146         return this.xplainStrategy.explain(solver, this.constrs, this.assump);
147     }
148 
149     public int[] minimalExplanation() throws TimeoutException {
150         Collection<Integer> components = explain();
151         int[] model = new int[components.size()];
152         int i = 0;
153         for (int c : components) {
154             model[i++] = c;
155         }
156         Arrays.sort(model);
157         return model;
158     }
159 
160     /**
161      * @since 2.1
162      * @return
163      * @throws TimeoutException
164      */
165     public Collection<Integer> explain() throws TimeoutException {
166         IVecInt keys = explanationKeys();
167         Collection<Integer> explanation = new HashSet<Integer>(keys.size());
168         for (IteratorInt it = keys.iterator(); it.hasNext();) {
169             explanation.add(this.constrs.get(it.next()));
170         }
171         return explanation;
172     }
173 
174     /**
175      * @since 2.1
176      */
177     public void cancelExplanation() {
178         this.xplainStrategy.cancelExplanationComputation();
179     }
180 
181     @Override
182     public int[] findModel() throws TimeoutException {
183         this.assump = VecInt.EMPTY;
184         IVecInt extraVariables = new VecInt();
185         for (Integer p : this.constrs.keySet()) {
186             extraVariables.push(-p);
187         }
188         return super.findModel(extraVariables);
189     }
190 
191     @Override
192     public int[] findModel(IVecInt assumps) throws TimeoutException {
193         this.assump = assumps;
194         IVecInt extraVariables = new VecInt();
195         assumps.copyTo(extraVariables);
196         for (Integer p : this.constrs.keySet()) {
197             extraVariables.push(-p);
198         }
199         return super.findModel(extraVariables);
200     }
201 
202     @Override
203     public boolean isSatisfiable() throws TimeoutException {
204         this.assump = VecInt.EMPTY;
205         IVecInt extraVariables = new VecInt();
206         for (Integer p : this.constrs.keySet()) {
207             extraVariables.push(-p);
208         }
209         return super.isSatisfiable(extraVariables);
210     }
211 
212     @Override
213     public boolean isSatisfiable(boolean global) throws TimeoutException {
214         this.assump = VecInt.EMPTY;
215         IVecInt extraVariables = new VecInt();
216         for (Integer p : this.constrs.keySet()) {
217             extraVariables.push(-p);
218         }
219         return super.isSatisfiable(extraVariables, global);
220     }
221 
222     @Override
223     public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
224         this.assump = assumps;
225         IVecInt extraVariables = new VecInt();
226         assumps.copyTo(extraVariables);
227         for (Integer p : this.constrs.keySet()) {
228             extraVariables.push(-p);
229         }
230         return super.isSatisfiable(extraVariables);
231     }
232 
233     @Override
234     public boolean isSatisfiable(IVecInt assumps, boolean global)
235             throws TimeoutException {
236         this.assump = assumps;
237         IVecInt extraVariables = new VecInt();
238         assumps.copyTo(extraVariables);
239         for (Integer p : this.constrs.keySet()) {
240             extraVariables.push(-p);
241         }
242         return super.isSatisfiable(extraVariables, global);
243     }
244 
245     @Override
246     public int[] model() {
247         int[] fullmodel = super.model();
248         if (fullmodel == null) {
249             return null;
250         }
251         int[] model = new int[fullmodel.length - this.constrs.size()];
252         int j = 0;
253         for (int element : fullmodel) {
254             if (this.constrs.get(Math.abs(element)) == null) {
255                 model[j++] = element;
256             }
257         }
258         return model;
259     }
260 
261     @Override
262     public String toString(String prefix) {
263         System.out.println(prefix
264                 + "High Level Explanation (MUS) enabled solver");
265         System.out.println(prefix + this.xplainStrategy);
266         return super.toString(prefix);
267     }
268 
269     public void setMinimizationStrategy(MinimizationStrategy strategy) {
270         this.xplainStrategy = strategy;
271     }
272 
273 }