001package net.sf.cpsolver.ifs.example.csp; 002 003import java.io.File; 004import java.io.FileInputStream; 005import java.io.FileOutputStream; 006import java.io.FileWriter; 007import java.io.PrintWriter; 008import java.util.Date; 009import java.util.Iterator; 010import java.util.Locale; 011import java.util.StringTokenizer; 012 013import net.sf.cpsolver.ifs.model.Constraint; 014import net.sf.cpsolver.ifs.solution.Solution; 015import net.sf.cpsolver.ifs.solver.Solver; 016import net.sf.cpsolver.ifs.util.DataProperties; 017import net.sf.cpsolver.ifs.util.Progress; 018import net.sf.cpsolver.ifs.util.ProgressWriter; 019import net.sf.cpsolver.ifs.util.ToolBox; 020 021/** 022 * Test of Structured CSP problems. It takes one argument -- property file with 023 * all the parameters. It allows to execute given number of tests. It also 024 * allows to define several configurations which will be executed. For instance 025 * CSP(20,15,5%..95%,5..95%), 10 runs of each configuration. All such 026 * configuration are processed in one run of Test class. <br> 027 * <br> 028 * In Structured CSP, variables are divided into several kernels (some variables 029 * may remain ouside kernels). Different constraints (in density and tightnes) 030 * are generated according to whether variables are from the same kernel or not. <br> 031 * <br> 032 * Test's parameters: <br> 033 * <table border='1'> 034 * <tr> 035 * <th>Parameter</th> 036 * <th>Type</th> 037 * <th>Comment</th> 038 * </tr> 039 * <tr> 040 * <td>General.MPP</td> 041 * <td>{@link String}</td> 042 * <td>Minimal perturbation problem (if true), this mj. means that initial 043 * assignment will be generated</td> 044 * </tr> 045 * <tr> 046 * <td>CSP.Seed</td> 047 * <td>{@link Long}</td> 048 * <td>Random number generator seed, {@link System#currentTimeMillis()} is taken 049 * if not present</td> 050 * </tr> 051 * <tr> 052 * <td>CSP.ForceSolutionExistance</td> 053 * <td>{@link Boolean}</td> 054 * <td>If true, generated problem will always have at least one feasible 055 * solution</td> 056 * </tr> 057 * <tr> 058 * <td>CPS.NrTests</td> 059 * <td>{@link Integer}</td> 060 * <td>Number of tests (for each input configuration)</td> 061 * </tr> 062 * <tr> 063 * <td>CSP.NrVariables</td> 064 * <td>{@link Integer}</td> 065 * <td>Number of variables</td> 066 * </tr> 067 * <tr> 068 * <td>CSP.NrVariablesMin<br> 069 * CSP.NrVariablesMax<br> 070 * CSP.NrVariablesStep</td> 071 * <td>{@link Integer}</td> 072 * <td>Range of the number variables (a set of different configurations will be 073 * generated)<br> 074 * Use either CSP.NrVariables or these CSP.NrVariablesMin, CSP.NrVariablesMax, 075 * CSP.NrVariablesStep</td> 076 * </tr> 077 * <tr> 078 * <td>CSP.DomainSize</td> 079 * <td>{@link Integer}</td> 080 * <td>Number of values of every variable</td> 081 * </tr> 082 * <tr> 083 * <td>CSP.DomainSizeRatio</td> 084 * <td>{@link Double}</td> 085 * <td>Number of values as a ration of the number of variables. This way we can 086 * model for instance CSP(N,2N,p1,p2) problems with one configuration.<br> 087 * Use either CSP.DomainSize or CSP.DomainSizeRatio</td> 088 * </tr> 089 * <tr> 090 * <td>CSP.Tightness</td> 091 * <td>{@link Double}</td> 092 * <td>Tightness of constraints outside kernels</td> 093 * </tr> 094 * <tr> 095 * <td>CSP.TightnessMin<br> 096 * CSP.TightnessMax<br> 097 * CSP.TightnessStep</td> 098 * <td>{@link Double}</td> 099 * <td>Tightness of constraints outside kernels given as a range -> respective 100 * configurations will be generated and tested</td> 101 * </tr> 102 * <tr> 103 * <td>CSP.Density</td> 104 * <td>{@link Double}</td> 105 * <td>Density of constraints outside kernels</td> 106 * </tr> 107 * <tr> 108 * <td>CSP.DensityMin<br> 109 * CSP.DensityMax<br> 110 * CSP.DensityStep</td> 111 * <td>{@link Double}</td> 112 * <td>Density of constraints outside kernels given as a range -> respective 113 * configurations will be generated and tested</td> 114 * </tr> 115 * <tr> 116 * <td>CSP.NrKernels</td> 117 * <td>{@link Integer}</td> 118 * <td>Number of kernels (Structured CSP, use 0 for "normal" CSP)</td> 119 * </tr> 120 * <tr> 121 * <td>CSP.KernelSize</td> 122 * <td>{@link Integer}</td> 123 * <td>Number of variables in each kernel</td> 124 * </tr> 125 * <tr> 126 * <td>CSP.KernelTightness</td> 127 * <td>{@link Double}</td> 128 * <td>Tightness of constraints inside a kernel</td> 129 * </tr> 130 * <tr> 131 * <td>CSP.KernelDensity</td> 132 * <td>{@link Double}</td> 133 * <td>Density of constraints inside a kernel</td> 134 * </tr> 135 * <tr> 136 * <td>CSP.SameProblemEachStep</td> 137 * <td>{@link Boolean}</td> 138 * <td>If true, each configuration will start with the same seed</td> 139 * </tr> 140 * <tr> 141 * <td>CSP.SameProblemEachTest</td> 142 * <td>{@link Boolean}</td> 143 * <td>If true, each test of the same configuration will start with the same 144 * seed</td> 145 * </tr> 146 * <tr> 147 * <td>General.Output</td> 148 * <td>{@link String}</td> 149 * <td>Output folder where a log file and tables with results. In order not to 150 * overwrite the results if executed more than once, a subfolder with the name 151 * taken from current date and time will be created in this folder and all 152 * results will go to this subfolder.</td> 153 * </tr> 154 * </table> 155 * <br> 156 * <br> 157 * Also, the configuration file can consist only from one parameter (named 158 * INCLUDE_REGEXP) which is processed as a regular expression of semicolon 159 * separated list of property files, for instance 160 * <ul> 161 * <code>INCLUDE_REGEXP=general.ini;{CSP(50,12,250,p2)|CSP(25,15,198,p2)}.ini;{std|opt}.ini;{10x1min}.ini;{cbs|rw1|tabu20}.ini</code> 162 * <br> 163 * </ul> 164 * where {a|b|c|...} means a selection of a, b, c, .. All possible combinations 165 * are taken and for each of them an input configuration is combined from the 166 * relevant files. So, for instance, the above example will result into the 167 * following configurations: 168 * <ul> 169 * <li>general.ini;CSP(50,12,250,p2).ini;std.ini;10x1min.ini;cbs.ini 170 * <li>general.ini;CSP(50,12,250,p2).ini;std.ini;10x1min.ini;rw1.ini 171 * <li>general.ini;CSP(50,12,250,p2).ini;std.ini;10x1min.ini;tabu20.ini 172 * <li>general.ini;CSP(50,12,250,p2).ini;opt.ini;10x1min.ini;cbs.ini 173 * <li>general.ini;CSP(50,12,250,p2).ini;opt.ini;10x1min.ini;rw1.ini 174 * <li>general.ini;CSP(50,12,250,p2).ini;opt.ini;10x1min.ini;tabu20.ini 175 * <li>general.ini;CSP(25,15,198,p2).ini;std.ini;10x1min.ini;cbs.ini 176 * <li>general.ini;CSP(25,15,198,p2).ini;std.ini;10x1min.ini;rw1.ini 177 * <li>general.ini;CSP(25,15,198,p2).ini;std.ini;10x1min.ini;tabu20.ini 178 * <li>general.ini;CSP(25,15,198,p2).ini;opt.ini;10x1min.ini;cbs.ini 179 * <li>general.ini;CSP(25,15,198,p2).ini;opt.ini;10x1min.ini;rw1.ini 180 * <li>general.ini;CSP(25,15,198,p2).ini;opt.ini;10x1min.ini;tabu20.ini 181 * </ul> 182 * To be able to distinguish such configuration a subfolder in General.Output 183 * folder is created, its name is combined from the names which are in 184 * parenthesis. So, for instance the first bunch of tests will output into the 185 * folder: 186 * <ul> 187 * ${General.Output}\CSP(50,12,250,p2)_std_10x1min_csb\25-Feb-05_191136 188 * </ul> 189 * If one parameter is defined in more than one configuration files (e.g. in 190 * general.ini as well as cbs.ini) the one from the file more on the right is 191 * taken. <br> 192 * <br> 193 * An example of the configurations:<br> 194 * File<b> general.ini</b> 195 * <ul> 196 * <code> 197 * #Default settings common for all configurations<br> 198 * General.MPP=false<br> 199 * General.InitialAssignment=false<br> 200 * General.Output=output\\RandomCSP\\IFS<br> 201 * <br> 202 * #Value selection heuristics<br> 203 * Value.Class=net.sf.cpsolver.ifs.heuristics.GeneralValueSelection<br> 204 * Value.WeightWeightedConflicts=0.0<br> 205 * Value.RandomWalkProb=0.0<br> 206 * Value.WeightConflicts=1.0<br> 207 * Value.WeightNrAssignments=0.0<br> 208 * Value.WeightValue=0.0<br> 209 * Value.Tabu=0<br> 210 * <br> 211 * #Variable selection heuristics<br> 212 * Variable.Class=net.sf.cpsolver.ifs.heuristics.GeneralVariableSelection<br> 213 * Variable.RandomSelection=true<br> 214 * <br> 215 * #Termination condition<br> 216 * Termination.Class=net.sf.cpsolver.ifs.termination.GeneralTerminationCondition<br> 217 * Termination.MaxIters=-1<br> 218 * Termination.TimeOut=-1<br> 219 * Termination.StopWhenComplete=true<br> 220 * <br> 221 * #Solution comparator<br> 222 * Comparator.Class=net.sf.cpsolver.ifs.solution.GeneralSolutionComparator<br> 223 * </code> 224 * </ul> 225 * <br> 226 * File<b> CSP(50,12,250,p2).ini</b> 227 * <ul> 228 * <code> 229 * #Sparse problem CSP(50,12,250/1225,p2)<br> 230 * CSP.NrVariables=50<br> 231 * CSP.DomainSize=12<br> 232 * CSP.Density=0.2<br> 233 * CSP.TightnessMin=0.10<br> 234 * CSP.TightnessMax=0.95<br> 235 * CSP.TightnessStep=0.02<br> 236 * <br> 237 * CSP.Seed=780921<br> 238 * <br> 239 * CSP.ForceSolutionExistance=false<br> 240 * CSP.SameProblemEachStep=false<br> 241 * CSP.SameProblemEachTest=false<br> 242 * <br> 243 * CSP.NrKernels=0<br> 244 * </code> 245 * </ul> 246 * <br> 247 * File<b> std.ini</b> 248 * <ul> 249 * <code> 250 * #Standard problem<br> 251 * CSP.ForceSolutionExistance=false<br> 252 * </code> 253 * </ul> 254 * <br> 255 * File<b> opt.ini</b> 256 * <ul> 257 * <code> 258 * #Optimization problem (minCSP)<br> 259 * #Value selection: use weigh of a conflict, but when there are more than one value<br> 260 * # with the same number of conflicts, use the one with lower value<br> 261 * Value.WeightValue=0.0001<br> 262 * Value.WeightConflicts=1.0<br> 263 * #Do not stop when a complete solution is found<br> 264 * Termination.StopWhenComplete=false<br> 265 * </code> 266 * </ul> 267 * <br> 268 * File<b> 10x1min.ini</b> 269 * <ul> 270 * <code> 271 * #For each configuration, execute 10 tests, each with 1 minute timeout<br> 272 * CPS.NrTests=10<br> 273 * Termination.TimeOut=60<br> 274 * </code> 275 * </ul> 276 * <br> 277 * File<b> cbs.ini</b> 278 * <ul> 279 * <code> 280 * #Use conflict-based statistics<br> 281 * Extensions.Classes=net.sf.cpsolver.ifs.extension.ConflictStatistics<br> 282 * Value.WeightWeightedConflicts=1.0<br> 283 * </code> 284 * </ul> 285 * <br> 286 * File<b> tabu20.ini</b> 287 * <ul> 288 * <code> 289 * #Use tabu-list of the length 20<br> 290 * Value.Tabu=20<br> 291 * </code> 292 * </ul> 293 * <br> 294 * File<b> rw1.ini</b> 295 * <ul> 296 * <code> 297 * #Use 1% random walk selection<br> 298 * Value.RandomWalkProb=0.01<br> 299 * </code> 300 * </ul> 301 * <br> 302 * 303 * @see StructuredCSPModel 304 * @see net.sf.cpsolver.ifs.extension.ConflictStatistics 305 * @see net.sf.cpsolver.ifs.heuristics.GeneralValueSelection 306 * @see net.sf.cpsolver.ifs.heuristics.GeneralVariableSelection 307 * @see net.sf.cpsolver.ifs.termination.GeneralTerminationCondition 308 * @see net.sf.cpsolver.ifs.solution.GeneralSolutionComparator 309 * 310 * @version IFS 1.2 (Iterative Forward Search)<br> 311 * Copyright (C) 2006 - 2010 Tomáš Müller<br> 312 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 313 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 314 * <br> 315 * This library is free software; you can redistribute it and/or modify 316 * it under the terms of the GNU Lesser General Public License as 317 * published by the Free Software Foundation; either version 3 of the 318 * License, or (at your option) any later version. <br> 319 * <br> 320 * This library is distributed in the hope that it will be useful, but 321 * WITHOUT ANY WARRANTY; without even the implied warranty of 322 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 323 * Lesser General Public License for more details. <br> 324 * <br> 325 * You should have received a copy of the GNU Lesser General Public 326 * License along with this library; if not see 327 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 328 */ 329public class Test { 330 private static java.text.DecimalFormat sDoubleFormat = new java.text.DecimalFormat("0.000", 331 new java.text.DecimalFormatSymbols(Locale.US)); 332 private static java.text.SimpleDateFormat sDateFormat = new java.text.SimpleDateFormat("dd-MMM-yy_HHmmss", 333 java.util.Locale.US); 334 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(Test.class); 335 336 private static void test(DataProperties properties) throws Exception { 337 boolean sameProblemStep = properties.getPropertyBoolean("CSP.SameProblemEachStep", false); 338 boolean sameProblemTest = properties.getPropertyBoolean("CSP.SameProblemEachTest", false); 339 int nrVars = properties.getPropertyInt("CSP.NrVariables", 20); 340 int nrKernels = properties.getPropertyInt("CSP.NrKernels", 2); 341 int nrKernelVariables = properties.getPropertyInt("CSP.KernelSize", 8); 342 int nrVariablesMin = properties.getPropertyInt("CSP.NrVariablesMin", nrVars); 343 int nrVariablesMax = properties.getPropertyInt("CSP.NrVariablesMax", nrVars); 344 int nrVariablesStep = properties.getPropertyInt("CSP.NrVariablesStep", 1); 345 int nrValues = properties.getPropertyInt("CSP.DomainSize", 10); 346 double nrValuesRatio = properties.getPropertyDouble("CSP.DomainSizeRatio", -1); 347 float kernelTightness = properties.getPropertyFloat("CSP.KernelTightness", 0.097f); 348 float kernelDensity = properties.getPropertyFloat("CSP.KernelDensity", 0.097f); 349 float tightnessInit = properties.getPropertyFloat("CSP.Tightness", 0.4f); 350 float tightnessMin = properties.getPropertyFloat("CSP.TightnessMin", tightnessInit); 351 float tightnessMax = properties.getPropertyFloat("CSP.TightnessMax", tightnessInit) + 1e-6f; 352 float tightnessStep = properties.getPropertyFloat("CSP.TightnessStep", 0.1f); 353 float densityInit = properties.getPropertyFloat("CSP.Density", 0.4f); 354 float densityMin = properties.getPropertyFloat("CSP.DensityMin", densityInit); 355 float densityMax = properties.getPropertyFloat("CSP.DensityMax", densityInit) + 1e-6f; 356 float densityStep = properties.getPropertyFloat("CSP.DensityStep", 0.1f); 357 long seed = properties.getPropertyLong("CSP.Seed", System.currentTimeMillis()); 358 int nrTests = properties.getPropertyInt("CPS.NrTests", 10); 359 boolean mpp = properties.getPropertyBoolean("General.MPP", false); 360 PrintWriter logStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator 361 + "rcsp_" + nrVariablesMin + "_" + nrValues + ".csv")); 362 PrintWriter logAvgStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") 363 + File.separator + "avg_stat.csv")); 364 PrintWriter log = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator 365 + "info.txt")); 366 logStat 367 .println("testNr;nrVars;nrVals;density[%];tightness[%];time[s];iters;speed[it/s];unassConstr;assigned;assigned[%]" 368 + (mpp ? ";perts;perts[%]" : "") + ";value;totalValue"); 369 logAvgStat 370 .println("nrVars;nrVals;density[%];tightness[%];time[s];RMStime[s];iters;RMSiters;speed[it/s];unassConst;assigned;RMSassigned;assigned[%]" 371 + (mpp ? ";perts;RMSperts;perts[%]" : "") + ";value;RMSvalue;totalValue;RMStotalValue"); 372 System.out.println("Number of variables: " + nrVariablesMin + " .. " + nrVariablesMax + " (step=" 373 + nrVariablesStep + ")"); 374 System.out.println("Density: " + densityMin + " .. " + densityMax + " (step=" + densityStep + ")"); 375 System.out.println("Tightness: " + tightnessMin + " .. " + tightnessMax + " (step=" + tightnessStep 376 + ")"); 377 for (int nrVariables = nrVariablesMin; nrVariables <= nrVariablesMax; nrVariables += nrVariablesStep) { 378 if (nrValuesRatio > 0.0) 379 nrValues = (int) Math.round(nrValuesRatio * nrVariables); 380 for (float density = densityMin; density <= densityMax; density += densityStep) { 381 for (float tightness = tightnessMin; tightness <= tightnessMax; tightness += tightnessStep) { 382 log.println("CSP{#Var=" + nrVariables + ", #Val=" + nrValues + ", P(density)=" 383 + sDoubleFormat.format(100.0 * density) + "%, P(tighness)=" 384 + sDoubleFormat.format(100.0 * tightness) + ", " + nrKernels + "x Kernel{#Var=" 385 + nrKernelVariables + ", P(density)=" + sDoubleFormat.format(100.0 * kernelDensity) 386 + "%, P(tighness)=" + sDoubleFormat.format(100.0 * kernelTightness) + "%}}"); 387 double sumTime = 0; 388 double sumTime2 = 0; 389 int sumIters = 0; 390 int sumIters2 = 0; 391 int sumConfl = 0; 392 int sumAssign = 0; 393 int sumAssign2 = 0; 394 int sumPert = 0; 395 int sumPert2 = 0; 396 int sumVal = 0; 397 int sumVal2 = 0; 398 int sumTotalVal = 0; 399 int sumTotalVal2 = 0; 400 for (int test = 1; test <= nrTests; test++) { 401 log.println(" " + test + ". test"); 402 log.flush(); 403 properties.setProperty("CSP.NrVariables", String.valueOf(nrVariables)); 404 properties.setProperty("CSP.Tightness", String.valueOf(tightness)); 405 properties.setProperty("CSP.Density", String.valueOf(density)); 406 407 long currentSeed = (seed * 1000000L) 408 + (1000 * (long) ((sameProblemStep ? densityMin : density) * 1000.0)) 409 + ((long) ((sameProblemStep ? tightnessMin : tightness) * 1000.0)); 410 currentSeed = (currentSeed * nrTests) + (sameProblemTest ? 0 : test - 1); 411 412 sLogger.debug("Seed: " + currentSeed); 413 StructuredCSPModel csp = new StructuredCSPModel(properties, currentSeed); 414 415 Solver<CSPVariable, CSPValue> s = new Solver<CSPVariable, CSPValue>(properties); 416 s.setInitalSolution(csp); 417 s.currentSolution().clearBest(); 418 s.start(); 419 420 try { 421 s.getSolverThread().join(); 422 } catch (NullPointerException npe) { 423 } 424 425 if (s.lastSolution().getBestInfo() == null) 426 sLogger.error("No solution found :-("); 427 sLogger.debug("Last solution:" + s.lastSolution().getInfo()); 428 Solution<CSPVariable, CSPValue> best = s.lastSolution(); 429 sLogger.debug("Best solution:" + s.lastSolution().getBestInfo()); 430 best.restoreBest(); 431 int val = 0; 432 for (Iterator<CSPVariable> iv = best.getModel().assignedVariables().iterator(); iv.hasNext();) 433 val += (int) iv.next().getAssignment().toDouble(); 434 int totalVal = val + (best.getModel().unassignedVariables().size() * nrValues); 435 sLogger.debug("Last solution:" + best.getInfo()); 436 logStat.println(test 437 + ";" 438 + nrVariables 439 + ";" 440 + nrValues 441 + ";" 442 + sDoubleFormat.format(density) 443 + ";" 444 + sDoubleFormat.format(tightness) 445 + ";" 446 + sDoubleFormat.format(best.getTime()) 447 + ";" 448 + best.getIteration() 449 + ";" 450 + sDoubleFormat.format((best.getIteration()) / best.getTime()) 451 + ";" 452 + best.getModel().unassignedHardConstraints().size() 453 + ";" 454 + best.getModel().assignedVariables().size() 455 + ";" 456 + sDoubleFormat.format(100.0 * best.getModel().assignedVariables().size() 457 / best.getModel().variables().size()) 458 + (mpp ? ";" 459 + (best.getModel().perturbVariables().size() + best.getModel() 460 .unassignedVariables().size()) 461 + ";" 462 + sDoubleFormat.format(100.0 463 * (best.getModel().perturbVariables().size() + best.getModel() 464 .unassignedVariables().size()) 465 / best.getModel().variables().size()) : "") + ";" + val + ";" 466 + totalVal); 467 log.println(" seed: " + currentSeed); 468 log.println(" constraints: " + best.getModel().constraints().size()); 469 for (Iterator<Constraint<CSPVariable, CSPValue>> i = best.getModel().constraints().iterator(); i 470 .hasNext();) { 471 CSPBinaryConstraint c = (CSPBinaryConstraint) i.next(); 472 log.println(" " + c.getName() + " (" + c.first().getName() + "," 473 + c.second().getName() + ")"); 474 for (CSPValue v0 : c.first().values()) { 475 log.print(" "); 476 for (CSPValue v1 : c.second().values()) 477 log.print(c.isConsistent(v0, v1) ? "1 " : "0 "); 478 } 479 log.println(); 480 } 481 log.println(" time: " + sDoubleFormat.format(best.getTime()) + " s"); 482 log.println(" iteration: " + best.getIteration()); 483 log.println(" speed: " + sDoubleFormat.format((best.getIteration()) / best.getTime()) 484 + " it/s"); 485 log.println(" assigned: " 486 + best.getModel().assignedVariables().size() 487 + " (" 488 + sDoubleFormat.format(100.0 * best.getModel().assignedVariables().size() 489 / best.getModel().variables().size()) + "%)"); 490 log.println(" total value: " + val); 491 if (mpp) 492 log.println(" perturbations:" 493 + (best.getModel().perturbVariables().size() + best.getModel() 494 .unassignedVariables().size()) 495 + " (" 496 + sDoubleFormat 497 .format(100.0 498 * (best.getModel().perturbVariables().size() + best.getModel() 499 .unassignedVariables().size()) 500 / best.getModel().variables().size()) + "%)"); 501 log.print(" solution: "); 502 for (CSPVariable v : ((CSPModel) best.getModel()).variables()) { 503 if (v.getBestAssignment() == null) 504 continue; 505 log.print(v.getName() + "=" + v.getBestAssignment().getName()); 506 log.print(", "); 507 } 508 log.println(); 509 sumTime += best.getTime(); 510 sumTime2 += best.getTime() * best.getTime(); 511 sumIters += best.getIteration(); 512 sumIters2 += best.getIteration() * best.getIteration(); 513 sumConfl += best.getModel().unassignedHardConstraints().size(); 514 sumAssign += best.getModel().assignedVariables().size(); 515 sumAssign2 += best.getModel().assignedVariables().size() 516 * best.getModel().assignedVariables().size(); 517 sumVal += val; 518 sumVal2 += val * val; 519 sumTotalVal += totalVal; 520 sumTotalVal2 += totalVal * totalVal; 521 if (mpp) { 522 sumPert += (best.getModel().perturbVariables().size() + best.getModel() 523 .unassignedVariables().size()); 524 sumPert2 += (best.getModel().perturbVariables().size() + best.getModel() 525 .unassignedVariables().size()) 526 * (best.getModel().perturbVariables().size() + best.getModel() 527 .unassignedVariables().size()); 528 } 529 log.flush(); 530 logStat.flush(); 531 } 532 logAvgStat.println(nrVariables 533 + ";" 534 + nrValues 535 + ";" 536 + sDoubleFormat.format(density) 537 + ";" 538 + sDoubleFormat.format(tightness) 539 + ";" 540 + sDoubleFormat.format(sumTime / nrTests) 541 + ";" 542 + sDoubleFormat.format(ToolBox.rms(nrTests, sumTime, sumTime2)) 543 + ";" 544 + sDoubleFormat.format(((double) sumIters) / nrTests) 545 + ";" 546 + sDoubleFormat.format(ToolBox.rms(nrTests, sumIters, sumIters2)) 547 + ";" 548 + sDoubleFormat.format((sumIters) / sumTime) 549 + ";" 550 + sDoubleFormat.format(((double) sumConfl) / nrTests) 551 + ";" 552 + sDoubleFormat.format(((double) sumAssign) / nrTests) 553 + ";" 554 + sDoubleFormat.format(ToolBox.rms(nrTests, sumAssign, sumAssign2)) 555 + ";" 556 + sDoubleFormat.format(100.0 * (sumAssign) / (nrVariables * nrTests)) 557 + (mpp ? ";" + sDoubleFormat.format(((double) sumPert) / nrTests) + ";" 558 + sDoubleFormat.format(ToolBox.rms(nrTests, sumPert, sumPert2)) + ";" 559 + sDoubleFormat.format(100.0 * (sumPert) / (nrVariables * nrTests)) : "") 560 + ";" 561 + sDoubleFormat.format(((double) sumVal) / (nrTests * nrVariables)) 562 + ";" 563 + sDoubleFormat.format(ToolBox.rms(nrTests, (double) sumVal / nrVariables, (double) sumVal2 564 / (nrVariables * nrVariables))) + ";" 565 + sDoubleFormat.format(((double) sumTotalVal) / nrTests) + ";" 566 + sDoubleFormat.format(ToolBox.rms(nrTests, sumTotalVal, sumTotalVal2))); 567 logAvgStat.flush(); 568 } 569 } 570 } 571 log.flush(); 572 log.close(); 573 logStat.flush(); 574 logStat.close(); 575 logAvgStat.flush(); 576 logAvgStat.close(); 577 } 578 579 private static void test(File inputCfg, String name, String include, String regexp, String outDir) throws Exception { 580 if (regexp != null) { 581 String incFile; 582 583 if (regexp.indexOf(';') > 0) { 584 incFile = regexp.substring(0, regexp.indexOf(';')); 585 regexp = regexp.substring(regexp.indexOf(';') + 1); 586 } else { 587 incFile = regexp; 588 regexp = null; 589 } 590 if (incFile.startsWith("[") && incFile.endsWith("]")) { 591 test(inputCfg, name, include, regexp, outDir); 592 incFile = incFile.substring(1, incFile.length() - 1); 593 } 594 if (incFile.indexOf('{') >= 0 && incFile.indexOf('}') >= 0) { 595 String prefix = incFile.substring(0, incFile.indexOf('{')); 596 StringTokenizer middle = new StringTokenizer(incFile.substring(incFile.indexOf('{') + 1, incFile 597 .indexOf('}')), "|"); 598 String sufix = incFile.substring(incFile.indexOf('}') + 1); 599 600 while (middle.hasMoreTokens()) { 601 String m = middle.nextToken(); 602 603 test(inputCfg, (name == null ? "" : name + "_") + m, (include == null ? "" : include + ";") 604 + prefix + m + sufix, regexp, outDir); 605 } 606 } else { 607 test(inputCfg, name, (include == null ? "" : include + ";") + incFile, regexp, outDir); 608 } 609 } else { 610 DataProperties properties = ToolBox.loadProperties(inputCfg); 611 StringTokenizer inc = new StringTokenizer(include, ";"); 612 613 while (inc.hasMoreTokens()) { 614 String aFile = inc.nextToken(); 615 616 System.out.println(" Loading included file '" + aFile + "' ... "); 617 FileInputStream is = null; 618 619 if ((new File(aFile)).exists()) { 620 is = new FileInputStream(aFile); 621 } 622 if ((new File(inputCfg.getParent() + File.separator + aFile)).exists()) { 623 is = new FileInputStream(inputCfg.getParent() + File.separator + aFile); 624 } 625 if (is == null) { 626 System.err.println("Unable to find include file '" + aFile + "'."); 627 } 628 properties.load(is); 629 is.close(); 630 } 631 String outDirThisTest = (outDir == null ? properties.getProperty("General.Output", ".") : outDir) 632 + File.separator + name + File.separator + sDateFormat.format(new Date()); 633 properties.setProperty("General.Output", outDirThisTest.toString()); 634 System.out.println("Output folder: " + properties.getProperty("General.Output")); 635 (new File(outDirThisTest)).mkdirs(); 636 ToolBox.configureLogging(outDirThisTest, null); 637 FileOutputStream fos = new FileOutputStream(outDirThisTest + File.separator + "rcsp.conf"); 638 639 properties.store(fos, "Random CSP problem configuration file"); 640 fos.flush(); 641 fos.close(); 642 test(properties); 643 } 644 } 645 646 public static void main(String[] args) { 647 try { 648 Progress.getInstance().addProgressListener(new ProgressWriter(System.out)); 649 File inputCfg = new File(args[0]); 650 DataProperties properties = ToolBox.loadProperties(inputCfg); 651 if (properties.getProperty("INCLUDE_REGEXP") != null) { 652 test(inputCfg, null, null, properties.getProperty("INCLUDE_REGEXP"), (args.length > 1 ? args[1] : null)); 653 } else { 654 String outDir = properties.getProperty("General.Output", ".") + File.separator 655 + inputCfg.getName().substring(0, inputCfg.getName().lastIndexOf('.')) + File.separator 656 + sDateFormat.format(new Date()); 657 if (args.length > 1) 658 outDir = args[1] + File.separator + (sDateFormat.format(new Date())); 659 properties.setProperty("General.Output", outDir.toString()); 660 System.out.println("Output folder: " + properties.getProperty("General.Output")); 661 (new File(outDir)).mkdirs(); 662 ToolBox.configureLogging(outDir, null); 663 test(properties); 664 } 665 } catch (Exception e) { 666 e.printStackTrace(); 667 } 668 } 669}