001package org.cpsolver.ifs.example.rpp; 002 003import java.io.File; 004import java.io.FileInputStream; 005import java.io.FileOutputStream; 006import java.io.FileWriter; 007import java.io.PrintWriter; 008import java.util.ArrayList; 009import java.util.Collection; 010import java.util.Date; 011import java.util.Iterator; 012import java.util.List; 013import java.util.Locale; 014import java.util.StringTokenizer; 015 016import org.cpsolver.ifs.solution.Solution; 017import org.cpsolver.ifs.solver.Solver; 018import org.cpsolver.ifs.util.DataProperties; 019import org.cpsolver.ifs.util.JProf; 020import org.cpsolver.ifs.util.Progress; 021import org.cpsolver.ifs.util.ProgressWriter; 022import org.cpsolver.ifs.util.PrologFile; 023import org.cpsolver.ifs.util.ToolBox; 024 025 026/** 027 * RPP test. It takes one argument -- property file with all the parameters. It 028 * allows to execute given number of tests. The problem is loaded from 029 * prolog-based text files. For description of RPP problem see {@link RPPModel}. <br> 030 * <br> 031 * 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>. 032 * Each input problem (e.g., gen22.pl) has the following structure: 033 * <pre> 034 * <code> 035 * objects([ 036 * object( 037 * name( rect1 ), 038 * size( [ 2, 1 ] ), 039 * valid_positions( [ 0-38, 0-13 ] ) 040 * ), 041 * object( 042 * name( rect2 ), 043 * size( [ 2, 1 ] ), 044 * valid_positions( [ 0-38, 0-13 ] ) 045 * ), 046 * ... 047 * object( 048 * name( rect200 ), 049 * size( [ 2, 1 ] ), 050 * valid_positions( [ 0-38, 7-13 ] ) 051 * ) 052 * ] ). 053 * </code> 054 * </pre> 055 * Stating that the first rectangle (named rect1) has size 2x1 and its valid 056 * position are with x between 0 and 38, y between 0 and 13, and so on. <br> 057 * MPP instances contain an extra file with the solution (e.g., gen22.solution), 058 * with the following structure 059 * <pre> 060 * <code> 061 * assigned([[rect1X,[17]], [rect1Y,[5]], [rect2X,[24]], [rect2Y,[4]], ... [rect200X,[37]], [rect200Y,[10]]]). 062 * </code> 063 * </pre> 064 * Which means that the first rectangle (named rect1) is to be placed at [17,5], 065 * second at [24,4] and so on. <br> 066 * There is also a file (e.g., gen22.mpp) describing which input placements are 067 * to be prohibited (not that if the input placement is prohibited, it means 068 * that also all values with the same X or Y coordinate are prohibited). It has 069 * the following structure: 070 * <pre> 071 * <code> 072 * perturbation( 1, 0, [] ). 073 * perturbation( 2, 0, [] ). 074 * ... 075 * perturbation( 1, 2, [44,127] ). 076 * perturbation( 2, 2, [80,153] ). 077 * ... 078 * perturbation( 1, 4, [44,80,127,153] ). 079 * perturbation( 2, 4, [48,67,138,170] ). 080 * ... 081 * </code> 082 * </pre> 083 * Stating that for instance in the first test with 4 perturbations the 084 * rectangles rect44, rect80, rect127 and rect153 will have their initial value 085 * prohibited. <br> 086 * <br> 087 * Test's parameters: <br> 088 * <table border='1'><caption>Related Solver Parameters</caption> 089 * <tr> 090 * <th>Parameter</th> 091 * <th>Type</th> 092 * <th>Comment</th> 093 * </tr> 094 * <tr> 095 * <td>General.MPP</td> 096 * <td>{@link String}</td> 097 * <td>Minimal perturbation problem (if true), this mj. means that initial 098 * assignment will be generated</td> 099 * </tr> 100 * <tr> 101 * <td>RPP.NrTests</td> 102 * <td>{@link Integer}</td> 103 * <td>Number of tests to be executed for each input instance</td> 104 * </tr> 105 * <tr> 106 * <td>Rpp.Min<br> 107 * Rpp.Max<br> 108 * Rpp.Step</td> 109 * <td>{@link Integer}</td> 110 * <td>In case of MPP: minimal, maximal number and increment of input 111 * perturbations. An instance is loaded and tested for each given number of 112 * input perturbations.</td> 113 * </tr> 114 * <tr> 115 * <td>Rpp.Min<br> 116 * Rpp.Max</td> 117 * <td>{@link Integer}</td> 118 * <td>In case of initial problem: minimal and maximal number of the input 119 * problem. An instance is loaded and tested for each given number from RPP.Min 120 * to RPP.Max.</td> 121 * </tr> 122 * <tr> 123 * <td>Rpp.ProblemWidth<br> 124 * Rpp.ProblemHeight</td> 125 * <td>{@link Integer}</td> 126 * <td>Width and height of the placement area.</td> 127 * </tr> 128 * <tr> 129 * <td>General.Output</td> 130 * <td>{@link String}</td> 131 * <td>Output folder where a log file and tables with results. In order not to 132 * overwrite the results if executed more than once, a subfolder with the name 133 * taken from current date and time will be created in this folder and all 134 * results will go to this subfolder.</td> 135 * </tr> 136 * </table> 137 * <br> 138 * <br> 139 * Also, the configuration file can consist only from one parameter (named 140 * INCLUDE_REGEXP) which is processed as a regular expression of semicolon 141 * separated list of property files, for instance 142 * <pre> 143 * <code>INCLUDE_REGEXP=general.ini;{rpp85|rpp90|rpp95|mpp22}.ini;{5min}.ini;{cbs|rw1|tabu20}.ini</code> 144 * </pre> 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 * <pre> 168 * ${General.Output}\rpp85_5min_csb\25-Feb-05_191136 169 * </pre> 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 * <pre> 177 * <code> 178 * #Default settings common for all configurations 179 * General.MPP=false 180 * General.InitialAssignment=false 181 * General.Output=output\\RPP\\IFS 182 * 183 * #Value selection heuristics 184 * Value.Class=org.cpsolver.ifs.heuristics.GeneralValueSelection 185 * Value.WeightWeightedConflicts=0.0 186 * Value.RandomWalkProb=0.0 187 * Value.WeightConflicts=1.0 188 * Value.WeightNrAssignments=0.0 189 * Value.WeightValue=0.0 190 * Value.Tabu=0 191 * 192 * #Variable selection heuristics 193 * Variable.Class=org.cpsolver.ifs.heuristics.GeneralVariableSelection 194 * Variable.RandomSelection=true 195 * 196 * #Termination condition 197 * Termination.Class=org.cpsolver.ifs.termination.GeneralTerminationCondition 198 * Termination.MaxIters=-1 199 * Termination.TimeOut=-1 200 * Termination.StopWhenComplete=true 201 * 202 * #Solution comparator 203 * Comparator.Class=org.cpsolver.ifs.solution.GeneralSolutionComparator 204 * </code> 205 * </pre> 206 * 207 * File<b> rpp80.ini</b> 208 * <pre> 209 * <code> 210 * #RPP instances with 200 objects and the placement area filled to 80% in average 211 * General.Input=input\\rpp\\80 212 * Rpp.ProblemWidth=40 213 * Rpp.ProblemHeight=14 214 * #Use 10 problem instances (this means problem files gen1.pl, gen2.pl,... gen10.pl will be taken), each run 10 times 215 * Rpp.Min=1 216 * Rpp.Max=10 217 * Rpp.NrTests=10 218 * </code> 219 * </pre> 220 * 221 * File<b> mpp22.ini</b> 222 * <pre> 223 * <code> 224 * #RPP MPP instance 22 (with 200 objects and the placement area filled to 80% in average) 225 * # files gen22.pl (input problem), gen22.solution (initial solution) and gen22.mpp (input perturbations) are to be taken 226 * General.Input=input\\rpp-mpp\\gen22 227 * Rpp.ProblemWidth=40 228 * Rpp.ProblemHeight=14 229 * # 0, 4, 8, .. 200 input perturbations to be used 230 * Rpp.Min=0 231 * Rpp.Max=200 232 * Rpp.Step=4 233 * </code> 234 * </pre> 235 * 236 * File<b> 5min.ini</b> 237 * <pre> 238 * <code> 239 * #5 minute time limit for each run 240 * Termination.TimeOut=300 241 * </code> 242 * </pre> 243 * 244 * File<b> cbs.ini</b> 245 * <pre> 246 * <code> 247 * #Use conflict-based statistics 248 * Extensions.Classes=org.cpsolver.ifs.extension.ConflictStatistics 249 * Value.WeightWeightedConflicts=1.0 250 * </code> 251 * </pre> 252 * 253 * File<b> tabu20.ini</b> 254 * <pre> 255 * <code> 256 * #Use tabu-list of the length 20 257 * Value.Tabu=20 258 * </code> 259 * </pre> 260 * 261 * File<b> rw1.ini</b> 262 * <pre> 263 * <code> 264 * #Use 1% random walk selection 265 * Value.RandomWalkProb=0.01 266 * </code> 267 * </pre> 268 * 269 * @see RPPModel 270 * @see org.cpsolver.ifs.extension.ConflictStatistics 271 * @see org.cpsolver.ifs.heuristics.GeneralValueSelection 272 * @see org.cpsolver.ifs.heuristics.GeneralVariableSelection 273 * @see org.cpsolver.ifs.termination.GeneralTerminationCondition 274 * @see org.cpsolver.ifs.solution.GeneralSolutionComparator 275 * 276 * @author Tomáš Müller 277 * @version IFS 1.3 (Iterative Forward Search)<br> 278 * Copyright (C) 2006 - 2014 Tomáš Müller<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 */ 296public 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.logging.log4j.Logger sLogger = org.apache.logging.log4j.LogManager.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(best.getAssignment()); 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(best.getAssignment()); 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}