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