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 java.io.FileWriter;
33  import java.io.IOException;
34  import java.io.ObjectInputStream;
35  import java.io.PrintWriter;
36  import java.io.Writer;
37  import java.util.Map;
38  
39  import org.sat4j.core.Vec;
40  import org.sat4j.specs.IConstr;
41  import org.sat4j.specs.ISolverService;
42  import org.sat4j.specs.RandomAccessModel;
43  import org.sat4j.specs.Lbool;
44  
45  /**
46   * Class allowing to express the search as a tree in the dot language. The
47   * resulting file can be viewed in a tool like <a
48   * href="http://www.graphviz.org/">Graphviz</a>
49   * 
50   * To use only on small benchmarks.
51   * 
52   * Note that also does not make sense to use such a listener on a distributed or
53   * remote solver.
54   * 
55   * @author daniel
56   * @since 2.2
57   */
58  public class DotSearchTracing<T> extends SearchListenerAdapter<ISolverService> {
59  
60      /**
61       * 
62       */
63      private static final long serialVersionUID = 1L;
64  
65      private final Vec<String> pile;
66  
67      private String currentNodeName = null;
68  
69      private transient Writer out;
70  
71      private boolean estOrange = false;
72  
73      private final Map<Integer, T> mapping;
74  
75      /**
76       * @since 2.1
77       */
78      public DotSearchTracing(final String fileNameToSave, Map<Integer, T> mapping) {
79          this.pile = new Vec<String>();
80          this.mapping = mapping;
81          try {
82              this.out = new FileWriter(fileNameToSave);
83          } catch (IOException e) {
84              System.err.println("Problem when created file.");
85          }
86      }
87  
88      private String node(int dimacs) {
89          if (this.mapping != null) {
90              int var = Math.abs(dimacs);
91              T t = this.mapping.get(var);
92              if (t != null) {
93                  if (dimacs > 0) {
94                      return t.toString();
95                  }
96                  return "-" + t.toString();
97              }
98          }
99          return Integer.toString(dimacs);
100     }
101 
102     @Override
103     public final void assuming(final int p) {
104         final int absP = Math.abs(p);
105         String newName;
106 
107         if (this.currentNodeName == null) {
108             newName = "" + absP;
109             this.pile.push(newName);
110             saveLine(lineTab("\"" + newName + "\"" + "[label=\"" + node(p)
111                     + "\", shape=circle, color=blue, style=filled]"));
112         } else {
113             newName = this.currentNodeName;
114             this.pile.push(newName);
115             saveLine(lineTab("\"" + newName + "\"" + "[label=\"" + node(p)
116                     + "\", shape=circle, color=blue, style=filled]"));
117         }
118         this.currentNodeName = newName;
119     }
120 
121     /**
122      * @since 2.1
123      */
124     @Override
125     public final void propagating(final int p, IConstr reason) {
126         String newName = this.currentNodeName + "." + p;
127 
128         if (this.currentNodeName == null) {
129             saveLine(lineTab("\"null\" [label=\"\", shape=point]"));
130         }
131         final String couleur = this.estOrange ? "orange" : "green";
132 
133         saveLine(lineTab("\"" + newName + "\"" + "[label=\"" + node(p)
134                 + "\",shape=point, color=black]"));
135         saveLine(lineTab("\"" + this.currentNodeName + "\"" + " -- " + "\""
136                 + newName + "\"" + "[label=" + "\" " + node(p)
137                 + "\", fontcolor =" + couleur + ", color = " + couleur
138                 + ", style = bold]"));
139         this.currentNodeName = newName;
140         this.estOrange = false;
141     }
142 
143     @Override
144     public final void backtracking(final int p) {
145         final String temp = this.pile.last();
146         this.pile.pop();
147         saveLine("\"" + temp + "\"" + "--" + "\"" + this.currentNodeName + "\""
148                 + "[label=\"\", color=red, style=dotted]");
149         this.currentNodeName = temp;
150     }
151 
152     @Override
153     public final void adding(final int p) {
154         this.estOrange = true;
155     }
156 
157     /**
158      * @since 2.1
159      */
160     @Override
161     public final void learn(final IConstr clause) {
162     }
163 
164     @Override
165     public final void delete(final int[] clause) {
166     }
167 
168     /**
169      * @since 2.1
170      */
171     @Override
172     public final void conflictFound(IConstr confl, int dlevel, int trailLevel) {
173         saveLine(lineTab("\"" + this.currentNodeName
174                 + "\" [label=\"\", shape=box, color=\"red\", style=filled]"));
175     }
176 
177     /**
178      * @since 2.1
179      */
180     @Override
181     public final void conflictFound(int p) {
182         saveLine(lineTab("\"" + this.currentNodeName
183                 + "\" [label=\"\", shape=box, color=\"red\", style=filled]"));
184     }
185 
186     @Override
187     public final void solutionFound(int[] model, RandomAccessModel lazyModel) {
188         saveLine(lineTab("\"" + this.currentNodeName
189                 + "\" [label=\"\", shape=box, color=\"green\", style=filled]"));
190     }
191 
192     @Override
193     public final void beginLoop() {
194     }
195 
196     @Override
197     public final void start() {
198         saveLine("graph G {");
199     }
200 
201     /**
202      * @since 2.1
203      */
204     @Override
205     public final void end(Lbool result) {
206         saveLine("}");
207     }
208 
209     private String lineTab(final String line) {
210         return "\t" + line;
211     }
212 
213     private void saveLine(final String line) {
214         try {
215             this.out.write(line + '\n');
216             if ("}".equals(line)) {
217                 this.out.close();
218             }
219         } catch (IOException e) {
220             e.printStackTrace();
221         }
222     }
223 
224     private void readObject(ObjectInputStream stream) throws IOException,
225             ClassNotFoundException {
226         // if the solver is serialized, out is linked to stdout
227         stream.defaultReadObject();
228         this.out = new PrintWriter(System.out);
229     }
230 }