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.minisat;
31  
32  import org.sat4j.core.ASolverFactory;
33  import org.sat4j.minisat.constraints.MixedDataStructureDanielHT;
34  import org.sat4j.minisat.constraints.MixedDataStructureDanielWL;
35  import org.sat4j.minisat.constraints.MixedDataStructureSingleWL;
36  import org.sat4j.minisat.core.DataStructureFactory;
37  import org.sat4j.minisat.core.ICDCL;
38  import org.sat4j.minisat.core.IOrder;
39  import org.sat4j.minisat.core.SearchParams;
40  import org.sat4j.minisat.core.Solver;
41  import org.sat4j.minisat.learning.LimitedLearning;
42  import org.sat4j.minisat.learning.MiniSATLearning;
43  import org.sat4j.minisat.learning.NoLearningButHeuristics;
44  import org.sat4j.minisat.learning.PercentLengthLearning;
45  import org.sat4j.minisat.orders.PhaseCachingAutoEraseStrategy;
46  import org.sat4j.minisat.orders.RSATLastLearnedClausesPhaseSelectionStrategy;
47  import org.sat4j.minisat.orders.RSATPhaseSelectionStrategy;
48  import org.sat4j.minisat.orders.RandomWalkDecorator;
49  import org.sat4j.minisat.orders.VarOrderHeap;
50  import org.sat4j.minisat.restarts.ArminRestarts;
51  import org.sat4j.minisat.restarts.Glucose21Restarts;
52  import org.sat4j.minisat.restarts.LubyRestarts;
53  import org.sat4j.minisat.restarts.MiniSATRestarts;
54  import org.sat4j.minisat.restarts.NoRestarts;
55  import org.sat4j.opt.MinOneDecorator;
56  import org.sat4j.specs.ISolver;
57  import org.sat4j.tools.DimacsOutputSolver;
58  import org.sat4j.tools.ManyCore;
59  import org.sat4j.tools.OptToSatAdapter;
60  import org.sat4j.tools.StatisticsSolver;
61  
62  /**
63   * User friendly access to pre-constructed solvers.
64   * 
65   * @author leberre
66   */
67  public final class SolverFactory extends ASolverFactory<ISolver> {
68  
69      /**
70       * 
71       */
72      private static final long serialVersionUID = 1L;
73  
74      // thread safe implementation of the singleton design pattern
75      private static SolverFactory instance;
76  
77      /**
78       * Private constructor. Use singleton method instance() instead.
79       * 
80       * @see #instance()
81       */
82      private SolverFactory() {
83          super();
84      }
85  
86      private static synchronized void createInstance() {
87          if (instance == null) {
88              instance = new SolverFactory();
89          }
90      }
91  
92      /**
93       * Access to the single instance of the factory.
94       * 
95       * @return the singleton of that class.
96       */
97      public static SolverFactory instance() {
98          if (instance == null) {
99              createInstance();
100         }
101         return instance;
102     }
103 
104     /**
105      * @return a "default" "minilearning" solver learning clauses of size
106      *         smaller than 10 % of the total number of variables with a heap
107      *         based var order.
108      */
109     public static Solver<DataStructureFactory> newMiniLearningHeap() {
110         return newMiniLearningHeap(new MixedDataStructureDanielWL());
111     }
112 
113     public static ICDCL<DataStructureFactory> newMiniLearningHeapEZSimp() {
114         Solver<DataStructureFactory> solver = newMiniLearningHeap();
115         solver.setSimplifier(solver.SIMPLE_SIMPLIFICATION);
116         return solver;
117     }
118 
119     public static Solver<DataStructureFactory> newMiniLearningHeapExpSimp() {
120         Solver<DataStructureFactory> solver = newMiniLearningHeap();
121         solver.setSimplifier(solver.EXPENSIVE_SIMPLIFICATION);
122         return solver;
123     }
124 
125     public static Solver<DataStructureFactory> newMiniLearningHeapRsatExpSimp() {
126         Solver<DataStructureFactory> solver = newMiniLearningHeapExpSimp();
127         solver.setOrder(new VarOrderHeap(new RSATPhaseSelectionStrategy()));
128         return solver;
129     }
130 
131     public static Solver<DataStructureFactory> newMiniLearningHeapRsatExpSimpBiere() {
132         Solver<DataStructureFactory> solver = newMiniLearningHeapRsatExpSimp();
133         solver.setRestartStrategy(new ArminRestarts());
134         solver.setSearchParams(new SearchParams(1.1, 100));
135         return solver;
136     }
137 
138     public static ICDCL<DataStructureFactory> newMiniLearningHeapRsatExpSimpLuby() {
139         ICDCL<DataStructureFactory> solver = newMiniLearningHeapRsatExpSimp();
140         solver.setRestartStrategy(new LubyRestarts(512));
141         return solver;
142     }
143 
144     public static ICDCL<DataStructureFactory> newGlucose21() {
145         Solver<DataStructureFactory> solver = newMiniLearningHeapRsatExpSimp();
146         solver.setRestartStrategy(new Glucose21Restarts());
147         solver.setLearnedConstraintsDeletionStrategy(solver.glucose);
148         return solver;
149     }
150 
151     private static Solver<DataStructureFactory> newBestCurrentSolverConfiguration(
152             DataStructureFactory dsf) {
153         MiniSATLearning<DataStructureFactory> learning = new MiniSATLearning<DataStructureFactory>();
154         Solver<DataStructureFactory> solver = new Solver<DataStructureFactory>(
155                 learning, dsf, new VarOrderHeap(
156                         new RSATPhaseSelectionStrategy()), new ArminRestarts());
157         solver.setSearchParams(new SearchParams(1.1, 100));
158         solver.setSimplifier(solver.EXPENSIVE_SIMPLIFICATION);
159         return solver;
160     }
161 
162     /**
163      * 
164      * @since 2.2
165      */
166     public static ICDCL<DataStructureFactory> newGreedySolver() {
167         MiniSATLearning<DataStructureFactory> learning = new MiniSATLearning<DataStructureFactory>();
168         Solver<DataStructureFactory> solver = new Solver<DataStructureFactory>(
169                 learning, new MixedDataStructureDanielWL(),
170                 new RandomWalkDecorator(new VarOrderHeap(
171                         new RSATPhaseSelectionStrategy())), new NoRestarts());
172         // solver.setSearchParams(new SearchParams(1.1, 100));
173         solver.setSimplifier(solver.EXPENSIVE_SIMPLIFICATION);
174         return solver;
175     }
176 
177     /**
178      * @since 2.2
179      */
180     public static ICDCL<DataStructureFactory> newDefaultAutoErasePhaseSaving() {
181         ICDCL<DataStructureFactory> solver = newBestWL();
182         solver.setOrder(new VarOrderHeap(new PhaseCachingAutoEraseStrategy()));
183         return solver;
184     }
185 
186     /**
187      * @since 2.2.3
188      */
189     public static ICDCL<DataStructureFactory> newDefaultMS21PhaseSaving() {
190         ICDCL<DataStructureFactory> solver = newBestWL();
191         solver.setOrder(new VarOrderHeap(
192                 new RSATLastLearnedClausesPhaseSelectionStrategy()));
193         return solver;
194     }
195 
196     /**
197      * @since 2.1
198      */
199     public static Solver<DataStructureFactory> newBestWL() {
200         return newBestCurrentSolverConfiguration(new MixedDataStructureDanielWL());
201     }
202 
203     /**
204      * 
205      * @since 2.1
206      */
207     public static ICDCL<DataStructureFactory> newBestHT() {
208         return newBestCurrentSolverConfiguration(new MixedDataStructureDanielHT());
209     }
210 
211     /**
212      * 
213      * @since 2.2
214      */
215     public static ICDCL<DataStructureFactory> newBest17() {
216         Solver<DataStructureFactory> solver = newBestCurrentSolverConfiguration(new MixedDataStructureSingleWL());
217         solver.setSimplifier(solver.EXPENSIVE_SIMPLIFICATION_WLONLY);
218         solver.setLearnedConstraintsDeletionStrategy(solver.memory_based);
219         LimitedLearning<DataStructureFactory> learning = new PercentLengthLearning<DataStructureFactory>(
220                 10);
221         solver.setLearningStrategy(learning);
222         return solver;
223     }
224 
225     /**
226      * @since 2.1
227      */
228     public static Solver<DataStructureFactory> newGlucose() {
229         Solver<DataStructureFactory> solver = newBestWL();
230         solver.setLearnedConstraintsDeletionStrategy(solver.glucose);
231         solver.setRestartStrategy(new LubyRestarts(512));
232         return solver;
233     }
234 
235     /**
236      * @param dsf
237      *            a specific data structure factory
238      * @return a default "minilearning" solver using a specific data structure
239      *         factory, learning clauses of length smaller or equals to 10 % of
240      *         the number of variables and a heap based VSIDS heuristics
241      */
242     public static Solver<DataStructureFactory> newMiniLearningHeap(
243             DataStructureFactory dsf) {
244         return newMiniLearning(dsf, new VarOrderHeap());
245     }
246 
247     /**
248      * @param dsf
249      *            the data structure factory used to represent literals and
250      *            clauses
251      * @param order
252      *            the heuristics
253      * @return a SAT solver with learning limited to clauses of length smaller
254      *         or equal to 10 percent of the total number of variables, the dsf
255      *         data structure, the FirstUIP clause generator and order as
256      *         heuristics.
257      */
258     public static Solver<DataStructureFactory> newMiniLearning(
259             DataStructureFactory dsf, IOrder order) {
260         // LimitedLearning<DataStructureFactory> learning = new
261         // PercentLengthLearning<DataStructureFactory>(10);
262         MiniSATLearning<DataStructureFactory> learning = new MiniSATLearning<DataStructureFactory>();
263         Solver<DataStructureFactory> solver = new Solver<DataStructureFactory>(
264                 learning, dsf, order, new MiniSATRestarts());
265         return solver;
266     }
267 
268     /**
269      * @return a default MiniLearning without restarts.
270      */
271     public static ICDCL<DataStructureFactory> newMiniLearningHeapEZSimpNoRestarts() {
272         LimitedLearning<DataStructureFactory> learning = new PercentLengthLearning<DataStructureFactory>(
273                 10);
274         Solver<DataStructureFactory> solver = new Solver<DataStructureFactory>(
275                 learning, new MixedDataStructureDanielWL(), new SearchParams(
276                         Integer.MAX_VALUE), new VarOrderHeap(),
277                 new MiniSATRestarts());
278         learning.setSolver(solver);
279         solver.setSimplifier(solver.SIMPLE_SIMPLIFICATION);
280         return solver;
281     }
282 
283     /**
284      * @return a default MiniLearning with restarts beginning at 1000 conflicts.
285      */
286     public static ICDCL<DataStructureFactory> newMiniLearningHeapEZSimpLongRestarts() {
287         LimitedLearning<DataStructureFactory> learning = new PercentLengthLearning<DataStructureFactory>(
288                 10);
289         Solver<DataStructureFactory> solver = new Solver<DataStructureFactory>(
290                 learning, new MixedDataStructureDanielWL(), new SearchParams(
291                         1000), new VarOrderHeap(), new MiniSATRestarts());
292         learning.setSolver(solver);
293         solver.setSimplifier(solver.SIMPLE_SIMPLIFICATION);
294         return solver;
295     }
296 
297     /**
298      * @return a SAT solver very close to the original MiniSAT sat solver.
299      */
300     public static Solver<DataStructureFactory> newMiniSATHeap() {
301         return newMiniSATHeap(new MixedDataStructureDanielWL());
302     }
303 
304     /**
305      * @return a SAT solver very close to the original MiniSAT sat solver
306      *         including easy reason simplification.
307      */
308     public static ICDCL<DataStructureFactory> newMiniSATHeapEZSimp() {
309         Solver<DataStructureFactory> solver = newMiniSATHeap();
310         solver.setSimplifier(solver.SIMPLE_SIMPLIFICATION);
311         return solver;
312     }
313 
314     public static ICDCL<DataStructureFactory> newMiniSATHeapExpSimp() {
315         Solver<DataStructureFactory> solver = newMiniSATHeap();
316         solver.setSimplifier(solver.EXPENSIVE_SIMPLIFICATION);
317         return solver;
318     }
319 
320     public static Solver<DataStructureFactory> newMiniSATHeap(
321             DataStructureFactory dsf) {
322         MiniSATLearning<DataStructureFactory> learning = new MiniSATLearning<DataStructureFactory>();
323         Solver<DataStructureFactory> solver = new Solver<DataStructureFactory>(
324                 learning, dsf, new VarOrderHeap(), new MiniSATRestarts());
325         learning.setDataStructureFactory(solver.getDSFactory());
326         learning.setVarActivityListener(solver);
327         return solver;
328     }
329 
330     /**
331      * @return MiniSAT with VSIDS heuristics, FirstUIP clause generator for
332      *         backjumping but no learning.
333      */
334     public static ICDCL<MixedDataStructureDanielWL> newBackjumping() {
335         NoLearningButHeuristics<MixedDataStructureDanielWL> learning = new NoLearningButHeuristics<MixedDataStructureDanielWL>();
336         Solver<MixedDataStructureDanielWL> solver = new Solver<MixedDataStructureDanielWL>(
337                 learning, new MixedDataStructureDanielWL(), new VarOrderHeap(),
338                 new MiniSATRestarts());
339         learning.setVarActivityListener(solver);
340         return solver;
341     }
342 
343     /**
344      * @return a solver computing models with a minimum number of satisfied
345      *         literals.
346      */
347     public static ISolver newMinOneSolver() {
348         return new OptToSatAdapter(new MinOneDecorator(newDefault()));
349     }
350 
351     /**
352      * Default solver of the SolverFactory. This solver is meant to be used on
353      * challenging SAT benchmarks.
354      * 
355      * @return the best "general purpose" SAT solver available in the factory.
356      * @see #defaultSolver() the same method, polymorphic, to be called from an
357      *      instance of ASolverFactory.
358      */
359     public static ISolver newDefault() {
360         return newGlucose21(); // newMiniLearningHeapRsatExpSimpBiere();
361     }
362 
363     @Override
364     public ISolver defaultSolver() {
365         return newDefault();
366     }
367 
368     /**
369      * Small footprint SAT solver.
370      * 
371      * @return a SAT solver suitable for solving small/easy SAT benchmarks.
372      * @see #lightSolver() the same method, polymorphic, to be called from an
373      *      instance of ASolverFactory.
374      */
375     public static ISolver newLight() {
376         return newMiniLearningHeap();
377     }
378 
379     @Override
380     public ISolver lightSolver() {
381         return newLight();
382     }
383 
384     public static ISolver newDimacsOutput() {
385         return new DimacsOutputSolver();
386     }
387 
388     public static ISolver newStatistics() {
389         return new StatisticsSolver();
390     }
391 
392     public static ISolver newParallel() {
393         return new ManyCore(newSAT(), newUNSAT(),
394                 newMiniLearningHeapRsatExpSimpLuby(),
395                 newMiniLearningHeapRsatExpSimp(),
396                 newDefaultAutoErasePhaseSaving(), newMiniLearningHeap(),
397                 newMiniSATHeapExpSimp(), newMiniSATHeapEZSimp());
398     }
399 
400     /**
401      * Two solvers are running in //: one for solving SAT instances, the other
402      * one for solving unsat instances.
403      * 
404      * @return a parallel solver for both SAT and UNSAT problems.
405      */
406     public static ISolver newSATUNSAT() {
407         return new ManyCore(newSAT(), newUNSAT());
408     }
409 
410     /**
411      * That solver is expected to perform better on satisfiable benchmarks.
412      * 
413      * @return a solver for satisfiable benchmarks.
414      */
415     public static Solver newSAT() {
416         Solver solver = (Solver) newGlucose21();
417         solver.setRestartStrategy(new LubyRestarts(100));
418         solver.setLearnedConstraintsDeletionStrategy(solver.memory_based);
419         return solver;
420     }
421 
422     /**
423      * That solver is expected to perform better on unsatisfiable benchmarks.
424      * 
425      * @return a solver for unsatisfiable benchmarks.
426      */
427     public static Solver newUNSAT() {
428         Solver solver = (Solver) newGlucose21();
429         solver.setRestartStrategy(new NoRestarts());
430         solver.setSimplifier(solver.SIMPLE_SIMPLIFICATION);
431         return solver;
432     }
433 }