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.tools;
31  
32  import org.sat4j.specs.ContradictionException;
33  import org.sat4j.specs.IConstr;
34  import org.sat4j.specs.IVecInt;
35  import org.sat4j.specs.IteratorInt;
36  
37  /**
38   * Solver used to write down a CNF into a String.
39   * 
40   * It is especially useful compared to the DimacsOutputSolver because the number
41   * of clauses does not need to be known in advance.
42   * 
43   * @author leberre
44   * 
45   */
46  public class DimacsStringSolver extends AbstractOutputSolver {
47  
48      /**
49       * 
50       */
51      private static final long serialVersionUID = 1L;
52  
53      private StringBuffer out;
54  
55      private int firstCharPos;
56  
57      private final int initBuilderSize;
58  
59      private int maxvarid = 0;
60  
61      public DimacsStringSolver() {
62          this(16);
63      }
64  
65      public DimacsStringSolver(int initSize) {
66          this.out = new StringBuffer(initSize);
67          this.initBuilderSize = initSize;
68      }
69  
70      public StringBuffer getOut() {
71          return this.out;
72      }
73  
74      public int newVar() {
75          return 0;
76      }
77  
78      @Override
79      public int newVar(int howmany) {
80          setNbVars(howmany);
81          return howmany;
82      }
83  
84      protected void setNbVars(int howmany) {
85          this.nbvars = howmany;
86          this.maxvarid = howmany;
87      }
88  
89      public void setExpectedNumberOfClauses(int nb) {
90          this.out.append(" ");
91          this.out.append(nb);
92          this.nbclauses = nb;
93          this.fixedNbClauses = true;
94      }
95  
96      public IConstr addClause(IVecInt literals) throws ContradictionException {
97          if (this.firstConstr) {
98              if (!this.fixedNbClauses) {
99                  this.firstCharPos = 7 + Integer.toString(this.nbvars).length();
100                 this.out.append("                    ");
101                 this.out.append("\n");
102                 this.nbclauses = 0;
103             }
104             this.firstConstr = false;
105         }
106         if (!this.fixedNbClauses) {
107             this.nbclauses++;
108         }
109         for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
110             this.out.append(iterator.next()).append(" ");
111         }
112         this.out.append("0\n");
113         return null;
114     }
115 
116     public IConstr addAtMost(IVecInt literals, int degree)
117             throws ContradictionException {
118         if (degree > 1) {
119             throw new UnsupportedOperationException(
120                     "Not a clausal problem! degree " + degree);
121         }
122         assert degree == 1;
123         if (this.firstConstr) {
124             this.firstCharPos = 0;
125             this.out.append("                    ");
126             this.out.append("\n");
127             this.nbclauses = 0;
128             this.firstConstr = false;
129         }
130 
131         for (int i = 0; i <= literals.size(); i++) {
132             for (int j = i + 1; j < literals.size(); j++) {
133                 if (!this.fixedNbClauses) {
134                     this.nbclauses++;
135                 }
136                 this.out.append(-literals.get(i));
137                 this.out.append(" ");
138                 this.out.append(-literals.get(j));
139                 this.out.append(" 0\n");
140             }
141         }
142         return null;
143     }
144 
145     public IConstr addExactly(IVecInt literals, int n)
146             throws ContradictionException {
147         if (n > 1) {
148             throw new UnsupportedOperationException(
149                     "Not a clausal problem! degree " + n);
150         }
151         assert n == 1;
152         addAtMost(literals, n);
153         addAtLeast(literals, n);
154         return null;
155     }
156 
157     public IConstr addAtLeast(IVecInt literals, int degree)
158             throws ContradictionException {
159         if (degree > 1) {
160             throw new UnsupportedOperationException(
161                     "Not a clausal problem! degree " + degree);
162         }
163         assert degree == 1;
164         return addClause(literals);
165     }
166 
167     public void reset() {
168         this.fixedNbClauses = false;
169         this.firstConstr = true;
170         this.out = new StringBuffer(this.initBuilderSize);
171         this.maxvarid = 0;
172     }
173 
174     public String toString(String prefix) {
175         return "Dimacs output solver";
176     }
177 
178     @Override
179     public int nConstraints() {
180         return this.nbclauses;
181     }
182 
183     @Override
184     public int nVars() {
185         return this.maxvarid;
186     }
187 
188     @Override
189     public String toString() {
190         this.out.insert(this.firstCharPos, "p cnf " + this.maxvarid + " "
191                 + this.nbclauses);
192         return this.out.toString();
193     }
194 
195     /**
196      * @since 2.1
197      */
198     public int nextFreeVarId(boolean reserve) {
199         if (reserve) {
200             return ++this.maxvarid;
201         }
202         return this.maxvarid + 1;
203     }
204 
205     /**
206      * @since 2.3.1
207      */
208     public int[] modelWithInternalVariables() {
209         throw new UnsupportedOperationException();
210     }
211 
212     public int realNumberOfVariables() {
213         return this.maxvarid;
214     }
215 
216     public void registerLiteral(int p) {
217         throw new UnsupportedOperationException();
218     }
219 
220     /**
221      * @since 2.3.2
222      */
223     public boolean primeImplicant(int p) {
224         throw new UnsupportedOperationException();
225     }
226 }