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