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;
31  
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  import org.sat4j.core.ASolverFactory;
36  import org.sat4j.core.VecInt;
37  import org.sat4j.specs.ContradictionException;
38  import org.sat4j.specs.ISolver;
39  import org.sat4j.specs.IVecInt;
40  import org.sat4j.specs.TimeoutException;
41  
42  /**
43   * This is a tool for computing all the MUSes (Minimum Unsatisfiable Sets) of a
44   * set of clauses.
45   * 
46   * @author sroussel
47   * @since 2.3.3
48   */
49  public class AllMUSes {
50  
51      private AbstractClauseSelectorSolver<ISolver> css;
52      private final List<IVecInt> mssList;
53      private final List<IVecInt> secondPhaseClauses;
54      private final List<IVecInt> musList;
55      private final ASolverFactory<? extends ISolver> factory;
56  
57      public AllMUSes(boolean group, ASolverFactory<? extends ISolver> factory) {
58          if (!group) {
59              this.css = new FullClauseSelectorSolver<ISolver>(
60                      factory.defaultSolver(), false);
61          } else {
62              this.css = new GroupClauseSelectorSolver<ISolver>(
63                      factory.defaultSolver());
64          }
65          this.mssList = new ArrayList<IVecInt>();
66          this.musList = new ArrayList<IVecInt>();
67          this.secondPhaseClauses = new ArrayList<IVecInt>();
68          this.factory = factory;
69      }
70  
71      public AllMUSes(ASolverFactory<? extends ISolver> factory) {
72          this(false, factory);
73      }
74  
75      /**
76       * Gets an instance of ISolver that can be used to compute all MUSes
77       * 
78       * @return the instance of ISolver to which the clauses will be added
79       */
80      public <T extends ISolver> T getSolverInstance() {
81          return (T) this.css;
82      }
83  
84      public List<IVecInt> computeAllMUSes() {
85          return computeAllMUSes(SolutionFoundListener.VOID);
86      }
87  
88      /**
89       * Computes all the MUSes associated to the set of constraints added to the
90       * solver
91       * 
92       * @param solver
93       *            the <code>ISolver</code> that contains the set of clauses
94       * @return a list containing all the MUSes
95       */
96      public List<IVecInt> computeAllMUSes(SolutionFoundListener listener) {
97          if (secondPhaseClauses.isEmpty()) {
98              computeAllMSS();
99          }
100         ISolver solver = factory.defaultSolver();
101         for (IVecInt v : secondPhaseClauses) {
102             try {
103                 solver.addClause(v);
104             } catch (ContradictionException e) {
105                 return musList;
106             }
107         }
108         AbstractMinimalModel minSolver = new Minimal4InclusionModel(solver,
109                 Minimal4InclusionModel.positiveLiterals(solver));
110         return computeAllMUSes(listener, minSolver);
111     }
112 
113     public List<IVecInt> computeAllMUSesOrdered(SolutionFoundListener listener) {
114         if (secondPhaseClauses.isEmpty()) {
115             computeAllMSS();
116         }
117         ISolver solver = factory.defaultSolver();
118         for (IVecInt v : secondPhaseClauses) {
119             try {
120                 solver.addClause(v);
121             } catch (ContradictionException e) {
122                 return musList;
123             }
124         }
125         AbstractMinimalModel minSolver = new Minimal4CardinalityModel(solver,
126                 Minimal4InclusionModel.positiveLiterals(solver));
127         return computeAllMUSes(listener, minSolver);
128     }
129 
130     private List<IVecInt> computeAllMUSes(SolutionFoundListener listener,
131             ISolver minSolver) {
132         if (css.isVerbose()) {
133             System.out.println(css.getLogPrefix() + "Computing all MUSes ...");
134         }
135         css.internalState();
136 
137         IVecInt mus;
138 
139         IVecInt blockingClause;
140 
141         try {
142 
143             while (minSolver.isSatisfiable()) {
144                 blockingClause = new VecInt();
145                 mus = new VecInt();
146 
147                 int[] model = minSolver.model();
148 
149                 for (int i = 0; i < model.length; i++) {
150                     if (model[i] > 0) {
151                         blockingClause.push(-model[i]);
152                         mus.push(model[i]);
153                     }
154                 }
155                 musList.add(mus);
156                 listener.onSolutionFound(mus);
157 
158                 minSolver.addBlockingClause(blockingClause);
159             }
160 
161         } catch (ContradictionException e) {
162         } catch (TimeoutException e) {
163             e.printStackTrace();
164         }
165         if (css.isVerbose()) {
166             System.out.println(css.getLogPrefix() + "... done.");
167         }
168         css.externalState();
169         return musList;
170     }
171 
172     public List<IVecInt> computeAllMSS() {
173         return computeAllMSS(SolutionFoundListener.VOID);
174     }
175 
176     public List<IVecInt> computeAllMSS(SolutionFoundListener listener) {
177         IVecInt pLits = new VecInt();
178         for (Integer i : css.getAddedVars()) {
179             pLits.push(i);
180         }
181 
182         AbstractMinimalModel min4Inc = new Minimal4InclusionModel(css, pLits);
183         return computeAllMSS(listener, min4Inc, pLits);
184     }
185 
186     public List<IVecInt> computeAllMSSOrdered(SolutionFoundListener listener) {
187         IVecInt pLits = new VecInt();
188         for (Integer i : css.getAddedVars()) {
189             pLits.push(i);
190         }
191 
192         AbstractMinimalModel min4Inc = new Minimal4CardinalityModel(css, pLits);
193         return computeAllMSS(listener, min4Inc, pLits);
194     }
195 
196     private List<IVecInt> computeAllMSS(SolutionFoundListener listener,
197             ISolver min4Inc, IVecInt pLits) {
198         if (css.isVerbose()) {
199             System.out.println(css.getLogPrefix() + "Computing all MSSes ...");
200         }
201         css.internalState();
202         int nVar = css.nVars();
203 
204         IVecInt blockingClause;
205 
206         IVecInt secondPhaseClause;
207 
208         IVecInt fullMSS = new VecInt();
209         IVecInt mss;
210 
211         int clause;
212 
213         for (int i = 0; i < css.getAddedVars().size(); i++) {
214             fullMSS.push(i + 1);
215         }
216 
217         // first phase
218         try {
219 
220             while (min4Inc.isSatisfiable()) {
221                 int[] fullmodel = min4Inc.modelWithInternalVariables();
222 
223                 mss = new VecInt();
224                 fullMSS.copyTo(mss);
225 
226                 blockingClause = new VecInt();
227                 secondPhaseClause = new VecInt();
228                 for (int i = 0; i < pLits.size(); i++) {
229                     clause = Math.abs(pLits.get(i));
230                     if (fullmodel[clause - 1] > 0) {
231                         blockingClause.push(-clause);
232                         secondPhaseClause.push(clause - nVar);
233                         mss.remove(clause - nVar);
234                     }
235                 }
236 
237                 mssList.add(mss);
238 
239                 listener.onSolutionFound(mss);
240 
241                 secondPhaseClauses.add(secondPhaseClause);
242                 css.addBlockingClause(blockingClause);
243 
244             }
245 
246         } catch (TimeoutException e) {
247             e.printStackTrace();
248         } catch (ContradictionException e) {
249 
250         }
251         if (css.isVerbose()) {
252             System.out.println(css.getLogPrefix() + "... done.");
253         }
254         css.externalState();
255         return mssList;
256     }
257 
258     public List<IVecInt> getMssList() {
259         return mssList;
260     }
261 
262 }