001package org.cpsolver.ifs.example.tt; 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.Date; 010import java.util.List; 011import java.util.Locale; 012import java.util.StringTokenizer; 013 014import org.cpsolver.ifs.assignment.Assignment; 015import org.cpsolver.ifs.assignment.DefaultSingleAssignment; 016import org.cpsolver.ifs.solution.Solution; 017import org.cpsolver.ifs.solver.Solver; 018import org.cpsolver.ifs.util.DataProperties; 019import org.cpsolver.ifs.util.Progress; 020import org.cpsolver.ifs.util.ProgressWriter; 021import org.cpsolver.ifs.util.ToolBox; 022 023 024/** 025 * Test 026 * 027 * @version IFS 1.3 (Iterative Forward Search)<br> 028 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 029 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 030 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 031 * <br> 032 * This library is free software; you can redistribute it and/or modify 033 * it under the terms of the GNU Lesser General Public License as 034 * published by the Free Software Foundation; either version 3 of the 035 * License, or (at your option) any later version. <br> 036 * <br> 037 * This library is distributed in the hope that it will be useful, but 038 * WITHOUT ANY WARRANTY; without even the implied warranty of 039 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 040 * Lesser General Public License for more details. <br> 041 * <br> 042 * You should have received a copy of the GNU Lesser General Public 043 * License along with this library; if not see 044 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 045 */ 046public class Test { 047 private static java.text.DecimalFormat sDoubleFormat = new java.text.DecimalFormat("0.000", 048 new java.text.DecimalFormatSymbols(Locale.US)); 049 private static java.text.SimpleDateFormat sDateFormat = new java.text.SimpleDateFormat("dd-MMM-yy_HHmmss", 050 java.util.Locale.US); 051 private static org.apache.logging.log4j.Logger sLogger = org.apache.logging.log4j.LogManager.getLogger(Test.class); 052 053 public static void test2(DataProperties properties) throws Exception { 054 int nrTests = properties.getPropertyInt("Test.NrTests", 1); 055 PrintWriter logStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator + "output.csv")); 056 PrintWriter logAvgStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") 057 + File.separator + "avg_stat.csv")); 058 logStat.println("fillFact;nrResources;testNr;time[s];iters;speed[it/s];assigned;assigned[%];value;totalValue"); 059 logAvgStat 060 .println("fillFact;nrResources;time[s];RMStime[s];iters;RMSiters;speed[it/s];assigned;RMSassigned;assigned[%];value;RMSvalue"); 061 062 int nrResourcesMin = properties.getPropertyInt("Test.NrResourcesMin", -1); 063 int nrResourcesMax = properties.getPropertyInt("Test.NrResourcesMax", -1); 064 int nrResourcesStep = properties.getPropertyInt("Test.NrResourcesStep", 1); 065 double fillFactorMin = properties.getPropertyDouble("Test.FillFactorMin", -1.0); 066 double fillFactorMax = properties.getPropertyDouble("Test.FillFactorMax", -1.0); 067 double fillFactorStep = properties.getPropertyDouble("Test.FillFactorStep", 0.01); 068 069 boolean saveInit = properties.getPropertyBoolean("General.SaveInitialXML", true); 070 boolean saveSol = properties.getPropertyBoolean("General.SaveSolutionXML", true); 071 072 for (int nrResources = nrResourcesMin; nrResources <= nrResourcesMax; nrResources += nrResourcesStep) { 073 for (double fillFactor = fillFactorMin; fillFactor <= fillFactorMax; fillFactor += fillFactorStep) { 074 double sumTime = 0; 075 double sumTime2 = 0; 076 int sumIters = 0; 077 int sumIters2 = 0; 078 int sumAssign = 0; 079 int sumAssign2 = 0; 080 int sumVal = 0; 081 int sumVal2 = 0; 082 int sumVar = 0; 083 for (int test = 1; test <= nrTests; test++) { 084 if (nrResources >= 0) { 085 properties.setProperty("Generator.NrRooms", String.valueOf(nrResources)); 086 properties.setProperty("Generator.NrClasses", String.valueOf(nrResources)); 087 properties.setProperty("Generator.NrInstructors", String.valueOf(nrResources)); 088 } 089 if (fillFactor >= 0.0) { 090 properties.setProperty("Generator.FillFactor", String.valueOf(fillFactor)); 091 } 092 Assignment<Activity, Location> assignment = new DefaultSingleAssignment<Activity, Location>(); 093 TimetableModel m = TimetableModel.generate(properties, assignment); 094 095 Solver<Activity, Location> s = new Solver<Activity, Location>(properties); 096 if (saveInit) 097 m.saveAsXML(properties, true, null, assignment, new File(properties.getProperty("General.Output") 098 + File.separator 099 + "SimpleTT(" 100 + (nrResources < 0 ? properties.getPropertyInt("Generator.NrRooms", 20) : nrResources) 101 + "," 102 + ((int) (100.0 * (fillFactor < 0.0 ? properties.getPropertyDouble( 103 "Generator.FillFactor", 0.8) : fillFactor) + 0.5)) + "," 104 + properties.getPropertyInt("Generator.NrDependencies", 50) + ")_" + test + ".xml")); 105 s.setInitalSolution(new Solution<Activity, Location>(m, assignment)); 106 s.currentSolution().clearBest(); 107 s.start(); 108 try { 109 s.getSolverThread().join(); 110 } catch (NullPointerException npe) { 111 } 112 113 if (s.lastSolution().getBestInfo() == null) 114 sLogger.error("No solution found :-("); 115 sLogger.debug("Last solution:" + s.lastSolution().getInfo()); 116 Solution<Activity, Location> best = s.lastSolution(); 117 sLogger.debug("Best solution:" + s.lastSolution().getBestInfo()); 118 best.restoreBest(); 119 int val = 0; 120 for (Activity var : ((TimetableModel) best.getModel()).assignedVariables(best.getAssignment())) 121 val += (int) var.getAssignment(best.getAssignment()).toDouble(); 122 if (saveSol) 123 m.saveAsXML(properties, true, best, best.getAssignment(), new File(properties.getProperty("General.Output") + 124 File.separator + "SimpleTT(" + 125 (nrResources < 0 ? properties.getPropertyInt("Generator.NrRooms", 20) : nrResources) + "," + 126 ((int) (100.0 * (fillFactor < 0.0 ? properties.getPropertyDouble("Generator.FillFactor", 0.8) : fillFactor) + 0.5)) + "," + 127 properties.getPropertyInt("Generator.NrDependencies", 50) + ")_" + test + "_sol.xml")); 128 sLogger.debug("Last solution:" + best.getInfo()); 129 logStat.println(sDoubleFormat.format(properties.getPropertyDouble("Generator.FillFactor", 0.0)) 130 + ";" 131 + sDoubleFormat.format(properties.getPropertyInt("Generator.NrRooms", 0)) 132 + ";" 133 + test 134 + ";" 135 + sDoubleFormat.format(best.getTime()) 136 + ";" 137 + best.getIteration() 138 + ";" 139 + sDoubleFormat.format((best.getIteration()) / best.getTime()) 140 + ";" 141 + best.getModel().assignedVariables(best.getAssignment()).size() 142 + ";" 143 + sDoubleFormat.format(100.0 * best.getModel().assignedVariables(best.getAssignment()).size() 144 / best.getModel().variables().size()) + ";" + val); 145 sLogger.debug(" time: " + sDoubleFormat.format(best.getTime()) + " s"); 146 sLogger.debug(" iteration: " + best.getIteration()); 147 sLogger.debug(" speed: " + sDoubleFormat.format((best.getIteration()) / best.getTime()) 148 + " it/s"); 149 sLogger.debug(" assigned: " 150 + best.getModel().assignedVariables(best.getAssignment()).size() 151 + " (" 152 + sDoubleFormat.format(100.0 * best.getModel().assignedVariables(best.getAssignment()).size() 153 / best.getModel().variables().size()) + "%)"); 154 sLogger.debug(" value: " + val); 155 sumTime += best.getTime(); 156 sumTime2 += best.getTime() * best.getTime(); 157 sumIters += best.getIteration(); 158 sumIters2 += best.getIteration() * best.getIteration(); 159 sumAssign += best.getModel().assignedVariables(best.getAssignment()).size(); 160 sumAssign2 += best.getModel().assignedVariables(best.getAssignment()).size() 161 * best.getModel().assignedVariables(best.getAssignment()).size(); 162 sumVal += val; 163 sumVal2 += val * val; 164 sumVar += m.variables().size(); 165 logStat.flush(); 166 } 167 logAvgStat.println(sDoubleFormat.format(properties.getPropertyDouble("Generator.FillFactor", 0.0)) 168 + ";" + sDoubleFormat.format(properties.getPropertyInt("Generator.NrRooms", 0)) + ";" 169 + sDoubleFormat.format(sumTime / nrTests) + ";" 170 + sDoubleFormat.format(ToolBox.rms(nrTests, sumTime, sumTime2)) + ";" 171 + sDoubleFormat.format(((double) sumIters) / nrTests) + ";" 172 + sDoubleFormat.format(ToolBox.rms(nrTests, sumIters, sumIters2)) + ";" 173 + sDoubleFormat.format((sumIters) / sumTime) + ";" 174 + sDoubleFormat.format(((double) sumAssign) / nrTests) + ";" 175 + sDoubleFormat.format(ToolBox.rms(nrTests, sumAssign, sumAssign2)) + ";" 176 + sDoubleFormat.format(100.0 * (sumAssign) / sumVar) + ";" 177 + sDoubleFormat.format(((double) sumVal) / nrTests) + ";" 178 + sDoubleFormat.format(ToolBox.rms(nrTests, sumVal, sumVal2))); 179 logAvgStat.flush(); 180 } 181 } 182 logStat.close(); 183 logAvgStat.close(); 184 } 185 186 public static void test3(DataProperties properties, File xmlFile) throws Exception { 187 int nrTests = properties.getPropertyInt("Test.NrTests", 1); 188 PrintWriter logStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output") + File.separator 189 + "output.csv")); 190 logStat.println("fillFact;nrResources;testNr;time[s];iters;speed[it/s];assigned;assigned[%];value;totalValue"); 191 192 boolean saveSol = properties.getPropertyBoolean("General.SaveSolutionXML", true); 193 boolean assign = properties.getPropertyBoolean("General.InitialAssignment", true); 194 int forcedPerturbances = properties.getPropertyInt("General.ForcedPerturbances", 0); 195 196 for (int test = 1; test <= nrTests; test++) { 197 Assignment<Activity, Location> assignment = new DefaultSingleAssignment<Activity, Location>(); 198 TimetableModel m = TimetableModel.loadFromXML(xmlFile, assign ? assignment : null); 199 200 if (forcedPerturbances > 0) { 201 List<Activity> initialVariables = new ArrayList<Activity>(); 202 for (Activity v : m.variables()) { 203 if (v.getInitialAssignment() != null) 204 initialVariables.add(v); 205 } 206 for (int i = 0; i < forcedPerturbances; i++) { 207 if (initialVariables.isEmpty()) 208 break; 209 Activity var = ToolBox.random(initialVariables); 210 initialVariables.remove(var); 211 var.removeInitialValue(); 212 } 213 } 214 215 Solver<Activity, Location> s = new Solver<Activity, Location>(properties); 216 s.setInitalSolution(new Solution<Activity, Location>(m, assignment)); 217 s.currentSolution().clearBest(); 218 s.start(); 219 try { 220 s.getSolverThread().join(); 221 } catch (NullPointerException npe) { 222 } 223 224 if (s.lastSolution().getBestInfo() == null) 225 sLogger.error("No solution found :-("); 226 sLogger.debug("Last solution:" + s.lastSolution().getInfo()); 227 Solution<Activity, Location> best = s.lastSolution(); 228 sLogger.debug("Best solution:" + s.lastSolution().getBestInfo()); 229 best.restoreBest(); 230 int val = 0; 231 for (Location loc : best.getAssignment().assignedValues()) 232 val += (int) loc.toDouble(); 233 if (saveSol) 234 m.saveAsXML(properties, false, best, best.getAssignment(), new File(properties.getProperty("General.Output") + File.separator 235 + "solution_" + test + ".xml")); 236 sLogger.debug("Last solution:" + best.getInfo()); 237 logStat.println(sDoubleFormat.format(properties.getPropertyDouble("Generator.FillFactor", 0.0)) 238 + ";" 239 + sDoubleFormat.format(properties.getPropertyInt("Generator.NrRooms", 0)) 240 + ";" 241 + test 242 + ";" 243 + sDoubleFormat.format(best.getTime()) 244 + ";" 245 + best.getIteration() 246 + ";" 247 + sDoubleFormat.format((best.getIteration()) / best.getTime()) 248 + ";" 249 + best.getAssignment().nrAssignedVariables() 250 + ";" 251 + sDoubleFormat.format(100.0 * best.getAssignment().nrAssignedVariables() 252 / best.getModel().variables().size()) + ";" + val); 253 sLogger.debug(" time: " + sDoubleFormat.format(best.getTime()) + " s"); 254 sLogger.debug(" iteration: " + best.getIteration()); 255 sLogger 256 .debug(" speed: " + sDoubleFormat.format((best.getIteration()) / best.getTime()) 257 + " it/s"); 258 sLogger.debug(" assigned: " 259 + best.getAssignment().nrAssignedVariables() 260 + " (" 261 + sDoubleFormat.format(100.0 * best.getAssignment().nrAssignedVariables() 262 / best.getModel().variables().size()) + "%)"); 263 sLogger.debug(" value: " + val); 264 logStat.flush(); 265 } 266 logStat.close(); 267 } 268 269 public static void test(File inputCfg, String name, String include, String regexp, String outDir) throws Exception { 270 if (regexp != null) { 271 String incFile; 272 273 if (regexp.indexOf(';') > 0) { 274 incFile = regexp.substring(0, regexp.indexOf(';')); 275 regexp = regexp.substring(regexp.indexOf(';') + 1); 276 } else { 277 incFile = regexp; 278 regexp = null; 279 } 280 if (incFile.startsWith("[") && incFile.endsWith("]")) { 281 test(inputCfg, name, include, regexp, outDir); 282 incFile = incFile.substring(1, incFile.length() - 1); 283 } 284 if (incFile.indexOf('{') >= 0 && incFile.indexOf('}') >= 0) { 285 String prefix = incFile.substring(0, incFile.indexOf('{')); 286 StringTokenizer middle = new StringTokenizer(incFile.substring(incFile.indexOf('{') + 1, incFile 287 .indexOf('}')), "|"); 288 String sufix = incFile.substring(incFile.indexOf('}') + 1); 289 290 while (middle.hasMoreTokens()) { 291 String m = middle.nextToken(); 292 293 test(inputCfg, (name == null ? "" : name + "_") + m, (include == null ? "" : include + ";") 294 + prefix + m + sufix, regexp, outDir); 295 } 296 } else { 297 test(inputCfg, name, (include == null ? "" : include + ";") + incFile, regexp, outDir); 298 } 299 } else { 300 DataProperties properties = ToolBox.loadProperties(inputCfg); 301 StringTokenizer inc = new StringTokenizer(include, ";"); 302 303 while (inc.hasMoreTokens()) { 304 String aFile = inc.nextToken(); 305 306 System.out.println(" Loading included file '" + aFile + "' ... "); 307 FileInputStream is = null; 308 309 if ((new File(aFile)).exists()) { 310 is = new FileInputStream(aFile); 311 } 312 if ((new File(inputCfg.getParent() + File.separator + aFile)).exists()) { 313 is = new FileInputStream(inputCfg.getParent() + File.separator + aFile); 314 } 315 if (is == null) { 316 System.err.println("Unable to find include file '" + aFile + "'."); 317 } 318 properties.load(is); 319 is.close(); 320 } 321 String outDirThisTest = (outDir == null ? properties.getProperty("General.Output", ".") : outDir) 322 + File.separator + name + File.separator + sDateFormat.format(new Date()); 323 properties.setProperty("General.Output", outDirThisTest.toString()); 324 System.out.println("Output folder: " + properties.getProperty("General.Output")); 325 (new File(outDirThisTest)).mkdirs(); 326 ToolBox.configureLogging(outDirThisTest, null); 327 FileOutputStream fos = new FileOutputStream(outDirThisTest + File.separator + "rcsp.conf"); 328 329 properties.store(fos, "Random CSP problem configuration file"); 330 fos.flush(); 331 fos.close(); 332 test2(properties); 333 } 334 } 335 336 public static void main(String[] args) { 337 try { 338 Progress.getInstance().addProgressListener(new ProgressWriter(System.out)); 339 if (args.length == 0) { 340 ToolBox.configureLogging(); 341 DataProperties config = new DataProperties(System.getProperties()); 342 config.setProperty("Termination.StopWhenComplete", "false"); 343 config.setProperty("Termination.TimeOut", "60"); 344 config.setProperty("General.Output", System.getProperty("user.dir")); 345 test2(config); 346 return; 347 } 348 File inputCfg = new File(args[0]); 349 DataProperties properties = ToolBox.loadProperties(inputCfg); 350 if (args.length == 3) { 351 File xmlFile = new File(args[1]); 352 String outDir = args[2] + File.separator + (sDateFormat.format(new Date())); 353 properties.setProperty("General.Output", outDir.toString()); 354 System.out.println("Input file: " + xmlFile); 355 System.out.println("Output folder: " + properties.getProperty("General.Output")); 356 (new File(outDir)).mkdirs(); 357 ToolBox.configureLogging(outDir, null); 358 test3(properties, xmlFile); 359 } else if (properties.getProperty("INCLUDE_REGEXP") != null) { 360 test(inputCfg, null, null, properties.getProperty("INCLUDE_REGEXP"), (args.length > 1 ? args[1] : null)); 361 } else { 362 String outDir = properties.getProperty("General.Output", ".") + File.separator 363 + inputCfg.getName().substring(0, inputCfg.getName().lastIndexOf('.')) + File.separator 364 + sDateFormat.format(new Date()); 365 if (args.length > 1) 366 outDir = args[1] + File.separator + (sDateFormat.format(new Date())); 367 properties.setProperty("General.Output", outDir.toString()); 368 System.out.println("Output folder: " + properties.getProperty("General.Output")); 369 (new File(outDir)).mkdirs(); 370 ToolBox.configureLogging(outDir, null); 371 test2(properties); 372 } 373 } catch (Exception e) { 374 e.printStackTrace(); 375 } 376 } 377}