001    package ifs.example.tt;
002    
003    import ifs.model.*;
004    import ifs.solution.*;
005    import ifs.solver.*;
006    import ifs.util.*;
007    
008    import java.io.*;
009    import java.util.*;
010    
011    /**
012     * Test
013     *
014     * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
015     * @version 1.0
016     */
017    public class Test {
018        private static java.text.DecimalFormat sDoubleFormat = new java.text.DecimalFormat("0.000", new java.text.DecimalFormatSymbols(Locale.US));
019        private static java.text.SimpleDateFormat sDateFormat = new java.text.SimpleDateFormat("dd-MMM-yy_HHmmss", java.util.Locale.US);
020        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(Test.class);
021        
022        public static void test2(DataProperties properties) throws Exception {
023            int nrTests = properties.getPropertyInt("Test.NrTests",1);
024            PrintWriter logStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output")+File.separator+"output.csv"));
025            PrintWriter logAvgStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output")+File.separator+"avg_stat.csv"));
026            logStat.println("fillFact;nrResources;testNr;time[s];iters;speed[it/s];assigned;assigned[%];value;totalValue");
027            logAvgStat.println("fillFact;nrResources;time[s];RMStime[s];iters;RMSiters;speed[it/s];assigned;RMSassigned;assigned[%];value;RMSvalue");
028            
029            int nrResourcesMin = properties.getPropertyInt("Test.NrResourcesMin", -1);
030            int nrResourcesMax = properties.getPropertyInt("Test.NrResourcesMax", -1);
031            int nrResourcesStep = properties.getPropertyInt("Test.NrResourcesStep", 1);
032            double fillFactorMin = properties.getPropertyDouble("Test.FillFactorMin", -1.0);
033            double fillFactorMax = properties.getPropertyDouble("Test.FillFactorMax", -1.0);
034            double fillFactorStep = properties.getPropertyDouble("Test.FillFactorStep", 0.01);
035            
036            boolean saveInit = properties.getPropertyBoolean("General.SaveInitialXML", true);
037            boolean saveSol = properties.getPropertyBoolean("General.SaveSolutionXML", true);
038            
039            for (int nrResources=nrResourcesMin;nrResources<=nrResourcesMax;nrResources+=nrResourcesStep) {
040                for (double fillFactor=fillFactorMin;fillFactor<=fillFactorMax;fillFactor+=fillFactorStep) {
041                    double sumTime = 0;
042                    double sumTime2 = 0;
043                    int sumIters = 0;
044                    int sumIters2 = 0;
045                    int sumAssign = 0;
046                    int sumAssign2 = 0;
047                    int sumVal = 0;
048                    int sumVal2 = 0;
049                    int sumVar = 0;
050                    int sumVar2 = 0;
051                    for (int test=1;test<=nrTests;test++) {
052                        if (nrResources>=0) {
053                            properties.setProperty("Generator.NrRooms", String.valueOf(nrResources));
054                            properties.setProperty("Generator.NrClasses", String.valueOf(nrResources));
055                            properties.setProperty("Generator.NrInstructors", String.valueOf(nrResources));
056                        }
057                        if (fillFactor>=0.0) {
058                            properties.setProperty("Generator.FillFactor", String.valueOf(fillFactor));
059                        }
060                        TimetableModel m = TimetableModel.generate(properties);
061                        
062                        Solver s = new Solver(properties);
063                        if (saveInit) m.saveAsXML(properties, true, null,
064                                new File(properties.getProperty("General.Output")+File.separator+"SimpleTT("+
065                                (nrResources<0?properties.getPropertyInt("Generator.NrRooms",20):nrResources)+","+
066                                ((int)(100.0*(fillFactor<0.0?properties.getPropertyDouble("Generator.FillFactor",0.8):fillFactor)+0.5))+","+
067                                properties.getPropertyInt("Generator.NrDependencies",50)+")_"+test+".xml"));
068                        s.setInitalSolution(m);
069                        s.currentSolution().clearBest();
070                        s.start();
071                        try {
072                            s.getSolverThread().join();
073                        } catch (NullPointerException npe) {}
074                        
075                        
076                        
077                        if (s.lastSolution().getBestInfo()==null) sLogger.error("No solution found :-(");
078                        sLogger.debug("Last solution:"+s.lastSolution().getInfo());
079                        Solution best = s.lastSolution();
080                        sLogger.debug("Best solution:"+s.lastSolution().getBestInfo());
081                        best.restoreBest();
082                        int val = 0;
083                        for (Enumeration iv = best.getModel().assignedVariables().elements(); iv.hasMoreElements();)
084                            val += ((Variable)iv.nextElement()).getAssignment().toInt();
085                        if (saveSol) m.saveAsXML(properties, true, best,
086                                new File(properties.getProperty("General.Output")+File.separator+"SimpleTT("+
087                                (nrResources<0?properties.getPropertyInt("Generator.NrRooms",20):nrResources)+","+
088                                ((int)(100.0*(fillFactor<0.0?properties.getPropertyDouble("Generator.FillFactor",0.8):fillFactor)+0.5))+","+
089                                properties.getPropertyInt("Generator.NrDependencies",50)+")_"+test+"_sol.xml"));
090                        sLogger.debug("Last solution:"+best.getInfo());
091                        logStat.println(
092                                sDoubleFormat.format(properties.getPropertyDouble("Generator.FillFactor",0.0))+";"+
093                                sDoubleFormat.format(properties.getPropertyInt("Generator.NrRooms",0))+";"+
094                                test+";"+sDoubleFormat.format(best.getTime())+";"+best.getIteration()+";"+sDoubleFormat.format(((double)best.getIteration())/best.getTime())+";"+best.getModel().assignedVariables().size()+";"+sDoubleFormat.format(100.0 * best.getModel().assignedVariables().size() / best.getModel().variables().size())+";"+val);
095                        sLogger.debug("    time:         "+sDoubleFormat.format(best.getTime())+" s");
096                        sLogger.debug("    iteration:    "+best.getIteration());
097                        sLogger.debug("    speed:        "+sDoubleFormat.format(((double)best.getIteration())/best.getTime())+" it/s");
098                        sLogger.debug("    assigned:     "+best.getModel().assignedVariables().size()+" ("+sDoubleFormat.format(100.0 * best.getModel().assignedVariables().size() / best.getModel().variables().size())+"%)");
099                        sLogger.debug("    value:        "+val);
100                        sumTime += best.getTime();
101                        sumTime2 += best.getTime()*best.getTime();
102                        sumIters += best.getIteration();
103                        sumIters2 += best.getIteration()*best.getIteration();
104                        sumAssign += best.getModel().assignedVariables().size();
105                        sumAssign2 += best.getModel().assignedVariables().size()*best.getModel().assignedVariables().size();
106                        sumVal += val;
107                        sumVal2 += val * val;
108                        sumVar += m.variables().size();
109                        sumVar2 += m.variables().size()*m.variables().size();
110                        logStat.flush();
111                    }
112                    logAvgStat.println(
113                            sDoubleFormat.format(properties.getPropertyDouble("Generator.FillFactor",0.0))+";"+
114                            sDoubleFormat.format(properties.getPropertyInt("Generator.NrRooms",0))+";"+
115                            sDoubleFormat.format(sumTime/nrTests)+";"+
116                            sDoubleFormat.format(ToolBox.rms(nrTests,sumTime,sumTime2))+";"+
117                            sDoubleFormat.format(((double)sumIters)/nrTests)+";"+
118                            sDoubleFormat.format(ToolBox.rms(nrTests,(double)sumIters,(double)sumIters2))+";"+
119                            sDoubleFormat.format(((double)sumIters)/sumTime)+";"+
120                            sDoubleFormat.format(((double)sumAssign)/nrTests)+";"+
121                            sDoubleFormat.format(ToolBox.rms(nrTests,(double)sumAssign,(double)sumAssign2))+";"+
122                            sDoubleFormat.format(100.0 * ((double) sumAssign) / sumVar)+";"+
123                            sDoubleFormat.format(((double)sumVal)/nrTests)+";"+
124                            sDoubleFormat.format(ToolBox.rms(nrTests,(double)sumVal,(double)sumVal2)));
125                    logAvgStat.flush();
126                }
127            }
128            logStat.close();
129            logAvgStat.close();
130        }
131        
132        public static void test3(DataProperties properties, File xmlFile) throws Exception {
133            int nrTests = properties.getPropertyInt("Test.NrTests",1);
134            PrintWriter logStat = new PrintWriter(new FileWriter(properties.getProperty("General.Output")+File.separator+"output.csv"));
135            logStat.println("fillFact;nrResources;testNr;time[s];iters;speed[it/s];assigned;assigned[%];value;totalValue");
136            
137            boolean saveSol = properties.getPropertyBoolean("General.SaveSolutionXML", true);
138            boolean assign = properties.getPropertyBoolean("General.InitialAssignment", true);
139            int forcedPerturbances = properties.getPropertyInt("General.ForcedPerturbances", 0);
140            
141            for (int test=1;test<=nrTests;test++) {
142                TimetableModel m = TimetableModel.loadFromXML(xmlFile, assign);
143                
144                if (forcedPerturbances>0) {
145                    Vector initialVariables = new Vector();
146                    for (Enumeration e=m.variables().elements();e.hasMoreElements();) {
147                        Variable v = (Variable)e.nextElement();
148                        if (v.getInitialAssignment()!=null)
149                            initialVariables.addElement(v);
150                    }
151                    for (int i=0;i<forcedPerturbances;i++) {
152                        if (initialVariables.isEmpty()) break;
153                        Variable var = (Variable)ToolBox.random(initialVariables);
154                        initialVariables.remove(var);
155                        var.removeInitialValue();
156                    }
157                }
158                
159                Solver s = new Solver(properties);
160                s.setInitalSolution(m);
161                s.currentSolution().clearBest();
162                s.start();
163                try {
164                    s.getSolverThread().join();
165                } catch (NullPointerException npe) {}
166                
167                if (s.lastSolution().getBestInfo()==null) sLogger.error("No solution found :-(");
168                sLogger.debug("Last solution:"+s.lastSolution().getInfo());
169                Solution best = s.lastSolution();
170                sLogger.debug("Best solution:"+s.lastSolution().getBestInfo());
171                best.restoreBest();
172                int val = 0;
173                for (Enumeration iv = best.getModel().assignedVariables().elements(); iv.hasMoreElements();)
174                    val += ((Variable)iv.nextElement()).getAssignment().toInt();
175                if (saveSol) m.saveAsXML(properties, false, best, new File(properties.getProperty("General.Output")+File.separator+"solution_"+test+".xml"));
176                sLogger.debug("Last solution:"+best.getInfo());
177                logStat.println(
178                        sDoubleFormat.format(properties.getPropertyDouble("Generator.FillFactor",0.0))+";"+
179                        sDoubleFormat.format(properties.getPropertyInt("Generator.NrRooms",0))+";"+
180                        test+";"+sDoubleFormat.format(best.getTime())+";"+best.getIteration()+";"+sDoubleFormat.format(((double)best.getIteration())/best.getTime())+";"+best.getModel().assignedVariables().size()+";"+sDoubleFormat.format(100.0 * best.getModel().assignedVariables().size() / best.getModel().variables().size())+";"+val);
181                sLogger.debug("    time:         "+sDoubleFormat.format(best.getTime())+" s");
182                sLogger.debug("    iteration:    "+best.getIteration());
183                sLogger.debug("    speed:        "+sDoubleFormat.format(((double)best.getIteration())/best.getTime())+" it/s");
184                sLogger.debug("    assigned:     "+best.getModel().assignedVariables().size()+" ("+sDoubleFormat.format(100.0 * best.getModel().assignedVariables().size() / best.getModel().variables().size())+"%)");
185                sLogger.debug("    value:        "+val);
186                logStat.flush();
187            }
188            logStat.close();
189        }
190        
191        public static void test(File inputCfg, String name, String include, String regexp, String outDir) throws Exception {
192            if (regexp != null) {
193                String incFile;
194                
195                if (regexp.indexOf(';') > 0) {
196                    incFile = regexp.substring(0, regexp.indexOf(';'));
197                    regexp = regexp.substring(regexp.indexOf(';') + 1);
198                } else {
199                    incFile = regexp;
200                    regexp = null;
201                }
202                if (incFile.startsWith("[") && incFile.endsWith("]")) {
203                    test(inputCfg, name, include, regexp, outDir);
204                    incFile = incFile.substring(1, incFile.length() - 1);
205                }
206                if (incFile.indexOf('{') >= 0 && incFile.indexOf('}') >= 0) {
207                    String prefix = incFile.substring(0, incFile.indexOf('{'));
208                    StringTokenizer middle = new StringTokenizer(incFile.substring(incFile.indexOf('{') + 1, incFile.indexOf('}')), "|");
209                    String sufix = incFile.substring(incFile.indexOf('}') + 1);
210                    
211                    while (middle.hasMoreTokens()) {
212                        String m = middle.nextToken();
213                        
214                        test(inputCfg, (name == null ? "" : name + "_") + m, (include == null ? "" : include + ";") + prefix + m + sufix, regexp, outDir);
215                    }
216                } else {
217                    test(inputCfg, name, (include == null ? "" : include + ";") + incFile, regexp, outDir);
218                }
219            } else {
220                DataProperties properties = ToolBox.loadProperties(inputCfg);
221                StringTokenizer inc = new StringTokenizer(include, ";");
222                
223                while (inc.hasMoreTokens()) {
224                    String aFile = inc.nextToken();
225                    
226                    System.out.println("  Loading included file '" + aFile + "' ... ");
227                    FileInputStream is = null;
228                    
229                    if ((new File(aFile)).exists()) {
230                        is = new FileInputStream(aFile);
231                    }
232                    if ((new File(inputCfg.getParent() + File.separator + aFile)).exists()) {
233                        is = new FileInputStream(inputCfg.getParent() + File.separator + aFile);
234                    }
235                    if (is == null) {
236                        System.err.println("Unable to find include file '" + aFile + "'.");
237                    }
238                    properties.load(is);
239                    is.close();
240                }
241                String outDirThisTest = (outDir==null?properties.getProperty("General.Output","."):outDir)+File.separator + name+File.separator+sDateFormat.format(new Date());
242                properties.setProperty("General.Output", outDirThisTest.toString());
243                System.out.println("Output folder: "+properties.getProperty("General.Output"));
244                (new File(outDirThisTest)).mkdirs();
245                ToolBox.configureLogging(outDirThisTest, null);
246                FileOutputStream fos = new FileOutputStream(outDirThisTest + File.separator + "rcsp.conf");
247                
248                properties.store(fos, "Random CSP problem configuration file");
249                fos.flush(); fos.close();
250                test2(properties);
251            }
252        }
253        
254        public static void main(String[] args) {
255            try {
256                Progress.getInstance().addProgressListener(new ProgressWriter(System.out));
257                File inputCfg = new File(args[0]);
258                DataProperties properties = ToolBox.loadProperties(inputCfg);
259                if (args.length==3) {
260                    File xmlFile = new File(args[1]);
261                    String outDir = args[2]+File.separator+(sDateFormat.format(new Date()));
262                    properties.setProperty("General.Output", outDir.toString());
263                    System.out.println("Input file: "+xmlFile);
264                    System.out.println("Output folder: "+properties.getProperty("General.Output"));
265                    (new File(outDir)).mkdirs();
266                    ToolBox.configureLogging(outDir, null);
267                    test3(properties, xmlFile);
268                } else if (properties.getProperty("INCLUDE_REGEXP") != null) {
269                    test(inputCfg, null, null, properties.getProperty("INCLUDE_REGEXP"), (args.length>1?args[1]:null));
270                } else {
271                    String outDir = properties.getProperty("General.Output", ".") + File.separator + inputCfg.getName().substring(0, inputCfg.getName().lastIndexOf('.')) + File.separator + sDateFormat.format(new Date());
272                    if (args.length>1)
273                        outDir = args[1]+File.separator+(sDateFormat.format(new Date()));
274                    properties.setProperty("General.Output", outDir.toString());
275                    System.out.println("Output folder: "+properties.getProperty("General.Output"));
276                    (new File(outDir)).mkdirs();
277                    ToolBox.configureLogging(outDir, null);
278                    test2(properties);
279                }
280            } catch (Exception e) {
281                e.printStackTrace();
282            }
283        }
284    }