package iterators; import java.io.*; import main.BetterTokenizer; import main.*; import parameters.*; import java.util.Vector; import java.util.Enumeration; /** */ public class PopEvolveExpanderIterator extends ModelIterator { int popSize = 1000; float initVariationMultiple = 2; int numChildrenPerParent = 16; int targetNumSuccessfulChildren = 8; float mutationRate = 0.1f, mutationAmount = 0.1f; int maxNumRounds = 5; float thresholdGood = 0.95f; ParameterSetArray paramSets = null, paramSets2 = null; public PopEvolveExpanderIterator() { setPrint(true); } /** Loads parameters specific to this iterator. */ protected void loadParameter(String info, BetterTokenizer tokenizer) throws Exception { if(info.equals("PopSize")) {GeneralInput.nextToken(tokenizer); popSize = (int)tokenizer.nval; } else if(info.equals("InitialVariationMultiple")) {GeneralInput.nextToken(tokenizer); initVariationMultiple = (float)tokenizer.nval; } else if(info.equals("NumChildrenPerParent")) {GeneralInput.nextToken(tokenizer); numChildrenPerParent = (int)tokenizer.nval; } else if(info.equals("TargetNumSuccessfulChildren")) {GeneralInput.nextToken(tokenizer); targetNumSuccessfulChildren = (int)tokenizer.nval; } else if(info.equals("MaxNumRounds")) {GeneralInput.nextToken(tokenizer); maxNumRounds = (int)tokenizer.nval; } else if(info.equals("ThresholdPercentGood")) {GeneralInput.nextToken(tokenizer); thresholdGood = (float)tokenizer.nval; } else if(info.equals("MutationRate")) {GeneralInput.nextToken(tokenizer); mutationRate = (float)tokenizer.nval; } else if(info.equals("MutationAmount")) {GeneralInput.nextToken(tokenizer); mutationAmount = (float)tokenizer.nval; } else super.loadParameter(info, tokenizer); } public void reset() { super.reset(); } public void doRun() { float percent_good_children = 1; try { reset(); paramSets = new ParameterSetArray(); paramSets2 = new ParameterSetArray(); // Add the current parameter set into the array to start things off ParameterSet orig_set = model.getModelParameterSet(); paramSets.addSet(orig_set); /* ParameterSet params_copy = orig_set.copy(); float [] p_arranged = orig_set.getParVals(); int [] arrangement = new int[orig_set.getNumParams()]; ParameterSet tempset = paramSets.getSetNum(0); for(int i = 0; i < tempset.getNumParams(); i++) arrangement[i] = orig_set.getPosition(tempset.getName(i)); */ int i, param_num; float sum_vigor = 0, sum_sqr_vigor = 0; int num_good, tot_num_tried; for(int round = 0; round < maxNumRounds && percent_good_children > thresholdGood; round++) { paramSets2.removeAll(); sum_vigor = 0; sum_sqr_vigor = 0; num_good = 0; tot_num_tried = 0; for(int parent = 0; parent < paramSets.getNumSets(); parent++) { ParameterSet param_set = paramSets.getSetNum(parent); for(int child = 0; child < numChildrenPerParent; child++) { System.out.println("Round " + round + " \tParent " + parent + " of " + paramSets.getNumSets() + " \tChild " + child); ParameterSet par_set2 = paramSets.getSetNum(MoreMath.randomInt(0, paramSets.getNumSets())); p = IteratorUtilFuncs.crossParameters(param_set.getParVals(), par_set2.getParVals(), mutationRate, mutationAmount); // for(i = 0; i < p.length; i++) { // p_arranged[ arrangement[i] ] = p[i]; //System.out.println(i + " " + arrangement[i] + " " + p_arranged[ arrangement[i] ]); } float score = F(p); if(getStopper().didPass()) { ParameterSet new_set = orig_set.copy(); new_set.setFrom(p); score = getHybridityScore(param_set, par_set2); new_set.setScore(score); sum_vigor += score; sum_sqr_vigor += score * score; paramSets2.addSet(new_set); num_good++; } tot_num_tried++; } } // Adjust the number of children per parent to get successes to around the target if(paramSets2.getNumSets() > (targetNumSuccessfulChildren + 1) * paramSets.getNumSets()) numChildrenPerParent--; else if(paramSets2.getNumSets() < (targetNumSuccessfulChildren - 1) * paramSets.getNumSets()) numChildrenPerParent++; if(numChildrenPerParent < 1) numChildrenPerParent = 1; percent_good_children = (float)num_good / tot_num_tried; // Save all the good ones we found try { ps.println("&Round\t" + round); ps.println("&PercentGood\t" + percent_good_children); } catch(Exception e) { System.out.println("Error saving param sets from PopEvolve iterator: " + e.toString()); } // Transfer the ones we want to keep from second back to first parameter set array if(paramSets2.getNumSets() > 0) { paramSets.removeAll(); float proportion_survive = (float)popSize / paramSets2.getNumSets(); float avg_vigor = sum_vigor / paramSets2.getNumSets(); float std_dev_vigor = MoreMath.getStdDev(sum_vigor, sum_sqr_vigor, paramSets2.getNumSets()); if(avg_vigor == 0) { avg_vigor = 1; std_dev_vigor = 1; } float score = 0; for(i = 0; i < paramSets2.getNumSets(); i++) { ParameterSet param_set = paramSets2.getSetNum(i); float chance_survive = 1 + 0.5f * (param_set.getScore() - avg_vigor) / std_dev_vigor; chance_survive *= proportion_survive; if(Math.random() < chance_survive) paramSets.addSet(param_set); score += param_set.getScore(); } System.out.println("Round " + round + ": Avg Score = " + (score / paramSets2.getNumSets()) + " Num good = " + num_good + " Num Picked = " + paramSets.getNumSets()); } else { System.out.println("Round " + round + ": No good parameter sets found"); round = maxNumRounds; // To force exit } } // Save out the offspring from the last mating try { ps.println("&endHeader"); paramSets2.saveParameters(ps, "\t"); } catch(Exception e) { System.out.println("Error in saving parameters from PopPopEvolveExpander: " + e.toString()); } // Calculate and print some statistic(s) float [] mins = new float[orig_set.getNumParams()]; float [] maxs = new float[orig_set.getNumParams()]; for(param_num = 0; param_num < mins.length; param_num++) { mins[param_num] = 1000000000; maxs[param_num] = -1000000000; } for(i = 0; i < paramSets.getNumSets(); i++) { ParameterSet param_set = paramSets.getSetNum(i); for(param_num = 0; param_num < mins.length; param_num++) { if(param_set.getValue(param_num) < mins[param_num]) mins[param_num] = param_set.getValue(param_num); if(param_set.getValue(param_num) > maxs[param_num]) maxs[param_num] = param_set.getValue(param_num); } } float avg = 0; for(param_num = 0; param_num < mins.length; param_num++) { if(maxs[param_num] == mins[param_num]) avg += 0; else if(orig_set.getUpperBound(param_num) == orig_set.getLowerBound(param_num)) avg += 0; else if(orig_set.getVariationMode(param_num) == Parameter.LOGARITHMIC) avg += (Math.log(maxs[param_num]) - Math.log(mins[param_num])) / (Math.log(orig_set.getUpperBound(param_num)) - Math.log(orig_set.getLowerBound(param_num))); else avg += (maxs[param_num] - mins[param_num]) / (orig_set.getUpperBound(param_num) - orig_set.getLowerBound(param_num)); } ps.println("&AverageGoodParamPercent\t" + avg / orig_set.getNumParams()); } catch(Exception e) { System.out.println("Error in Pop Expand iterator: " + e.toString()); } } public float getHybridityScore(ParameterSet p1, ParameterSet p2) { float score = 0; for(int param_num = 0; param_num < p1.getNumParams(); param_num++) { if(p1.getUpperBound(param_num) > p1.getLowerBound(param_num)) { if(p1.getVariationMode(param_num) == Parameter.LOGARITHMIC) score += (float)Math.abs(Math.log(p1.getValue(param_num)) - Math.log(p2.getValue(param_num))) / (Math.log(p1.getUpperBound(param_num)) - Math.log(p1.getLowerBound(param_num))); else score += (float)Math.abs(p1.getValue(param_num) - p2.getValue(param_num)) / (p1.getUpperBound(param_num) - p1.getLowerBound(param_num)); } } return score; } /** Override to return true so we can save all the extra parameter sets we come up with. */ public boolean isSaveExtra() { return true; } }