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