View Javadoc

1   /*******************************************************************************
2    * SAT4J: a SATisfiability library for Java Copyright (C) 2004-2008 Daniel Le Berre
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   * The reason simplification methods are coming from MiniSAT 1.14 released under 
28   * the MIT license:
29   * MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
30   *
31   * Permission is hereby granted, free of charge, to any person obtaining a
32   * copy of this software and associated documentation files (the
33   * "Software"), to deal in the Software without restriction, including
34   * without limitation the rights to use, copy, modify, merge, publish,
35   * distribute, sublicense, and/or sell copies of the Software, and to
36   * permit persons to whom the Software is furnished to do so, subject to
37   * the following conditions:
38   *
39   * The above copyright notice and this permission notice shall be included
40   * in all copies or substantial portions of the Software.
41   * 
42   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
43   * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
45   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
46   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
47   * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
48   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
49   *******************************************************************************/
50  package org.sat4j.minisat.core;
51  
52  import static org.sat4j.core.LiteralsUtils.toDimacs;
53  import static org.sat4j.core.LiteralsUtils.var;
54  
55  import java.io.PrintStream;
56  import java.io.PrintWriter;
57  import java.io.Serializable;
58  import java.lang.reflect.Field;
59  import java.util.Comparator;
60  import java.util.HashMap;
61  import java.util.Iterator;
62  import java.util.Map;
63  import java.util.Timer;
64  import java.util.TimerTask;
65  
66  import org.sat4j.core.Vec;
67  import org.sat4j.core.VecInt;
68  import org.sat4j.specs.ContradictionException;
69  import org.sat4j.specs.IConstr;
70  import org.sat4j.specs.ISolver;
71  import org.sat4j.specs.IVec;
72  import org.sat4j.specs.IVecInt;
73  import org.sat4j.specs.IteratorInt;
74  import org.sat4j.specs.Lbool;
75  import org.sat4j.specs.SearchListener;
76  import org.sat4j.specs.TimeoutException;
77  
78  /**
79   * The backbone of the library providing the modular implementation of a MiniSAT
80   * (Chaff) like solver.
81   * 
82   * @author leberre
83   */
84  public class Solver<D extends DataStructureFactory> implements ISolver,
85  		UnitPropagationListener, ActivityListener, Learner {
86  
87  	private static final long serialVersionUID = 1L;
88  
89  	private static final double CLAUSE_RESCALE_FACTOR = 1e-20;
90  
91  	private static final double CLAUSE_RESCALE_BOUND = 1 / CLAUSE_RESCALE_FACTOR;
92  
93  	/**
94  	 * Set of original constraints.
95  	 */
96  	private final IVec<Constr> constrs = new Vec<Constr>(); // Constr
97  
98  	/**
99  	 * Set of learned constraints.
100 	 */
101 	private final IVec<Constr> learnts = new Vec<Constr>(); // Clause
102 
103 	/**
104 	 * incr?ment pour l'activit? des clauses.
105 	 */
106 	private double claInc = 1.0;
107 
108 	/**
109 	 * decay factor pour l'activit? des clauses.
110 	 */
111 	private double claDecay = 1.0;
112 
113 	/**
114 	 * Queue de propagation
115 	 */
116 	// head of the queue in trail ... (taken from MiniSAT 1.14)
117 	private int qhead = 0;
118 
119 	// queue
120 
121 	/**
122 	 * affectation en ordre chronologique
123 	 */
124 	protected final IVecInt trail = new VecInt(); // lit
125 
126 	// vector
127 
128 	/**
129 	 * indice des s?parateurs des diff?rents niveau de d?cision dans trail
130 	 */
131 	protected final IVecInt trailLim = new VecInt(); // int
132 
133 	// vector
134 
135 	/**
136 	 * S?pare les hypoth?ses incr?mentale et recherche
137 	 */
138 	protected int rootLevel;
139 
140 	private int[] model = null;
141 
142 	protected ILits voc;
143 
144 	private IOrder order;
145 
146 	private final ActivityComparator comparator = new ActivityComparator();
147 
148 	private SolverStats stats = new SolverStats();
149 
150 	private LearningStrategy<D> learner;
151 
152 	protected final AssertingClauseGenerator analyzer;
153 
154 	private volatile boolean undertimeout;
155 
156 	private long timeout = Integer.MAX_VALUE;
157 
158 	private boolean timeBasedTimeout = true;
159 
160 	protected D dsfactory;
161 
162 	private SearchParams params;
163 
164 	private final IVecInt __dimacs_out = new VecInt();
165 
166 	private SearchListener slistener = new VoidTracing();
167 
168 	private RestartStrategy restarter;
169 
170 	private final Map<String, Counter> constrTypes = new HashMap<String, Counter>();
171 
172 	private boolean isDBSimplificationAllowed = false;
173 
174 	private final IVecInt learnedLiterals = new VecInt();
175 
176 	private boolean verbose = true;
177 
178 	private String prefix = "c ";
179 
180 	protected IVecInt dimacs2internal(IVecInt in) {
181 		__dimacs_out.clear();
182 		__dimacs_out.ensure(in.size());
183 		for (int i = 0; i < in.size(); i++) {
184 			assert (in.get(i) != 0);
185 			__dimacs_out.unsafePush(voc.getFromPool(in.get(i)));
186 		}
187 		return __dimacs_out;
188 	}
189 
190 	/**
191 	 * creates a Solver without LearningListener. A learningListener must be
192 	 * added to the solver, else it won't backtrack!!! A data structure factory
193 	 * must be provided, else it won't work either.
194 	 * 
195 	 * @param acg
196 	 *            an asserting clause generator
197 	 */
198 
199 	public Solver(AssertingClauseGenerator acg, LearningStrategy<D> learner,
200 			D dsf, IOrder order, RestartStrategy restarter) {
201 		this(acg, learner, dsf, new SearchParams(), order, restarter);
202 	}
203 
204 	public Solver(AssertingClauseGenerator acg, LearningStrategy<D> learner,
205 			D dsf, SearchParams params, IOrder order, RestartStrategy restarter) {
206 		analyzer = acg;
207 		this.learner = learner;
208 		this.order = order;
209 		this.params = params;
210 		setDataStructureFactory(dsf);
211 		this.restarter = restarter;
212 	}
213 
214 	/**
215 	 * Change the internal representation of the constraints. Note that the
216 	 * heuristics must be changed prior to calling that method.
217 	 * 
218 	 * @param dsf
219 	 *            the internal factory
220 	 */
221 	public final void setDataStructureFactory(D dsf) {
222 		dsfactory = dsf;
223 		dsfactory.setUnitPropagationListener(this);
224 		dsfactory.setLearner(this);
225 		voc = dsf.getVocabulary();
226 		order.setLits(voc);
227 	}
228 
229 	/**
230 	 * @since 2.2
231 	 */
232 	public boolean isVerbose() {
233 		return verbose;
234 	}
235 
236 	/**
237 	 * @param value
238 	 * @since 2.2
239 	 */
240 	public void setVerbose(boolean value) {
241 		verbose = value;
242 	}
243 
244 	/**
245 	 * @since 2.1
246 	 */
247 	public void setSearchListener(SearchListener sl) {
248 		slistener = sl;
249 	}
250 
251 	/**
252 	 * @since 2.2
253 	 */
254 	public SearchListener getSearchListener() {
255 		return slistener;
256 	}
257 
258 	/**
259 	 * @since 2.2
260 	 */
261 	public void setLearner(LearningStrategy<D> learner) {
262 		this.learner = learner;
263 	}
264 
265 	public void setTimeout(int t) {
266 		timeout = t * 1000L;
267 		timeBasedTimeout = true;
268 	}
269 
270 	public void setTimeoutMs(long t) {
271 		timeout = t;
272 		timeBasedTimeout = true;
273 	}
274 
275 	public void setTimeoutOnConflicts(int count) {
276 		timeout = count;
277 		timeBasedTimeout = false;
278 	}
279 
280 	public void setSearchParams(SearchParams sp) {
281 		params = sp;
282 	}
283 
284 	public void setRestartStrategy(RestartStrategy restarter) {
285 		this.restarter = restarter;
286 	}
287 
288 	public void expireTimeout() {
289 		undertimeout = false;
290 	}
291 
292 	protected int nAssigns() {
293 		return trail.size();
294 	}
295 
296 	public int nConstraints() {
297 		return constrs.size() + trail.size();
298 	}
299 
300 	public void learn(Constr c) {
301 		learnts.push(c);
302 		c.setLearnt();
303 		c.register();
304 		stats.learnedclauses++;
305 		switch (c.size()) {
306 		case 2:
307 			stats.learnedbinaryclauses++;
308 			break;
309 		case 3:
310 			stats.learnedternaryclauses++;
311 			break;
312 		default:
313 			// do nothing
314 		}
315 	}
316 
317 	public final int decisionLevel() {
318 		return trailLim.size();
319 	}
320 
321 	@Deprecated
322 	public int newVar() {
323 		int index = voc.nVars() + 1;
324 		voc.ensurePool(index);
325 		return index;
326 	}
327 
328 	public int newVar(int howmany) {
329 		voc.ensurePool(howmany);
330 		return voc.nVars();
331 	}
332 
333 	public IConstr addClause(IVecInt literals) throws ContradictionException {
334 		IVecInt vlits = dimacs2internal(literals);
335 		return addConstr(dsfactory.createClause(vlits));
336 	}
337 
338 	public boolean removeConstr(IConstr co) {
339 		if (co == null) {
340 			throw new IllegalArgumentException(
341 					"Reference to the constraint to remove needed!"); //$NON-NLS-1$
342 		}
343 		Constr c = (Constr) co;
344 		c.remove(this);
345 		constrs.remove(c);
346 		clearLearntClauses();
347 		String type = c.getClass().getName();
348 		constrTypes.get(type).dec();
349 		return true;
350 	}
351 
352 	/**
353 	 * @since 2.1
354 	 */
355 	public boolean removeSubsumedConstr(IConstr co) {
356 		if (co == null) {
357 			throw new IllegalArgumentException(
358 					"Reference to the constraint to remove needed!"); //$NON-NLS-1$
359 		}
360 		if (constrs.last() != co) {
361 			throw new IllegalArgumentException(
362 					"Can only remove latest added constraint!!!"); //$NON-NLS-1$
363 		}
364 		Constr c = (Constr) co;
365 		c.remove(this);
366 		constrs.pop();
367 		String type = c.getClass().getName();
368 		constrTypes.get(type).dec();
369 		return true;
370 	}
371 
372 	public void addAllClauses(IVec<IVecInt> clauses)
373 			throws ContradictionException {
374 		for (Iterator<IVecInt> iterator = clauses.iterator(); iterator
375 				.hasNext();) {
376 			addClause(iterator.next());
377 		}
378 	}
379 
380 	public IConstr addAtMost(IVecInt literals, int degree)
381 			throws ContradictionException {
382 		int n = literals.size();
383 		IVecInt opliterals = new VecInt(n);
384 		for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
385 			opliterals.push(-iterator.next());
386 		}
387 		return addAtLeast(opliterals, n - degree);
388 	}
389 
390 	public IConstr addAtLeast(IVecInt literals, int degree)
391 			throws ContradictionException {
392 		IVecInt vlits = dimacs2internal(literals);
393 		return addConstr(dsfactory.createCardinalityConstraint(vlits, degree));
394 	}
395 
396 	@SuppressWarnings("unchecked")
397 	public boolean simplifyDB() {
398 		// Simplifie la base de clauses apres la premiere propagation des
399 		// clauses unitaires
400 		IVec<Constr>[] cs = new IVec[] { constrs, learnts };
401 		for (int type = 0; type < 2; type++) {
402 			int j = 0;
403 			for (int i = 0; i < cs[type].size(); i++) {
404 				if (cs[type].get(i).simplify()) {
405 					// enleve les contraintes satisfaites de la base
406 					cs[type].get(i).remove(this);
407 				} else {
408 					cs[type].moveTo(j++, i);
409 				}
410 			}
411 			cs[type].shrinkTo(j);
412 		}
413 		return true;
414 	}
415 
416 	/**
417 	 * Si un mod?le est trouv?, ce vecteur contient le mod?le.
418 	 * 
419 	 * @return un mod?le de la formule.
420 	 */
421 	public int[] model() {
422 		if (model == null) {
423 			throw new UnsupportedOperationException(
424 					"Call the solve method first!!!"); //$NON-NLS-1$
425 		}
426 		int[] nmodel = new int[model.length];
427 		System.arraycopy(model, 0, nmodel, 0, model.length);
428 		return nmodel;
429 	}
430 
431 	/**
432 	 * Satisfait un litt?ral
433 	 * 
434 	 * @param p
435 	 *            le litt?ral
436 	 * @return true si tout se passe bien, false si un conflit appara?t.
437 	 */
438 	public boolean enqueue(int p) {
439 		return enqueue(p, null);
440 	}
441 
442 	/**
443 	 * Put the literal on the queue of assignments to be done.
444 	 * 
445 	 * @param p
446 	 *            the literal.
447 	 * @param from
448 	 *            the reason to propagate that literal, else null
449 	 * @return true if the assignment can be made, false if a conflict is
450 	 *         detected.
451 	 */
452 	public boolean enqueue(int p, Constr from) {
453 		assert p > 1;
454 		if (voc.isSatisfied(p)) {
455 			// literal is already satisfied. Skipping.
456 			return true;
457 		}
458 		if (voc.isFalsified(p)) {
459 			// conflicting enqueued assignment
460 			return false;
461 		}
462 		// new fact, store it
463 		voc.satisfies(p);
464 		voc.setLevel(p, decisionLevel());
465 		voc.setReason(p, from);
466 		trail.push(p);
467 		return true;
468 	}
469 
470 	private boolean[] mseen = new boolean[0];
471 
472 	private final IVecInt mpreason = new VecInt();
473 
474 	private final IVecInt moutLearnt = new VecInt();
475 
476 	public void analyze(Constr confl, Pair results) {
477 		assert confl != null;
478 
479 		final boolean[] seen = mseen;
480 		final IVecInt outLearnt = moutLearnt;
481 		final IVecInt preason = mpreason;
482 
483 		outLearnt.clear();
484 		assert outLearnt.size() == 0;
485 		for (int i = 0; i < seen.length; i++) {
486 			seen[i] = false;
487 		}
488 
489 		analyzer.initAnalyze();
490 		int p = ILits.UNDEFINED;
491 
492 		outLearnt.push(ILits.UNDEFINED);
493 		// reserve de la place pour le litteral falsifie
494 		int outBtlevel = 0;
495 
496 		do {
497 			preason.clear();
498 			assert confl != null;
499 			confl.calcReason(p, preason);
500 			learnedConstraintsDeletionStrategy.onConflictAnalysis(confl);
501 			// Trace reason for p
502 			for (int j = 0; j < preason.size(); j++) {
503 				int q = preason.get(j);
504 				order.updateVar(q);
505 				if (!seen[q >> 1]) {
506 					seen[q >> 1] = true;
507 					if (voc.getLevel(q) == decisionLevel()) {
508 						analyzer.onCurrentDecisionLevelLiteral(q);
509 					} else if (voc.getLevel(q) > 0) {
510 						// only literals assigned after decision level 0 part of
511 						// the explanation
512 						outLearnt.push(q ^ 1);
513 						outBtlevel = Math.max(outBtlevel, voc.getLevel(q));
514 					}
515 				}
516 			}
517 
518 			// select next reason to look at
519 			do {
520 				p = trail.last();
521 				confl = voc.getReason(p);
522 				undoOne();
523 			} while (!seen[p >> 1]);
524 			// seen[p.var] indique que p se trouve dans outLearnt ou dans
525 			// le dernier niveau de d?cision
526 		} while (analyzer.clauseNonAssertive(confl));
527 
528 		outLearnt.set(0, p ^ 1);
529 		simplifier.simplify(outLearnt);
530 
531 		Constr c = dsfactory.createUnregisteredClause(outLearnt);
532 		slistener.learn(c);
533 		learnedConstraintsDeletionStrategy.onConflict(c);
534 		results.reason = c;
535 
536 		assert outBtlevel > -1;
537 		results.backtrackLevel = outBtlevel;
538 	}
539 
540 	/**
541 	 * Derive a subset of the assumptions causing the inconistency.
542 	 * 
543 	 * @param confl
544 	 *            the last conflict of the search, occuring at root level.
545 	 * @param assumps
546 	 *            the set of assumption literals
547 	 * @param conflictingLiteral
548 	 *            the literal detected conflicting while propagating
549 	 *            assumptions.
550 	 * @return a subset of assumps causing the inconsistency.
551 	 * @since 2.2
552 	 */
553 	public IVecInt analyzeFinalConflictInTermsOfAssumptions(Constr confl,
554 			IVecInt assumps, int conflictingLiteral) {
555 		if (assumps.size() == 0) {
556 			return null;
557 		}
558 		final boolean[] seen = mseen;
559 		final IVecInt outLearnt = moutLearnt;
560 		final IVecInt preason = mpreason;
561 
562 		outLearnt.clear();
563 		assert outLearnt.size() == 0;
564 		for (int i = 0; i < seen.length; i++) {
565 			seen[i] = false;
566 		}
567 
568 		if (confl == null) {
569 			seen[conflictingLiteral >> 1] = true;
570 		}
571 
572 		int p = ILits.UNDEFINED;
573 		while (confl == null) {
574 			p = trail.last();
575 			confl = voc.getReason(p);
576 			undoOne();
577 			if (trail.size() <= trailLim.last()) {
578 				trailLim.pop();
579 			}
580 		}
581 		do {
582 
583 			preason.clear();
584 			confl.calcReason(p, preason);
585 			// Trace reason for p
586 			for (int j = 0; j < preason.size(); j++) {
587 				int q = preason.get(j);
588 				if (!seen[q >> 1]) {
589 					seen[q >> 1] = true;
590 					if (voc.getReason(q) == null && voc.getLevel(q) > 0) {
591 						assert assumps.contains(toDimacs(q));
592 						outLearnt.push(toDimacs(q));
593 					}
594 				}
595 			}
596 
597 			// select next reason to look at
598 			do {
599 				p = trail.last();
600 				confl = voc.getReason(p);
601 				undoOne();
602 				if (decisionLevel() > 0 && trail.size() <= trailLim.last()) {
603 					trailLim.pop();
604 				}
605 			} while (trail.size() > 0 && decisionLevel() > 0
606 					&& (!seen[p >> 1] || confl == null));
607 		} while (decisionLevel() > 0);
608 		return outLearnt;
609 	}
610 
611 	interface ISimplifier extends Serializable {
612 		void simplify(IVecInt outLearnt);
613 	}
614 
615 	public static final ISimplifier NO_SIMPLIFICATION = new ISimplifier() {
616 		/**
617          * 
618          */
619 		private static final long serialVersionUID = 1L;
620 
621 		public void simplify(IVecInt outLearnt) {
622 		}
623 
624 		@Override
625 		public String toString() {
626 			return "No reason simplification"; //$NON-NLS-1$
627 		}
628 	};
629 
630 	public final ISimplifier SIMPLE_SIMPLIFICATION = new ISimplifier() {
631 		/**
632          * 
633          */
634 		private static final long serialVersionUID = 1L;
635 
636 		public void simplify(IVecInt conflictToReduce) {
637 			simpleSimplification(conflictToReduce);
638 		}
639 
640 		@Override
641 		public String toString() {
642 			return "Simple reason simplification"; //$NON-NLS-1$
643 		}
644 	};
645 
646 	public final ISimplifier EXPENSIVE_SIMPLIFICATION = new ISimplifier() {
647 
648 		/**
649          * 
650          */
651 		private static final long serialVersionUID = 1L;
652 
653 		public void simplify(IVecInt conflictToReduce) {
654 			expensiveSimplification(conflictToReduce);
655 		}
656 
657 		@Override
658 		public String toString() {
659 			return "Expensive reason simplification"; //$NON-NLS-1$
660 		}
661 	};
662 
663 	private ISimplifier simplifier = NO_SIMPLIFICATION;
664 
665 	/**
666 	 * Setup the reason simplification strategy. By default, there is no reason
667 	 * simplification. NOTE THAT REASON SIMPLIFICATION DOES NOT WORK WITH
668 	 * SPECIFIC DATA STRUCTURE FOR HANDLING BOTH BINARY AND TERNARY CLAUSES.
669 	 * 
670 	 * @param simp
671 	 *            the name of the simplifier (one of NO_SIMPLIFICATION,
672 	 *            SIMPLE_SIMPLIFICATION, EXPENSIVE_SIMPLIFICATION).
673 	 */
674 	public void setSimplifier(String simp) {
675 		Field f;
676 		try {
677 			f = Solver.class.getDeclaredField(simp);
678 			simplifier = (ISimplifier) f.get(this);
679 		} catch (Exception e) {
680 			e.printStackTrace();
681 			simplifier = NO_SIMPLIFICATION;
682 		}
683 	}
684 
685 	/**
686 	 * Setup the reason simplification strategy. By default, there is no reason
687 	 * simplification. NOTE THAT REASON SIMPLIFICATION IS ONLY ALLOWED FOR WL
688 	 * CLAUSAL data structures. USING REASON SIMPLIFICATION ON CB CLAUSES,
689 	 * CARDINALITY CONSTRAINTS OR PB CONSTRAINTS MIGHT RESULT IN INCORRECT
690 	 * RESULTS.
691 	 * 
692 	 * @param simp
693 	 */
694 	public void setSimplifier(ISimplifier simp) {
695 		simplifier = simp;
696 	}
697 
698 	// MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson
699 	//
700 	// Permission is hereby granted, free of charge, to any person obtaining a
701 	// copy of this software and associated documentation files (the
702 	// "Software"), to deal in the Software without restriction, including
703 	// without limitation the rights to use, copy, modify, merge, publish,
704 	// distribute, sublicense, and/or sell copies of the Software, and to
705 	// permit persons to whom the Software is furnished to do so, subject to
706 	// the following conditions:
707 	//
708 	// The above copyright notice and this permission notice shall be included
709 	// in all copies or substantial portions of the Software.
710 	//
711 	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
712 	// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
713 	// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
714 	// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
715 	// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
716 	// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
717 	// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
718 
719 	// Taken from MiniSAT 1.14: Simplify conflict clause (a little):
720 	private void simpleSimplification(IVecInt conflictToReduce) {
721 		int i, j;
722 		final boolean[] seen = mseen;
723 		for (i = j = 1; i < conflictToReduce.size(); i++) {
724 			IConstr r = voc.getReason(conflictToReduce.get(i));
725 			if (r == null) {
726 				conflictToReduce.moveTo(j++, i);
727 			} else {
728 				for (int k = 0; k < r.size(); k++)
729 					if (voc.isFalsified(r.get(k)) && !seen[r.get(k) >> 1]
730 							&& (voc.getLevel(r.get(k)) != 0)) {
731 						conflictToReduce.moveTo(j++, i);
732 						break;
733 					}
734 			}
735 		}
736 		conflictToReduce.shrink(i - j);
737 		stats.reducedliterals += (i - j);
738 	}
739 
740 	private final IVecInt analyzetoclear = new VecInt();
741 
742 	private final IVecInt analyzestack = new VecInt();
743 
744 	// Taken from MiniSAT 1.14
745 	private void expensiveSimplification(IVecInt conflictToReduce) {
746 		// Simplify conflict clause (a lot):
747 		//
748 		int i, j;
749 		// (maintain an abstraction of levels involved in conflict)
750 		analyzetoclear.clear();
751 		conflictToReduce.copyTo(analyzetoclear);
752 		for (i = 1, j = 1; i < conflictToReduce.size(); i++)
753 			if (voc.getReason(conflictToReduce.get(i)) == null
754 					|| !analyzeRemovable(conflictToReduce.get(i)))
755 				conflictToReduce.moveTo(j++, i);
756 		conflictToReduce.shrink(i - j);
757 		stats.reducedliterals += (i - j);
758 	}
759 
760 	// Check if 'p' can be removed.' min_level' is used to abort early if
761 	// visiting literals at a level that cannot be removed.
762 	//
763 	private boolean analyzeRemovable(int p) {
764 		assert voc.getReason(p) != null;
765 		analyzestack.clear();
766 		analyzestack.push(p);
767 		final boolean[] seen = mseen;
768 		int top = analyzetoclear.size();
769 		while (analyzestack.size() > 0) {
770 			int q = analyzestack.last();
771 			assert voc.getReason(q) != null;
772 			Constr c = voc.getReason(q);
773 			analyzestack.pop();
774 			for (int i = 0; i < c.size(); i++) {
775 				int l = c.get(i);
776 				if (voc.isFalsified(l) && !seen[var(l)] && voc.getLevel(l) != 0) {
777 					if (voc.getReason(l) == null) {
778 						for (int j = top; j < analyzetoclear.size(); j++)
779 							seen[analyzetoclear.get(j) >> 1] = false;
780 						analyzetoclear.shrink(analyzetoclear.size() - top);
781 						return false;
782 					}
783 					seen[l >> 1] = true;
784 					analyzestack.push(l);
785 					analyzetoclear.push(l);
786 				}
787 			}
788 		}
789 
790 		return true;
791 	}
792 
793 	// END Minisat 1.14 cut and paste
794 
795 	/**
796      * 
797      */
798 	protected void undoOne() {
799 		// recupere le dernier litteral affecte
800 		int p = trail.last();
801 		assert p > 1;
802 		assert voc.getLevel(p) >= 0;
803 		int x = p >> 1;
804 		// desaffecte la variable
805 		voc.unassign(p);
806 		voc.setReason(p, null);
807 		voc.setLevel(p, -1);
808 		// met a jour l'heuristique
809 		order.undo(x);
810 		// depile le litteral des affectations
811 		trail.pop();
812 		// met a jour les contraintes apres desaffectation du litteral :
813 		// normalement, il n'y a rien a faire ici pour les prouveurs de type
814 		// Chaff??
815 		IVec<Undoable> undos = voc.undos(p);
816 		assert undos != null;
817 		while (undos.size() > 0) {
818 			undos.last().undo(p);
819 			undos.pop();
820 		}
821 	}
822 
823 	/**
824 	 * Propagate activity to a constraint
825 	 * 
826 	 * @param confl
827 	 *            a constraint
828 	 */
829 	public void claBumpActivity(Constr confl) {
830 		confl.incActivity(claInc);
831 		if (confl.getActivity() > CLAUSE_RESCALE_BOUND)
832 			claRescalActivity();
833 		// for (int i = 0; i < confl.size(); i++) {
834 		// varBumpActivity(confl.get(i));
835 		// }
836 	}
837 
838 	public void varBumpActivity(int p) {
839 		order.updateVar(p);
840 	}
841 
842 	private void claRescalActivity() {
843 		for (int i = 0; i < learnts.size(); i++) {
844 			learnts.get(i).rescaleBy(CLAUSE_RESCALE_FACTOR);
845 		}
846 		claInc *= CLAUSE_RESCALE_FACTOR;
847 	}
848 
849 	/**
850 	 * @return null if not conflict is found, else a conflicting constraint.
851 	 */
852 	public Constr propagate() {
853 		while (qhead < trail.size()) {
854 			stats.propagations++;
855 			int p = trail.get(qhead++);
856 			slistener.propagating(toDimacs(p), null);
857 			order.assignLiteral(p);
858 			// p is the literal to propagate
859 			// Moved original MiniSAT code to dsfactory to avoid
860 			// watches manipulation in counter Based clauses for instance.
861 			assert p > 1;
862 			IVec<Propagatable> watched = dsfactory.getWatchesFor(p);
863 
864 			final int size = watched.size();
865 			for (int i = 0; i < size; i++) {
866 				stats.inspects++;
867 				if (!watched.get(i).propagate(this, p)) {
868 					// Constraint is conflicting: copy remaining watches to
869 					// watches[p]
870 					// and return constraint
871 					dsfactory.conflictDetectedInWatchesFor(p, i);
872 					qhead = trail.size(); // propQ.clear();
873 					// FIXME enlever le transtypage
874 					return (Constr) watched.get(i);
875 				}
876 			}
877 		}
878 		return null;
879 	}
880 
881 	void record(Constr constr) {
882 		constr.assertConstraint(this);
883 		slistener.adding(toDimacs(constr.get(0)));
884 		if (constr.size() == 1) {
885 			stats.learnedliterals++;
886 		} else {
887 			learner.learns(constr);
888 		}
889 	}
890 
891 	/**
892 	 * @return false ssi conflit imm?diat.
893 	 */
894 	public boolean assume(int p) {
895 		// Precondition: assume propagation queue is empty
896 		assert trail.size() == qhead;
897 		trailLim.push(trail.size());
898 		return enqueue(p);
899 	}
900 
901 	/**
902 	 * Revert to the state before the last push()
903 	 */
904 	private void cancel() {
905 		// assert trail.size() == qhead || !undertimeout;
906 		int decisionvar = trail.unsafeGet(trailLim.last());
907 		slistener.backtracking(toDimacs(decisionvar));
908 		for (int c = trail.size() - trailLim.last(); c > 0; c--) {
909 			undoOne();
910 		}
911 		trailLim.pop();
912 	}
913 
914 	/**
915 	 * Restore literals
916 	 */
917 	private void cancelLearntLiterals(int learnedLiteralsLimit) {
918 		learnedLiterals.clear();
919 		// assert trail.size() == qhead || !undertimeout;
920 		while (trail.size() > learnedLiteralsLimit) {
921 			learnedLiterals.push(trail.last());
922 			undoOne();
923 		}
924 		qhead = trail.size();
925 		// learnedLiterals = 0;
926 	}
927 
928 	/**
929 	 * Cancel several levels of assumptions
930 	 * 
931 	 * @param level
932 	 */
933 	protected void cancelUntil(int level) {
934 		while (decisionLevel() > level) {
935 			cancel();
936 		}
937 		qhead = trail.size();
938 	}
939 
940 	private final Pair analysisResult = new Pair();
941 
942 	private boolean[] fullmodel;
943 
944 	private IVecInt unsatExplanationInTermsOfAssumptions;
945 
946 	Lbool search(long nofConflicts, IVecInt assumps) {
947 		assert rootLevel == decisionLevel();
948 		stats.starts++;
949 		int conflictC = 0;
950 		int backjumpLevel;
951 
952 		// varDecay = 1 / params.varDecay;
953 		order.setVarDecay(1 / params.getVarDecay());
954 		claDecay = 1 / params.getClaDecay();
955 
956 		do {
957 			slistener.beginLoop();
958 			// propage les clauses unitaires
959 			Constr confl = propagate();
960 			assert trail.size() == qhead;
961 
962 			if (confl == null) {
963 				// No conflict found
964 				// simpliFYDB() prevents a correct use of
965 				// constraints removal.
966 				if (decisionLevel() == 0 && isDBSimplificationAllowed) {
967 					// // Simplify the set of problem clause
968 					// // iff rootLevel==0
969 					stats.rootSimplifications++;
970 					boolean ret = simplifyDB();
971 					assert ret;
972 				}
973 				// was learnts.size() - nAssigns() > nofLearnts
974 				// if (nofLearnts.obj >= 0 && learnts.size() > nofLearnts.obj) {
975 				assert nAssigns() <= voc.realnVars();
976 				if (nAssigns() == voc.realnVars()) {
977 					slistener.solutionFound();
978 					modelFound();
979 					return Lbool.TRUE;
980 				}
981 				if (conflictC >= nofConflicts) {
982 					// Reached bound on number of conflicts
983 					// Force a restart
984 					cancelUntil(rootLevel);
985 					return Lbool.UNDEFINED;
986 				}
987 				if (needToReduceDB) {
988 					reduceDB();
989 					needToReduceDB = false;
990 					// Runtime.getRuntime().gc();
991 				}
992 				// New variable decision
993 				stats.decisions++;
994 				int p = order.select();
995 				assert p > 1;
996 				slistener.assuming(toDimacs(p));
997 				boolean ret = assume(p);
998 				assert ret;
999 			} else {
1000 				// un conflit apparait
1001 				stats.conflicts++;
1002 				conflictC++;
1003 				slistener.conflictFound(confl, decisionLevel(), trail.size());
1004 				conflictCount.newConflict();
1005 
1006 				if (decisionLevel() == rootLevel) {
1007 					// on est a la racine, la formule est inconsistante
1008 					unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1009 							confl, assumps, ILits.UNDEFINED);
1010 					return Lbool.FALSE;
1011 				}
1012 				// analyze conflict
1013 				analyze(confl, analysisResult);
1014 				assert analysisResult.backtrackLevel < decisionLevel();
1015 				backjumpLevel = Math.max(analysisResult.backtrackLevel,
1016 						rootLevel);
1017 				slistener.backjump(backjumpLevel);
1018 				cancelUntil(backjumpLevel);
1019 				if (backjumpLevel == rootLevel) {
1020 					conflictC = 0;
1021 				}
1022 				assert (decisionLevel() >= rootLevel)
1023 						&& (decisionLevel() >= analysisResult.backtrackLevel);
1024 				if (analysisResult.reason == null) {
1025 					return Lbool.FALSE;
1026 				}
1027 				record(analysisResult.reason);
1028 				analysisResult.reason = null;
1029 				decayActivities();
1030 			}
1031 		} while (undertimeout);
1032 		return Lbool.UNDEFINED; // timeout occured
1033 	}
1034 
1035 	protected void analyzeAtRootLevel(Constr conflict) {
1036 	}
1037 
1038 	/**
1039      * 
1040      */
1041 	void modelFound() {
1042 		model = new int[trail.size()];
1043 		fullmodel = new boolean[nVars()];
1044 		int index = 0;
1045 		for (int i = 1; i <= voc.nVars(); i++) {
1046 			if (voc.belongsToPool(i)) {
1047 				int p = voc.getFromPool(i);
1048 				if (!voc.isUnassigned(p)) {
1049 					model[index++] = voc.isSatisfied(p) ? i : -i;
1050 					fullmodel[i - 1] = voc.isSatisfied(p);
1051 				}
1052 			}
1053 		}
1054 		assert index == model.length;
1055 		cancelUntil(rootLevel);
1056 	}
1057 
1058 	public boolean model(int var) {
1059 		if (var <= 0 || var > nVars()) {
1060 			throw new IllegalArgumentException(
1061 					"Use a valid Dimacs var id as argument!"); //$NON-NLS-1$
1062 		}
1063 		if (fullmodel == null) {
1064 			throw new UnsupportedOperationException(
1065 					"Call the solve method first!!!"); //$NON-NLS-1$
1066 		}
1067 		return fullmodel[var - 1];
1068 	}
1069 
1070 	public void clearLearntClauses() {
1071 		for (Iterator<Constr> iterator = learnts.iterator(); iterator.hasNext();)
1072 			iterator.next().remove(this);
1073 		learnts.clear();
1074 		learnedLiterals.clear();
1075 	}
1076 
1077 	protected void reduceDB() {
1078 		sortOnActivity();
1079 		stats.reduceddb++;
1080 		learnedConstraintsDeletionStrategy.reduce(learnts);
1081 		System.gc();
1082 	}
1083 
1084 	/**
1085 	 * @param learnts
1086 	 */
1087 	private void sortOnActivity() {
1088 		learnts.sort(comparator);
1089 	}
1090 
1091 	/**
1092      * 
1093      */
1094 	protected void decayActivities() {
1095 		order.varDecayActivity();
1096 		claDecayActivity();
1097 	}
1098 
1099 	/**
1100      * 
1101      */
1102 	private void claDecayActivity() {
1103 		claInc *= claDecay;
1104 	}
1105 
1106 	/**
1107 	 * @return true iff the set of constraints is satisfiable, else false.
1108 	 */
1109 	public boolean isSatisfiable() throws TimeoutException {
1110 		return isSatisfiable(VecInt.EMPTY);
1111 	}
1112 
1113 	/**
1114 	 * @return true iff the set of constraints is satisfiable, else false.
1115 	 */
1116 	public boolean isSatisfiable(boolean global) throws TimeoutException {
1117 		return isSatisfiable(VecInt.EMPTY, global);
1118 	}
1119 
1120 	private double timebegin = 0;
1121 
1122 	private boolean needToReduceDB;
1123 
1124 	private ConflictTimer conflictCount;
1125 
1126 	private transient Timer timer;
1127 
1128 	public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
1129 		return isSatisfiable(assumps, false);
1130 	}
1131 
1132 	interface LearnedConstraintsDeletionStrategy extends Serializable {
1133 
1134 		void init();
1135 
1136 		ConflictTimer getTimer();
1137 
1138 		void reduce(IVec<Constr> learnedConstrs);
1139 
1140 		void onConflict(Constr outLearnt);
1141 
1142 		void onConflictAnalysis(Constr reason);
1143 	}
1144 
1145 	/**
1146 	 * @since 2.1
1147 	 */
1148 	public final LearnedConstraintsDeletionStrategy memory_based = new LearnedConstraintsDeletionStrategy() {
1149 
1150 		/**
1151 		 * 
1152 		 */
1153 		private static final long serialVersionUID = 1L;
1154 
1155 		final long memorybound = Runtime.getRuntime().freeMemory() / 10;
1156 
1157 		private final ConflictTimer freeMem = new ConflictTimerAdapter(500) {
1158 			private static final long serialVersionUID = 1L;
1159 
1160 			@Override
1161 			void run() {
1162 				long freemem = Runtime.getRuntime().freeMemory();
1163 				// System.out.println("c Free memory "+freemem);
1164 				if (freemem < memorybound) {
1165 					// Reduce the set of learnt clauses
1166 					needToReduceDB = true;
1167 				}
1168 			}
1169 		};
1170 
1171 		public void reduce(IVec<Constr> learnedConstrs) {
1172 			int i, j;
1173 			for (i = j = 0; i < learnts.size() / 2; i++) {
1174 				Constr c = learnts.get(i);
1175 				if (c.locked() || c.size() == 2) {
1176 					learnts.set(j++, learnts.get(i));
1177 				} else {
1178 					c.remove(Solver.this);
1179 				}
1180 			}
1181 			for (; i < learnts.size(); i++) {
1182 				learnts.set(j++, learnts.get(i));
1183 			}
1184 			if (verbose) {
1185 				System.out.println(getLogPrefix()
1186 						+ "cleaning " + (learnts.size() - j) //$NON-NLS-1$
1187 						+ " clauses out of " + learnts.size()); //$NON-NLS-1$ //$NON-NLS-2$
1188 			}
1189 			learnts.shrinkTo(j);
1190 		}
1191 
1192 		public ConflictTimer getTimer() {
1193 			return freeMem;
1194 		}
1195 
1196 		@Override
1197 		public String toString() {
1198 			return "Memory based learned constraints deletion strategy";
1199 		}
1200 
1201 		public void init() {
1202 			// do nothing
1203 		}
1204 
1205 		public void onConflict(Constr constr) {
1206 			// do nothing
1207 
1208 		}
1209 
1210 		public void onConflictAnalysis(Constr reason) {
1211 			if (reason.learnt())
1212 				claBumpActivity(reason);
1213 		}
1214 	};
1215 
1216 	/**
1217 	 * @since 2.1
1218 	 */
1219 	public final LearnedConstraintsDeletionStrategy glucose = new LearnedConstraintsDeletionStrategy() {
1220 
1221 		/**
1222 		 * 
1223 		 */
1224 		private static final long serialVersionUID = 1L;
1225 		private int[] flags = new int[0];
1226 		private int flag = 0;
1227 		private int wall = 0;
1228 
1229 		private final ConflictTimer clauseManagement = new ConflictTimerAdapter(
1230 				1000) {
1231 			private static final long serialVersionUID = 1L;
1232 			private int nbconflict = 0;
1233 			private static final int MAX_CLAUSE = 5000;
1234 			private static final int INC_CLAUSE = 1000;
1235 			private int nextbound = MAX_CLAUSE;
1236 
1237 			@Override
1238 			void run() {
1239 				nbconflict += bound();
1240 				if (nbconflict >= nextbound) {
1241 					nextbound += INC_CLAUSE;
1242 					if (nextbound > wall) {
1243 						nextbound = wall;
1244 					}
1245 					nbconflict = 0;
1246 					needToReduceDB = true;
1247 				}
1248 			}
1249 		};
1250 
1251 		public void reduce(IVec<Constr> learnedConstrs) {
1252 			int i, j;
1253 			for (i = j = learnedConstrs.size() / 2; i < learnedConstrs.size(); i++) {
1254 				Constr c = learnedConstrs.get(i);
1255 				if (c.locked() || c.getActivity() <= 2.0) {
1256 					learnedConstrs.set(j++, learnts.get(i));
1257 				} else {
1258 					c.remove(Solver.this);
1259 				}
1260 			}
1261 			if (verbose) {
1262 				System.out
1263 						.println(getLogPrefix()
1264 								+ "cleaning " + (learnedConstrs.size() - j) //$NON-NLS-1$
1265 								+ " clauses out of " + learnedConstrs.size() + " with flag " + flag + "/" + stats.conflicts); //$NON-NLS-1$ //$NON-NLS-2$
1266 			}
1267 			learnts.shrinkTo(j);
1268 
1269 		}
1270 
1271 		public ConflictTimer getTimer() {
1272 			return clauseManagement;
1273 		}
1274 
1275 		@Override
1276 		public String toString() {
1277 			return "Glucose learned constraints deletion strategy";
1278 		}
1279 
1280 		public void init() {
1281 			final int howmany = voc.nVars();
1282 			wall = constrs.size() > 10000 ? constrs.size() : 10000;
1283 			if (flags.length <= howmany) {
1284 				flags = new int[howmany + 1];
1285 			}
1286 
1287 		}
1288 
1289 		public void onConflict(Constr constr) {
1290 			int nblevel = 1;
1291 			flag++;
1292 			int currentLevel;
1293 			for (int i = 1; i < constr.size(); i++) {
1294 				currentLevel = voc.getLevel(constr.get(i));
1295 				if (flags[currentLevel] != flag) {
1296 					flags[currentLevel] = flag;
1297 					nblevel++;
1298 				}
1299 			}
1300 			constr.incActivity(nblevel);
1301 		}
1302 
1303 		public void onConflictAnalysis(Constr reason) {
1304 			// do nothing
1305 		}
1306 	};
1307 
1308 	private LearnedConstraintsDeletionStrategy learnedConstraintsDeletionStrategy = glucose;
1309 
1310 	/**
1311 	 * @param lcds
1312 	 * @since 2.1
1313 	 */
1314 	public void setLearnedConstraintsDeletionStrategy(
1315 			LearnedConstraintsDeletionStrategy lcds) {
1316 		learnedConstraintsDeletionStrategy = lcds;
1317 	}
1318 
1319 	public boolean isSatisfiable(IVecInt assumps, boolean global)
1320 			throws TimeoutException {
1321 		Lbool status = Lbool.UNDEFINED;
1322 		undertimeout = true;
1323 		final int howmany = voc.nVars();
1324 		if (mseen.length <= howmany) {
1325 			mseen = new boolean[howmany + 1];
1326 		}
1327 		trail.ensure(howmany);
1328 		trailLim.ensure(howmany);
1329 		learnedLiterals.ensure(howmany);
1330 		timebegin = System.currentTimeMillis();
1331 		slistener.start();
1332 		model = null; // forget about previous model
1333 		fullmodel = null;
1334 		unsatExplanationInTermsOfAssumptions = null;
1335 		order.init();
1336 		learnedConstraintsDeletionStrategy.init();
1337 
1338 		int learnedLiteralsLimit = trail.size();
1339 
1340 		// push previously learned literals
1341 		for (IteratorInt iterator = learnedLiterals.iterator(); iterator
1342 				.hasNext();) {
1343 			enqueue(iterator.next());
1344 		}
1345 
1346 		// propagate constraints
1347 		Constr confl = propagate();
1348 		if (confl != null) {
1349 			analyzeAtRootLevel(confl);
1350 			slistener.conflictFound(confl, 0, 0);
1351 			slistener.end(Lbool.FALSE);
1352 			cancelUntil(0);
1353 			cancelLearntLiterals(learnedLiteralsLimit);
1354 			return false;
1355 		}
1356 
1357 		// push incremental assumptions
1358 		for (IteratorInt iterator = assumps.iterator(); iterator.hasNext();) {
1359 			int assump = iterator.next();
1360 			int p = voc.getFromPool(assump);
1361 			if (!assume(p) || ((confl = propagate()) != null)) {
1362 				if (confl == null) {
1363 					slistener.conflictFound(p);
1364 					unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1365 							null, assumps, p);
1366 					unsatExplanationInTermsOfAssumptions.push(assump);
1367 				} else {
1368 					slistener.conflictFound(confl, decisionLevel(),
1369 							trail.size());
1370 					unsatExplanationInTermsOfAssumptions = analyzeFinalConflictInTermsOfAssumptions(
1371 							confl, assumps, ILits.UNDEFINED);
1372 				}
1373 
1374 				slistener.end(Lbool.FALSE);
1375 				cancelUntil(0);
1376 				cancelLearntLiterals(learnedLiteralsLimit);
1377 				return false;
1378 			}
1379 		}
1380 		rootLevel = decisionLevel();
1381 		// moved initialization here if new literals are added in the
1382 		// assumptions.
1383 		order.init(); // duplicated on purpose
1384 		learner.init();
1385 
1386 		boolean firstTimeGlobal = false;
1387 		if (timeBasedTimeout) {
1388 			if (!global || timer == null) {
1389 				firstTimeGlobal = true;
1390 				TimerTask stopMe = new TimerTask() {
1391 					@Override
1392 					public void run() {
1393 						undertimeout = false;
1394 					}
1395 				};
1396 				timer = new Timer(true);
1397 				timer.schedule(stopMe, timeout);
1398 				conflictCount = learnedConstraintsDeletionStrategy.getTimer();
1399 			}
1400 		} else {
1401 			if (!global || conflictCount == null) {
1402 				firstTimeGlobal = true;
1403 				ConflictTimer conflictTimeout = new ConflictTimerAdapter(
1404 						(int) timeout) {
1405 					private static final long serialVersionUID = 1L;
1406 
1407 					@Override
1408 					public void run() {
1409 						undertimeout = false;
1410 					}
1411 				};
1412 				conflictCount = new ConflictTimerContainer().add(
1413 						conflictTimeout).add(
1414 						learnedConstraintsDeletionStrategy.getTimer());
1415 			}
1416 		}
1417 		if (!global || firstTimeGlobal)
1418 			restarter.init(params);
1419 		needToReduceDB = false;
1420 		// Solve
1421 		while ((status == Lbool.UNDEFINED) && undertimeout) {
1422 			status = search(restarter.nextRestartNumberOfConflict(), assumps);
1423 			if (status == Lbool.UNDEFINED) {
1424 				restarter.onRestart();
1425 				slistener.restarting();
1426 			}
1427 		}
1428 
1429 		cancelUntil(0);
1430 		cancelLearntLiterals(learnedLiteralsLimit);
1431 		if (!global && timeBasedTimeout) {
1432 			timer.cancel();
1433 			timer = null;
1434 		}
1435 		slistener.end(status);
1436 		if (!undertimeout) {
1437 			String message = " Timeout (" + timeout
1438 					+ (timeBasedTimeout ? "s" : " conflicts") + ") exceeded";
1439 			throw new TimeoutException(message); //$NON-NLS-1$//$NON-NLS-2$
1440 		}
1441 		return status == Lbool.TRUE;
1442 	}
1443 
1444 	public void printInfos(PrintWriter out, String prefix) {
1445 		out.print(prefix);
1446 		out.println("constraints type ");
1447 		for (Map.Entry<String, Counter> entry : constrTypes.entrySet()) {
1448 			out.println(prefix + entry.getKey() + " => " + entry.getValue());
1449 		}
1450 	}
1451 
1452 	/**
1453 	 * @since 2.1
1454 	 */
1455 	public void printLearntClausesInfos(PrintWriter out, String prefix) {
1456 		Map<String, Counter> learntTypes = new HashMap<String, Counter>();
1457 		for (Iterator<Constr> it = learnts.iterator(); it.hasNext();) {
1458 			String type = it.next().getClass().getName();
1459 			Counter count = learntTypes.get(type);
1460 			if (count == null) {
1461 				learntTypes.put(type, new Counter());
1462 			} else {
1463 				count.inc();
1464 			}
1465 		}
1466 		out.print(prefix);
1467 		out.println("learnt constraints type ");
1468 		for (Map.Entry<String, Counter> entry : learntTypes.entrySet()) {
1469 			out.println(prefix + entry.getKey() + " => " + entry.getValue());
1470 		}
1471 	}
1472 
1473 	public SolverStats getStats() {
1474 		return stats;
1475 	}
1476 
1477 	/**
1478 	 * 
1479 	 * @param myStats
1480 	 * @since 2.2
1481 	 */
1482 	protected void initStats(SolverStats myStats) {
1483 		this.stats = myStats;
1484 	}
1485 
1486 	public IOrder getOrder() {
1487 		return order;
1488 	}
1489 
1490 	public void setOrder(IOrder h) {
1491 		order = h;
1492 		order.setLits(voc);
1493 	}
1494 
1495 	public ILits getVocabulary() {
1496 		return voc;
1497 	}
1498 
1499 	public void reset() {
1500 		trail.clear();
1501 		trailLim.clear();
1502 		qhead = 0;
1503 		for (Iterator<Constr> iterator = constrs.iterator(); iterator.hasNext();)
1504 			iterator.next().remove(this);
1505 		constrs.clear();
1506 		clearLearntClauses();
1507 		voc.resetPool();
1508 		dsfactory.reset();
1509 		stats.reset();
1510 		constrTypes.clear();
1511 	}
1512 
1513 	public int nVars() {
1514 		return voc.nVars();
1515 	}
1516 
1517 	/**
1518 	 * @param constr
1519 	 *            a constraint implementing the Constr interface.
1520 	 * @return a reference to the constraint for external use.
1521 	 */
1522 	protected IConstr addConstr(Constr constr) {
1523 		if (constr != null) {
1524 			constrs.push(constr);
1525 			String type = constr.getClass().getName();
1526 			Counter count = constrTypes.get(type);
1527 			if (count == null) {
1528 				constrTypes.put(type, new Counter());
1529 			} else {
1530 				count.inc();
1531 			}
1532 		}
1533 		return constr;
1534 	}
1535 
1536 	public DataStructureFactory getDSFactory() {
1537 		return dsfactory;
1538 	}
1539 
1540 	public IVecInt getOutLearnt() {
1541 		return moutLearnt;
1542 	}
1543 
1544 	/**
1545 	 * returns the ith constraint in the solver.
1546 	 * 
1547 	 * @param i
1548 	 *            the constraint number (begins at 0)
1549 	 * @return the ith constraint
1550 	 */
1551 	public IConstr getIthConstr(int i) {
1552 		return constrs.get(i);
1553 	}
1554 
1555 	/*
1556 	 * (non-Javadoc)
1557 	 * 
1558 	 * @see org.sat4j.specs.ISolver#printStat(java.io.PrintStream,
1559 	 * java.lang.String)
1560 	 */
1561 	public void printStat(PrintStream out, String prefix) {
1562 		printStat(new PrintWriter(out, true), prefix);
1563 	}
1564 
1565 	public void printStat(PrintWriter out, String prefix) {
1566 		stats.printStat(out, prefix);
1567 		double cputime = (System.currentTimeMillis() - timebegin) / 1000;
1568 		out.println(prefix
1569 				+ "speed (assignments/second)\t: " + stats.propagations //$NON-NLS-1$
1570 				/ cputime);
1571 		order.printStat(out, prefix);
1572 		printLearntClausesInfos(out, prefix);
1573 	}
1574 
1575 	/*
1576 	 * (non-Javadoc)
1577 	 * 
1578 	 * @see java.lang.Object#toString()
1579 	 */
1580 	public String toString(String prefix) {
1581 		StringBuffer stb = new StringBuffer();
1582 		Object[] objs = { analyzer, dsfactory, learner, params, order,
1583 				simplifier, restarter, learnedConstraintsDeletionStrategy };
1584 		stb.append(prefix);
1585 		stb.append("--- Begin Solver configuration ---"); //$NON-NLS-1$
1586 		stb.append("\n"); //$NON-NLS-1$
1587 		for (Object o : objs) {
1588 			stb.append(prefix);
1589 			stb.append(o.toString());
1590 			stb.append("\n"); //$NON-NLS-1$
1591 		}
1592 		stb.append(prefix);
1593 		stb.append("timeout=");
1594 		if (timeBasedTimeout) {
1595 			stb.append(timeout / 1000);
1596 			stb.append("s\n");
1597 		} else {
1598 			stb.append(timeout);
1599 			stb.append(" conflicts\n");
1600 		}
1601 		stb.append(prefix);
1602 		stb.append("DB Simplification allowed=");
1603 		stb.append(isDBSimplificationAllowed);
1604 		stb.append("\n");
1605 		stb.append(prefix);
1606 		stb.append("--- End Solver configuration ---"); //$NON-NLS-1$
1607 		return stb.toString();
1608 	}
1609 
1610 	/*
1611 	 * (non-Javadoc)
1612 	 * 
1613 	 * @see java.lang.Object#toString()
1614 	 */
1615 	@Override
1616 	public String toString() {
1617 		return toString(""); //$NON-NLS-1$
1618 	}
1619 
1620 	public int getTimeout() {
1621 		return (int) (timeBasedTimeout ? timeout / 1000 : timeout);
1622 	}
1623 
1624 	/**
1625 	 * @since 2.1
1626 	 */
1627 	public long getTimeoutMs() {
1628 		if (!timeBasedTimeout) {
1629 			throw new UnsupportedOperationException(
1630 					"The timeout is given in number of conflicts!");
1631 		}
1632 		return timeout;
1633 	}
1634 
1635 	public void setExpectedNumberOfClauses(int nb) {
1636 		constrs.ensure(nb);
1637 	}
1638 
1639 	public Map<String, Number> getStat() {
1640 		return stats.toMap();
1641 	}
1642 
1643 	public int[] findModel() throws TimeoutException {
1644 		if (isSatisfiable()) {
1645 			return model();
1646 		}
1647 		// DLB findbugs ok
1648 		// A zero length array would mean that the formula is a tautology.
1649 		return null;
1650 	}
1651 
1652 	public int[] findModel(IVecInt assumps) throws TimeoutException {
1653 		if (isSatisfiable(assumps)) {
1654 			return model();
1655 		}
1656 		// DLB findbugs ok
1657 		// A zero length array would mean that the formula is a tautology.
1658 		return null;
1659 	}
1660 
1661 	public boolean isDBSimplificationAllowed() {
1662 		return isDBSimplificationAllowed;
1663 	}
1664 
1665 	public void setDBSimplificationAllowed(boolean status) {
1666 		isDBSimplificationAllowed = status;
1667 	}
1668 
1669 	/**
1670 	 * @since 2.1
1671 	 */
1672 	public int nextFreeVarId(boolean reserve) {
1673 		return voc.nextFreeVarId(reserve);
1674 	}
1675 
1676 	/**
1677 	 * @since 2.1
1678 	 */
1679 	public IConstr addBlockingClause(IVecInt literals)
1680 			throws ContradictionException {
1681 		return addClause(literals);
1682 	}
1683 
1684 	/**
1685 	 * @since 2.1
1686 	 */
1687 	public void unset(int p) {
1688 		int current = trail.last();
1689 		while (current != p) {
1690 			undoOne();
1691 			current = trail.last();
1692 		}
1693 		undoOne();
1694 	}
1695 
1696 	/**
1697 	 * @since 2.2
1698 	 */
1699 	public void setLogPrefix(String prefix) {
1700 		this.prefix = prefix;
1701 	}
1702 
1703 	/**
1704 	 * @since 2.2
1705 	 */
1706 	public String getLogPrefix() {
1707 		return prefix;
1708 	}
1709 
1710 	/**
1711 	 * @since 2.2
1712 	 */
1713 	public IVecInt unsatExplanation() {
1714 		return unsatExplanationInTermsOfAssumptions;
1715 	}
1716 
1717 }
1718 
1719 class ActivityComparator implements Comparator<Constr>, Serializable {
1720 
1721 	private static final long serialVersionUID = 1L;
1722 
1723 	/*
1724 	 * (non-Javadoc)
1725 	 * 
1726 	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
1727 	 */
1728 	public int compare(Constr c1, Constr c2) {
1729 		long delta = Math.round(c1.getActivity() - c2.getActivity());
1730 		if (delta == 0) {
1731 			return c1.size() - c2.size();
1732 		}
1733 		return (int) delta;
1734 	}
1735 }
1736 
1737 interface ConflictTimer {
1738 
1739 	void reset();
1740 
1741 	void newConflict();
1742 }
1743 
1744 abstract class ConflictTimerAdapter implements Serializable, ConflictTimer {
1745 
1746 	/**
1747 	 * 
1748 	 */
1749 	private static final long serialVersionUID = 1L;
1750 
1751 	private int counter;
1752 
1753 	private final int bound;
1754 
1755 	ConflictTimerAdapter(final int bound) {
1756 		this.bound = bound;
1757 		counter = 0;
1758 	}
1759 
1760 	public void reset() {
1761 		counter = 0;
1762 	}
1763 
1764 	public void newConflict() {
1765 		counter++;
1766 		if (counter == bound) {
1767 			run();
1768 			counter = 0;
1769 		}
1770 	}
1771 
1772 	abstract void run();
1773 
1774 	public int bound() {
1775 		return bound;
1776 	}
1777 }
1778 
1779 class ConflictTimerContainer implements Serializable, ConflictTimer {
1780 
1781 	/**
1782 	 * 
1783 	 */
1784 	private static final long serialVersionUID = 1L;
1785 
1786 	private final IVec<ConflictTimer> timers = new Vec<ConflictTimer>();
1787 
1788 	ConflictTimerContainer add(ConflictTimer timer) {
1789 		timers.push(timer);
1790 		return this;
1791 	}
1792 
1793 	public void reset() {
1794 		Iterator<ConflictTimer> it = timers.iterator();
1795 		while (it.hasNext()) {
1796 			it.next().reset();
1797 		}
1798 	}
1799 
1800 	public void newConflict() {
1801 		Iterator<ConflictTimer> it = timers.iterator();
1802 		while (it.hasNext()) {
1803 			it.next().newConflict();
1804 		}
1805 	}
1806 }