001 package net.sf.cpsolver.ifs.example.rpp;
002
003 import java.io.File;
004 import java.io.FileInputStream;
005 import java.io.FileOutputStream;
006 import java.io.FileWriter;
007 import java.io.PrintWriter;
008 import java.util.ArrayList;
009 import java.util.Collection;
010 import java.util.Date;
011 import java.util.Iterator;
012 import java.util.List;
013 import java.util.Locale;
014 import java.util.StringTokenizer;
015
016 import net.sf.cpsolver.ifs.solution.Solution;
017 import net.sf.cpsolver.ifs.solver.Solver;
018 import net.sf.cpsolver.ifs.util.DataProperties;
019 import net.sf.cpsolver.ifs.util.JProf;
020 import net.sf.cpsolver.ifs.util.Progress;
021 import net.sf.cpsolver.ifs.util.ProgressWriter;
022 import net.sf.cpsolver.ifs.util.PrologFile;
023 import net.sf.cpsolver.ifs.util.ToolBox;
024
025 /**
026 * RPP test. It takes one argument -- property file with all the parameters. It
027 * allows to execute given number of tests. The problem is loaded from
028 * prolog-based text files. For description of RPP problem see {@link RPPModel}. <br>
029 * <br>
030 * Description of the input problem files can be found at <a href='http://www.fi.muni.cz/~hanka/rpp/instances.html'>http://www.fi.muni.cz/~hanka/rpp/instances.html</a>.
031 * Each input problem (e.g., gen22.pl) has the following structure:
032 * <ul>
033 * <code>
034 * objects([<br>
035 * object(<br>
036 * name( rect1 ),<br>
037 * size( [ 2, 1 ] ),<br>
038 * valid_positions( [ 0-38, 0-13 ] )<br>
039 * ),<br>
040 * object(<br>
041 * name( rect2 ),<br>
042 * size( [ 2, 1 ] ),<br>
043 * valid_positions( [ 0-38, 0-13 ] )<br>
044 * ), <br>
045 * ... <br>
046 * object(<br>
047 * name( rect200 ),<br>
048 * size( [ 2, 1 ] ),<br>
049 * valid_positions( [ 0-38, 7-13 ] )<br>
050 * )<br>
051 * ] ). <br>
052 * </code>
053 * </ul>
054 * Stating that the first rectangle (named rect1) has size 2x1 and its valid
055 * position are with x between 0 and 38, y between 0 and 13, and so on. <br>
056 * MPP instances contain an extra file with the solution (e.g., gen22.solution),
057 * with the following structure
058 * <ul>
059 * <code>
060 * assigned([[rect1X,[17]], [rect1Y,[5]], [rect2X,[24]], [rect2Y,[4]], ... [rect200X,[37]], [rect200Y,[10]]]).
061 * </code>
062 * </ul>
063 * Which means that the first rectangle (named rect1) is to be placed at [17,5],
064 * second at [24,4] and so on. <br>
065 * There is also a file (e.g., gen22.mpp) describing which input placements are
066 * to be prohibited (not that if the input placement is prohibited, it means
067 * that also all values with the same X or Y coordinate are prohibited). It has
068 * the following structure:
069 * <ul>
070 * <code>
071 * perturbation( 1, 0, [] ).<br>
072 * perturbation( 2, 0, [] ).<br>
073 * ...<br>
074 * perturbation( 1, 2, [44,127] ).<br>
075 * perturbation( 2, 2, [80,153] ).<br>
076 * ...<br>
077 * perturbation( 1, 4, [44,80,127,153] ).<br>
078 * perturbation( 2, 4, [48,67,138,170] ). <br>
079 * ...<br>
080 * </code>
081 * </ul>
082 * Stating that for instance in the first test with 4 perturbations the
083 * rectangles rect44, rect80, rect127 and rect153 will have their initial value
084 * prohibited. <br>
085 * <br>
086 * Test's parameters: <br>
087 * <table border='1'>
088 * <tr>
089 * <th>Parameter</th>
090 * <th>Type</th>
091 * <th>Comment</th>
092 * </tr>
093 * <tr>
094 * <td>General.MPP</td>
095 * <td>{@link String}</td>
096 * <td>Minimal perturbation problem (if true), this mj. means that initial
097 * assignment will be generated</td>
098 * </tr>
099 * <tr>
100 * <td>RPP.NrTests</td>
101 * <td>{@link Integer}</td>
102 * <td>Number of tests to be executed for each input instance</td>
103 * </tr>
104 * <tr>
105 * <td>Rpp.Min<br>
106 * Rpp.Max<br>
107 * Rpp.Step</td>
108 * <td>{@link Integer}</td>
109 * <td>In case of MPP: minimal, maximal number and increment of input
110 * perturbations. An instance is loaded and tested for each given number of
111 * input perturbations.</td>
112 * </tr>
113 * <tr>
114 * <td>Rpp.Min<br>
115 * Rpp.Max</td>
116 * <td>{@link Integer}</td>
117 * <td>In case of initial problem: minimal and maximal number of the input
118 * problem. An instance is loaded and tested for each given number from RPP.Min
119 * to RPP.Max.</td>
120 * </tr>
121 * <tr>
122 * <td>Rpp.ProblemWidth<br>
123 * Rpp.ProblemHeight</td>
124 * <td>{@link Integer}</td>
125 * <td>Width and height of the placement area.</td>
126 * </tr>
127 * <tr>
128 * <td>General.Output</td>
129 * <td>{@link String}</td>
130 * <td>Output folder where a log file and tables with results. In order not to
131 * overwrite the results if executed more than once, a subfolder with the name
132 * taken from current date and time will be created in this folder and all
133 * results will go to this subfolder.</td>
134 * </tr>
135 * </table>
136 * <br>
137 * <br>
138 * Also, the configuration file can consist only from one parameter (named
139 * INCLUDE_REGEXP) which is processed as a regular expression of semicolon
140 * separated list of property files, for instance
141 * <ul>
142 * <code>INCLUDE_REGEXP=general.ini;{rpp85|rpp90|rpp95|mpp22}.ini;{5min}.ini;{cbs|rw1|tabu20}.ini</code>
143 * <br>
144 * </ul>
145 * where {a|b|c|...} means a selection of a, b, c, .. All possible combinations
146 * are taken and for each of them an input configuration is combined from the
147 * relevant files. So, for instance, the above example will result into the
148 * following configurations:
149 * <ul>
150 * <li>general.ini;rpp85.ini;5min.ini;cbs.ini
151 * <li>general.ini;rpp85.ini;5min.ini;rw1.ini
152 * <li>general.ini;rpp85.ini;5min.ini;tabu20.ini
153 * <li>general.ini;rpp90.ini;5min.ini;cbs.ini
154 * <li>general.ini;rpp90.ini;5min.ini;rw1.ini
155 * <li>general.ini;rpp90.ini;5min.ini;tabu20.ini
156 * <li>general.ini;rpp95.ini;5min.ini;cbs.ini
157 * <li>general.ini;rpp95.ini;5min.ini;rw1.ini
158 * <li>general.ini;rpp95.ini;5min.ini;tabu20.ini
159 * <li>general.ini;mpp22.ini;5min.ini;cbs.ini
160 * <li>general.ini;mpp22.ini;5min.ini;rw1.ini
161 * <li>general.ini;mpp22.ini;5min.ini;tabu20.ini
162 * </ul>
163 * To be able to distinguish such configuration a subfolder in General.Output
164 * folder is created, its name is combined from the names which are in
165 * parenthesis. So, for instance the first bunch of tests will output into the
166 * folder:
167 * <ul>
168 * ${General.Output}\rpp85_5min_csb\25-Feb-05_191136
169 * </ul>
170 * If one parameter is defined in more than one configuration files (e.g. in
171 * general.ini as well as cbs.ini) the one from the file more on the right is
172 * taken. <br>
173 * <br>
174 * An example of the configurations:<br>
175 * File<b> general.ini</b>
176 * <ul>
177 * <code>
178 * #Default settings common for all configurations<br>
179 * General.MPP=false<br>
180 * General.InitialAssignment=false<br>
181 * General.Output=output\\RPP\\IFS<br>
182 * <br>
183 * #Value selection heuristics<br>
184 * Value.Class=net.sf.cpsolver.ifs.heuristics.GeneralValueSelection<br>
185 * Value.WeightWeightedConflicts=0.0<br>
186 * Value.RandomWalkProb=0.0<br>
187 * Value.WeightConflicts=1.0<br>
188 * Value.WeightNrAssignments=0.0<br>
189 * Value.WeightValue=0.0<br>
190 * Value.Tabu=0<br>
191 * <br>
192 * #Variable selection heuristics<br>
193 * Variable.Class=net.sf.cpsolver.ifs.heuristics.GeneralVariableSelection<br>
194 * Variable.RandomSelection=true<br>
195 * <br>
196 * #Termination condition<br>
197 * Termination.Class=net.sf.cpsolver.ifs.termination.GeneralTerminationCondition<br>
198 * Termination.MaxIters=-1<br>
199 * Termination.TimeOut=-1<br>
200 * Termination.StopWhenComplete=true<br>
201 * <br>
202 * #Solution comparator<br>
203 * Comparator.Class=net.sf.cpsolver.ifs.solution.GeneralSolutionComparator<br>
204 * </code>
205 * </ul>
206 * <br>
207 * File<b> rpp80.ini</b>
208 * <ul>
209 * <code>
210 * #RPP instances with 200 objects and the placement area filled to 80% in average<br>
211 * General.Input=input\\rpp\\80<br>
212 * Rpp.ProblemWidth=40<br>
213 * Rpp.ProblemHeight=14<br>
214 * #Use 10 problem instances (this means problem files gen1.pl, gen2.pl,... gen10.pl will be taken), each run 10 times<br>
215 * Rpp.Min=1<br>
216 * Rpp.Max=10<br>
217 * Rpp.NrTests=10<br>
218 * </code>
219 * </ul>
220 * <br>
221 * File<b> mpp22.ini</b>
222 * <ul>
223 * <code>
224 * #RPP MPP instance 22 (with 200 objects and the placement area filled to 80% in average)<br>
225 * # files gen22.pl (input problem), gen22.solution (initial solution) and gen22.mpp (input perturbations) are to be taken<br>
226 * General.Input=input\\rpp-mpp\\gen22<br>
227 * Rpp.ProblemWidth=40<br>
228 * Rpp.ProblemHeight=14<br>
229 * # 0, 4, 8, .. 200 input perturbations to be used<br>
230 * Rpp.Min=0<br>
231 * Rpp.Max=200<br>
232 * Rpp.Step=4<br>
233 * </code>
234 * </ul>
235 * <br>
236 * File<b> 5min.ini</b>
237 * <ul>
238 * <code>
239 * #5 minute time limit for each run<br>
240 * Termination.TimeOut=300<br>
241 * </code>
242 * </ul>
243 * <br>
244 * File<b> cbs.ini</b>
245 * <ul>
246 * <code>
247 * #Use conflict-based statistics<br>
248 * Extensions.Classes=net.sf.cpsolver.ifs.extension.ConflictStatistics<br>
249 * Value.WeightWeightedConflicts=1.0<br>
250 * </code>
251 * </ul>
252 * <br>
253 * File<b> tabu20.ini</b>
254 * <ul>
255 * <code>
256 * #Use tabu-list of the length 20<br>
257 * Value.Tabu=20<br>
258 * </code>
259 * </ul>
260 * <br>
261 * File<b> rw1.ini</b>
262 * <ul>
263 * <code>
264 * #Use 1% random walk selection<br>
265 * Value.RandomWalkProb=0.01<br>
266 * </code>
267 * </ul>
268 * <br>
269 *
270 * @see RPPModel
271 * @see net.sf.cpsolver.ifs.extension.ConflictStatistics
272 * @see net.sf.cpsolver.ifs.heuristics.GeneralValueSelection
273 * @see net.sf.cpsolver.ifs.heuristics.GeneralVariableSelection
274 * @see net.sf.cpsolver.ifs.termination.GeneralTerminationCondition
275 * @see net.sf.cpsolver.ifs.solution.GeneralSolutionComparator
276 *
277 * @version IFS 1.2 (Iterative Forward Search)<br>
278 * Copyright (C) 2006 - 2010 Tomas Muller<br>
279 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
280 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
281 * <br>
282 * This library is free software; you can redistribute it and/or modify
283 * it under the terms of the GNU Lesser General Public License as
284 * published by the Free Software Foundation; either version 3 of the
285 * License, or (at your option) any later version. <br>
286 * <br>
287 * This library is distributed in the hope that it will be useful, but
288 * WITHOUT ANY WARRANTY; without even the implied warranty of
289 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
290 * Lesser General Public License for more details. <br>
291 * <br>
292 * You should have received a copy of the GNU Lesser General Public
293 * License along with this library; if not see
294 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
295 */
296 public class Test {
297 private static java.text.DecimalFormat sDoubleFormat = new java.text.DecimalFormat("0.00",
298 new java.text.DecimalFormatSymbols(Locale.US));
299 private static java.text.SimpleDateFormat sDateFormat = new java.text.SimpleDateFormat("dd-MMM-yy_HHmmss",
300 java.util.Locale.US);
301 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(Test.class);
302
303 private static RPPModel loadModel(int mWidth, int mHeight, List<PrologFile.Term> objects,
304 List<PrologFile.Term> assigned, List<PrologFile.Term> perturbations, int perb, int test) {
305 try {
306 sLogger.debug("Loading model " + perb + "." + test + " ...");
307 double startTime = JProf.currentTimeSec();
308 RPPModel m = new RPPModel();
309 ResourceConstraint c = new ResourceConstraint(mWidth, mHeight);
310 m.addConstraint(c);
311 for (PrologFile.Term object : objects.get(0).getContent().get(0).getContent()) {
312 String name = object.elementAt(0).elementAt(0).getText();
313 int width = object.elementAt(1).elementAt(0).elementAt(0).toInt();
314 int height = object.elementAt(1).elementAt(0).elementAt(1).toInt();
315 String xpos = object.elementAt(2).elementAt(0).elementAt(0).getText();
316 String ypos = object.elementAt(2).elementAt(0).elementAt(1).getText();
317 int xmin = Integer.parseInt(xpos.substring(0, xpos.indexOf('-')));
318 int xmax = Integer.parseInt(xpos.substring(xpos.indexOf('-') + 1));
319 int ymin = Integer.parseInt(ypos.substring(0, ypos.indexOf('-')));
320 int ymax = Integer.parseInt(ypos.substring(ypos.indexOf('-') + 1));
321 Rectangle r = new Rectangle(name, width, height, xmin, xmax, ymin, ymax, null);
322 m.addVariable(r);
323 c.addVariable(r);
324 }
325 for (Iterator<PrologFile.Term> i = assigned.get(0).elementAt(0).getContent().iterator(); i.hasNext();) {
326 PrologFile.Term assignment = i.next();
327 String name = assignment.elementAt(0).getText();
328 name = name.substring(0, name.length() - 1);
329 int x = assignment.elementAt(1).elementAt(0).toInt();
330 assignment = i.next();
331 int y = assignment.elementAt(1).elementAt(0).toInt();
332 m.getRectangle(name).setInitialAssignment(new Location(m.getRectangle(name), x, y));
333 }
334 for (PrologFile.Term pert : perturbations) {
335 if (test == pert.elementAt(0).toInt() && perb == pert.elementAt(1).toInt() && perb > 0) {
336 for (PrologFile.Term t : pert.elementAt(2).getContent()) {
337 int rec = t.toInt();
338 m.getRectangle("rect" + rec).setProhibited();
339 }
340 }
341 }
342 sLogger.debug("Loaded in " + sDoubleFormat.format(JProf.currentTimeSec() - startTime) + " sec.");
343 return m;
344 } catch (Exception e) {
345 e.printStackTrace();
346 return null;
347 }
348 }
349
350 private static RPPModel loadModel(int mWidth, int mHeight, List<PrologFile.Term> objects) {
351 try {
352 sLogger.debug("Loading model ...");
353 double startTime = JProf.currentTimeSec();
354 RPPModel m = new RPPModel();
355 ResourceConstraint c = new ResourceConstraint(mWidth, mHeight);
356 m.addConstraint(c);
357 for (PrologFile.Term object : objects.get(0).getContent().get(0).getContent()) {
358 String name = object.elementAt(0).elementAt(0).getText();
359 int width = object.elementAt(1).elementAt(0).elementAt(0).toInt();
360 int height = object.elementAt(1).elementAt(0).elementAt(1).toInt();
361 String xpos = object.elementAt(2).elementAt(0).elementAt(0).getText();
362 String ypos = object.elementAt(2).elementAt(0).elementAt(1).getText();
363 int xmin = Integer.parseInt(xpos.substring(0, xpos.indexOf('-')));
364 int xmax = Integer.parseInt(xpos.substring(xpos.indexOf('-') + 1));
365 int ymin = Integer.parseInt(ypos.substring(0, ypos.indexOf('-')));
366 int ymax = Integer.parseInt(ypos.substring(ypos.indexOf('-') + 1));
367 Rectangle r = new Rectangle(name, width, height, xmin, xmax, ymin, ymax, null);
368 m.addVariable(r);
369 c.addVariable(r);
370 }
371 sLogger.debug("Loaded in " + sDoubleFormat.format(JProf.currentTimeSec() - startTime) + " sec.");
372 return m;
373 } catch (Exception e) {
374 e.printStackTrace();
375 return null;
376 }
377 }
378
379 private static void testMPP(DataProperties properties) {
380 try {
381 FileInputStream fis = new FileInputStream(properties.getProperty("General.Input") + ".pl");
382 List<PrologFile.Term> v1 = PrologFile.readTermsFromStream(fis, "objects");
383 fis.close();
384 fis = new FileInputStream(properties.getProperty("General.Input") + ".solution");
385 List<PrologFile.Term> v2 = PrologFile.readTermsFromStream(fis, "assigned");
386 fis.close();
387 fis = new FileInputStream(properties.getProperty("General.Input") + ".mpp");
388 List<PrologFile.Term> v3 = PrologFile.readTermsFromStream(fis, "perturbation");
389 fis.close();
390
391 PrintWriter res = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator
392 + "result.pl"));
393 PrintWriter stat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator
394 + "stat.pl"));
395 PrintWriter txt = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator
396 + "stat.csv"));
397 txt.println("pert;time[s];timeRMS;assigned;assignedRMS;perturbations;perturbationsRMS;iters;itersRMS");
398 java.text.DecimalFormat nf = new java.text.DecimalFormat("0.000", new java.text.DecimalFormatSymbols(
399 Locale.US));
400 int size = -1; // gen80_22_initial().getRectangles().size();
401 int tests = properties.getPropertyInt("Rpp.NrTests", 10);
402 int step = properties.getPropertyInt("Rpp.Step", 4);
403 int min = properties.getPropertyInt("Rpp.Min", 0);
404 int max = properties.getPropertyInt("Rpp.Max", -1);
405 for (int i = min; size == -1 || i <= (max > 0 ? Math.min(max, size) : size); i += step) {
406 double time = 0;
407 long assigned = 0;
408 long perturbation = 0;
409 long iters = 0;
410 double time2 = 0;
411 long assigned2 = 0;
412 long perturbation2 = 0;
413 long iters2 = 0;
414 for (int t = 1; t <= tests; t++) {
415 RPPModel m = loadModel(properties.getPropertyInt("Rpp.ProblemWidth", 40), properties
416 .getPropertyInt("Rpp.ProblemHeight", 14), v1, v2, v3, i, t);
417 if (size < 0)
418 size = m.variables().size();
419 Solver<Rectangle, Location> s = new Solver<Rectangle, Location>(properties);
420 s.setInitalSolution(m);
421 s.start();
422 s.getSolverThread().join();
423 Solution<Rectangle, Location> best = s.currentSolution();
424 best.restoreBest();
425 res.println("result(" + t + "," + i + "," + nf.format(best.getBestTime()) + ","
426 + (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables()) + ","
427 + best.getBestIteration() + ",");
428 Collection<Rectangle> notPlaced = best.getModel().bestUnassignedVariables();
429 if (notPlaced == null)
430 notPlaced = new ArrayList<Rectangle>();
431 res.print(" unassigned(" + (2 * notPlaced.size()) + "/[");
432 for (Iterator<Rectangle> it = notPlaced.iterator(); it.hasNext();) {
433 Rectangle rect = it.next();
434 res.print(rect.getName() + "X," + rect.getName() + "Y" + (it.hasNext() ? "," : ""));
435 }
436 res.println("]),");
437 StringBuffer sb = new StringBuffer();
438 int perts = 0;
439 for (Rectangle rect : ((RPPModel) best.getModel()).variables()) {
440 if (rect.getBestAssignment() != null
441 && (rect.getInitialAssignment() == null || !rect.getBestAssignment().equals(
442 rect.getInitialAssignment()))) {
443 sb.append(sb.length() == 0 ? "" : ",");
444 sb.append(rect.getName() + "X-" + (rect.getBestAssignment()).getX());
445 sb.append(sb.length() == 0 ? "" : ",");
446 sb.append(rect.getName() + "Y-" + (rect.getBestAssignment()).getY());
447 perts++;
448 }
449 if (rect.getBestAssignment() == null) {
450 perts++;
451 }
452 }
453 res.println(" perturbations(" + (2 * perts) + "/[" + sb + "])");
454 res.println(").");
455 res.flush();
456 iters += best.getBestIteration();
457 iters2 += (best.getBestIteration() * best.getBestIteration());
458 time += best.getBestTime();
459 time2 += (best.getBestTime() * best.getBestTime());
460 assigned += (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables());
461 assigned2 += (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables())
462 * (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables());
463 perturbation += perts;
464 perturbation2 += perts * perts;
465 }
466 txt.println(i + ";" + nf.format(time / tests) + ";" + nf.format(ToolBox.rms(tests, time, time2)) + ";"
467 + nf.format(((double) assigned) / tests) + ";"
468 + nf.format(ToolBox.rms(tests, assigned, assigned2)) + ";"
469 + nf.format(((double) perturbation) / tests) + ";"
470 + nf.format(ToolBox.rms(tests, perturbation, perturbation2)) + ";"
471 + nf.format(((double) iters) / tests) + ";" + nf.format(ToolBox.rms(tests, iters, iters2)));
472 txt.flush();
473 stat.println("averages( initperturbations( " + i + " ), time( " + nf.format(time / tests)
474 + " ), assigned( " + nf.format(((double) assigned) / tests) + " ), perturbations( "
475 + nf.format(((double) perturbation) / tests) + " ) ).");
476 stat.println("deviations( initperturbations( " + i + " ), time( "
477 + nf.format(ToolBox.rms(tests, time, time2)) + " ), assigned( "
478 + nf.format(ToolBox.rms(tests, assigned, assigned2)) + " ), perturbations( "
479 + nf.format(ToolBox.rms(tests, perturbation, perturbation2)) + " ) ).");
480 stat.flush();
481 }
482 res.close();
483 txt.close();
484 stat.close();
485 } catch (Exception e) {
486 e.printStackTrace();
487 }
488 }
489
490 private static void test(DataProperties properties) {
491 try {
492 int tests = properties.getPropertyInt("Rpp.NrTests", 10);
493 int min = properties.getPropertyInt("Rpp.Min", 0);
494 int max = properties.getPropertyInt("Rpp.Max", -1);
495 PrintWriter res = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator
496 + "result.pl"));
497 PrintWriter stat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator
498 + "stat.pl"));
499 PrintWriter txt = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator
500 + "stat.csv"));
501 txt.println("gen;time[s];timeRMS;assigned;assignedRMS;iters;itersRMS");
502 java.text.DecimalFormat nf = new java.text.DecimalFormat("0.000", new java.text.DecimalFormatSymbols(
503 Locale.US));
504 for (int genNr = min; genNr <= max; genNr++) {
505 FileInputStream fis = new FileInputStream(properties.getProperty("General.Input") + File.separator
506 + "gen" + genNr + ".pl");
507 List<PrologFile.Term> v1 = PrologFile.readTermsFromStream(fis, "objects");
508 fis.close();
509 double time = 0;
510 long assigned = 0;
511 long iters = 0;
512 double time2 = 0;
513 long assigned2 = 0;
514 long iters2 = 0;
515 for (int t = 1; t <= tests; t++) {
516 RPPModel m = loadModel(properties.getPropertyInt("Rpp.ProblemWidth", 40), properties
517 .getPropertyInt("Rpp.ProblemHeight", 14), v1);
518 Solver<Rectangle, Location> s = new Solver<Rectangle, Location>(properties);
519 s.setInitalSolution(m);
520 s.start();
521 s.getSolverThread().join();
522 Solution<Rectangle, Location> best = s.currentSolution();
523 best.restoreBest();
524 iters += best.getBestIteration();
525 iters2 += (best.getBestIteration() * best.getBestIteration());
526 time += best.getBestTime();
527 time2 += (best.getBestTime() * best.getBestTime());
528 assigned += (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables());
529 assigned2 += (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables())
530 * (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables());
531 res.println("result(" + genNr + "," + t + "," + nf.format(best.getBestTime()) + ","
532 + (best.getModel().variables().size() - best.getModel().getBestUnassignedVariables()) + ","
533 + best.getBestIteration() + ",");
534 Collection<Rectangle> notPlaced = best.getModel().bestUnassignedVariables();
535 if (notPlaced == null)
536 notPlaced = new ArrayList<Rectangle>();
537 res.print(" unassigned(" + (2 * notPlaced.size()) + "/[");
538 for (Iterator<Rectangle> it = notPlaced.iterator(); it.hasNext();) {
539 Rectangle rect = it.next();
540 res.print(rect.getName() + "X," + rect.getName() + "Y" + (it.hasNext() ? "," : ""));
541 }
542 res.println("]),");
543 int perts = 0;
544 StringBuffer sb = new StringBuffer();
545 for (Rectangle rect : ((RPPModel) best.getModel()).variables()) {
546 if (rect.getBestAssignment() != null) {
547 sb.append(sb.length() == 0 ? "" : ",");
548 sb.append(rect.getName() + "X-" + (rect.getBestAssignment()).getX());
549 sb.append(sb.length() == 0 ? "" : ",");
550 sb.append(rect.getName() + "Y-" + (rect.getBestAssignment()).getY());
551 perts++;
552 }
553 }
554 res.println(" assigned(" + (2 * perts) + "/[" + sb + "])");
555 res.println(").");
556 res.flush();
557 }
558 txt.println(genNr + ";" + nf.format(time / tests) + ";" + nf.format(ToolBox.rms(tests, time, time2))
559 + ";" + nf.format(((double) assigned) / tests) + ";"
560 + nf.format(ToolBox.rms(tests, assigned, assigned2)) + ";"
561 + nf.format(((double) iters) / tests) + ";" + nf.format(ToolBox.rms(tests, iters, iters2)));
562 txt.flush();
563 stat.println("averages( problem( " + genNr + " ), time( " + nf.format(time / tests) + " ), assigned( "
564 + nf.format(((double) assigned) / tests) + " ) ).");
565 stat.println("deviations( problem( " + genNr + " ), time( "
566 + nf.format(ToolBox.rms(tests, time, time2)) + " ), assigned( "
567 + nf.format(ToolBox.rms(tests, assigned, assigned2)) + " ) ).");
568 stat.flush();
569 }
570 res.close();
571 txt.close();
572 stat.close();
573 } catch (Exception e) {
574 e.printStackTrace();
575 }
576 }
577
578 private static void test(File inputCfg, String name, String include, String regexp, String outDir) throws Exception {
579 if (regexp != null) {
580 String incFile;
581 if (regexp.indexOf(';') > 0) {
582 incFile = regexp.substring(0, regexp.indexOf(';'));
583 regexp = regexp.substring(regexp.indexOf(';') + 1);
584 } else {
585 incFile = regexp;
586 regexp = null;
587 }
588 if (incFile.startsWith("[") && incFile.endsWith("]")) {
589 test(inputCfg, name, include, regexp, outDir);
590 incFile = incFile.substring(1, incFile.length() - 1);
591 }
592 if (incFile.indexOf('{') >= 0 && incFile.indexOf('}') >= 0) {
593 String prefix = incFile.substring(0, incFile.indexOf('{'));
594 StringTokenizer middle = new StringTokenizer(incFile.substring(incFile.indexOf('{') + 1, incFile
595 .indexOf('}')), "|");
596 String sufix = incFile.substring(incFile.indexOf('}') + 1);
597 while (middle.hasMoreTokens()) {
598 String m = middle.nextToken();
599 test(inputCfg, (name == null ? "" : name + "_") + m, (include == null ? "" : include + ";")
600 + prefix + m + sufix, regexp, outDir);
601 }
602 } else {
603 test(inputCfg, name, (include == null ? "" : include + ";") + incFile, regexp, outDir);
604 }
605 } else {
606 DataProperties properties = ToolBox.loadProperties(inputCfg);
607 StringTokenizer inc = new StringTokenizer(include, ";");
608 while (inc.hasMoreTokens()) {
609 String aFile = inc.nextToken();
610 System.out.println(" Loading included file '" + aFile + "' ... ");
611 FileInputStream is = null;
612 if ((new File(aFile)).exists())
613 is = new FileInputStream(aFile);
614 if ((new File(inputCfg.getParent() + File.separator + aFile)).exists())
615 is = new FileInputStream(inputCfg.getParent() + File.separator + aFile);
616 if (is == null)
617 System.err.println("Unable to find include file '" + aFile + "'.");
618 properties.load(is);
619 is.close();
620 }
621 String outDirTisTest = (outDir == null ? properties.getProperty("General.Output", ".") : outDir)
622 + File.separator + name + File.separator + sDateFormat.format(new Date());
623 properties.setProperty("General.Output", outDirTisTest.toString());
624 System.out.println("Output folder: " + properties.getProperty("General.Output"));
625 (new File(outDirTisTest)).mkdirs();
626 ToolBox.configureLogging(outDirTisTest, null);
627 FileOutputStream fos = new FileOutputStream(outDirTisTest + File.separator + "rcsp.conf");
628 properties.store(fos, "Random CSP problem configuration file");
629 fos.flush();
630 fos.close();
631 boolean mpp = properties.getPropertyBoolean("General.MPP", true);
632 if (mpp)
633 testMPP(properties);
634 else
635 test(properties);
636 }
637 }
638
639 /**
640 * RPP test.
641 *
642 * @param args
643 * the command line arguments
644 */
645 public static void main(String[] args) {
646 try {
647 Progress.getInstance().addProgressListener(new ProgressWriter(System.out));
648
649 File inputCfg = new File(args[0]);
650 DataProperties properties = ToolBox.loadProperties(inputCfg);
651 if (properties.getProperty("INCLUDE_REGEXP") != null) {
652 if (args.length > 1)
653 properties.setProperty("General.Output", args[1]);
654 test(inputCfg, null, null, properties.getProperty("INCLUDE_REGEXP"), (args.length > 1 ? args[1] : null));
655 } else {
656 String outDir = properties.getProperty("General.Output", ".") + File.separator
657 + inputCfg.getName().substring(0, inputCfg.getName().lastIndexOf('.')) + File.separator
658 + sDateFormat.format(new Date());
659 if (args.length > 1)
660 outDir = args[1] + File.separator + (sDateFormat.format(new Date()));
661 (new File(outDir)).mkdirs();
662 properties.setProperty("General.Output", outDir.toString());
663 System.out.println("Output folder: " + properties.getProperty("General.Output"));
664 ToolBox.configureLogging(outDir, null);
665 boolean mpp = properties.getPropertyBoolean("General.MPP", false);
666 if (mpp)
667 testMPP(properties);
668 else
669 test(properties);
670 }
671
672 } catch (Exception e) {
673 e.printStackTrace();
674 }
675 }
676 }