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.pb;
31  
32  import java.math.BigInteger;
33  
34  import org.sat4j.specs.ContradictionException;
35  import org.sat4j.specs.IConstr;
36  import org.sat4j.specs.IVec;
37  import org.sat4j.specs.IVecInt;
38  import org.sat4j.specs.IteratorInt;
39  import org.sat4j.specs.TimeoutException;
40  import org.sat4j.tools.DimacsStringSolver;
41  
42  /**
43   * Solver used to display in a string the pb-instance in OPB format.
44   * 
45   * That solver is useful to produce LP files to be used by third party solvers
46   * (of which CPLEX)
47   * 
48   * This is a preliminary implementation
49   * 
50   * @author sroussel
51   * 
52   */
53  public class LPStringSolver extends DimacsStringSolver implements IPBSolver {
54  
55      private static final String FAKE_I_CONSTR_MSG = "Fake IConstr";
56  
57      /**
58  	 * 
59  	 */
60      private static final long serialVersionUID = 1L;
61  
62      private int indxConstrObj;
63  
64      private int nbOfConstraints;
65  
66      private ObjectiveFunction obj;
67  
68      private boolean inserted = false;
69  
70      private static final IConstr FAKE_CONSTR = new IConstr() {
71  
72          public int size() {
73              throw new UnsupportedOperationException(FAKE_I_CONSTR_MSG);
74          }
75  
76          public boolean learnt() {
77              throw new UnsupportedOperationException(FAKE_I_CONSTR_MSG);
78          }
79  
80          public double getActivity() {
81              throw new UnsupportedOperationException(FAKE_I_CONSTR_MSG);
82          }
83  
84          public int get(int i) {
85              throw new UnsupportedOperationException(FAKE_I_CONSTR_MSG);
86          }
87  
88          public boolean canBePropagatedMultipleTimes() {
89              throw new UnsupportedOperationException(FAKE_I_CONSTR_MSG);
90          }
91      };
92  
93      /**
94  	 * 
95  	 */
96      public LPStringSolver() {
97      }
98  
99      /**
100      * @param initSize
101      */
102     public LPStringSolver(int initSize) {
103         super(initSize);
104     }
105 
106     @Override
107     public boolean isSatisfiable(IVecInt assumps) throws TimeoutException {
108         for (IteratorInt it = assumps.iterator(); it.hasNext();) {
109             int p = it.next();
110             if (p > 0) {
111                 getOut().append("x" + p + " >= 1 \n");
112             } else {
113                 getOut().append("- x" + -p + " >= 0 \n");
114             }
115             this.nbOfConstraints++;
116         }
117         throw new TimeoutException();
118     }
119 
120     @Override
121     public boolean isSatisfiable(IVecInt assumps, boolean global)
122             throws TimeoutException {
123         return super.isSatisfiable(assumps, global);
124     }
125 
126     public IConstr addPseudoBoolean(IVecInt lits, IVec<BigInteger> coeffs,
127             boolean moreThan, BigInteger d) throws ContradictionException {
128         if (moreThan) {
129             return addAtLeast(lits, coeffs, d);
130         }
131         return addAtMost(lits, coeffs, d);
132     }
133 
134     public void setObjectiveFunction(ObjectiveFunction obj) {
135         this.obj = obj;
136     }
137 
138     @Override
139     public IConstr addAtLeast(IVecInt literals, int degree)
140             throws ContradictionException {
141         StringBuffer out = getOut();
142         this.nbOfConstraints++;
143         int negationweight = 0;
144         int p;
145         boolean first = true;
146         for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
147             p = iterator.next();
148             assert p != 0;
149             if (first) {
150                 if (p > 0) {
151                     getOut().append("x" + p + " ");
152                 } else {
153                     getOut().append("- x" + -p + " ");
154                     negationweight++;
155                 }
156                 first = false;
157             } else {
158                 if (p > 0) {
159                     out.append("+ x" + p + " ");
160                 } else {
161                     out.append("- x" + -p + " ");
162                     negationweight++;
163                 }
164             }
165         }
166         out.append(">= " + (degree - negationweight) + " \n");
167         return FAKE_CONSTR;
168     }
169 
170     @Override
171     public IConstr addAtMost(IVecInt literals, int degree)
172             throws ContradictionException {
173         StringBuffer out = getOut();
174         this.nbOfConstraints++;
175         int negationweight = 0;
176         int p;
177         boolean first = true;
178         for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
179             p = iterator.next();
180             assert p != 0;
181             if (first) {
182                 if (p > 0) {
183                     getOut().append("- x" + p + " ");
184                 } else {
185                     getOut().append("x" + -p + " ");
186                     negationweight++;
187                 }
188                 first = false;
189             } else {
190                 if (p > 0) {
191                     out.append("- x" + p + " ");
192                 } else {
193                     out.append("+ x" + -p + " ");
194                     negationweight++;
195                 }
196             }
197         }
198         out.append(">= " + (-degree + negationweight) + " \n");
199         return FAKE_CONSTR;
200     }
201 
202     @Override
203     public IConstr addClause(IVecInt literals) throws ContradictionException {
204         StringBuffer out = getOut();
205         this.nbOfConstraints++;
206         int lit;
207         boolean first = true;
208         int negationweight = 0;
209         for (IteratorInt iterator = literals.iterator(); iterator.hasNext();) {
210             lit = iterator.next();
211 
212             if (first) {
213                 if (lit > 0) {
214                     out.append("x" + lit + " ");
215                 } else {
216                     out.append("-x" + -lit + " ");
217                     negationweight++;
218                 }
219                 first = false;
220             } else {
221                 if (lit > 0) {
222                     out.append("+ x" + lit + " ");
223                 } else {
224                     out.append("- x" + -lit + " ");
225                     negationweight++;
226                 }
227             }
228         }
229         out.append(">= " + (1 - negationweight) + "\n");
230         return FAKE_CONSTR;
231     }
232 
233     /*
234      * (non-Javadoc)
235      * 
236      * @see org.sat4j.pb.IPBSolver#getExplanation()
237      */
238     public String getExplanation() {
239         // TODO Auto-generated method stub
240         return null;
241     }
242 
243     /*
244      * (non-Javadoc)
245      * 
246      * @see
247      * org.sat4j.pb.IPBSolver#setListOfVariablesForExplanation(org.sat4j.specs
248      * .IVecInt)
249      */
250     public void setListOfVariablesForExplanation(IVecInt listOfVariables) {
251         // TODO Auto-generated method stub
252 
253     }
254 
255     public void objectiveFunctionToLP(ObjectiveFunction obj, StringBuffer buffer) {
256         buffer.append("Minimize \n");
257         buffer.append("obj: ");
258         IVecInt variables = obj.getVars();
259         IVec<BigInteger> coeffs = obj.getCoeffs();
260         int n = variables.size();
261         if (n > 0) {
262             buffer.append(coeffs.get(0));
263             buffer.append("x");
264             buffer.append(variables.get(0));
265             buffer.append(" ");
266         }
267         BigInteger coeff;
268         for (int i = 1; i < n; i++) {
269             coeff = coeffs.get(i);
270             if (coeff.signum() > 0) {
271                 buffer.append("+ " + coeff);
272             } else {
273                 buffer.append("- " + coeff.negate());
274             }
275             buffer.append("x");
276             buffer.append(variables.get(i));
277             buffer.append(" ");
278         }
279 
280     }
281 
282     @Override
283     public String toString() {
284         StringBuffer out = getOut();
285         if (!this.inserted) {
286             StringBuffer tmp = new StringBuffer();
287             // tmp.append("* #variable= ");
288             // tmp.append(nVars());
289             // tmp.append(" #constraint= ");
290             // tmp.append(nbOfConstraints);
291             if (this.obj != null) {
292                 objectiveFunctionToLP(this.obj, tmp);
293                 tmp.append("\n");
294                 tmp.append("Subject To\n ");
295             }
296             // TODO : there must an objective function
297             out.insert(this.indxConstrObj, tmp.toString());
298             this.inserted = true;
299         }
300         // out.append("\n");
301         out.append("Binary \n");
302         // TODO : V�rifier que les variables sont bien num�rot�es de 1 �
303         // maxvarid
304         for (int i = 1; i <= nVars(); i++) {
305             out.append("x" + i + "\n");
306         }
307         out.append("\n");
308         out.append("End");
309         return out.toString();
310     }
311 
312     @Override
313     public String toString(String prefix) {
314         return toString();
315     }
316 
317     @Override
318     public int newVar(int howmany) {
319         StringBuffer out = getOut();
320         setNbVars(howmany);
321         // to add later the number of constraints
322         this.indxConstrObj = out.length();
323         out.append("\n");
324         return howmany;
325     }
326 
327     @Override
328     public void setExpectedNumberOfClauses(int nb) {
329     }
330 
331     public ObjectiveFunction getObjectiveFunction() {
332         return this.obj;
333     }
334 
335     @Override
336     public int nConstraints() {
337         return this.nbOfConstraints;
338     }
339 
340     public IConstr addAtMost(IVecInt literals, IVecInt coeffs, int degree)
341             throws ContradictionException {
342         StringBuffer out = getOut();
343         assert literals.size() == coeffs.size();
344         this.nbOfConstraints++;
345         int n = literals.size();
346         if (n > 0) {
347             out.append(-coeffs.get(0));
348             out.append("x");
349             out.append(literals.get(0));
350             out.append(" ");
351         }
352         int coeff;
353         for (int i = 1; i < n; i++) {
354             coeff = coeffs.get(i);
355             if (coeff > 0) {
356                 out.append("+ " + -coeff);
357             } else {
358                 out.append("- " + coeff);
359             }
360             out.append("x");
361             out.append(literals.get(i));
362             out.append(" ");
363         }
364         out.append(">= ");
365         out.append(-degree);
366         out.append(" \n");
367         return FAKE_CONSTR;
368     }
369 
370     public IConstr addAtMost(IVecInt literals, IVec<BigInteger> coeffs,
371             BigInteger degree) throws ContradictionException {
372         StringBuffer out = getOut();
373         assert literals.size() == coeffs.size();
374         this.nbOfConstraints++;
375         int n = literals.size();
376         if (n > 0) {
377             out.append(coeffs.get(0).negate());
378             out.append("x");
379             out.append(literals.get(0));
380             out.append(" ");
381         }
382         BigInteger coeff;
383         for (int i = 1; i < n; i++) {
384             coeff = coeffs.get(i);
385             if (coeff.signum() < 0) {
386                 out.append("+ " + coeff.negate());
387             } else {
388                 out.append("- " + coeff);
389             }
390             out.append("x");
391             out.append(literals.get(i));
392             out.append(" ");
393         }
394         out.append(">= ");
395         out.append(degree.negate());
396         out.append(" \n");
397         return FAKE_CONSTR;
398     }
399 
400     public IConstr addAtLeast(IVecInt literals, IVecInt coeffs, int degree)
401             throws ContradictionException {
402         StringBuffer out = getOut();
403         assert literals.size() == coeffs.size();
404         this.nbOfConstraints++;
405         int n = literals.size();
406         if (n > 0) {
407             out.append(coeffs.get(0));
408             out.append("x");
409             out.append(literals.get(0));
410             out.append(" ");
411         }
412         int coeff;
413         for (int i = 1; i < n; i++) {
414             coeff = coeffs.get(i);
415             if (coeff > 0) {
416                 out.append("+ " + coeff);
417             } else {
418                 out.append("- " + coeff * -1);
419             }
420             out.append("x");
421             out.append(literals.get(i));
422             out.append(" ");
423         }
424         out.append(">= ");
425         out.append(degree);
426         out.append(" \n");
427         return FAKE_CONSTR;
428     }
429 
430     public IConstr addAtLeast(IVecInt literals, IVec<BigInteger> coeffs,
431             BigInteger degree) throws ContradictionException {
432         StringBuffer out = getOut();
433         assert literals.size() == coeffs.size();
434         this.nbOfConstraints++;
435         int n = literals.size();
436         if (n > 0) {
437             out.append(coeffs.get(0));
438             out.append("x");
439             out.append(literals.get(0));
440             out.append(" ");
441         }
442         BigInteger coeff;
443         for (int i = 1; i < n; i++) {
444             coeff = coeffs.get(i);
445             if (coeff.signum() > 0) {
446                 out.append("+ " + coeff);
447             } else {
448                 out.append("- " + coeff.negate());
449             }
450             out.append("x");
451             out.append(literals.get(i));
452             out.append(" ");
453         }
454         out.append(">= ");
455         out.append(degree);
456         out.append(" \n");
457         return FAKE_CONSTR;
458 
459     }
460 
461     public IConstr addExactly(IVecInt literals, IVecInt coeffs, int weight)
462             throws ContradictionException {
463         StringBuffer out = getOut();
464         assert literals.size() == coeffs.size();
465         this.nbOfConstraints++;
466         int n = literals.size();
467         if (n > 0) {
468             out.append(coeffs.get(0));
469             out.append("x");
470             out.append(literals.get(0));
471             out.append(" ");
472         }
473         int coeff;
474         for (int i = 1; i < n; i++) {
475             coeff = coeffs.get(i);
476             if (coeff > 0) {
477                 out.append("+ " + coeff);
478             } else {
479                 out.append("- " + coeff * -1);
480             }
481             out.append("x");
482             out.append(literals.get(i));
483             out.append(" ");
484         }
485         out.append("= ");
486         out.append(weight);
487         out.append(" \n");
488         return FAKE_CONSTR;
489     }
490 
491     public IConstr addExactly(IVecInt literals, IVec<BigInteger> coeffs,
492             BigInteger weight) throws ContradictionException {
493         StringBuffer out = getOut();
494         assert literals.size() == coeffs.size();
495         this.nbOfConstraints++;
496         int n = literals.size();
497         if (n > 0) {
498             out.append(coeffs.get(0));
499             out.append("x");
500             out.append(literals.get(0));
501             out.append(" ");
502         }
503         BigInteger coeff;
504         for (int i = 1; i < n; i++) {
505             coeff = coeffs.get(i);
506             if (coeff.signum() > 0) {
507                 out.append("+ " + coeff);
508             } else {
509                 out.append("- " + coeff.negate());
510             }
511             out.append("x");
512             out.append(literals.get(i));
513             out.append(" ");
514         }
515         out.append("= ");
516         out.append(weight);
517         out.append(" \n");
518         return FAKE_CONSTR;
519     }
520 
521 }