View Javadoc

1   package org.sat4j.sat.visu;
2   
3   import java.awt.Color;
4   import java.io.BufferedReader;
5   import java.io.FileOutputStream;
6   import java.io.IOException;
7   import java.io.InputStreamReader;
8   import java.io.PrintStream;
9   
10  import org.sat4j.minisat.core.ICDCLLogger;
11  
12  public class GnuplotBasedSolverVisualisation implements SolverVisualisation {
13  
14      private VisuPreferences visuPreferences;
15      private int nVar;
16      private Process gnuplotProcess;
17      private String dataPath;
18      private ICDCLLogger logger;
19  
20      public GnuplotBasedSolverVisualisation(VisuPreferences visuPref, int nbVar,
21              String path, ICDCLLogger logger) {
22          this.visuPreferences = visuPref;
23          this.nVar = nbVar;
24          this.dataPath = path;
25          this.logger = logger;
26      }
27  
28      public void start() {
29          traceGnuplot();
30      }
31  
32      public void end() {
33          stopGnuplot();
34      }
35  
36      public void traceGnuplot() {
37  
38          if (this.gnuplotProcess == null) {
39              try {
40  
41                  double verybottom = 0.0;
42                  double bottom = 0.33;
43                  double top = 0.66;
44                  double left = 0.0;
45                  double middle = 0.33;
46                  double right = 0.66;
47  
48                  double width = 0.33;
49                  double height = 0.33;
50  
51                  PrintStream out = new PrintStream(new FileOutputStream(
52                          this.dataPath + "-gnuplot.gnuplot"));
53                  out.println("set terminal x11");
54                  out.println("set multiplot");
55                  out.println("set autoscale x");
56                  out.println("set autoscale y");
57                  out.println("set nologscale x");
58                  out.println("set nologscale y");
59                  out.println("set ytics auto");
60  
61                  GnuplotFunction f = new GnuplotFunction("2", Color.black, "");
62  
63                  // bottom right: Decision Level when conflict
64                  if (this.visuPreferences.isDisplayConflictsDecision()) {
65                      out.println("set size " + width + "," + height);
66                      out.println("set origin " + right + "," + bottom);
67                      out.println("set title \"Decision level at which the conflict occurs\"");
68                      out.println("set autoscale ymax");
69                      out.println("set y2range [0:]");
70                      GnuplotDataFile conflictLevelDF = new GnuplotDataFile(
71                              this.dataPath + "-conflict-level.dat",
72                              Color.magenta, "Conflict Level");
73                      GnuplotDataFile conflictLevelRestartDF = new GnuplotDataFile(
74                              this.dataPath + "-conflict-level-restart.dat",
75                              Color.gray, "Restart", "impulses");
76                      GnuplotDataFile conflictLevelCleanDF = new GnuplotDataFile(
77                              this.dataPath + "-conflict-level-clean.dat",
78                              Color.orange, "Clean", "impulses");
79                      // out.println(gnuplotPreferences.generatePlotLine(conflictLevelDF,
80                      // true));
81                      out.println(this.visuPreferences
82                              .generatePlotLineOnDifferenteAxes(
83                                      new GnuplotDataFile[] { conflictLevelDF },
84                                      new GnuplotDataFile[] {
85                                              conflictLevelRestartDF,
86                                              conflictLevelCleanDF }, true));
87                      // out.println(visuPreferences.generatePlotLine(conflictLevelDF,f,
88                      // instancePath+ "-conflict-level-restart.dat", true));
89                  }
90  
91                  // top left: size of learned clause
92                  if (this.visuPreferences.isDisplayClausesSize()) {
93                      out.println("unset autoscale");
94                      out.println("set autoscale x");
95                      out.println("set autoscale ymax");
96                      out.println("set y2range [0:]");
97                      // out.println("set y2range[0:"+nbVariables+"]");
98                      // out.println("set autoscale y2");
99                      // out.println("set nologscale x");
100                     // out.println("set nologscale y");
101                     out.println("set size " + width + "," + height);
102                     out.println("set origin " + left + "," + top);
103                     out.println("set title \"Size of the clause learned (after minimization if any)\"");
104                     GnuplotDataFile learnedClausesDF = new GnuplotDataFile(
105                             this.dataPath + "-learned-clauses-size.dat",
106                             Color.blue, "Size");
107                     GnuplotDataFile learnedClausesRestartDF = new GnuplotDataFile(
108                             this.dataPath + "-learned-clauses-size-restart.dat",
109                             Color.gray, "Restart", "impulses");
110                     GnuplotDataFile learnedClausesCleanDF = new GnuplotDataFile(
111                             this.dataPath + "-learned-clauses-size-clean.dat",
112                             Color.orange, "Clean", "impulses");
113                     // out.println(gnuplotPreferences.generatePlotLine(learnedClausesDF,
114                     // true));
115                     out.println(this.visuPreferences
116                             .generatePlotLineOnDifferenteAxes(
117                                     new GnuplotDataFile[] { learnedClausesDF },
118                                     new GnuplotDataFile[] {
119                                             learnedClausesCleanDF,
120                                             learnedClausesRestartDF }, true));
121                 }
122 
123                 // top middle: clause activity
124                 if (this.visuPreferences.isDisplayConflictsDecision()) {
125                     out.println("set autoscale x");
126                     out.println("set autoscale y");
127                     out.println("set size " + width + "," + height);
128                     out.println("set origin " + middle + "," + top);
129                     out.println("set title \"Value of learned clauses evaluation\"");
130                     GnuplotDataFile learnedDF = new GnuplotDataFile(
131                             this.dataPath + "-learned.dat", Color.blue,
132                             "Evaluation");
133                     out.println(this.visuPreferences.generatePlotLine(
134                             learnedDF, f, "", false));
135                 }
136 
137                 // for bottom graphs, y range should be O-maxVar
138                 out.println("set autoscale x");
139                 out.println("set nologscale x");
140                 out.println("set nologscale y");
141                 out.println("set autoscale y");
142                 out.println("set yrange [1:" + this.nVar + "]");
143                 out.println("set ytics add (1," + this.nVar + ")");
144 
145                 // bottom left: index decision variable
146                 if (this.visuPreferences.isDisplayDecisionIndexes()) {
147                     out.println("unset autoscale");
148                     out.println("if(system(\"head "
149                             + this.dataPath
150                             + "-decision-indexes-pos.dat | wc -l\")!=0){set autoscale x;}");
151                     out.println("if(system(\"head "
152                             + this.dataPath
153                             + "-decision-indexes-pos.dat | wc -l\")!=0){set yrange [1:"
154                             + this.nVar + "]};");
155                     // out.println("set nologscale x");
156                     // out.println("set nologscale y");
157                     out.println("set size " + width + "," + height);
158                     out.println("set origin " + left + "," + bottom);
159                     out.println("set title \"Index of the decision variables\"");
160                     GnuplotDataFile negativeDF = new GnuplotDataFile(
161                             this.dataPath + "-decision-indexes-neg.dat",
162                             Color.red, "Negative Decision");
163                     GnuplotDataFile decisionRestartDF = new GnuplotDataFile(
164                             this.dataPath + "-decision-indexes-restart.dat",
165                             Color.gray, "Restart", "impulses");
166                     GnuplotDataFile decisionCleanDF = new GnuplotDataFile(
167                             this.dataPath + "-decision-indexes-clean.dat",
168                             Color.orange, "Clean", "impulses");
169                     // out.println(gnuplotPreferences.generatePlotLine(negativeDF,
170                     // true));
171                     out.println(this.visuPreferences
172                             .generatePlotLineOnDifferenteAxes(
173                                     new GnuplotDataFile[] { negativeDF },
174                                     new GnuplotDataFile[] { decisionRestartDF,
175                                             decisionCleanDF }, true,
176                                     this.visuPreferences.getNbLinesRead() * 4));
177                     // out.println(visuPreferences.generatePlotLine(negativeDF,f,instancePath+
178                     // "-decision-indexes-restart.dat" , true,
179                     // visuPreferences.getNbLinesRead()*4));
180 
181                     // verybottom left: index decision variable
182                     out.println("unset autoscale");
183                     out.println("if(system(\"head "
184                             + this.dataPath
185                             + "-decision-indexes-pos.dat | wc -l\")!=0){set autoscale x;set yrange [1:"
186                             + this.nVar + "]; set y2range [0:]; }");
187                     // out.println("set autoscale y");
188 
189                     // out.println("if(system(\"head "+ instancePath+
190                     // "-decision-indexes-pos.dat | wc -l\")!=0){set yrange [1:"+nbVariables+"];}");
191                     // out.println("set nologscale x");
192                     // out.println("set nologscale y");
193                     out.println("set size " + width + "," + height);
194                     out.println("set origin " + left + "," + verybottom);
195                     out.println("set title \"Index of the decision variables\"");
196                     GnuplotDataFile positiveDF = new GnuplotDataFile(
197                             this.dataPath + "-decision-indexes-pos.dat",
198                             Color.green, "Positive Decision");
199                     // out.println(gnuplotPreferences.generatePlotLine(positiveDF,
200                     // true));
201                     // out.println(visuPreferences.generatePlotLine(positiveDF,f,instancePath+
202                     // "-decision-indexes-restart.dat", true,
203                     // visuPreferences.getNbLinesRead()*4));
204                     out.println(this.visuPreferences
205                             .generatePlotLineOnDifferenteAxes(
206                                     new GnuplotDataFile[] { positiveDF },
207                                     new GnuplotDataFile[] { decisionRestartDF,
208                                             decisionCleanDF }, true,
209                                     this.visuPreferences.getNbLinesRead() * 4));
210                 }
211 
212                 // top right: depth search when conflict
213                 if (this.visuPreferences.isDisplayConflictsTrail()) {
214                     out.println("set autoscale x");
215                     out.println("set autoscale y");
216                     out.println("set nologscale x");
217                     out.println("set nologscale y");
218                     out.println("set size " + width + "," + height);
219                     out.println("set origin " + right + "," + top);
220                     out.println("set title \"Trail level when the conflict occurs\"");
221                     out.println("set y2range [0:]");
222                     GnuplotDataFile trailLevelDF = new GnuplotDataFile(
223                             this.dataPath + "-conflict-depth.dat",
224                             Color.magenta, "Trail level");
225                     GnuplotFunction nbVar2 = new GnuplotFunction("" + this.nVar
226                             / 2, Color.green, "#Var/2");
227                     GnuplotDataFile trailLevelRestartDF = new GnuplotDataFile(
228                             this.dataPath + "-conflict-depth-restart.dat",
229                             Color.gray, "Restart", "impulses");
230                     GnuplotDataFile trailLevelCleanDF = new GnuplotDataFile(
231                             this.dataPath + "-conflict-depth-clean.dat",
232                             Color.orange, "Clean", "impulses");
233                     // out.println(gnuplotPreferences.generatePlotLine(trailLevelDF,true));
234                     out.println(this.visuPreferences
235                             .generatePlotLineOnDifferenteAxes(
236                                     new GnuplotDataFile[] { trailLevelDF },
237                                     new GnuplotDataFile[] {
238                                             trailLevelRestartDF,
239                                             trailLevelCleanDF },
240                                     new GnuplotFunction[] { nbVar2 }, true));
241                     out.println(this.visuPreferences.generatePlotLine(
242                             trailLevelDF, nbVar2, this.dataPath
243                                     + "-conflict-level-restart.dat", true));
244                 }
245 
246                 // bottom middle: variable activity
247                 if (this.visuPreferences.isDisplayVariablesEvaluation()) {
248                     out.println("unset autoscale");
249                     out.println("set autoscale y");
250                     out.println("set nologscale x");
251                     out.println("set nologscale y");
252                     out.println("set yrange [1:" + this.nVar + "]");
253                     out.println("set xrange [0.5:*]");
254                     out.println("set size " + width + "," + height);
255                     out.println("set origin " + middle + "," + bottom);
256                     out.println("set title \"Value of variables activity\"");
257                     GnuplotDataFile heuristicsDF = new GnuplotDataFile(
258                             this.dataPath + "-heuristics.dat", Color.red,
259                             "Activity", "lines");
260                     out.println(this.visuPreferences.generatePlotLine(
261                             heuristicsDF, f, "", false));
262                 }
263                 // out.println("plot \"" + instancePath+
264                 // "-heuristics.dat\" with lines title \"Activity\"");
265 
266                 if (this.visuPreferences.isDisplaySpeed()) {
267                     out.println("set autoscale x");
268                     out.println("set nologscale x");
269                     out.println("set nologscale y");
270                     out.println("set size " + width + "," + height);
271                     out.println("set origin " + middle + "," + verybottom);
272                     out.println("set title \"Number of propagations per second\"");
273                     out.println("set y2range [0:]");
274                     GnuplotDataFile speedDF = new GnuplotDataFile(this.dataPath
275                             + "-speed.dat", Color.cyan, "Speed", "lines");
276                     GnuplotDataFile cleanDF = new GnuplotDataFile(this.dataPath
277                             + "-speed-clean.dat", Color.orange, "Clean",
278                             "impulses");
279                     GnuplotDataFile restartDF = new GnuplotDataFile(
280                             this.dataPath + "-speed-restart.dat", Color.gray,
281                             "Restart", "impulses");
282                     out.println(this.visuPreferences
283                             .generatePlotLineOnDifferenteAxes(
284                                     new GnuplotDataFile[] { speedDF },
285                                     new GnuplotDataFile[] { cleanDF, restartDF },
286                                     true, 50));
287                 }
288                 out.println("unset multiplot");
289                 double pauseTime = this.visuPreferences.getRefreshTime() / 1000;
290                 out.println("pause " + pauseTime);
291                 out.println("reread");
292                 out.close();
293 
294                 this.logger.log("Gnuplot will start in a few seconds.");
295 
296                 Thread errorStreamThread = new Thread() {
297                     @Override
298                     public void run() {
299 
300                         try {
301                             try {
302                                 Thread.sleep(GnuplotBasedSolverVisualisation.this.visuPreferences
303                                         .getTimeBeforeLaunching());
304                             } catch (InterruptedException e) {
305                                 e.printStackTrace();
306                             }
307 
308                             GnuplotBasedSolverVisualisation.this.logger
309                                     .log("reads "
310                                             + GnuplotBasedSolverVisualisation.this.dataPath
311                                             + "-gnuplot.gnuplot");
312                             GnuplotBasedSolverVisualisation.this.gnuplotProcess = Runtime
313                                     .getRuntime()
314                                     .exec(GnuplotBasedSolverVisualisation.this.visuPreferences
315                                             .createCommandLine(GnuplotBasedSolverVisualisation.this.dataPath
316                                                     + "-gnuplot.gnuplot"));
317 
318                             GnuplotBasedSolverVisualisation.this.logger
319                                     .log("Gnuplot should have started now.");
320 
321                             BufferedReader gnuInt = new BufferedReader(
322                                     new InputStreamReader(
323                                             GnuplotBasedSolverVisualisation.this.gnuplotProcess
324                                                     .getErrorStream()));
325                             String s;
326 
327                             while ((s = gnuInt.readLine()) != null) {
328                                 if (s.trim().length() > 0
329                                         && !s.toLowerCase().contains("warning")
330                                         && !s.toLowerCase().contains("plot")) {
331                                     System.out.println(s);
332                                 }
333                             }
334                         } catch (IOException e) {
335                             e.printStackTrace();
336                         }
337                     }
338                 };
339                 errorStreamThread.start();
340 
341             } catch (IOException e) {
342                 e.printStackTrace();
343             }
344         }
345     }
346 
347     public void stopGnuplot() {
348         if (this.gnuplotProcess != null) {
349             this.gnuplotProcess.destroy();
350             this.logger.log("Gnuplot should be deactivated...");
351         }
352         this.gnuplotProcess = null;
353     }
354 
355     public void setnVar(int n) {
356         this.nVar = n;
357     }
358 
359 }