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 *******************************************************************************/ 28 package org.sat4j.tools; 29 30 import org.sat4j.core.VecInt; 31 import org.sat4j.specs.ContradictionException; 32 import org.sat4j.specs.ISolver; 33 import org.sat4j.specs.IVecInt; 34 import org.sat4j.specs.TimeoutException; 35 36 /** 37 * That class allows to iterate through all the models (implicants) of a 38 * formula. 39 * 40 * <pre> 41 * ISolver solver = new ModelIterator(SolverFactory.OneSolver()); 42 * boolean unsat = true; 43 * while (solver.isSatisfiable()) { 44 * unsat = false; 45 * int[] model = solver.model(); 46 * // do something with model 47 * } 48 * if (unsat) { 49 * // UNSAT case 50 * } 51 * </pre> 52 * 53 * It is also possible to limit the number of models returned: 54 * 55 * <pre> 56 * ISolver solver = new ModelIterator(SolverFactory.OneSolver(), 10); 57 * </pre> 58 * 59 * will return at most 10 models. 60 * 61 * @author leberre 62 */ 63 public class ModelIterator extends SolverDecorator<ISolver> { 64 65 private static final long serialVersionUID = 1L; 66 67 private boolean trivialfalsity = false; 68 private final int bound; 69 private int nbModelFound = 0; 70 71 /** 72 * @param solver 73 */ 74 public ModelIterator(ISolver solver) { 75 this(solver, Integer.MAX_VALUE); 76 } 77 78 /** 79 * 80 * @param solver 81 * @param bound 82 * @since 2.1 83 */ 84 public ModelIterator(ISolver solver, int bound) { 85 super(solver); 86 this.bound = bound; 87 } 88 89 /* 90 * (non-Javadoc) 91 * 92 * @see org.sat4j.ISolver#model() 93 */ 94 @Override 95 public int[] model() { 96 int[] last = super.model(); 97 nbModelFound++; 98 IVecInt clause = new VecInt(last.length); 99 for (int q : last) { 100 clause.push(-q); 101 } 102 try { 103 // System.out.println("adding " + clause); 104 addBlockingClause(clause); 105 } catch (ContradictionException e) { 106 trivialfalsity = true; 107 } 108 return last; 109 } 110 111 /* 112 * (non-Javadoc) 113 * 114 * @see org.sat4j.ISolver#isSatisfiable() 115 */ 116 @Override 117 public boolean isSatisfiable() throws TimeoutException { 118 if (trivialfalsity || nbModelFound >= bound) { 119 return false; 120 } 121 trivialfalsity = false; 122 return super.isSatisfiable(true); 123 } 124 125 /* 126 * (non-Javadoc) 127 * 128 * @see org.sat4j.ISolver#isSatisfiable(org.sat4j.datatype.VecInt) 129 */ 130 @Override 131 public boolean isSatisfiable(IVecInt assumps) throws TimeoutException { 132 if (trivialfalsity || nbModelFound >= bound) { 133 return false; 134 } 135 trivialfalsity = false; 136 return super.isSatisfiable(assumps, true); 137 } 138 139 /* 140 * (non-Javadoc) 141 * 142 * @see org.sat4j.ISolver#reset() 143 */ 144 @Override 145 public void reset() { 146 trivialfalsity = false; 147 nbModelFound = 0; 148 super.reset(); 149 } 150 }