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.io.PrintWriter;
33  
34  import org.sat4j.core.VecInt;
35  import org.sat4j.specs.ContradictionException;
36  import org.sat4j.specs.IOptimizationProblem;
37  import org.sat4j.specs.IVecInt;
38  import org.sat4j.specs.TimeoutException;
39  import org.sat4j.tools.SolutionFoundListener;
40  
41  /**
42   * Utility class to use optimization solvers instead of simple SAT solvers in
43   * code meant for SAT solvers.
44   * 
45   * @author daniel
46   */
47  public class OptToPBSATAdapter extends PBSolverDecorator {
48  
49      /**
50       * 
51       */
52      private static final long serialVersionUID = 1L;
53  
54      IOptimizationProblem problem;
55  
56      private final IVecInt assumps = new VecInt();
57  
58      private long begin;
59  
60      private SolutionFoundListener sfl;
61  
62      public OptToPBSATAdapter(IOptimizationProblem problem) {
63          this(problem, SolutionFoundListener.VOID);
64      }
65  
66      public OptToPBSATAdapter(IOptimizationProblem problem,
67              SolutionFoundListener sfl) {
68          super((IPBSolver) problem);
69          this.problem = problem;
70          this.sfl = sfl;
71      }
72  
73      @Override
74      public boolean isSatisfiable() throws TimeoutException {
75          return isSatisfiable(VecInt.EMPTY);
76      }
77  
78      @Override
79      public boolean isSatisfiable(boolean global) throws TimeoutException {
80          return isSatisfiable();
81      }
82  
83      @Override
84      public boolean isSatisfiable(IVecInt myAssumps, boolean global)
85              throws TimeoutException {
86          return isSatisfiable(myAssumps);
87      }
88  
89      @Override
90      public boolean isSatisfiable(IVecInt myAssumps) throws TimeoutException {
91          this.assumps.clear();
92          myAssumps.copyTo(this.assumps);
93          this.begin = System.currentTimeMillis();
94          if (this.problem.hasNoObjectiveFunction()) {
95              return this.problem.isSatisfiable(myAssumps);
96          }
97          boolean satisfiable = false;
98          try {
99              while (this.problem.admitABetterSolution(myAssumps)) {
100                 satisfiable = true;
101                 sfl.onSolutionFound(this.problem.model());
102                 this.problem.discardCurrentSolution();
103                 if (isVerbose()) {
104                     System.out.println(getLogPrefix()
105                             + "Current objective function value: "
106                             + this.problem.getObjectiveValue() + "("
107                             + (System.currentTimeMillis() - this.begin)
108                             / 1000.0 + "s)");
109                 }
110             }
111             sfl.onUnsatTermination();
112         } catch (ContradictionException ce) {
113             sfl.onUnsatTermination();
114         }
115         return satisfiable;
116     }
117 
118     @Override
119     public int[] model() {
120         return model(new PrintWriter(System.out, true));
121     }
122 
123     /**
124      * Compute a minimal model according to the objective function of the
125      * IPBProblem decorated.
126      * 
127      * @param out
128      *            a writer to display information in verbose mode
129      * @since 2.3.2
130      */
131     public int[] model(PrintWriter out) {
132         return this.problem.model();
133     }
134 
135     @Override
136     public boolean model(int var) {
137         return this.problem.model(var);
138     }
139 
140     @Override
141     public String toString(String prefix) {
142         return prefix + "Optimization to Pseudo Boolean adapter\n"
143                 + super.toString(prefix);
144     }
145 
146     public boolean isOptimal() {
147         return this.problem.isOptimal();
148     }
149 
150     /**
151      * Return the value of the objective function in the last model found.
152      * 
153      * @return
154      * @since 2.3.2
155      */
156     public Number getCurrentObjectiveValue() {
157         return this.problem.getObjectiveValue();
158     }
159 
160     /**
161      * Allow to set a specific timeout when the solver is in optimization mode.
162      * The solver internal timeout will be set to that value once it has found a
163      * solution. That way, the original timeout of the solver may be reduced if
164      * the solver finds quickly a solution, or increased if the solver finds
165      * regularly new solutions (thus giving more time to the solver each time).
166      * 
167      * @see IOptimizationProblem#setTimeoutForFindingBetterSolution(int)
168      */
169     public void setTimeoutForFindingBetterSolution(int seconds) {
170         this.problem.setTimeoutForFindingBetterSolution(seconds);
171     }
172 
173     public void setSolutionFoundListener(SolutionFoundListener sfl) {
174         this.sfl = sfl;
175     }
176 }