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