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.core;
31  
32  import static org.sat4j.core.LiteralsUtils.neg;
33  import static org.sat4j.core.LiteralsUtils.toDimacs;
34  import static org.sat4j.core.LiteralsUtils.toInternal;
35  import static org.sat4j.core.LiteralsUtils.var;
36  
37  import java.io.PrintStream;
38  import java.io.PrintWriter;
39  import java.lang.reflect.Field;
40  import java.util.ArrayList;
41  import java.util.Collections;
42  import java.util.Comparator;
43  import java.util.HashMap;
44  import java.util.HashSet;
45  import java.util.Iterator;
46  import java.util.List;
47  import java.util.Map;
48  import java.util.Set;
49  import java.util.Timer;
50  import java.util.TimerTask;
51  
52  import org.sat4j.core.ConstrGroup;
53  import org.sat4j.core.LiteralsUtils;
54  import org.sat4j.core.Vec;
55  import org.sat4j.core.VecInt;
56  import org.sat4j.specs.ContradictionException;
57  import org.sat4j.specs.IConstr;
58  import org.sat4j.specs.ILogAble;
59  import org.sat4j.specs.ISolver;
60  import org.sat4j.specs.ISolverService;
61  import org.sat4j.specs.IVec;
62  import org.sat4j.specs.IVecInt;
63  import org.sat4j.specs.IteratorInt;
64  import org.sat4j.specs.Lbool;
65  import org.sat4j.specs.SearchListener;
66  import org.sat4j.specs.TimeoutException;
67  import org.sat4j.specs.UnitClauseProvider;
68  
69  /**
70   * The backbone of the library providing the modular implementation of a MiniSAT
71   * (Chaff) like solver.
72   * 
73   * @author leberre
74   */
75  public class Solver<D extends DataStructureFactory> implements ISolverService,
76          ICDCL<D> {
77  
78      private static final long serialVersionUID = 1L;
79  
80      private static final double CLAUSE_RESCALE_FACTOR = 1e-20;
81  
82      private static final double CLAUSE_RESCALE_BOUND = 1 / CLAUSE_RESCALE_FACTOR;
83  
84      protected ILogAble out;
85  
86      /**
87       * Set of original constraints.
88       */
89      protected final IVec<Constr> constrs = new Vec<Constr>();
90  
91      /**
92       * Set of learned constraints.
93       */
94      protected final IVec<Constr> learnts = new Vec<Constr>();
95  
96      /**
97       * Increment for clause activity.
98       */
99      private double claInc = 1.0;
100 
101     /**
102      * decay factor pour l'activit? des clauses.
103      */
104     private double claDecay = 1.0;
105 
106     /**
107      * propagation queue
108      */
109     // head of the queue in trail ... (taken from MiniSAT 1.14)
110     private int qhead = 0;
111 
112     /**
113      * variable assignments (literals) in chronological order.
114      */
115     protected final IVecInt trail = new VecInt();
116 
117     /**
118      * position of the decision levels on the trail.
119      */
120     protected final IVecInt trailLim = new VecInt();
121 
122     /**
123      * position of assumptions before starting the search.
124      */
125     protected int rootLevel;
126 
127     private int[] model = null;
128 
129     protected ILits voc;
130 
131     private IOrder order;
132 
133     private final ActivityComparator comparator = new ActivityComparator();
134 
135     private SolverStats stats = new SolverStats();
136 
137     private LearningStrategy<D> learner;
138 
139     protected volatile boolean undertimeout;
140 
141     private long timeout = Integer.MAX_VALUE;
142 
143     private boolean timeBasedTimeout = true;
144 
145     protected D dsfactory;
146 
147     private SearchParams params;
148 
149     private final IVecInt __dimacs_out = new VecInt();
150 
151     protected SearchListener slistener = new VoidTracing();
152 
153     private RestartStrategy restarter;
154 
155     private final Map<String, Counter> constrTypes = new HashMap<String, Counter>();
156 
157     private boolean isDBSimplificationAllowed = false;
158 
159     private final IVecInt learnedLiterals = new VecInt();
160 
161     private boolean verbose = false;
162 
163     private boolean keepHot = false;
164 
165     private String prefix = "c ";
166     private int declaredMaxVarId = 0;
167 
168     private UnitClauseProvider unitClauseProvider = UnitClauseProvider.VOID;
169 
170     protected IVecInt dimacs2internal(IVecInt in) {
171         this.__dimacs_out.clear();
172         this.__dimacs_out.ensure(in.size());
173         int p;
174         for (int i = 0; i < in.size(); i++) {
175             p = in.get(i);
176             if (p == 0) {
177                 throw new IllegalArgumentException(
178                         "0 is not a valid variable identifier");
179             }
180             this.__dimacs_out.unsafePush(this.voc.getFromPool(p));
181         }
182         return this.__dimacs_out;
183     }
184 
185     /*
186      * @since 2.3.1
187      */
188     public void registerLiteral(int p) {
189         this.voc.getFromPool(p);
190     }
191 
192     /**
193      * creates a Solver without LearningListener. A learningListener must be
194      * added to the solver, else it won't backtrack!!! A data structure factory
195      * must be provided, else it won't work either.
196      */
197 
198     public Solver(LearningStrategy<D> learner, D dsf, IOrder order,
199             RestartStrategy restarter) {
200         this(learner, dsf, new SearchParams(), order, restarter);
201     }
202 
203     public Solver(LearningStrategy<D> learner, D dsf, SearchParams params,
204             IOrder order, RestartStrategy restarter) {
205         this(learner, dsf, params, order, restarter, ILogAble.CONSOLE);
206     }
207 
208     public Solver(LearningStrategy<D> learner, D dsf, SearchParams params,
209             IOrder order, RestartStrategy restarter, ILogAble logger) {
210         this.order = order;
211         this.params = params;
212         this.restarter = restarter;
213         this.out = logger;
214         setDataStructureFactory(dsf);
215         // should be called after dsf has been set up
216         setLearningStrategy(learner);
217     }
218 
219     /*
220      * (non-Javadoc)
221      * 
222      * @see org.sat4j.minisat.core.ICDCL#setDataStructureFactory(D)
223      */
224     public final void setDataStructureFactory(D dsf) {
225         this.dsfactory = dsf;
226         this.dsfactory.setUnitPropagationListener(this);
227         this.dsfactory.setLearner(this);
228         this.voc = dsf.getVocabulary();
229         this.order.setLits(this.voc);
230     }
231 
232     /**
233      * @since 2.2
234      */
235     public boolean isVerbose() {
236         return this.verbose;
237     }
238 
239     /**
240      * @param value
241      * @since 2.2
242      */
243     public void setVerbose(boolean value) {
244         this.verbose = value;
245     }
246 
247     /*
248      * (non-Javadoc)
249      * 
250      * @see
251      * org.sat4j.minisat.core.ICDCL#setSearchListener(org.sat4j.specs.SearchListener
252      * )
253      */
254     public <S extends ISolverService> void setSearchListener(
255             SearchListener<S> sl) {
256         this.slistener = sl;
257     }
258 
259     /*
260      * (non-Javadoc)
261      * 
262      * @see org.sat4j.minisat.core.ICDCL#getSearchListener()
263      */
264     public <S extends ISolverService> SearchListener<S> getSearchListener() {
265         return this.slistener;
266     }
267 
268     /*
269      * (non-Javadoc)
270      * 
271      * @see org.sat4j.minisat.core.ICDCL#setLearner(org.sat4j.minisat.core.
272      * LearningStrategy)
273      */
274     public void setLearner(LearningStrategy<D> strategy) {
275         setLearningStrategy(strategy);
276     }
277 
278     /*
279      * (non-Javadoc)
280      * 
281      * @see
282      * org.sat4j.minisat.core.ICDCL#setLearningStrategy(org.sat4j.minisat.core.
283      * LearningStrategy)
284      */
285     public void setLearningStrategy(LearningStrategy<D> strategy) {
286         if (this.learner != null) {
287             this.learner.setSolver(null);
288         }
289         this.learner = strategy;
290         strategy.setSolver(this);
291     }
292 
293     public void setTimeout(int t) {
294         this.timeout = t * 1000L;
295         this.timeBasedTimeout = true;
296     }
297 
298     public void setTimeoutMs(long t) {
299         this.timeout = t;
300         this.timeBasedTimeout = true;
301     }
302 
303     public void setTimeoutOnConflicts(int count) {
304         this.timeout = count;
305         this.timeBasedTimeout = false;
306     }
307 
308     /*
309      * (non-Javadoc)
310      * 
311      * @see org.sat4j.minisat.core.ICDCL#setSearchParams(org.sat4j.minisat.core.
312      * SearchParams)
313      */
314     public void setSearchParams(SearchParams sp) {
315         this.params = sp;
316     }
317 
318     public SearchParams getSearchParams() {
319         return this.params;
320     }
321 
322     /*
323      * (non-Javadoc)
324      * 
325      * @see
326      * org.sat4j.minisat.core.ICDCL#setRestartStrategy(org.sat4j.minisat.core
327      * .RestartStrategy)
328      */
329     public void setRestartStrategy(RestartStrategy restarter) {
330         this.restarter = restarter;
331     }
332 
333     /*
334      * (non-Javadoc)
335      * 
336      * @see org.sat4j.minisat.core.ICDCL#getRestartStrategy()
337      */
338     public RestartStrategy getRestartStrategy() {
339         return this.restarter;
340     }
341 
342     public void expireTimeout() {
343         this.undertimeout = false;
344         if (this.timeBasedTimeout) {
345             if (this.timer != null) {
346                 this.timer.cancel();
347                 this.timer = null;
348             }
349         } else {
350             if (this.conflictCount != null) {
351                 this.conflictCount = null;
352             }
353         }
354     }
355 
356     protected int nAssigns() {
357         return this.trail.size();
358     }
359 
360     public int nConstraints() {
361         return this.constrs.size();
362     }
363 
364     public void learn(Constr c) {
365         this.slistener.learn(c);
366         this.learnts.push(c);
367         c.setLearnt();
368         c.register();
369         this.stats.learnedclauses++;
370         switch (c.size()) {
371         case 2:
372             this.stats.learnedbinaryclauses++;
373             break;
374         case 3:
375             this.stats.learnedternaryclauses++;
376             break;
377         default:
378             // do nothing
379         }
380     }
381 
382     public final int decisionLevel() {
383         return this.trailLim.size();
384     }
385 
386     @Deprecated
387     public int newVar() {
388         int index = this.voc.nVars() + 1;
389         this.voc.ensurePool(index);
390         return index;
391     }
392 
393     public int newVar(int howmany) {
394         this.voc.ensurePool(howmany);
395         this.declaredMaxVarId = howmany;
396         return howmany;
397     }
398 
399     public IConstr addClause(IVecInt literals) throws ContradictionException {
400         IVecInt vlits = dimacs2internal(literals);
401         return addConstr(this.dsfactory.createClause(vlits));
402     }
403 
404     public boolean removeConstr(IConstr co) {
405         if (co == null) {
406             throw new IllegalArgumentException(
407                     "Reference to the constraint to remove needed!"); //$NON-NLS-1$
408         }
409         Constr c = (Constr) co;
410         c.remove(this);
411         this.constrs.remove(c);
412         clearLearntClauses();
413         String type = c.getClass().getName();
414         this.constrTypes.get(type).dec();
415         return true;
416     }
417 
418     /**
419      * @since 2.1
420      */
421     public boolean removeSubsumedConstr(IConstr co) {
422         if (co == null) {
423             throw new IllegalArgumentException(
424                     "Reference to the constraint to remove needed!"); //$NON-NLS-1$
425         }
426         if (this.constrs.last() != co) {
427             throw new IllegalArgumentException(
428                     "Can only remove latest added constraint!!!"); //$NON-NLS-1$
429         }
430         Constr c = (Constr) co;
431         c.remove(this);
432         this.constrs.pop();
433         String type = c.getClass().getName();
434         this.constrTypes.get(type).dec();
435         return true;
436     }
437 
438     public void addAllClauses(IVec<IVecInt> clauses)
439             throws ContradictionException {
440         for (Iterator<IVecInt> iterator = clauses.iterator(); iterator
441                 .hasNext();) {
442             addClause(iterator.next());
443         }
444     }
445 
446     public IConstr addAtMost(IVecInt literals, int degree)
447             throws ContradictionException {
448         int n = literals.size();
449         IVecInt opliterals = new VecInt(n);
450         for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
451             opliterals.push(-iterator.next());
452         }
453         return addAtLeast(opliterals, n - degree);
454     }
455 
456     public IConstr addAtLeast(IVecInt literals, int degree)
457             throws ContradictionException {
458         IVecInt vlits = dimacs2internal(literals);
459         return addConstr(this.dsfactory.createCardinalityConstraint(vlits,
460                 degree));
461     }
462 
463     public IConstr addExactly(IVecInt literals, int n)
464             throws ContradictionException {
465         ConstrGroup group = new ConstrGroup(false);
466         group.add(addAtMost(literals, n));
467         group.add(addAtLeast(literals, n));
468         return group;
469     }
470 
471     @SuppressWarnings("unchecked")
472     public boolean simplifyDB() {
473         // Simplifie la base de clauses apres la premiere propagation des
474         // clauses unitaires
475         IVec<Constr>[] cs = new IVec[] { this.constrs, this.learnts };
476         for (int type = 0; type < 2; type++) {
477             int j = 0;
478             for (int i = 0; i < cs[type].size(); i++) {
479                 if (cs[type].get(i).simplify()) {
480                     // enleve les contraintes satisfaites de la base
481                     cs[type].get(i).remove(this);
482                 } else {
483                     cs[type].moveTo(j++, i);
484                 }
485             }
486             cs[type].shrinkTo(j);
487         }
488         return true;
489     }
490 
491     /**
492      * Si un mod?le est trouv?, ce vecteur contient le mod?le.
493      * 
494      * @return un mod?le de la formule.
495      */
496     public int[] model() {
497         if (this.model == null) {
498             throw new UnsupportedOperationException(
499                     "Call the solve method first!!!"); //$NON-NLS-1$
500         }
501         int[] nmodel = new int[this.model.length];
502         System.arraycopy(this.model, 0, nmodel, 0, this.model.length);
503         return nmodel;
504     }
505 
506     /*
507      * (non-Javadoc)
508      * 
509      * @see org.sat4j.minisat.core.ICDCL#enqueue(int)
510      */
511     public boolean enqueue(int p) {
512         return enqueue(p, null);
513     }
514 
515     /*
516      * (non-Javadoc)
517      * 
518      * @see org.sat4j.minisat.core.ICDCL#enqueue(int,
519      * org.sat4j.minisat.core.Constr)
520      */
521     public boolean enqueue(int p, Constr from) {
522         assert p > 1;
523         if (this.voc.isSatisfied(p)) {
524             // literal is already satisfied. Skipping.
525             return true;
526         }
527         if (this.voc.isFalsified(p)) {
528             // conflicting enqueued assignment
529             return false;
530         }
531         // new fact, store it
532         this.voc.satisfies(p);
533         this.voc.setLevel(p, decisionLevel());
534         this.voc.setReason(p, from);
535         this.trail.push(p);
536         if (from != null && from.learnt()) {
537             this.learnedConstraintsDeletionStrategy.onPropagation(from);
538         }
539         return true;
540     }
541 
542     private boolean[] mseen = new boolean[0];
543 
544     private final IVecInt mpreason = new VecInt();
545 
546     private final IVecInt moutLearnt = new VecInt();
547 
548     /**
549      * @throws TimeoutException
550      *             if the timeout is reached during conflict analysis.
551      */
552     public void analyze(Constr confl, Pair results) throws TimeoutException {
553         assert confl != null;
554 
555         final boolean[] seen = this.mseen;
556         final IVecInt outLearnt = this.moutLearnt;
557         final IVecInt preason = this.mpreason;
558 
559         outLearnt.clear();
560         assert outLearnt.size() == 0;
561         for (int i = 0; i < seen.length; i++) {
562             seen[i] = false;
563         }
564 
565         int counter = 0;
566         int p = ILits.UNDEFINED;
567 
568         outLearnt.push(ILits.UNDEFINED);
569         // reserve de la place pour le litteral falsifie
570         int outBtlevel = 0;
571         IConstr prevConfl = null;
572 
573         do {
574             preason.clear();
575             assert confl != null;
576             if (prevConfl != confl) {
577                 confl.calcReason(p, preason);
578                 this.learnedConstraintsDeletionStrategy
579                         .onConflictAnalysis(confl);
580                 // Trace reason for p
581                 for (int j = 0; j < preason.size(); j++) {
582                     int q = preason.get(j);
583                     this.order.updateVar(q);
584                     if (!seen[q >> 1]) {
585                         seen[q >> 1] = true;
586                         if (this.voc.getLevel(q) == decisionLevel()) {
587                             counter++;
588                             this.order.updateVarAtDecisionLevel(q);
589                         } else if (this.voc.getLevel(q) > 0) {
590                             // only literals assigned after decision level 0
591                             // part of
592                             // the explanation
593                             outLearnt.push(q ^ 1);
594                             outBtlevel = Math.max(outBtlevel,
595                                     this.voc.getLevel(q));
596                         }
597                     }
598                 }
599             }
600             prevConfl = confl;
601             // select next reason to look at
602             do {
603                 p = this.trail.last();
604                 confl = this.voc.getReason(p);
605                 undoOne();
606             } while (!seen[p >> 1]);
607             // seen[p.var] indique que p se trouve dans outLearnt ou dans
608             // le dernier niveau de d?cision
609         } while (--counter > 0);
610 
611         outLearnt.set(0, p ^ 1);
612         this.simplifier.simplify(outLearnt);
613 
614         Constr c = this.dsfactory.createUnregisteredClause(outLearnt);
615         // slistener.learn(c);
616         this.learnedConstraintsDeletionStrategy.onClauseLearning(c);
617         results.reason = c;
618 
619         assert outBtlevel > -1;
620         results.backtrackLevel = outBtlevel;
621     }
622 
623     /**
624      * Derive a subset of the assumptions causing the inconistency.
625      * 
626      * @param confl
627      *            the last conflict of the search, occuring at root level.
628      * @param assumps
629      *            the set of assumption literals
630      * @param conflictingLiteral
631      *            the literal detected conflicting while propagating
632      *            assumptions.
633      * @return a subset of assumps causing the inconsistency.
634      * @since 2.2
635      */
636     public IVecInt analyzeFinalConflictInTermsOfAssumptions(Constr confl,
637             IVecInt assumps, int conflictingLiteral) {
638         if (assumps.size() == 0) {
639             return null;
640         }
641         while (!this.trailLim.isEmpty()
642                 && this.trailLim.last() == this.trail.size()) {
643             // conflict detected when assuming a value
644             this.trailLim.pop();
645         }
646         final boolean[] seen = this.mseen;
647         final IVecInt outLearnt = this.moutLearnt;
648         final IVecInt preason = this.mpreason;
649 
650         outLearnt.clear();
651         if (this.trailLim.size() == 0) {
652             // conflict detected on unit clauses
653             return outLearnt;
654         }
655 
656         assert outLearnt.size() == 0;
657         for (int i = 0; i < seen.length; i++) {
658             seen[i] = false;
659         }
660 
661         if (confl == null) {
662             seen[conflictingLiteral >> 1] = true;
663         }
664 
665         int p = ILits.UNDEFINED;
666         while (confl == null && this.trail.size() > 0
667                 && this.trailLim.size() > 0) {
668             p = this.trail.last();
669             confl = this.voc.getReason(p);
670             undoOne();
671             if (confl == null && p == (conflictingLiteral ^ 1)) {
672                 outLearnt.push(toDimacs(p));
673             }
674             if (this.trail.size() <= this.trailLim.last()) {
675                 this.trailLim.pop();
676             }
677         }
678         if (confl == null) {
679             return outLearnt;
680         }
681         do {
682 
683             preason.clear();
684             confl.calcReason(p, preason);
685             // Trace reason for p
686             for (int j = 0; j < preason.size(); j++) {
687                 int q = preason.get(j);
688                 if (!seen[q >> 1]) {
689                     seen[q >> 1] = true;
690                     if (this.voc.getReason(q) == null
691                             && this.voc.getLevel(q) > 0) {
692                         assert assumps.contains(toDimacs(q));
693                         outLearnt.push(toDimacs(q));
694                     }
695                 }
696             }
697 
698             // select next reason to look at
699             do {
700                 p = this.trail.last();
701                 confl = this.voc.getReason(p);
702                 undoOne();
703                 if (decisionLevel() > 0
704                         && this.trail.size() <= this.trailLim.last()) {
705                     this.trailLim.pop();
706                 }
707             } while (this.trail.size() > 0 && decisionLevel() > 0
708                     && (!seen[p >> 1] || confl == null));
709         } while (decisionLevel() > 0);
710         return outLearnt;
711     }
712 
713     public static final ISimplifier NO_SIMPLIFICATION = new ISimplifier() {
714         /**
715          * 
716          */
717         private static final long serialVersionUID = 1L;
718 
719         public void simplify(IVecInt outLearnt) {
720         }
721 
722         @Override
723         public String toString() {
724             return "No reason simplification"; //$NON-NLS-1$
725         }
726     };
727 
728     public final ISimplifier SIMPLE_SIMPLIFICATION = new ISimplifier() {
729         /**
730          * 
731          */
732         private static final long serialVersionUID = 1L;
733 
734         public void simplify(IVecInt conflictToReduce) {
735             simpleSimplification(conflictToReduce);
736         }
737 
738         @Override
739         public String toString() {
740             return "Simple reason simplification"; //$NON-NLS-1$
741         }
742     };
743 
744     public final ISimplifier EXPENSIVE_SIMPLIFICATION = new ISimplifier() {
745 
746         /**
747          * 
748          */
749         private static final long serialVersionUID = 1L;
750 
751         public void simplify(IVecInt conflictToReduce) {
752             expensiveSimplification(conflictToReduce);
753         }
754 
755         @Override
756         public String toString() {
757             return "Expensive reason simplification"; //$NON-NLS-1$
758         }
759     };
760 
761     public final ISimplifier EXPENSIVE_SIMPLIFICATION_WLONLY = new ISimplifier() {
762 
763         /**
764          * 
765          */
766         private static final long serialVersionUID = 1L;
767 
768         public void simplify(IVecInt conflictToReduce) {
769             expensiveSimplificationWLOnly(conflictToReduce);
770         }
771 
772         @Override
773         public String toString() {
774             return "Expensive reason simplification specific for WL data structure"; //$NON-NLS-1$
775         }
776     };
777 
778     private ISimplifier simplifier = NO_SIMPLIFICATION;
779 
780     /*
781      * (non-Javadoc)
782      * 
783      * @see org.sat4j.minisat.core.ICDCL#setSimplifier(java.lang.String)
784      */
785     public void setSimplifier(SimplificationType simp) {
786         Field f;
787         try {
788             f = Solver.class.getDeclaredField(simp.toString());
789             this.simplifier = (ISimplifier) f.get(this);
790         } catch (Exception e) {
791             e.printStackTrace();
792             this.simplifier = NO_SIMPLIFICATION;
793         }
794     }
795 
796     /*
797      * (non-Javadoc)
798      * 
799      * @see
800      * org.sat4j.minisat.core.ICDCL#setSimplifier(org.sat4j.minisat.core.Solver
801      * .ISimplifier)
802      */
803     public void setSimplifier(ISimplifier simp) {
804         this.simplifier = simp;
805     }
806 
807     /*
808      * (non-Javadoc)
809      * 
810      * @see org.sat4j.minisat.core.ICDCL#getSimplifier()
811      */
812     public ISimplifier getSimplifier() {
813         return this.simplifier;
814     }
815 
816     // MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
817     //
818     // Permission is hereby granted, free of charge, to any person obtaining a
819     // copy of this software and associated documentation files (the
820     // "Software"), to deal in the Software without restriction, including
821     // without limitation the rights to use, copy, modify, merge, publish,
822     // distribute, sublicense, and/or sell copies of the Software, and to
823     // permit persons to whom the Software is furnished to do so, subject to
824     // the following conditions:
825     //
826     // The above copyright notice and this permission notice shall be included
827     // in all copies or substantial portions of the Software.
828     //
829     // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
830     // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
831     // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
832     // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
833     // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
834     // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
835     // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
836 
837     // Taken from MiniSAT 1.14: Simplify conflict clause (a little):
838     private void simpleSimplification(IVecInt conflictToReduce) {
839         int i, j, p;
840         final boolean[] seen = this.mseen;
841         IConstr r;
842         for (i = j = 1; i < conflictToReduce.size(); i++) {
843             r = this.voc.getReason(conflictToReduce.get(i));
844             if (r == null || r.canBePropagatedMultipleTimes()) {
845                 conflictToReduce.moveTo(j++, i);
846             } else {
847                 for (int k = 0; k < r.size(); k++) {
848                     p = r.get(k);
849                     if (!seen[p >> 1] && this.voc.isFalsified(p)
850                             && this.voc.getLevel(p) != 0) {
851                         conflictToReduce.moveTo(j++, i);
852                         break;
853                     }
854                 }
855             }
856         }
857         conflictToReduce.shrink(i - j);
858         this.stats.reducedliterals += i - j;
859     }
860 
861     private final IVecInt analyzetoclear = new VecInt();
862 
863     private final IVecInt analyzestack = new VecInt();
864 
865     // Taken from MiniSAT 1.14
866     private void expensiveSimplification(IVecInt conflictToReduce) {
867         // Simplify conflict clause (a lot):
868         //
869         int i, j;
870         // (maintain an abstraction of levels involved in conflict)
871         this.analyzetoclear.clear();
872         conflictToReduce.copyTo(this.analyzetoclear);
873         for (i = 1, j = 1; i < conflictToReduce.size(); i++) {
874             if (this.voc.getReason(conflictToReduce.get(i)) == null
875                     || !analyzeRemovable(conflictToReduce.get(i))) {
876                 conflictToReduce.moveTo(j++, i);
877             }
878         }
879         conflictToReduce.shrink(i - j);
880         this.stats.reducedliterals += i - j;
881     }
882 
883     // Check if 'p' can be removed.' min_level' is used to abort early if
884     // visiting literals at a level that cannot be removed.
885     //
886     private boolean analyzeRemovable(int p) {
887         assert this.voc.getReason(p) != null;
888         ILits lvoc = this.voc;
889         IVecInt lanalyzestack = this.analyzestack;
890         IVecInt lanalyzetoclear = this.analyzetoclear;
891         lanalyzestack.clear();
892         lanalyzestack.push(p);
893         final boolean[] seen = this.mseen;
894         int top = lanalyzetoclear.size();
895         while (lanalyzestack.size() > 0) {
896             int q = lanalyzestack.last();
897             assert lvoc.getReason(q) != null;
898             Constr c = lvoc.getReason(q);
899             lanalyzestack.pop();
900             if (c.canBePropagatedMultipleTimes()) {
901                 for (int j = top; j < lanalyzetoclear.size(); j++) {
902                     seen[lanalyzetoclear.get(j) >> 1] = false;
903                 }
904                 lanalyzetoclear.shrink(lanalyzetoclear.size() - top);
905                 return false;
906             }
907             for (int i = 0; i < c.size(); i++) {
908                 int l = c.get(i);
909                 if (!seen[var(l)] && lvoc.isFalsified(l)
910                         && lvoc.getLevel(l) != 0) {
911                     if (lvoc.getReason(l) == null) {
912                         for (int j = top; j < lanalyzetoclear.size(); j++) {
913                             seen[lanalyzetoclear.get(j) >> 1] = false;
914                         }
915                         lanalyzetoclear.shrink(lanalyzetoclear.size() - top);
916                         return false;
917                     }
918                     seen[l >> 1] = true;
919                     lanalyzestack.push(l);
920                     lanalyzetoclear.push(l);
921                 }
922             }
923 
924         }
925 
926         return true;
927     }
928 
929     // Taken from MiniSAT 1.14
930     private void expensiveSimplificationWLOnly(IVecInt conflictToReduce) {
931         // Simplify conflict clause (a lot):
932         //
933         int i, j;
934         // (maintain an abstraction of levels involved in conflict)
935         this.analyzetoclear.clear();
936         conflictToReduce.copyTo(this.analyzetoclear);
937         for (i = 1, j = 1; i < conflictToReduce.size(); i++) {
938             if (this.voc.getReason(conflictToReduce.get(i)) == null
939                     || !analyzeRemovableWLOnly(conflictToReduce.get(i))) {
940                 conflictToReduce.moveTo(j++, i);
941             }
942         }
943         conflictToReduce.shrink(i - j);
944         this.stats.reducedliterals += i - j;
945     }
946 
947     // Check if 'p' can be removed.' min_level' is used to abort early if
948     // visiting literals at a level that cannot be removed.
949     //
950     private boolean analyzeRemovableWLOnly(int p) {
951         assert this.voc.getReason(p) != null;
952         this.analyzestack.clear();
953         this.analyzestack.push(p);
954         final boolean[] seen = this.mseen;
955         int top = this.analyzetoclear.size();
956         while (this.analyzestack.size() > 0) {
957             int q = this.analyzestack.last();
958             assert this.voc.getReason(q) != null;
959             Constr c = this.voc.getReason(q);
960             this.analyzestack.pop();
961             for (int i = 1; i < c.size(); i++) {
962                 int l = c.get(i);
963                 if (!seen[var(l)] && this.voc.getLevel(l) != 0) {
964                     if (this.voc.getReason(l) == null) {
965                         for (int j = top; j < this.analyzetoclear.size(); j++) {
966                             seen[this.analyzetoclear.get(j) >> 1] = false;
967                         }
968                         this.analyzetoclear.shrink(this.analyzetoclear.size()
969                                 - top);
970                         return false;
971                     }
972                     seen[l >> 1] = true;
973                     this.analyzestack.push(l);
974                     this.analyzetoclear.push(l);
975                 }
976             }
977         }
978 
979         return true;
980     }
981 
982     // END Minisat 1.14 cut and paste
983 
984     /**
985      * 
986      */
987     protected void undoOne() {
988         // gather last assigned literal
989         int p = this.trail.last();
990         assert p > 1;
991         assert this.voc.getLevel(p) >= 0;
992         int x = p >> 1;
993         // unassign variable
994         this.voc.unassign(p);
995         this.voc.setReason(p, null);
996         this.voc.setLevel(p, -1);
997         // update heuristics value
998         this.order.undo(x);
999         // remove literal from the trail
1000         this.trail.pop();
1001         // update constraints on backtrack.
1002         // not used if the solver uses watched literals.
1003         IVec<Undoable> undos = this.voc.undos(p);
1004         assert undos != null;
1005         for (int size = undos.size(); size > 0; size--) {
1006             undos.last().undo(p);
1007             undos.pop();
1008         }
1009     }
1010 
1011     /**
1012      * Propagate activity to a constraint
1013      * 
1014      * @param confl
1015      *            a constraint
1016      */
1017     public void claBumpActivity(Constr confl) {
1018         confl.incActivity(this.claInc);
1019         if (confl.getActivity() > CLAUSE_RESCALE_BOUND) {
1020             claRescalActivity();
1021             // for (int i = 0; i < confl.size(); i++) {
1022             // varBumpActivity(confl.get(i));
1023             // }
1024         }
1025     }
1026 
1027     public void varBumpActivity(int p) {
1028         this.order.updateVar(p);
1029     }
1030 
1031     private void claRescalActivity() {
1032         for (int i = 0; i < this.learnts.size(); i++) {
1033             this.learnts.get(i).rescaleBy(CLAUSE_RESCALE_FACTOR);
1034         }
1035         this.claInc *= CLAUSE_RESCALE_FACTOR;
1036     }
1037 
1038     private final IVec<Propagatable> watched = new Vec<Propagatable>();
1039 
1040     /**
1041      * @return null if not conflict is found, else a conflicting constraint.
1042      */
1043     public final Constr propagate() {
1044         IVecInt ltrail = this.trail;
1045         SolverStats lstats = this.stats;
1046         IOrder lorder = this.order;
1047         SearchListener lslistener = this.slistener;
1048         // ltrail.size() changes due to propagation
1049         // cannot cache that value.
1050         while (this.qhead < ltrail.size()) {
1051             lstats.propagations++;
1052             int p = ltrail.get(this.qhead++);
1053             lslistener.propagating(toDimacs(p), null);
1054             lorder.assignLiteral(p);
1055             Constr confl = reduceClausesForFalsifiedLiteral(p);
1056             if (confl != null) {
1057                 return confl;
1058             }
1059         }
1060         return null;
1061     }
1062 
1063     private Constr reduceClausesForFalsifiedLiteral(int p) {
1064         // p is the literal to propagate
1065         // Moved original MiniSAT code to dsfactory to avoid
1066         // watches manipulation in counter Based clauses for instance.
1067         assert p > 1;
1068         IVec<Propagatable> lwatched = this.watched;
1069         lwatched.clear();
1070         this.voc.watches(p).moveTo(lwatched);
1071         final int size = lwatched.size();
1072         for (int i = 0; i < size; i++) {
1073             this.stats.inspects++;
1074             // try shortcut
1075             // shortcut = shortcuts.get(i);
1076             // if (shortcut != ILits.UNDEFINED && voc.isSatisfied(shortcut))
1077             // {
1078             // voc.watch(p, watched.get(i), shortcut);
1079             // stats.shortcuts++;
1080             // continue;
1081             // }
1082             if (!lwatched.get(i).propagate(this, p)) {
1083                 // Constraint is conflicting: copy remaining watches to
1084                 // watches[p]
1085                 // and return constraint
1086                 final int sizew = lwatched.size();
1087                 for (int j = i + 1; j < sizew; j++) {
1088                     this.voc.watch(p, lwatched.get(j));
1089                 }
1090                 this.qhead = this.trail.size(); // propQ.clear();
1091                 return lwatched.get(i).toConstraint();
1092             }
1093         }
1094         return null;
1095     }
1096 
1097     void record(Constr constr) {
1098         constr.assertConstraint(this);
1099         int p = toDimacs(constr.get(0));
1100         this.slistener.adding(p);
1101         if (constr.size() == 1) {
1102             this.stats.learnedliterals++;
1103             this.slistener.learnUnit(p);
1104         } else {
1105             this.learner.learns(constr);
1106         }
1107     }
1108 
1109     /**
1110      * @return false ssi conflit imm?diat.
1111      */
1112     public boolean assume(int p) {
1113         // Precondition: assume propagation queue is empty
1114         assert this.trail.size() == this.qhead;
1115         assert !this.trailLim.contains(this.trail.size());
1116         this.trailLim.push(this.trail.size());
1117         return enqueue(p);
1118     }
1119 
1120     /**
1121      * Revert to the state before the last assume()
1122      */
1123     private void cancel() {
1124         // assert trail.size() == qhead || !undertimeout;
1125         int decisionvar = this.trail.unsafeGet(this.trailLim.last());
1126         this.slistener.backtracking(toDimacs(decisionvar));
1127         for (int c = this.trail.size() - this.trailLim.last(); c > 0; c--) {
1128             undoOne();
1129         }
1130         this.trailLim.pop();
1131         this.qhead = this.trail.size();
1132     }
1133 
1134     /**
1135      * Restore literals
1136      */
1137     private void cancelLearntLiterals(int learnedLiteralsLimit) {
1138         this.learnedLiterals.clear();
1139         // assert trail.size() == qhead || !undertimeout;
1140         while (this.trail.size() > learnedLiteralsLimit) {
1141             this.learnedLiterals.push(this.trail.last());
1142             undoOne();
1143         }
1144         // qhead = 0;
1145         // learnedLiterals = 0;
1146     }
1147 
1148     /**
1149      * Cancel several levels of assumptions
1150      * 
1151      * @param level
1152      */
1153     protected void cancelUntil(int level) {
1154         while (decisionLevel() > level) {
1155             cancel();
1156         }
1157     }
1158 
1159     private final Pair analysisResult = new Pair();
1160 
1161     private boolean[] userbooleanmodel;
1162 
1163     private IVecInt unsatExplanationInTermsOfAssumptions;
1164 
1165     Lbool search(IVecInt assumps) {
1166         assert this.rootLevel == decisionLevel();
1167         this.stats.starts++;
1168         int backjumpLevel;
1169 
1170         // varDecay = 1 / params.varDecay;
1171         this.order.setVarDecay(1 / this.params.getVarDecay());
1172         this.claDecay = 1 / this.params.getClaDecay();
1173 
1174         do {
1175             this.slistener.beginLoop();
1176             // propagate unit clauses and other constraints
1177             Constr confl = propagate();
1178             assert this.trail.size() == this.qhead;
1179 
1180             if (confl == null) {
1181                 // No conflict found
1182                 if (decisionLevel() == 0 && this.isDBSimplificationAllowed) {
1183                     this.stats.rootSimplifications++;
1184                     boolean ret = simplifyDB();
1185                     assert ret;
1186                 }
1187                 assert nAssigns() <= this.voc.realnVars();
1188                 if (nAssigns() == this.voc.realnVars()) {
1189                     modelFound();
1190                     this.slistener.solutionFound(
1191                             (this.fullmodel != null) ? this.fullmodel
1192                                     : this.model, this);
1193                     if (this.sharedConflict == null) {
1194                         cancelUntil(this.rootLevel);
1195                         return Lbool.TRUE;
1196                     } else {
1197                         confl = this.sharedConflict;
1198                     }
1199                 } else {
1200                     if (this.restarter.shouldRestart()) {
1201                         cancelUntil(this.rootLevel);
1202                         return Lbool.UNDEFINED;
1203                     }
1204                     if (this.needToReduceDB) {
1205                         reduceDB();
1206                         this.needToReduceDB = false;
1207                     }
1208                     if (this.sharedConflict == null) {
1209                         // New variable decision
1210                         this.stats.decisions++;
1211                         int p = this.order.select();
1212                         if (p == ILits.UNDEFINED) {
1213                             confl = preventTheSameDecisionsToBeMade();
1214                             this.lastConflictMeansUnsat = false;
1215                         } else {
1216                             assert p > 1;
1217                             this.slistener.assuming(toDimacs(p));
1218                             boolean ret = assume(p);
1219                             assert ret;
1220                         }
1221                     } else {
1222                         confl = this.sharedConflict;
1223                     }
1224                 }
1225             }
1226             if (confl != null) {
1227                 // conflict found
1228                 this.stats.conflicts++;
1229                 this.slistener.conflictFound(confl, decisionLevel(),
1230                         this.trail.size());
1231                 this.conflictCount.newConflict();
1232 
1233                 if (decisionLevel() == this.rootLevel) {
1234                     if (this.lastConflictMeansUnsat) {
1235                         // conflict at root level, the formula is inconsistent
1236                         this.unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1237                                 confl, assumps, ILits.UNDEFINED);
1238                         return Lbool.FALSE;
1239                     }
1240                     return Lbool.UNDEFINED;
1241                 }
1242                 int conflictTrailLevel = this.trail.size();
1243                 // analyze conflict
1244                 try {
1245                     analyze(confl, this.analysisResult);
1246                 } catch (TimeoutException e) {
1247                     return Lbool.UNDEFINED;
1248                 }
1249                 assert this.analysisResult.backtrackLevel < decisionLevel();
1250                 backjumpLevel = Math.max(this.analysisResult.backtrackLevel,
1251                         this.rootLevel);
1252                 this.slistener.backjump(backjumpLevel);
1253                 cancelUntil(backjumpLevel);
1254                 if (backjumpLevel == this.rootLevel) {
1255                     this.restarter.onBackjumpToRootLevel();
1256                 }
1257                 if (confl == this.sharedConflict) {
1258                     this.sharedConflict.assertConstraintIfNeeded(this);
1259                     this.sharedConflict = null;
1260                 }
1261                 assert decisionLevel() >= this.rootLevel
1262                         && decisionLevel() >= this.analysisResult.backtrackLevel;
1263                 if (this.analysisResult.reason == null) {
1264                     return Lbool.FALSE;
1265                 }
1266                 record(this.analysisResult.reason);
1267                 this.restarter.newLearnedClause(this.analysisResult.reason,
1268                         conflictTrailLevel);
1269                 this.analysisResult.reason = null;
1270                 decayActivities();
1271             }
1272         } while (this.undertimeout);
1273         return Lbool.UNDEFINED; // timeout occured
1274     }
1275 
1276     private Constr preventTheSameDecisionsToBeMade() {
1277         IVecInt clause = new VecInt(nVars());
1278         int p;
1279         for (int i = this.trail.size() - 1; i >= this.rootLevel; i--) {
1280             p = this.trail.get(i);
1281             if (this.voc.getReason(p) == null) {
1282                 clause.push(p ^ 1);
1283             }
1284         }
1285         return this.dsfactory.createUnregisteredClause(clause);
1286     }
1287 
1288     protected void analyzeAtRootLevel(Constr conflict) {
1289     }
1290 
1291     private final IVecInt implied = new VecInt();
1292     private final IVecInt decisions = new VecInt();
1293 
1294     private int[] fullmodel;
1295 
1296     /**
1297      * 
1298      */
1299     void modelFound() {
1300         IVecInt tempmodel = new VecInt(nVars());
1301         this.userbooleanmodel = new boolean[realNumberOfVariables()];
1302         this.fullmodel = null;
1303         for (int i = 1; i <= nVars(); i++) {
1304             if (this.voc.belongsToPool(i)) {
1305                 int p = this.voc.getFromPool(i);
1306                 if (!this.voc.isUnassigned(p)) {
1307                     tempmodel.push(this.voc.isSatisfied(p) ? i : -i);
1308                     this.userbooleanmodel[i - 1] = this.voc.isSatisfied(p);
1309                     if (this.voc.getReason(p) == null && voc.getLevel(p) > 0) {
1310                         this.decisions.push(tempmodel.last());
1311                     } else {
1312                         this.implied.push(tempmodel.last());
1313                     }
1314                 }
1315             }
1316         }
1317         this.model = new int[tempmodel.size()];
1318         tempmodel.copyTo(this.model);
1319         if (realNumberOfVariables() > nVars()) {
1320             for (int i = nVars() + 1; i <= realNumberOfVariables(); i++) {
1321                 if (this.voc.belongsToPool(i)) {
1322                     int p = this.voc.getFromPool(i);
1323                     if (!this.voc.isUnassigned(p)) {
1324                         tempmodel.push(this.voc.isSatisfied(p) ? i : -i);
1325                         this.userbooleanmodel[i - 1] = this.voc.isSatisfied(p);
1326                         if (this.voc.getReason(p) == null) {
1327                             this.decisions.push(tempmodel.last());
1328                         } else {
1329                             this.implied.push(tempmodel.last());
1330                         }
1331                     }
1332                 }
1333             }
1334             this.fullmodel = new int[tempmodel.size()];
1335             tempmodel.moveTo(this.fullmodel);
1336         } else {
1337             this.fullmodel = this.model;
1338         }
1339     }
1340 
1341     /**
1342      * Forget a variable in the formula by falsifying both its positive and
1343      * negative literals.
1344      * 
1345      * @param var
1346      *            a variable
1347      * @return a conflicting constraint resulting from the disparition of those
1348      *         literals.
1349      */
1350     private Constr forget(int var) {
1351         boolean satisfied = this.voc.isSatisfied(toInternal(var));
1352         this.voc.forgets(var);
1353         Constr confl;
1354         if (satisfied) {
1355             confl = reduceClausesForFalsifiedLiteral(LiteralsUtils
1356                     .toInternal(-var));
1357         } else {
1358             confl = reduceClausesForFalsifiedLiteral(LiteralsUtils
1359                     .toInternal(var));
1360         }
1361         return confl;
1362     }
1363 
1364     /**
1365      * Assume literal p and perform unit propagation
1366      * 
1367      * @param p
1368      *            a literal
1369      * @return true if no conflict is reached, false if a conflict is found.
1370      */
1371     private boolean setAndPropagate(int p) {
1372         if (voc.isUnassigned(p)) {
1373             assert !trail.contains(p);
1374             assert !trail.contains(neg(p));
1375             return assume(p) && propagate() == null;
1376         }
1377         return voc.isSatisfied(p);
1378     }
1379 
1380     private int[] prime;
1381 
1382     public int[] primeImplicant() {
1383         assert this.qhead == this.trail.size() + this.learnedLiterals.size();
1384         if (this.learnedLiterals.size() > 0) {
1385             this.qhead = trail.size();
1386         }
1387         if (isVerbose()) {
1388             System.out.printf("%s implied: %d, decision: %d %n",
1389                     getLogPrefix(), implied.size(), decisions.size());
1390         }
1391         this.prime = new int[realNumberOfVariables() + 1];
1392         int p, d;
1393         for (int i = 0; i < this.prime.length; i++) {
1394             this.prime[i] = 0;
1395         }
1396         boolean noproblem;
1397         for (IteratorInt it = this.implied.iterator(); it.hasNext();) {
1398             d = it.next();
1399             p = toInternal(d);
1400             this.prime[Math.abs(d)] = d;
1401             noproblem = setAndPropagate(p);
1402             assert noproblem;
1403         }
1404         boolean canBeRemoved;
1405         int rightlevel;
1406         int removed = 0;
1407         int propagated = 0;
1408         int tested = 0;
1409         int l2propagation = 0;
1410 
1411         for (int i = 0; i < this.decisions.size(); i++) {
1412             d = this.decisions.get(i);
1413             assert !this.voc.isFalsified(toInternal(d));
1414             if (this.voc.isSatisfied(toInternal(d))) {
1415                 // d has been propagated
1416                 this.prime[Math.abs(d)] = d;
1417                 propagated++;
1418             } else if (setAndPropagate(toInternal(-d))) {
1419                 canBeRemoved = true;
1420                 tested++;
1421                 rightlevel = currentDecisionLevel();
1422                 for (int j = i + 1; j < this.decisions.size(); j++) {
1423                     l2propagation++;
1424                     if (!setAndPropagate(toInternal(this.decisions.get(j)))) {
1425                         canBeRemoved = false;
1426                         break;
1427                     }
1428                 }
1429                 cancelUntil(rightlevel);
1430                 if (canBeRemoved) {
1431                     // it is not a necessary literal
1432                     forget(Math.abs(d));
1433                     IConstr confl = propagate();
1434                     assert confl == null;
1435                     removed++;
1436                 } else {
1437                     this.prime[Math.abs(d)] = d;
1438                     cancel();
1439                     assert voc.isUnassigned(toInternal(d));
1440                     noproblem = setAndPropagate(toInternal(d));
1441                     assert noproblem;
1442                 }
1443             } else {
1444                 // conflict, literal is necessary
1445                 this.prime[Math.abs(d)] = d;
1446                 cancel();
1447                 noproblem = setAndPropagate(toInternal(d));
1448                 assert noproblem;
1449             }
1450         }
1451         cancelUntil(0);
1452         int[] implicant = new int[this.prime.length - removed - 1];
1453         int index = 0;
1454         for (int i : this.prime) {
1455             if (i != 0) {
1456                 implicant[index++] = i;
1457             }
1458         }
1459         if (isVerbose()) {
1460             System.out.printf("%s prime implicant computation statistics%n",
1461                     getLogPrefix());
1462             System.out
1463                     .printf("%s implied: %d, decision: %d (removed %d, tested %d, propagated %d), l2 propagation:%d%n",
1464                             getLogPrefix(), implied.size(), decisions.size(),
1465                             removed, tested, propagated, l2propagation);
1466         }
1467         return implicant;
1468     }
1469 
1470     public boolean primeImplicant(int p) {
1471         if (p == 0 || Math.abs(p) > realNumberOfVariables()) {
1472             throw new IllegalArgumentException(
1473                     "Use a valid Dimacs var id as argument!"); //$NON-NLS-1$
1474         }
1475         if (this.prime == null) {
1476             throw new UnsupportedOperationException(
1477                     "Call the primeImplicant method first!!!"); //$NON-NLS-1$
1478         }
1479         return this.prime[Math.abs(p)] == p;
1480     }
1481 
1482     public boolean model(int var) {
1483         if (var <= 0 || var > realNumberOfVariables()) {
1484             throw new IllegalArgumentException(
1485                     "Use a valid Dimacs var id as argument!"); //$NON-NLS-1$
1486         }
1487         if (this.userbooleanmodel == null) {
1488             throw new UnsupportedOperationException(
1489                     "Call the solve method first!!!"); //$NON-NLS-1$
1490         }
1491         return this.userbooleanmodel[var - 1];
1492     }
1493 
1494     public void clearLearntClauses() {
1495         for (Iterator<Constr> iterator = this.learnts.iterator(); iterator
1496                 .hasNext();) {
1497             iterator.next().remove(this);
1498         }
1499         this.learnts.clear();
1500         this.learnedLiterals.clear();
1501     }
1502 
1503     protected final void reduceDB() {
1504         this.stats.reduceddb++;
1505         this.slistener.cleaning();
1506         this.learnedConstraintsDeletionStrategy.reduce(this.learnts);
1507         System.gc();
1508     }
1509 
1510     /**
1511      * @param learnts
1512      */
1513     protected void sortOnActivity() {
1514         this.learnts.sort(this.comparator);
1515     }
1516 
1517     /**
1518      * 
1519      */
1520     protected void decayActivities() {
1521         this.order.varDecayActivity();
1522         claDecayActivity();
1523     }
1524 
1525     /**
1526      * 
1527      */
1528     private void claDecayActivity() {
1529         this.claInc *= this.claDecay;
1530     }
1531 
1532     /**
1533      * @return true iff the set of constraints is satisfiable, else false.
1534      */
1535     public boolean isSatisfiable() throws TimeoutException {
1536         return isSatisfiable(VecInt.EMPTY);
1537     }
1538 
1539     /**
1540      * @return true iff the set of constraints is satisfiable, else false.
1541      */
1542     public boolean isSatisfiable(boolean global) throws TimeoutException {
1543         return isSatisfiable(VecInt.EMPTY, global);
1544     }
1545 
1546     private double timebegin = 0;
1547 
1548     private boolean needToReduceDB;
1549 
1550     private ConflictTimerContainer conflictCount;
1551 
1552     private transient Timer timer;
1553 
1554     public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
1555         return isSatisfiable(assumps, false);
1556     }
1557 
1558     public final LearnedConstraintsDeletionStrategy fixedSize(final int maxsize) {
1559         return new LearnedConstraintsDeletionStrategy() {
1560 
1561             private static final long serialVersionUID = 1L;
1562             private final ConflictTimer aTimer = new ConflictTimerAdapter(
1563                     maxsize) {
1564 
1565                 private static final long serialVersionUID = 1L;
1566 
1567                 @Override
1568                 public void run() {
1569                     Solver.this.needToReduceDB = true;
1570                 }
1571             };
1572 
1573             public void reduce(IVec<Constr> learnedConstrs) {
1574                 int i, j, k;
1575                 for (i = j = k = 0; i < Solver.this.learnts.size()
1576                         && Solver.this.learnts.size() - k > maxsize; i++) {
1577                     Constr c = Solver.this.learnts.get(i);
1578                     if (c.locked() || c.size() == 2) {
1579                         Solver.this.learnts
1580                                 .set(j++, Solver.this.learnts.get(i));
1581                     } else {
1582                         c.remove(Solver.this);
1583                         k++;
1584                     }
1585                 }
1586                 for (; i < Solver.this.learnts.size(); i++) {
1587                     Solver.this.learnts.set(j++, Solver.this.learnts.get(i));
1588                 }
1589                 if (Solver.this.verbose) {
1590                     Solver.this.out.log(getLogPrefix()
1591                             + "cleaning " + (Solver.this.learnts.size() - j) //$NON-NLS-1$
1592                             + " clauses out of " + Solver.this.learnts.size()); //$NON-NLS-1$ 
1593                     // out.flush();
1594                 }
1595                 Solver.this.learnts.shrinkTo(j);
1596             }
1597 
1598             public void onConflictAnalysis(Constr reason) {
1599                 // TODO Auto-generated method stub
1600 
1601             }
1602 
1603             public void onClauseLearning(Constr outLearnt) {
1604                 // TODO Auto-generated method stub
1605 
1606             }
1607 
1608             @Override
1609             public String toString() {
1610                 return "Fixed size (" + maxsize
1611                         + ") learned constraints deletion strategy";
1612             }
1613 
1614             public void init() {
1615             }
1616 
1617             public ConflictTimer getTimer() {
1618                 return this.aTimer;
1619             }
1620 
1621             public void onPropagation(Constr from) {
1622                 // TODO Auto-generated method stub
1623 
1624             }
1625         };
1626     }
1627 
1628     private LearnedConstraintsDeletionStrategy activityBased(
1629             final ConflictTimer timer) {
1630         return new LearnedConstraintsDeletionStrategy() {
1631 
1632             private static final long serialVersionUID = 1L;
1633 
1634             private final ConflictTimer freeMem = timer;
1635 
1636             public void reduce(IVec<Constr> learnedConstrs) {
1637                 sortOnActivity();
1638                 int i, j;
1639                 for (i = j = 0; i < Solver.this.learnts.size() / 2; i++) {
1640                     Constr c = Solver.this.learnts.get(i);
1641                     if (c.locked() || c.size() == 2) {
1642                         Solver.this.learnts
1643                                 .set(j++, Solver.this.learnts.get(i));
1644                     } else {
1645                         c.remove(Solver.this);
1646                     }
1647                 }
1648                 for (; i < Solver.this.learnts.size(); i++) {
1649                     Solver.this.learnts.set(j++, Solver.this.learnts.get(i));
1650                 }
1651                 if (Solver.this.verbose) {
1652                     Solver.this.out.log(getLogPrefix()
1653                             + "cleaning " + (Solver.this.learnts.size() - j) //$NON-NLS-1$
1654                             + " clauses out of " + Solver.this.learnts.size()); //$NON-NLS-1$ 
1655                     // out.flush();
1656                 }
1657                 Solver.this.learnts.shrinkTo(j);
1658             }
1659 
1660             public ConflictTimer getTimer() {
1661                 return this.freeMem;
1662             }
1663 
1664             @Override
1665             public String toString() {
1666                 return "Memory based learned constraints deletion strategy";
1667             }
1668 
1669             public void init() {
1670                 // do nothing
1671             }
1672 
1673             public void onClauseLearning(Constr constr) {
1674                 // do nothing
1675 
1676             }
1677 
1678             public void onConflictAnalysis(Constr reason) {
1679                 if (reason.learnt()) {
1680                     claBumpActivity(reason);
1681                 }
1682             }
1683 
1684             public void onPropagation(Constr from) {
1685                 // do nothing
1686             }
1687         };
1688     }
1689 
1690     private final ConflictTimer memoryTimer = new ConflictTimerAdapter(500) {
1691         private static final long serialVersionUID = 1L;
1692         final long memorybound = Runtime.getRuntime().freeMemory() / 10;
1693 
1694         @Override
1695         public void run() {
1696             long freemem = Runtime.getRuntime().freeMemory();
1697             // System.out.println("c Free memory "+freemem);
1698             if (freemem < this.memorybound) {
1699                 // Reduce the set of learnt clauses
1700                 Solver.this.needToReduceDB = true;
1701             }
1702         }
1703     };
1704 
1705     /**
1706      * @since 2.1
1707      */
1708     public final LearnedConstraintsDeletionStrategy memory_based = activityBased(this.memoryTimer);
1709 
1710     private class GlucoseLCDS implements LearnedConstraintsDeletionStrategy {
1711 
1712         private static final long serialVersionUID = 1L;
1713         private int[] flags = new int[0];
1714         private int flag = 0;
1715         // private int wall = 0;
1716 
1717         private final ConflictTimer clauseManagement;
1718 
1719         GlucoseLCDS(ConflictTimer timer) {
1720             this.clauseManagement = timer;
1721         }
1722 
1723         public void reduce(IVec<Constr> learnedConstrs) {
1724             sortOnActivity();
1725             int i, j;
1726             for (i = j = learnedConstrs.size() / 2; i < learnedConstrs.size(); i++) {
1727                 Constr c = learnedConstrs.get(i);
1728                 if (c.locked() || c.getActivity() <= 2.0) {
1729                     learnedConstrs.set(j++, Solver.this.learnts.get(i));
1730                 } else {
1731                     c.remove(Solver.this);
1732                 }
1733             }
1734             if (Solver.this.verbose) {
1735                 Solver.this.out
1736                         .log(getLogPrefix()
1737                                 + "cleaning " + (learnedConstrs.size() - j) //$NON-NLS-1$
1738                                 + " clauses out of " + learnedConstrs.size() + " with flag " + this.flag + "/" + Solver.this.stats.conflicts); //$NON-NLS-1$ //$NON-NLS-2$
1739                 // out.flush();
1740             }
1741             Solver.this.learnts.shrinkTo(j);
1742 
1743         }
1744 
1745         public ConflictTimer getTimer() {
1746             return this.clauseManagement;
1747         }
1748 
1749         @Override
1750         public String toString() {
1751             return "Glucose learned constraints deletion strategy";
1752         }
1753 
1754         public void init() {
1755             final int howmany = Solver.this.voc.nVars();
1756             // wall = constrs.size() > 10000 ? constrs.size() : 10000;
1757             if (this.flags.length <= howmany) {
1758                 this.flags = new int[howmany + 1];
1759             }
1760             this.flag = 0;
1761             this.clauseManagement.reset();
1762         }
1763 
1764         public void onClauseLearning(Constr constr) {
1765             int nblevel = computeLBD(constr);
1766             constr.incActivity(nblevel);
1767         }
1768 
1769         protected int computeLBD(Constr constr) {
1770             int nblevel = 1;
1771             this.flag++;
1772             int currentLevel;
1773             for (int i = 1; i < constr.size(); i++) {
1774                 currentLevel = Solver.this.voc.getLevel(constr.get(i));
1775                 if (this.flags[currentLevel] != this.flag) {
1776                     this.flags[currentLevel] = this.flag;
1777                     nblevel++;
1778                 }
1779             }
1780             return nblevel;
1781         }
1782 
1783         public void onConflictAnalysis(Constr reason) {
1784 
1785         }
1786 
1787         public void onPropagation(Constr from) {
1788 
1789         }
1790     }
1791 
1792     private class Glucose2LCDS extends GlucoseLCDS {
1793 
1794         /**
1795 		 * 
1796 		 */
1797         private static final long serialVersionUID = 1L;
1798 
1799         Glucose2LCDS(ConflictTimer timer) {
1800             super(timer);
1801         }
1802 
1803         @Override
1804         public String toString() {
1805             return "Glucose 2 learned constraints deletion strategy";
1806         }
1807 
1808         @Override
1809         public void onPropagation(Constr from) {
1810             if (from.getActivity() > 2.0) {
1811                 int nblevel = computeLBD(from);
1812                 if (nblevel < from.getActivity()) {
1813                     Solver.this.stats.updateLBD++;
1814                     from.setActivity(nblevel);
1815                 }
1816             }
1817         }
1818 
1819     }
1820 
1821     private final ConflictTimer lbdTimer = new ConflictTimerAdapter(1000) {
1822         private static final long serialVersionUID = 1L;
1823         private int nbconflict = 0;
1824         private static final int MAX_CLAUSE = 5000;
1825         private static final int INC_CLAUSE = 1000;
1826         private int nextbound = MAX_CLAUSE;
1827 
1828         @Override
1829         public void run() {
1830             this.nbconflict += bound();
1831             if (this.nbconflict >= this.nextbound) {
1832                 this.nextbound += INC_CLAUSE;
1833                 // if (nextbound > wall) {
1834                 // nextbound = wall;
1835                 // }
1836                 this.nbconflict = 0;
1837                 Solver.this.needToReduceDB = true;
1838             }
1839         }
1840 
1841         @Override
1842         public void reset() {
1843             super.reset();
1844             this.nextbound = MAX_CLAUSE;
1845             if (this.nbconflict >= this.nextbound) {
1846                 this.nbconflict = 0;
1847                 Solver.this.needToReduceDB = true;
1848             }
1849         }
1850     };
1851 
1852     /**
1853      * @since 2.1
1854      */
1855     public final LearnedConstraintsDeletionStrategy glucose = new Glucose2LCDS(
1856             this.lbdTimer);
1857 
1858     protected LearnedConstraintsDeletionStrategy learnedConstraintsDeletionStrategy = this.glucose;
1859 
1860     /*
1861      * (non-Javadoc)
1862      * 
1863      * @see
1864      * org.sat4j.minisat.core.ICDCL#setLearnedConstraintsDeletionStrategy(org
1865      * .sat4j.minisat.core.Solver.LearnedConstraintsDeletionStrategy)
1866      */
1867     public void setLearnedConstraintsDeletionStrategy(
1868             LearnedConstraintsDeletionStrategy lcds) {
1869         if (this.conflictCount != null) {
1870             this.conflictCount.add(lcds.getTimer());
1871             assert this.learnedConstraintsDeletionStrategy != null;
1872             this.conflictCount.remove(this.learnedConstraintsDeletionStrategy
1873                     .getTimer());
1874         }
1875         this.learnedConstraintsDeletionStrategy = lcds;
1876     }
1877 
1878     private boolean lastConflictMeansUnsat;
1879 
1880     public boolean isSatisfiable(IVecInt assumps, boolean global)
1881             throws TimeoutException {
1882         Lbool status = Lbool.UNDEFINED;
1883         boolean alreadylaunched = this.conflictCount != null;
1884         final int howmany = this.voc.nVars();
1885         if (this.mseen.length <= howmany) {
1886             this.mseen = new boolean[howmany + 1];
1887         }
1888         this.trail.ensure(howmany);
1889         this.trailLim.ensure(howmany);
1890         this.learnedLiterals.ensure(howmany);
1891         this.decisions.clear();
1892         this.implied.clear();
1893         this.slistener.init(this);
1894         this.slistener.start();
1895         this.model = null; // forget about previous model
1896         this.userbooleanmodel = null;
1897         this.prime = null;
1898         this.unsatExplanationInTermsOfAssumptions = null;
1899         if (!alreadylaunched || !this.keepHot) {
1900             this.order.init();
1901         }
1902         this.learnedConstraintsDeletionStrategy.init();
1903         int learnedLiteralsLimit = this.trail.size();
1904 
1905         // Fix for Bug SAT37
1906         this.qhead = 0;
1907         // Apply undos on unit literals because they are getting propagated
1908         // again now that qhead is 0.
1909         for (int i = learnedLiteralsLimit - 1; i >= 0; i--) {
1910             int p = this.trail.get(i);
1911             IVec<Undoable> undos = this.voc.undos(p);
1912             assert undos != null;
1913             for (int size = undos.size(); size > 0; size--) {
1914                 undos.last().undo(p);
1915                 undos.pop();
1916             }
1917         }
1918         // push previously learned literals
1919         for (IteratorInt iterator = this.learnedLiterals.iterator(); iterator
1920                 .hasNext();) {
1921             enqueue(iterator.next());
1922         }
1923 
1924         // propagate constraints
1925         Constr confl = propagate();
1926         if (confl != null) {
1927             analyzeAtRootLevel(confl);
1928             this.slistener.conflictFound(confl, 0, 0);
1929             this.slistener.end(Lbool.FALSE);
1930             cancelUntil(0);
1931             cancelLearntLiterals(learnedLiteralsLimit);
1932             return false;
1933         }
1934 
1935         // push incremental assumptions
1936         for (IteratorInt iterator = assumps.iterator(); iterator.hasNext();) {
1937             int assump = iterator.next();
1938             int p = this.voc.getFromPool(assump);
1939             if (!this.voc.isSatisfied(p) && !assume(p)
1940                     || (confl = propagate()) != null) {
1941                 if (confl == null) {
1942                     this.slistener.conflictFound(p);
1943                     this.unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1944                             null, assumps, p);
1945                     this.unsatExplanationInTermsOfAssumptions.push(assump);
1946                 } else {
1947                     this.slistener.conflictFound(confl, decisionLevel(),
1948                             this.trail.size());
1949                     this.unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1950                             confl, assumps, ILits.UNDEFINED);
1951                 }
1952 
1953                 this.slistener.end(Lbool.FALSE);
1954                 cancelUntil(0);
1955                 cancelLearntLiterals(learnedLiteralsLimit);
1956                 return false;
1957             }
1958         }
1959         this.rootLevel = decisionLevel();
1960         // moved initialization here if new literals are added in the
1961         // assumptions.
1962         if (!alreadylaunched || !this.keepHot) {
1963             this.order.init(); // duplicated on purpose
1964         }
1965         this.learner.init();
1966 
1967         if (!alreadylaunched) {
1968             this.conflictCount = new ConflictTimerContainer();
1969             this.conflictCount.add(this.restarter);
1970             this.conflictCount.add(this.learnedConstraintsDeletionStrategy
1971                     .getTimer());
1972         }
1973         boolean firstTimeGlobal = false;
1974         if (this.timeBasedTimeout) {
1975             if (!global || this.timer == null) {
1976                 firstTimeGlobal = true;
1977                 this.undertimeout = true;
1978                 TimerTask stopMe = new TimerTask() {
1979                     @Override
1980                     public void run() {
1981                         Solver.this.undertimeout = false;
1982                     }
1983                 };
1984                 this.timer = new Timer(true);
1985                 this.timer.schedule(stopMe, this.timeout);
1986 
1987             }
1988         } else {
1989             if (!global || !alreadylaunched) {
1990                 firstTimeGlobal = true;
1991                 this.undertimeout = true;
1992                 ConflictTimer conflictTimeout = new ConflictTimerAdapter(
1993                         (int) this.timeout) {
1994                     private static final long serialVersionUID = 1L;
1995 
1996                     @Override
1997                     public void run() {
1998                         Solver.this.undertimeout = false;
1999                     }
2000                 };
2001                 this.conflictCount.add(conflictTimeout);
2002             }
2003         }
2004         if (!global || firstTimeGlobal) {
2005             this.restarter.init(this.params, this.stats);
2006             this.timebegin = System.currentTimeMillis();
2007         }
2008         this.needToReduceDB = false;
2009         // this is used to allow the solver to be incomplete,
2010         // when using a heuristics limited to a subset of variables
2011         this.lastConflictMeansUnsat = true;
2012         // Solve
2013         while (status == Lbool.UNDEFINED && this.undertimeout
2014                 && this.lastConflictMeansUnsat) {
2015             int before = this.trail.size();
2016             unitClauseProvider.provideUnitClauses(this);
2017             this.stats.importedUnits += this.trail.size() - before;
2018             status = search(assumps);
2019             if (status == Lbool.UNDEFINED) {
2020                 this.restarter.onRestart();
2021                 this.slistener.restarting();
2022             }
2023         }
2024 
2025         cancelUntil(0);
2026         cancelLearntLiterals(learnedLiteralsLimit);
2027         if (!global && this.timeBasedTimeout && this.timer != null) {
2028             this.timer.cancel();
2029             this.timer = null;
2030         }
2031         this.slistener.end(status);
2032         if (!this.undertimeout) {
2033             String message = " Timeout (" + this.timeout
2034                     + (this.timeBasedTimeout ? "s" : " conflicts")
2035                     + ") exceeded";
2036             throw new TimeoutException(message);
2037         }
2038         if (status == Lbool.UNDEFINED && !this.lastConflictMeansUnsat) {
2039             throw new TimeoutException("Cannot decide the satisfiability");
2040         }
2041         // When using a search enumerator (to compute all models)
2042         // the final answer is FALSE, however we are aware of at least one model
2043         // (the last one)
2044         return model != null;
2045     }
2046 
2047     public void printInfos(PrintWriter out) {
2048         printInfos(out, prefix);
2049     }
2050 
2051     public void printInfos(PrintWriter out, String prefix) {
2052         out.print(prefix);
2053         out.println("constraints type ");
2054         long total = 0;
2055         for (Map.Entry<String, Counter> entry : this.constrTypes.entrySet()) {
2056             out.println(prefix + entry.getKey() + " => " + entry.getValue());
2057             total += entry.getValue().getValue();
2058         }
2059         out.print(prefix);
2060         out.print(total);
2061         out.println(" constraints processed.");
2062     }
2063 
2064     /**
2065      * @since 2.1
2066      */
2067     public void printLearntClausesInfos(PrintWriter out, String prefix) {
2068         Map<String, Counter> learntTypes = new HashMap<String, Counter>();
2069         for (Iterator<Constr> it = this.learnts.iterator(); it.hasNext();) {
2070             String type = it.next().getClass().getName();
2071             Counter count = learntTypes.get(type);
2072             if (count == null) {
2073                 learntTypes.put(type, new Counter());
2074             } else {
2075                 count.inc();
2076             }
2077         }
2078         out.print(prefix);
2079         out.println("learnt constraints type ");
2080         for (Map.Entry<String, Counter> entry : learntTypes.entrySet()) {
2081             out.println(prefix + entry.getKey() + " => " + entry.getValue());
2082         }
2083     }
2084 
2085     public SolverStats getStats() {
2086         return this.stats;
2087     }
2088 
2089     /**
2090      * 
2091      * @param myStats
2092      * @since 2.2
2093      */
2094     protected void initStats(SolverStats myStats) {
2095         this.stats = myStats;
2096     }
2097 
2098     /*
2099      * (non-Javadoc)
2100      * 
2101      * @see org.sat4j.minisat.core.ICDCL#getOrder()
2102      */
2103     public IOrder getOrder() {
2104         return this.order;
2105     }
2106 
2107     /*
2108      * (non-Javadoc)
2109      * 
2110      * @see org.sat4j.minisat.core.ICDCL#setOrder(org.sat4j.minisat.core.IOrder)
2111      */
2112     public void setOrder(IOrder h) {
2113         this.order = h;
2114         this.order.setLits(this.voc);
2115     }
2116 
2117     public ILits getVocabulary() {
2118         return this.voc;
2119     }
2120 
2121     public void reset() {
2122         if (this.timer != null) {
2123             this.timer.cancel();
2124             this.timer = null;
2125         }
2126         this.trail.clear();
2127         this.trailLim.clear();
2128         this.qhead = 0;
2129         for (Iterator<Constr> iterator = this.constrs.iterator(); iterator
2130                 .hasNext();) {
2131             iterator.next().remove(this);
2132         }
2133         this.constrs.clear();
2134         clearLearntClauses();
2135         this.voc.resetPool();
2136         this.dsfactory.reset();
2137         this.stats.reset();
2138         this.constrTypes.clear();
2139     }
2140 
2141     public int nVars() {
2142         if (this.declaredMaxVarId == 0) {
2143             return this.voc.nVars();
2144         }
2145         return this.declaredMaxVarId;
2146     }
2147 
2148     /**
2149      * @param constr
2150      *            a constraint implementing the Constr interface.
2151      * @return a reference to the constraint for external use.
2152      */
2153     protected IConstr addConstr(Constr constr) {
2154         if (constr == null) {
2155             Counter count = this.constrTypes
2156                     .get("ignored satisfied constraints");
2157             if (count == null) {
2158                 this.constrTypes.put("ignored satisfied constraints",
2159                         new Counter());
2160             } else {
2161                 count.inc();
2162             }
2163         } else {
2164             this.constrs.push(constr);
2165             String type = constr.getClass().getName();
2166             Counter count = this.constrTypes.get(type);
2167             if (count == null) {
2168                 this.constrTypes.put(type, new Counter());
2169             } else {
2170                 count.inc();
2171             }
2172         }
2173         return constr;
2174     }
2175 
2176     public DataStructureFactory getDSFactory() {
2177         return this.dsfactory;
2178     }
2179 
2180     public IVecInt getOutLearnt() {
2181         return this.moutLearnt;
2182     }
2183 
2184     /**
2185      * returns the ith constraint in the solver.
2186      * 
2187      * @param i
2188      *            the constraint number (begins at 0)
2189      * @return the ith constraint
2190      */
2191     public IConstr getIthConstr(int i) {
2192         return this.constrs.get(i);
2193     }
2194 
2195     /*
2196      * (non-Javadoc)
2197      * 
2198      * @see org.sat4j.specs.ISolver#printStat(java.io.PrintStream,
2199      * java.lang.String)
2200      */
2201     public void printStat(PrintStream out, String prefix) {
2202         printStat(new PrintWriter(out, true), prefix);
2203     }
2204 
2205     public void printStat(PrintWriter out) {
2206         printStat(out, prefix);
2207     }
2208 
2209     public void printStat(PrintWriter out, String prefix) {
2210         this.stats.printStat(out, prefix);
2211         double cputime = (System.currentTimeMillis() - this.timebegin) / 1000;
2212         out.println(prefix
2213                 + "speed (assignments/second)\t: " + this.stats.propagations //$NON-NLS-1$
2214                 / cputime);
2215         this.order.printStat(out, prefix);
2216         printLearntClausesInfos(out, prefix);
2217     }
2218 
2219     /*
2220      * (non-Javadoc)
2221      * 
2222      * @see java.lang.Object#toString()
2223      */
2224     public String toString(String prefix) {
2225         StringBuffer stb = new StringBuffer();
2226         Object[] objs = { this.dsfactory, this.learner, this.params,
2227                 this.order, this.simplifier, this.restarter,
2228                 this.learnedConstraintsDeletionStrategy };
2229         stb.append(prefix);
2230         stb.append("--- Begin Solver configuration ---"); //$NON-NLS-1$
2231         stb.append("\n"); //$NON-NLS-1$
2232         for (Object o : objs) {
2233             stb.append(prefix);
2234             stb.append(o.toString());
2235             stb.append("\n"); //$NON-NLS-1$
2236         }
2237         stb.append(prefix);
2238         stb.append("timeout=");
2239         if (this.timeBasedTimeout) {
2240             stb.append(this.timeout / 1000);
2241             stb.append("s\n");
2242         } else {
2243             stb.append(this.timeout);
2244             stb.append(" conflicts\n");
2245         }
2246         stb.append(prefix);
2247         stb.append("DB Simplification allowed=");
2248         stb.append(this.isDBSimplificationAllowed);
2249         stb.append("\n");
2250         stb.append(prefix);
2251         if (isSolverKeptHot()) {
2252             stb.append("Heuristics kept accross calls (keep the solver \"hot\")\n");
2253             stb.append(prefix);
2254         }
2255         stb.append("Listener: ");
2256         stb.append(slistener);
2257         stb.append("\n");
2258         stb.append(prefix);
2259         stb.append("--- End Solver configuration ---"); //$NON-NLS-1$
2260         return stb.toString();
2261     }
2262 
2263     /*
2264      * (non-Javadoc)
2265      * 
2266      * @see java.lang.Object#toString()
2267      */
2268     @Override
2269     public String toString() {
2270         return toString(""); //$NON-NLS-1$
2271     }
2272 
2273     public int getTimeout() {
2274         return (int) (this.timeBasedTimeout ? this.timeout / 1000
2275                 : this.timeout);
2276     }
2277 
2278     /**
2279      * @since 2.1
2280      */
2281     public long getTimeoutMs() {
2282         if (!this.timeBasedTimeout) {
2283             throw new UnsupportedOperationException(
2284                     "The timeout is given in number of conflicts!");
2285         }
2286         return this.timeout;
2287     }
2288 
2289     public void setExpectedNumberOfClauses(int nb) {
2290         this.constrs.ensure(nb);
2291     }
2292 
2293     public Map<String, Number> getStat() {
2294         return this.stats.toMap();
2295     }
2296 
2297     public int[] findModel() throws TimeoutException {
2298         if (isSatisfiable()) {
2299             return model();
2300         }
2301         // DLB findbugs ok
2302         // A zero length array would mean that the formula is a tautology.
2303         return null;
2304     }
2305 
2306     public int[] findModel(IVecInt assumps) throws TimeoutException {
2307         if (isSatisfiable(assumps)) {
2308             return model();
2309         }
2310         // DLB findbugs ok
2311         // A zero length array would mean that the formula is a tautology.
2312         return null;
2313     }
2314 
2315     public boolean isDBSimplificationAllowed() {
2316         return this.isDBSimplificationAllowed;
2317     }
2318 
2319     public void setDBSimplificationAllowed(boolean status) {
2320         this.isDBSimplificationAllowed = status;
2321     }
2322 
2323     /**
2324      * @since 2.1
2325      */
2326     public int nextFreeVarId(boolean reserve) {
2327         return this.voc.nextFreeVarId(reserve);
2328     }
2329 
2330     /**
2331      * @since 2.1
2332      */
2333     public IConstr addBlockingClause(IVecInt literals)
2334             throws ContradictionException {
2335         return addClause(literals);
2336     }
2337 
2338     /**
2339      * @since 2.1
2340      */
2341     public void unset(int p) {
2342         // the literal might already have been
2343         // removed from the trail.
2344         if (this.voc.isUnassigned(p) || this.trail.isEmpty()) {
2345             return;
2346         }
2347         int current = this.trail.last();
2348         while (current != p) {
2349             undoOne();
2350             if (this.trail.isEmpty()) {
2351                 return;
2352             }
2353             current = this.trail.last();
2354         }
2355         undoOne();
2356         this.qhead = this.trail.size();
2357     }
2358 
2359     /**
2360      * @since 2.2
2361      */
2362     public void setLogPrefix(String prefix) {
2363         this.prefix = prefix;
2364     }
2365 
2366     /**
2367      * @since 2.2
2368      */
2369     public String getLogPrefix() {
2370         return this.prefix;
2371     }
2372 
2373     /**
2374      * @since 2.2
2375      */
2376     public IVecInt unsatExplanation() {
2377         IVecInt copy = new VecInt(
2378                 this.unsatExplanationInTermsOfAssumptions.size());
2379         this.unsatExplanationInTermsOfAssumptions.copyTo(copy);
2380         return copy;
2381     }
2382 
2383     /**
2384      * @since 2.3.1
2385      */
2386     public int[] modelWithInternalVariables() {
2387         if (this.model == null) {
2388             throw new UnsupportedOperationException(
2389                     "Call the solve method first!!!"); //$NON-NLS-1$
2390         }
2391         int[] nmodel;
2392         if (nVars() == realNumberOfVariables()) {
2393             nmodel = new int[this.model.length];
2394             System.arraycopy(this.model, 0, nmodel, 0, nmodel.length);
2395         } else {
2396             nmodel = new int[this.fullmodel.length];
2397             System.arraycopy(this.fullmodel, 0, nmodel, 0, nmodel.length);
2398         }
2399 
2400         return nmodel;
2401     }
2402 
2403     /**
2404      * @since 2.3.1
2405      */
2406     public int realNumberOfVariables() {
2407         return this.voc.nVars();
2408     }
2409 
2410     /**
2411      * @since 2.3.2
2412      */
2413     public void stop() {
2414         expireTimeout();
2415     }
2416 
2417     protected Constr sharedConflict;
2418 
2419     /**
2420      * @since 2.3.2
2421      */
2422     public void backtrack(int[] reason) {
2423         IVecInt clause = new VecInt(reason.length);
2424         for (int d : reason) {
2425             clause.push(LiteralsUtils.toInternal(d));
2426         }
2427         this.sharedConflict = this.dsfactory.createUnregisteredClause(clause);
2428         learn(this.sharedConflict);
2429     }
2430 
2431     /**
2432      * @since 2.3.2
2433      */
2434     public Lbool truthValue(int literal) {
2435         int p = LiteralsUtils.toInternal(literal);
2436         if (this.voc.isFalsified(p)) {
2437             return Lbool.FALSE;
2438         }
2439         if (this.voc.isSatisfied(p)) {
2440             return Lbool.TRUE;
2441         }
2442         return Lbool.UNDEFINED;
2443     }
2444 
2445     /**
2446      * @since 2.3.2
2447      */
2448     public int currentDecisionLevel() {
2449         return decisionLevel();
2450     }
2451 
2452     /**
2453      * @since 2.3.2
2454      */
2455     public int[] getLiteralsPropagatedAt(int decisionLevel) {
2456         throw new UnsupportedOperationException("Not implemented yet!");
2457     }
2458 
2459     /**
2460      * @since 2.3.2
2461      */
2462     public void suggestNextLiteralToBranchOn(int l) {
2463         throw new UnsupportedOperationException("Not implemented yet!");
2464     }
2465 
2466     protected boolean isNeedToReduceDB() {
2467         return this.needToReduceDB;
2468     }
2469 
2470     public void setNeedToReduceDB(boolean needToReduceDB) {
2471         this.needToReduceDB = needToReduceDB;
2472     }
2473 
2474     public void setLogger(ILogAble out) {
2475         this.out = out;
2476     }
2477 
2478     public ILogAble getLogger() {
2479         return this.out;
2480     }
2481 
2482     public double[] getVariableHeuristics() {
2483         return this.order.getVariableHeuristics();
2484     }
2485 
2486     public IVec<Constr> getLearnedConstraints() {
2487         return this.learnts;
2488     }
2489 
2490     /**
2491      * @since 2.3.2
2492      */
2493     public void setLearnedConstraintsDeletionStrategy(ConflictTimer timer,
2494             LearnedConstraintsEvaluationType evaluation) {
2495         if (this.conflictCount != null) {
2496             this.conflictCount.add(timer);
2497             this.conflictCount.remove(this.learnedConstraintsDeletionStrategy
2498                     .getTimer());
2499         }
2500         switch (evaluation) {
2501         case ACTIVITY:
2502             this.learnedConstraintsDeletionStrategy = activityBased(timer);
2503             break;
2504         case LBD:
2505             this.learnedConstraintsDeletionStrategy = new GlucoseLCDS(timer);
2506             break;
2507         case LBD2:
2508             this.learnedConstraintsDeletionStrategy = new Glucose2LCDS(timer);
2509             break;
2510         }
2511         if (this.conflictCount != null) {
2512             this.learnedConstraintsDeletionStrategy.init();
2513         }
2514     }
2515 
2516     /**
2517      * @since 2.3.2
2518      */
2519     public void setLearnedConstraintsDeletionStrategy(
2520             LearnedConstraintsEvaluationType evaluation) {
2521         ConflictTimer aTimer = this.learnedConstraintsDeletionStrategy
2522                 .getTimer();
2523         switch (evaluation) {
2524         case ACTIVITY:
2525             this.learnedConstraintsDeletionStrategy = activityBased(aTimer);
2526             break;
2527         case LBD:
2528             this.learnedConstraintsDeletionStrategy = new GlucoseLCDS(aTimer);
2529             break;
2530         case LBD2:
2531             this.learnedConstraintsDeletionStrategy = new Glucose2LCDS(aTimer);
2532             break;
2533         }
2534         if (this.conflictCount != null) {
2535             this.learnedConstraintsDeletionStrategy.init();
2536         }
2537     }
2538 
2539     public boolean isSolverKeptHot() {
2540         return this.keepHot;
2541     }
2542 
2543     public void setKeepSolverHot(boolean keepHot) {
2544         this.keepHot = keepHot;
2545     }
2546 
2547     private final Comparator<Integer> dimacsLevel = new Comparator<Integer>() {
2548         public int compare(Integer i1, Integer i2) {
2549             return voc.getLevel(Math.abs(i2)) - voc.getLevel(Math.abs(i1));
2550         }
2551     };
2552 
2553     public IConstr addClauseOnTheFly(int[] literals) {
2554         List<Integer> lliterals = new ArrayList<Integer>();
2555         for (Integer d : literals) {
2556             lliterals.add(d);
2557         }
2558         Collections.sort(lliterals, dimacsLevel);
2559         IVecInt clause = new VecInt(literals.length);
2560         for (int d : lliterals) {
2561             clause.push(LiteralsUtils.toInternal(d));
2562         }
2563         this.sharedConflict = this.dsfactory.createUnregisteredClause(clause);
2564         this.sharedConflict.register();
2565         addConstr(this.sharedConflict);
2566         IVecInt reason = new VecInt();
2567         this.sharedConflict.calcReasonOnTheFly(ILits.UNDEFINED, trail, reason);
2568         Set<Integer> subset = fromLastDecisionLevel(reason);
2569         while (!trail.isEmpty() && !subset.contains(trail.last())) {
2570             undoOne();
2571             if (!trailLim.isEmpty() && trailLim.last() == trail.size()) {
2572                 trailLim.pop();
2573             }
2574         }
2575         return this.sharedConflict;
2576     }
2577 
2578     public ISolver getSolvingEngine() {
2579         return this;
2580     }
2581 
2582     /**
2583      * 
2584      * @param literals
2585      */
2586     public IConstr addAtMostOnTheFly(int[] literals, int degree) {
2587         IVecInt clause = new VecInt(literals.length);
2588         for (int d : literals) {
2589             clause.push(LiteralsUtils.toInternal(-d));
2590         }
2591         IVecInt copy = new VecInt(clause.size());
2592         clause.copyTo(copy);
2593         this.sharedConflict = this.dsfactory
2594                 .createUnregisteredCardinalityConstraint(copy, literals.length
2595                         - degree);
2596         this.sharedConflict.register();
2597         addConstr(this.sharedConflict);
2598         // backtrack to the first decision level with a reason
2599         // for falsifying that constraint
2600         IVecInt reason = new VecInt();
2601         this.sharedConflict.calcReasonOnTheFly(ILits.UNDEFINED, trail, reason);
2602         Set<Integer> subset = fromLastDecisionLevel(reason);
2603         while (!trail.isEmpty() && !subset.contains(trail.last())) {
2604             undoOne();
2605             if (!trailLim.isEmpty() && trailLim.last() == trail.size()) {
2606                 trailLim.pop();
2607             }
2608         }
2609         return this.sharedConflict;
2610     }
2611 
2612     protected Set<Integer> fromLastDecisionLevel(IVecInt lits) {
2613         Set<Integer> subset = new HashSet<Integer>();
2614         int max = -1, q, level;
2615         for (int i = 0; i < lits.size(); i++) {
2616             q = lits.get(i);
2617             level = voc.getLevel(q);
2618             if (level > max) {
2619                 subset.clear();
2620                 subset.add(q);
2621                 max = level;
2622             } else if (level == max) {
2623                 subset.add(q);
2624             }
2625         }
2626         return subset;
2627     }
2628 
2629     public void setUnitClauseProvider(UnitClauseProvider ucp) {
2630         this.unitClauseProvider = ucp;
2631     }
2632 }