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