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.ArrayList;
33  import java.util.Collection;
34  import java.util.Collections;
35  import java.util.List;
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.FullClauseSelectorSolver;
45  import org.sat4j.tools.SolverDecorator;
46  
47  /**
48   * Explanation framework for SAT4J.
49   * 
50   * The explanation uses selector variables and assumptions.
51   * 
52   * It is based on a two steps method: 1) extraction of a set of assumptions
53   * implying the inconsistency 2) minimization of that set.
54   * 
55   * @author daniel
56   * 
57   * @param <T>
58   *            a subinterface to ISolver.
59   * @since 2.1
60   */
61  public class Xplain<T extends ISolver> extends FullClauseSelectorSolver<T>
62          implements Explainer {
63  
64      private IVecInt assump;
65  
66      private MinimizationStrategy xplainStrategy = new DeletionStrategy();
67  
68      public Xplain(T solver, boolean skipDuplicatedEntries) {
69          super(solver, skipDuplicatedEntries);
70      }
71  
72      public Xplain(T solver) {
73          this(solver, true);
74      }
75  
76      @Override
77      public IConstr addExactly(IVecInt literals, int n)
78              throws ContradictionException {
79          throw new UnsupportedOperationException(
80                  "Explanation requires Pseudo Boolean support. See XplainPB class instead.");
81      }
82  
83      @Override
84      public IConstr addAtLeast(IVecInt literals, int degree)
85              throws ContradictionException {
86          throw new UnsupportedOperationException(
87                  "Explanation requires Pseudo Boolean support. See XplainPB class instead.");
88      }
89  
90      @Override
91      public IConstr addAtMost(IVecInt literals, int degree)
92              throws ContradictionException {
93          throw new UnsupportedOperationException(
94                  "Explanation requires Pseudo Boolean support. See XplainPB class instead.");
95      }
96  
97      /**
98  	 * 
99  	 */
100     private static final long serialVersionUID = 1L;
101 
102     /**
103      * @since 2.2.4
104      * @return
105      * @throws TimeoutException
106      */
107     private IVecInt explanationKeys() throws TimeoutException {
108         assert !isSatisfiable(this.assump);
109         ISolver solver = decorated();
110         if (solver instanceof SolverDecorator<?>) {
111             solver = ((SolverDecorator<? extends ISolver>) solver).decorated();
112         }
113         return this.xplainStrategy.explain(solver, getConstrs(), this.assump);
114     }
115 
116     /**
117      * Provide an explanation of the inconsistency in terms of a subset minimal
118      * set of constraints, each constraint being referred to as its index
119      * (order) in the solver: first constraint is numbered 1, the second 2, etc.
120      * 
121      * @return an array of indexes such that the set of indexed constraints is
122      *         inconsistent.
123      * @throws TimeoutException
124      * @see {@link #explain()}
125      */
126     public int[] minimalExplanation() throws TimeoutException {
127         IVecInt keys = explanationKeys();
128         keys.sort();
129         List<Integer> allKeys = new ArrayList<Integer>(getConstrs().keySet());
130         Collections.sort(allKeys);
131         int[] model = new int[keys.size()];
132         int i = 0;
133         for (IteratorInt it = keys.iterator(); it.hasNext();) {
134             model[i++] = allKeys.indexOf(it.next()) + 1;
135         }
136         return model;
137     }
138 
139     /**
140      * Provide an explanation of the inconsistency in term of a subset minimal
141      * set of constraints. Compared to {@link #minimalExplanation()}, the method
142      * returns a reference to the constraint object, instead of an index.
143      * 
144      * @since 2.1
145      * @return
146      * @throws TimeoutException
147      * @see {@link #minimalExplanation()}
148      */
149     public Collection<IConstr> explain() throws TimeoutException {
150         IVecInt keys = explanationKeys();
151         Collection<IConstr> explanation = new ArrayList<IConstr>(keys.size());
152         for (IteratorInt it = keys.iterator(); it.hasNext();) {
153             explanation.add(getConstrs().get(it.next()));
154         }
155         return explanation;
156     }
157 
158     /**
159      * @since 2.1
160      */
161     public void cancelExplanation() {
162         this.xplainStrategy.cancelExplanationComputation();
163     }
164 
165     @Override
166     public int[] findModel() throws TimeoutException {
167         this.assump = VecInt.EMPTY;
168         return super.findModel();
169     }
170 
171     @Override
172     public int[] findModel(IVecInt assumps) throws TimeoutException {
173         this.assump = assumps;
174         return super.findModel(assumps);
175     }
176 
177     @Override
178     public boolean isSatisfiable() throws TimeoutException {
179         this.assump = VecInt.EMPTY;
180         return super.isSatisfiable();
181     }
182 
183     @Override
184     public boolean isSatisfiable(boolean global) throws TimeoutException {
185         this.assump = VecInt.EMPTY;
186         return super.isSatisfiable(global);
187     }
188 
189     @Override
190     public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
191         this.assump = assumps;
192         return super.isSatisfiable(assumps);
193     }
194 
195     @Override
196     public boolean isSatisfiable(IVecInt assumps, boolean global)
197             throws TimeoutException {
198         this.assump = assumps;
199         return super.isSatisfiable(assumps, global);
200     }
201 
202     @Override
203     public String toString(String prefix) {
204         System.out.println(prefix + "Explanation (MUS) enabled solver");
205         System.out.println(prefix + this.xplainStrategy);
206         return super.toString(prefix);
207     }
208 
209     public void setMinimizationStrategy(MinimizationStrategy strategy) {
210         this.xplainStrategy = strategy;
211     }
212 
213     @Override
214     public boolean removeConstr(IConstr c) {
215         if (getLastConstr() == c) {
216             getLastClause().clear();
217             setLastConstr(null);
218         }
219         return super.removeConstr(c);
220     }
221 
222     @Override
223     public boolean removeSubsumedConstr(IConstr c) {
224         if (getLastConstr() == c) {
225             getLastClause().clear();
226             setLastConstr(null);
227         }
228         return super.removeSubsumedConstr(c);
229     }
230 
231 }