package iterators; import java.io.*; import main.BetterTokenizer; import java.lang.*; import java.awt.*; import java.util.Random; import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; import main.*; import stoppers.SimpleStop; import parameters.Parameter; import parameters.ParameterSet; import parameters.ParameterSetArray; import main.Globals; import genegui.*; public class UberIterator extends ModelIterator implements Runnable { private static final int RANDOM_RANGE=0; private static final int FROM_FILE_LIST=1; private static final int FROM_CAM = 2; private static final int CAM_PLUS_RANDOM = 3; private int runmode=0; private int randomMode = RANDOM_RANGE; private int numEvals = 0; private float maxstep = 0f; private int randomseed = 0; private int runcount=0; private int goodcount=0; private boolean quit=false; private UberIteratorFunction theFunction; /** Used to reread an existing data file */ private BetterTokenizer dataFileTokenizer = null; /** Marks where in the evaluator chain to restart from when in FROM_FILE_LIST mode */ private String SIDTag = "start"; /** Used to store a psetarray to load param sets from */ private ParameterSetArray paramSets = null; /** When in CAM_PLUS_RANDOM mode, the number of random sets to make from each param set in the cam graph. */ private int numRepeatsPerCam = 10; private int repeatNumber = numRepeatsPerCam; /** File handle for iterator output */ private File OutputFile; /**File stream for iterator output */ private OutputStream OutputStream; public UberIterator() {} public void init(Network network, Model model) { outFileName = "output/GNOut"; super.init(network, model); verbose = true; randomseed = (int)((new Date()).getTime() % 100000000); MoreMath.setRandomSeed(randomseed); theFunction = new UberIteratorFunction(new ModelRunner(model, new SimpleStop()),ps); } public void quit() { quit = true; } public void reset() { super.reset(); runcount = 0; goodcount = 0; // Report reset event toIteratorViewer if (TheIteratorViewer!=null) { TheIteratorViewer.runReset(); } } public void loadParameters(BetterTokenizer tokenizer) throws Exception { String info = GeneralInput.findNextIDToken(tokenizer); // go straight to next line and look for runmode if(!info.equals("OutfileName") && !info.equals("OutpathName")) { makeOutputFile(); GeneralInput.echoOn(ps); } else { loadParameter(info, tokenizer); makeOutputFile(); GeneralInput.echoOn(ps); } // Echo the first couple lines of the input file to the output file. Do this here because output // file is first set up here. println("&Cam"); println(); println("&Iterator\t\tUberIterator"); // echo first line of input file to data file println("\t&ModelFile\t" + Globals.getModelFile()); println("\t&OutfileName\t" + outFileName); super.loadParameters(tokenizer); GeneralInput.echoOff(); println(""); theFunction.saveOutputTags(); println("&endHeader"); } private BetterTokenizer reopenDataFile(String file_name) throws Exception { if(file_name.equals("")) { // prompt user for filename FileDialog fd = new FileDialog(new Frame(), "DataFile"); fd.setVisible(true); if(fd.getFile() == null) throw new Exception("UberIterator: Ich habe kein data file gekriegt"); // Cancel else file_name = fd.getDirectory() + fd.getFile(); } BetterTokenizer tokenizer = new BetterTokenizer(new FileInputStream(file_name)); GeneralInput.setupTokenizer(tokenizer); return(tokenizer); } private BetterTokenizer readHeaderTo(String IDTag, BetterTokenizer tokenizer) throws Exception { String info = GeneralInput.findNextIDToken(tokenizer); if(IDTag.equals("start")) IDTag = "endUSParams"; while(!info.equals("endUSParams")) { loadParameter(info, tokenizer); info = GeneralInput.findNextIDToken(tokenizer); // always load UberIterator pars from datafile } while(!info.equals(IDTag)); // now copy header to new outfile up to IDTag GeneralInput.echoOff(); GeneralInput.findIDTag(tokenizer,"endHeader"); // now read to the end of the current header MoreMath.setRandomSeed((int)randomseed); return tokenizer; } private void makeOutputFile() throws Exception { try { OutputFile = new File(outFileName); OutputStream = new FileOutputStream(OutputFile); setPrintStream(new PrintWriter(OutputStream, true)); } catch(IOException e) { ps = null; throw new Exception ("Error creating UberIterator output file: " + e.toString()); } theFunction.setOutputStream(ps); } /** Called when the output file is changed. Over-rides method in ModelIterator @param File file - The new output file handle. @author WJS */ public void setOutputFile(String fileName) throws Exception { // Close current outputstream OutputStream.close(); // TODO // startKludge // A very, very temporary kludge to duplicate the file header of the // file created when the iterator was loaded. This will be eliminated // when proper XML-based save and load functions are available for all // objects. byte[] c = new byte[8192]; String header = new String(""); FileInputStream fs = new FileInputStream(OutputFile); int nbytes = fs.read(c); while (nbytes>0) { header += new String(c,0,nbytes); nbytes = fs.read(c); } nbytes = header.indexOf("&endHeader"); header = header.substring(0,nbytes+11); // endKludge try { outFileName = fileName; OutputFile = new File(fileName); OutputStream = new FileOutputStream(OutputFile); OutputStream.write(header.getBytes()); // Kludge revisited setPrintStream(new PrintWriter(OutputStream, true)); } catch(IOException e) { ps = null; throw e; } theFunction.setOutputStream(ps); } protected void loadParameter(String info, BetterTokenizer tokenizer) throws Exception { if(info.equals("RunMode")) { String rm; GeneralInput.nextToken(tokenizer); if(tokenizer.sval.equals("FromCam")) { paramSets = Globals.getCurParamSetArray(); if(paramSets == null) throw new Exception("UberIterator trying to use cam parameters, but no cam currently loaded."); print("\t" + paramSets.getFilename()); runmode = FROM_CAM; } else if(tokenizer.sval.equals("CamPlusRandom")) { paramSets = Globals.getCurParamSetArray(); if(paramSets == null) throw new Exception("UberIterator trying to use cam parameters, but no cam currently loaded."); print("\t" + paramSets.getFilename()); runmode = CAM_PLUS_RANDOM; if(GeneralInput.nextToken(tokenizer) != BetterTokenizer.TT_NUMBER) { // default to Uniform System.out.println("Number of repeats per param set not set : using default of 10"); } else { numRepeatsPerCam = (int)tokenizer.nval; repeatNumber = numRepeatsPerCam; } } else if(tokenizer.sval.equals("FromFileList")) { String file_name = ""; SIDTag = "start"; if(GeneralInput.nextToken(tokenizer) == BetterTokenizer.TT_WORD) // if no filename specified reopenDataFile prompts user for filename file_name = tokenizer.sval; // get evaluator ID Tag for where in evaluator chain to restart if(GeneralInput.nextToken(tokenizer) != BetterTokenizer.TT_WORD || tokenizer.sval.equals("start")) // if no IDTag or "start" specified. Assume start at beginning dataFileTokenizer = readHeaderTo(SIDTag,reopenDataFile(file_name)); else { SIDTag = tokenizer.sval; dataFileTokenizer = readHeaderTo(SIDTag,reopenDataFile(file_name)); runmode = FROM_FILE_LIST; } GeneralInput.findIDTag(tokenizer,"endIterator"); // ignore any spurious uberiterator params GeneralInput.echoOn(ps); // turn echo back on } else if(tokenizer.sval.equals("RandomRange") || tokenizer.sval.equals("Random")) { rm = tokenizer.sval; runmode = RANDOM_RANGE; if(GeneralInput.nextToken(tokenizer) != BetterTokenizer.TT_WORD) { // default to Uniform System.out.println("Random mode unspecified for random range: Using Uniform mode"); randomMode = MoreMath.UNIFORM; } else if(tokenizer.sval.equals("Gaussian")) randomMode = MoreMath.GAUSSIAN; else if(tokenizer.sval.equals("BrownNoise")) { System.out.println("Brown noise not implemented yet. Using Gaussian mode"); randomMode = MoreMath.GAUSSIAN; } else if(tokenizer.sval.equals("Uniform")) { randomMode = MoreMath.UNIFORM; } else { // default to Uniform System.out.println("Random mode unspecified for random range: Using Uniform mode"); randomMode = MoreMath.UNIFORM; } } theFunction.setRunMode(runmode); } else if(info.equals("MaxStepFraction")) { GeneralInput.nextToken(tokenizer); float ms = (float)tokenizer.nval; if(ms > 1.0f || ms <= 0.0f) throw new Exception("UberIterator: schlecht MaxStepFraction"); maxstep = ms; } else if(info.equals("RandomSeed")) { GeneralInput.nextToken(tokenizer); randomseed = (int)tokenizer.nval; MoreMath.setRandomSeed(randomseed); } else if(info.equals("Evaluators")) { GeneralInput.indent++; String eval_mode = "SequentialMode"; String eval_type = GeneralInput.findNextIDToken(tokenizer); boolean auto_pass = false; float FPStabilizer = 1f; ModelIterator serialIterator = null; String serial_name = "", class_name = "", id_tag = "", save_pars = "", start_where = "", int_mode = Globals.getIntegrationAlgorithm(); while(!eval_type.equals("endEvaluators")) { if(eval_type.equals("SerialMode")) { // switch to serial mode eval_mode = eval_type; info = GeneralInput.findNextIDToken(tokenizer); if(!info.equals("Iterator")) throw new Exception("SerialMode: Must specify a new iterator"); serial_name = GeneralInput.nextWordToken(tokenizer); serialIterator = makeIterator(serial_name, tokenizer); // make and parameterize the iterator serialIterator.setFunction(new CooptimizerFunction(new ModelRunner(model, new SimpleStop()))); // add new Cooptimizer function } else if(eval_type.equals("SequentialMode")) { eval_mode = eval_type; } else if(eval_type.equals("Stopper") || eval_type.equals("Iterator") || eval_type.equals("Experiment") || eval_type.equals("Cooptimize")) { // specifies a genuine evaluator id_tag = GeneralInput.nextWordToken(tokenizer); start_where = GeneralInput.nextWordToken(tokenizer); auto_pass = false; save_pars = ""; int_mode = Globals.getIntegrationAlgorithm(); while(GeneralInput.nextToken(tokenizer) != BetterTokenizer.TT_EOL) { if(tokenizer.sval.equals("Autopass")) auto_pass = true; else if(tokenizer.sval.equals("Savestartingpars") || tokenizer.sval.equals("Savefinalpars") || tokenizer.sval.equals("Saveboth")) save_pars = tokenizer.sval; // Allow specifying an integration mode for stoppers and experiments // Iterators do it through LoadParameters else if(tokenizer.sval.equals("Integrator=")) int_mode = GeneralInput.nextWordToken(tokenizer); } if(int_mode.equals("FixedPoint")) { String alpha = GeneralInput.findNextIDToken(tokenizer); if(!alpha.equals("FPStabilizer")) throw new Exception("Uberiterator: For evaluator: " + id_tag + "In Fixed mode, the line following the ID line must specify &FPStabilizer"); if(GeneralInput.nextToken(tokenizer) != BetterTokenizer.TT_NUMBER) System.out.println("Uberiterator: For evaluator: " + id_tag + "got a bad FPStabilizer value, using default alpha = 1"); FPStabilizer = (float) tokenizer.nval; } if(eval_type.equals("Experiment")) class_name = "Experiment"; else { class_name = GeneralInput.findNextIDToken(tokenizer); if(eval_type.equals("Cooptimize")) { if(!class_name.equals("iterator")) throw new Exception("Uberiterator: You must specify an iterator for cooptimizer" + id_tag); class_name = GeneralInput.nextWordToken(tokenizer); } } if(eval_mode.equals("SequentialMode")) { // just load the object theFunction.setFPStabilizer(FPStabilizer); theFunction.addObject(network, model,tokenizer,eval_type,class_name,id_tag,save_pars,start_where,auto_pass,int_mode); } // WARNING: emm 5/31 Serial Mode wont work since I added the Fixed Point and FPStabilizer inputs above, but I haven't taken the time to // fix it just yet else { // SerialMode: serialIterator.theFunction.addObject(model,tokenizer,eval_type,class_name); // add new eval object // to serialIterator ModelIterator new_Iter = serialIterator.copy(); // make copy of serial Iterator theFunction.addIterator(new_Iter,"Iterator",serial_name,id_tag,save_pars,start_where,auto_pass); } } else throw new Exception("UberIterator.loadParameters:\t" + info + "\tist nicht ein echt evaluator Typ"); eval_type = GeneralInput.findNextIDToken(tokenizer); } // end of evaluators loop GeneralInput.indent--; } else super.loadParameter(info, tokenizer); } private ModelIterator makeIterator(String class_name, BetterTokenizer tokenizer) throws Exception { Class c = Class.forName("iterators." + class_name); ModelIterator obj = (ModelIterator)c.newInstance(); obj.init(network, model); obj.loadParameters(tokenizer); return obj; } public void startRun() { // Override start to pick the first point to iterate from, set up files and functions if(!makeFirstPoint(parsTV, runmode)) // If true, something went wrong return; super.startRun(); } public void doRun() { float score = 0; while (!quit&running) { runThread.yield(); GregorianCalendar calendar = new GregorianCalendar(); System.out.println("Run #" + runcount + " : " + calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE)); // Report run count to the IteratorViewer if (TheIteratorViewer!=null) TheIteratorViewer.reportRunCount(runcount); //ELI 6/28/99 - changed to make call to checkForNaN and catch exception try { score = theFunction.evaluate(parsTV); if(parsTV.didPass()) { System.out.println("Yipee! Uberiterator found a good parameter set with score = " + score); goodcount++; // Report successsful run count to the IteratorViewer if (TheIteratorViewer!=null) { TheIteratorViewer.reportSuccessCount(GeneNet.TheModel.getModelState().cloneState(),parsTV.copy(),goodcount,score); TheIteratorViewer.setMessagesText("Yipee! Uberiterator found a good parameter set with score = " + score); } } } catch(Exception e) { ps.println("// Had an NaN in this model run"); System.out.println("shit"); System.out.println(e.toString()); } // Generate a new random point quit = !makeNewPoint(parsTV,runmode); // Report the parameter set change to the GUI if there is one loaded. if (GeneNet.TheMainGui!=null) GeneNet.TheMainGui.parameterSetChanged(GuiInterface.PARAMETER_SET_CHANGED,0,GeneNet.TheMainGui); runcount++; ps.println("// Count = " + runcount); } println(); println("&UberIterator tried " + runcount + " random picks and found " + goodcount + " good ones"); // ps.close(); // ps = null; // stopRun(); } // public void stopRun() { // // // override to close our output file // if(ps != null) ps.close(); // ps = null; // super.stopRun(); // // } /* private float rand(int mode) { if(mode == ParameterSet.UNIFORM) { float f = rng.nextFloat(); if(f < 0.5f) { return -(rng.nextFloat()); } else { return rng.nextFloat(); } } else if(mode == ParameterSet.GAUSSIAN) { return (float)rng.nextGaussian(); } else return rng.nextFloat(); } */ // ELI 6/2 - changed to return boolean saying whether new values are good - also added returns below public boolean makeNewPoint(ParameterSet pars, int runmode) { if(runmode == RANDOM_RANGE) { /* for(int i = 0; i < pars.getNumParams(); i++) { if(randomMode == UNIFORM) { if(pars.getVariationMode(i) == Parameter.LINEAR) { pars.setValue(i, pars.getLowerBound(i) + ((float)Math.abs(rand(randomMode)) * (pars.getUpperBound(i) - pars.getLowerBound(i)))); } else if(pars.getVariationMode(i) == Parameter.LOGARITHMIC) { float expRange = (float)Math.log((double)pars.getUpperBound(i)) - (float)Math.log((double)pars.getLowerBound(i)); float exp = ((float)Math.abs(rand(randomMode)) * expRange) + (float)Math.log((double)pars.getLowerBound(i)); pars.setValue(i, (float)Math.exp(exp)); } } else if(randomMode == GAUSSIAN) { // Note - gaussian ought to change to deal better with logarithmic ones float temp = rand(randomMode) * ((pars.getLowerBound(i) + pars.getUpperBound(i))/2); if(temp < pars.getLowerBound(i)) temp = pars.getLowerBound(i); if(temp > pars.getUpperBound(i)) temp = pars.getUpperBound(i); pars.setValue(i, temp); } } return true; */ int i = 0; while(i < 100 && !pars.makeNewPoint(randomMode)) i++; if(i == 100) { System.out.println("Couldn't find parameter set meeting rules after 100 tries"); return false; } return true; } else if(runmode == FROM_CAM) { ParameterSet set = paramSets.getNextSet(); if(set == null) return false; pars.setFrom(set); return true; } else if(runmode == CAM_PLUS_RANDOM) // Note - first picking full random set, then replace with values from params in cam { ParameterSet set; if(repeatNumber == numRepeatsPerCam) { set = paramSets.getNextSet(); repeatNumber = 0; } else set = paramSets.getCurSet(); if(set == null) return false; repeatNumber++; pars.setFrom(set); int i = 0; while(i < 100 && !pars.makeNewPoint(randomMode, set)) i++; if(i == 100) { System.out.println("Couldn't find parameter set meeting rules after 100 tries"); return false; } return true; } return false; // runmode is set badly for some reason } public boolean makeFirstPoint(ParameterSet pars, int runmode) { if(runmode == RANDOM_RANGE) { // return makeNewPoint(pars, runmode); return pars.makeNewPoint(randomMode); } else if(runmode == FROM_CAM) { ParameterSet set = paramSets.goToBeginning(); if(set == null) return false; pars.setFrom(set); return true; } else if(runmode == CAM_PLUS_RANDOM) { pars.makeNewPoint(randomMode); ParameterSet set = paramSets.goToBeginning(); if(set == null) return false; pars.setFrom(set); return true; } else return false; } }