Page 144
Java: Simulated Annealing for the TSP import java.io.*; import java.util.*; // has class Random public class sa { static String helptext[]={ "\n Simulated Annealing for a TSP using partial path reversal (ppr)", "", "Usage:\n\t prog [-v freq] [-i iterations] CityDataBase", "", "Note, the last argument is the city database file", "Database consists of # cities as first line, followed by x,y", "coordinates of the cities and that optionally followed by a", "label of up to 3 characters.", "freq = frequency of reports (e.g. 10000)", "iterations= ", }; private static final int NTRIALS=1000000; //for now /*--- ggglobal var ---*/ static CITY[] city; // city array, start with 1 static int NC; static int[] tour, modtour; static int nTrials=NTRIALS; static int vfreq = 0; static Random rndm; //mmm=== public static void main( String[] args) { getinputs(args); long seed; //seed ran. num. gen. against making random maps seed = System.currentTimeMillis(); // seed = 999402363; System.out.println("seed= "+seed); rndm = new Random(seed); /* //this prints the labels in "identity" order if( false ) { for( int i=0; i < tour.length; ++i ) tour[i] = i; print_tour(tour); } */ int[] t = new int[NC]; double dE, E; double r, bestE; // double d=2200, a = 0.03, T=73330; //for avg |dE| = 737 double d=190, a=.001, T=99500; //for avg |dE|=1000, #its=10^6 // double d=3000, a=.03, T=99500; //for avg |dE|=1000, #its=10^6 mkperm(NC,tour); //makeup a random permutation bestE = E = tourLength(tour); int its=0; /* double mean = 0; for( ; its < 40; ++its) { modtour = ppr(tour); dE = tourLength(modtour) - E; mean += Math.abs(dE); System.out.println("dE= "+dE); for( int i=0; i < NC; ++i) tour[i] = modtour[i]; } System.out.println("avg absolute mean: "+mean/its); System.exit(0); */ System.out.println("E0= "+bestE); print_tour(tour); //hhh for( its=0; its < nTrials; ++its ) { modtour = ppr(tour); dE = tourLength(modtour) - E; r = Math.exp(-dE/T); if( rndm.nextDouble() < r ) { for( int i=0; i < NC; ++i) tour[i] = modtour[i]; E = E + dE; } if( E < bestE) { bestE = Math.min(bestE,E); for( int i=0; i < t.length; ++i) t[i] = tour[i]; System.out.print("iteration "+its+", "); System.out.println( "new best: "+bestE+" (cf "+tourLength(t)+"), tour:"); // print_tour(t); } T = d/(a + Math.log(its)); } System.out.println("Done, #iterations= "+its+", best= "+bestE); print_tour(t); } //iii=== static void getinputs(String[] argv) { int i,j; int oo; int[] o = new int[1]; char s; int pc; String ipstring; // StringBuffer ipstring = new StringBuffer(); boolean labelsset=false; int k,p; // see if&get command line arg i = argv.length; int v=0; //index into argv while( i-- > 0 && argv[v].charAt(0) == '-') { s = argv[v].charAt(1); switch( s ) { case 'v': //System.out.println("v= "+v+" argv[v]= "+argv[v]+", argv[v+1]= "+argv[v+1]); if( argv[v].length() > 2 ) { //argument packed with -v vfreq = Integer.parseInt(argv[v].substring(2)); } else { //-v might have a detached argument or none at all if( i==0 ) { //no more arguments, an error break; } //check that first char of next arg is digit if( Character.isDigit(argv[v+1].charAt(0)) ) { //read it vfreq = Integer.parseInt(argv[++v]); --i; } } break; case 'i': if( argv[v].length() > 2 ) { //argument packed with -i nTrials = Integer.parseInt(argv[v].substring(2)); } else { //-i might have a detached argument or none at all if( i==0 ) { //no more arguments, an error break; } //check that first char of next arg is digit if( Character.isDigit(argv[v+1].charAt(0)) ) { //read it nTrials = Integer.parseInt(argv[++v]); --i; } } break; default: if( ! argv[v].equals("-h") ) System.out.println("Illegal option "+argv[v]); for( int l=0; l < helptext.length; ++l ) System.out.println(helptext[l]); System.exit(0); } } String inputFile = argv[argv.length-1]; try { // Open a reader on the file. FileInputStream stream = new FileInputStream(inputFile); //InputStream stream = getClass().getResourceAsStream("/"+inputFile); BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); ipstring = reader.readLine(); o[0]=0; oo = numpars(o,ipstring); NC = Integer.parseInt(ipstring.substring(o[0],oo)); //----- memory for ------ city = new CITY[NC+1]; //+1 so first=last char quoteChar; //get city coordinates for(j=0; j < NC; ){ city[j] = new CITY(); //default constructor ipstring = reader.readLine(); for( o[0] = 0; ; ) { if( (oo = numpars(o,ipstring)) < 0 ) break; city[j].x = Double.parseDouble(ipstring.substring(o[0],oo)); o[0] = oo; if( (oo = numpars(o,ipstring)) < 0 ) break; city[j].y = Double.parseDouble(ipstring.substring(o[0],oo)); o[0] = oo; //now scan for a label, otherwise make the label the index if( (pc=ipstring.indexOf('"',oo)) >= 0 ) quoteChar = '"'; else if( (pc=ipstring.indexOf('\'',oo)) >= 0 ) quoteChar = '\''; else quoteChar = 'z'; if( quoteChar != 'z' ) { //find " or ' in ipstring labelsset = true; o[0] = pc+1; //start of label if( (pc=ipstring.indexOf(quoteChar,o[0])) < 0 ) { //error System.out.println("Error, no end to label for: "+ipstring); System.exit(0); } for(k=0; k < (pc-o[0]); ++k ) { city[j].label[k] = ipstring.charAt(o[0]+k); } //city[j].label[k]=0; o[0] = pc; //for next round } else { //make labels = index (or index +1) if -1 is set if( labelsset ) { System.out.println("no label for "+ipstring); System.exit(0); } city[j].label = (Integer.toString(j+1)).toCharArray(); } if (++j==NC) break; } } // Close the file. reader.close(); stream.close(); } catch( IOException e ) { System.out.println(e.getMessage()); System.exit(0); } //set last city equal to the first city[NC] = new CITY(); city[NC].x = city[0].x; city[NC].y = city[0].y; tour = new int[NC]; modtour = new int[NC]; tour[0] = modtour[0] = 0; }//getinputs //=== static void print_tour(int[] tour) { int i,j; int len = (city[0].label).length; for( i=0; i < NC; ++i) { System.out.print((new String(city[tour[i]].label))+" "); } System.out.println(); } //=== static void COPY_PERM(int[] modtour,int[] wbest) { for(int i=0;i < NC;++i) wbest[i]=modtour[i]; } //=== static int numpars(int[] pi, String s) /*:::: scan string s for the next number starting from index *pi, advance *pi to the start of the number. Return value is -1 if no number encountered or the first location following the number otherwise. mod: fix for scientific notation, treat embedded E as a "digit" mod:(12/00) treat leading # as a comment, acts as if end of line ::::*/ { int i; //System.out.println("numpars: pi: "+pi[0]+", s: "+s); //check for error input (negative index) if( pi[0] < 0 || s.length() == 0 ) return -1; //check for comment line, begins with # if( pi[0]==0 && s.charAt(0) == '#' ) return -1; /*--- find beginning of a number ---*/ for(i = pi[0];;++i) { //System.out.print("(1)i now "+i); //if( i < s.length() ) System.out.println(" reading "+s.charAt(i)); //else System.out.println(" last char read was "+s.charAt(i-1)); if( s.length() == i || s.charAt(i) == '\n' || s.charAt(i) == '\r' ) return -1; if( s.charAt(i) >= '0' && s.charAt(i) <= '9' ) break; if( s.charAt(i) == '+' || s.charAt(i) == '-' || s.charAt(i) == '.' ) break; } pi[0] = i; /*--- find extent of the number, E followed by + or - is ok ---*/ for(++i;;++i) { //System.out.print("(2)i now "+i); //if( i < s.length() ) System.out.println(" reading "+s.charAt(i)); //else System.out.println(" last char read was "+s.charAt(i-1)); if( i >= s.length() ) return i; if( s.charAt(i) >= '0' && s.charAt(i) <= '9' ) continue; /*--- possible error here, should "continue" on - too ---*/ if( s.charAt(i) == '.' ) continue; if( s.charAt(i) == 'E' || s.charAt(i) == 'e' ) if( s.charAt(i+1) == '+' || s.charAt(i+1) == '-' ) { ++i; continue;} return i; } } //sss=== static double tourLength(int[] tour) // calculate tour length { double dx,dy,w=0; int i, k=0; //print_tour(tour); for( i=1; i < tour.length; ++i ) { dx = -city[tour[k]].x; dy = -city[tour[k]].y; ++k; dx += city[tour[k]].x; dy += city[tour[k]].y; w += Math.sqrt(dx*dx + dy*dy); //System.out.println("link "+tour[k-1]+" to "+tour[k]+" d= "+ // Math.sqrt(dx*dx + dy*dy)+", sum= "+w); } // pointer at N-1 when done // now get back to first city dx = -city[tour[k]].x; dy = -city[tour[k]].y; dx += city[tour[0]].x; dy += city[tour[0]].y; w += Math.sqrt(dx*dx + dy*dy); //System.out.println("link "+tour[k]+" to "+tour[0]+" d= "+ // Math.sqrt(dx*dx + dy*dy)+", sum= "+w); return w; } //=== static int[] ppr(int[] tour) { int i, j; int k, l; i = 1 + (int)((NC-2)*rndm.nextDouble()); j = i+1 + (int)((NC-i-1)*rndm.nextDouble()); // make up modtour by reversing path from i to j for( k=1; k < i; ++k ) modtour[k] = tour[k]; for( l=j; ; ) { modtour[k++]=tour[l]; if( --l < i ) break; } for( ; k < NC; ++k ) modtour[k] = tour[k]; return modtour; } //=== static void mkperm(int size, int[] perm) { int i,k,r; for( i=1; i < size; ++i) perm[i] = i; for( i=1; i < size-1; ++i) { k = 1+ (int)((size-i)*rndm.nextDouble()); r = perm[k]; for( ; k < size-i; ++k) perm[k] = perm[k+1]; perm[k] = r; } } } //kkk=== class CITY { double x,y; char[] label = {' ',' ',' ',' '}; }
Page 147
Java: Genetic Algorithms, Complete Population Turnover Style import java.io.*; import java.util.*; public class shekelGBS { static String[] helptext = { "Usage:\n\t <invoke program>", ""}; //command line variables static int vfreq=5; //vfreq=0; //hold overs we may yet implement static final int NCEXIT=80000; // no change exit condition //pertains to all instances static int nIterations=50; static int nTrials = 6; static Random r; static long seed; static ArrayList minPerformance = new ArrayList(); static ArrayList maxPerformance = new ArrayList(); //=== problem specifics static final int nBits = 10; //chromo length static final int nStates = -1 + (int)Math.rint(Math.exp(nBits*Math.log(2))); //0..2^nBits-1 static final double range = 10; static double[][] S={ {7.382, 10.295, 0.1613}, {1.972, 4.722, 0.2327}, {8.111, 10.928, 0.2047}, {2.714, 11.052, 0.1579}, {4.022, 3.820, 0.1268}, {5.480, 12.911, 0.0519}, {8.316, 7.974, 0.1340}, {7.771, 8.085, 0.1040}, {1.618, 4.047, 0.1719}, {6.918, 5.310, 0.0665}, {8.571, 13.860, 0.0838}, {9.517, 6.163, 0.2204}}; //max value: 19.32926329141593 at 5.48 /* {7.928, 11.380, 0.1515}, {7.480, 4.714, 0.1339}, {3.739, 7.692, 0.0900}, {1.535, 13.688, 0.0715}, {2.389, 11.687, 0.2139}, {8.236, 9.606, 0.1788}, {3.003, 12.746, 0.1783}, {5.249, 9.565, 0.1780}, {2.132, 9.786, 0.0551}, {3.773, 3.023, 0.1395}, {0.620, 13.985, 0.1181}, {3.929, 13.905, 0.2164}}; //max value: 18.349440998358663 at 2.132 */ //=== genetic specifics int popSize = 12; double pm; //mutation probability, set via constructor double geoRate = 1.0; //pm reduction rate, default to none //ggg=== critterSG[] c0 = new critterSG[popSize]; //ptrs to old critters critterSG[] c1 = new critterSG[popSize]; //ptrs to new critters critterSG bestCrit = new critterSG(this); long fevals=0L; /* keep track of fcn evaluations */ boolean logProg = false; double logBase = 0; //only log fitnesses exceeding this //sss=== double runGA(ArrayList runRecord) { int t = 1; //algorithm time for cooling/stopping purposes int noImprov=0; //no improvement count bestCrit.fitness = 0; //INITIALIZATION, create the population for(int i=0; i < popSize; ++i ) { c0[i] = new critterSG(this,r.nextInt(nStates+1)); //random init c1[i] = new critterSG(this); //System.out.println( //"critter "+i+", x= "+c[i].decode()+" fitness: "+c[i].fitness); } bestCrit.state = c0[0].state; bestCrit.fitness = c0[0].fitness; //EVOLUTION LOOP //initial mututation rate is 1 double[] breakPts = new double[popSize]; double sum, w; //double helpers int k, d, m, mc, x, y; //int helpers critterSG[] temp; //needed for relay int alIndex = 0; //record min/max progress periodically for( t=1; t <= nIterations; ++t) { if( vfreq!=0 && t%vfreq == 0 ) { double min = ((Double)shekelGBS.minPerformance.get(alIndex)).doubleValue(); double max = ((Double)shekelGBS.maxPerformance.get(alIndex)).doubleValue(); //System.out.format( //"before: t= %2d, alIndex= %3d, min= %.3f, max= %.3f, best= %.3f\n", //t,alIndex,min,max,bestCrit.fitness); if( bestCrit.fitness < min ) shekelGBS.minPerformance.set(alIndex,(Double)bestCrit.fitness); if( bestCrit.fitness > max ) shekelGBS.maxPerformance.set(alIndex,(Double)bestCrit.fitness); /* min = ((Double)shekelGBS.minPerformance.get(alIndex)).doubleValue(); max = ((Double)shekelGBS.maxPerformance.get(alIndex)).doubleValue(); System.out.format( "after: t= %2d, alIndex= %3d, min= %.3f, max= %.3f, best= %.3f\n", t,alIndex,min,max,bestCrit.fitness); */ ++alIndex; } //do roulette wheel selection sum=0; for(int i=0; i < popSize; ++i) //make up wheel { sum += c0[i].fitness; breakPts[i] = sum; //System.out.println("breakPt["+i+"]= "+sum); } //select popSize times & add to new critters for( int i=0; i < popSize; ++i) { w = sum*r.nextDouble(); // 0 <= w < sum, provided sum > 0 for( k=0; w>=breakPts[k]; ++k) {} //k selected //System.out.println("w= "+w+" break selected "+(k)); c1[i].state = c0[k].state; c1[i].fitness = c0[k].fitness; c1[i].x = c0[k].x; /* System.out.println(" gen. "+t+", break points:"); for( int g=0; g < popSize; ++g) System.out.println("breakPt["+g+"]= "+breakPts[g]); System.out.println("w= "+w+" break selected "+(k)); */ } /* if( vfreq!=0 && t%vfreq == 0 ){ System.out.println("post RWS pop. for generation "+(t)); for( int i=0; i < popSize; ++i) { System.out.println(""+c1[i].state+" fit: "+c1[i].fitness);} } */ //crossover critters 0 with 1, 2 with 3, etc for( int i=0; i < popSize; i += 2 ) { //select divide point, to right d = 1+r.nextInt(nBits-1); //d=0 or d=nBits just name change //bit mask and complement m = (~0 << d) & nStates; mc = ~m & nStates; //System.out.println("Xover at "+d+" mask: "+m+" complement: "+mc); x = c1[i].state; y = c1[i+1].state; c1[i].state = (x & m) | (y & mc); c1[i+1].state = (x & mc) | (y & m); c1[i].setFitness(); c1[i+1].setFitness(); //System.out.println( //"off1 state= "+c1[i].state+" fit: "+c1[i].fitness); //System.out.println( //"off2 state= "+c1[i+1].state+" fit: "+c1[i+1].fitness); } //check for improvement from mating for( int i=0; i < popSize; ++i) { if( c1[i].fitness > bestCrit.fitness ) { //copy c1[i] into best bestCrit.state = c1[i].state; bestCrit.x = c1[i].x; bestCrit.fitness = c1[i].fitness; noImprov=0; //check whether to print solution if( logProg && bestCrit.fitness > logBase ) { //report(1,0,t); //1=only print value, 0=only for best logBase = bestCrit.fitness; } } } //mutate each bit of each critter //System.out.println("cur. pm "+pm); for( int i=0; i < popSize; ++i ) { for( int j=0; j < nBits; ++j) { if( r.nextDouble() < pm ) { m = (1 << j); //System.out.println("bit "+j+" selected, state before: "+c1[i].state+ //" state after: "+(m^c1[i].state)); c1[i].state ^= m; } } c1[i].setFitness(); } //check for improvement from mutation for( int i=0; i < popSize; ++i) { if( c1[i].fitness > bestCrit.fitness ) { //copy c1[i] into best bestCrit.state = c1[i].state; bestCrit.x = c1[i].x; bestCrit.fitness = c1[i].fitness; noImprov=0; //check whether to print solution if( logProg && bestCrit.fitness > logBase ) { //report(1,0,t); //1=only print value, 0=only for best logBase = bestCrit.fitness; } } } runRecord.add((Double)bestCrit.fitness); //now c1 is the next population temp = c0; c0 = c1; c1 = temp; pm *= geoRate; //update the mutation rate ++noImprov; //update no improvement count } //report(2,0,t); //2= print value & matrix, 0= only for best //System.out.println( //"ending best: "+bestCrit.fitness+" @ x = "+bestCrit.x); return bestCrit.fitness; } //=== double objective( double x) { ++fevals; double y=0; for( int i=0; i < S.length; ++i ) { y += 1/(S[i][1]*S[i][1]*(x-S[i][0])*(x-S[i][0])+S[i][2]); //System.out.println("i= "+i+", y= "+y); } return y; } //ccc=== public shekelGBS(double pm) { this.pm = pm; } //ccc=== public shekelGBS(double pm, double gr) { this.pm = pm; geoRate = gr; } //ccc=== public shekelGBS(double pm, double gr, double logBase) { this.pm = pm; geoRate = gr; logProg = true; this.logBase = logBase; } //rrr=== void report( int rLevel, int todo, long its) { /*:::::: rLevel= extent to report: 0 minimal (just dots), 1 just fitness values 2 fitness values and entire matrix todo= # from top of gene pool to print its iteration count ::::::*/ if( rLevel == 0 ) { System.out.print("."); return;} if( rLevel == 1 ) { System.out.format( "best= %f, #its= %d\n",bestCrit.fitness, its); for( int i=0; i < todo; ++i) System.out.format("critter %2d fitness= %f\n",i,c1[i].fitness); return; } if( rLevel == 2 ) { System.out.format( "best= %f, #its= %d\n", bestCrit.fitness,its); for( int i=0; i < todo; ++i) { System.out.format("critter %2d fitness= %f\n",i,c1[i].fitness); } } } //mmm=== public static void main(String[] args) { seed = System.currentTimeMillis(); // seed = 1190902532283L; // uncomment for testing r = new Random(seed); System.out.println("\nseed: "+seed); double geoRate=1.00; double pm = 0.1; if( args.length >= 1 ) { pm = Double.parseDouble(args[0]); if( args.length >= 2 ) geoRate = Double.parseDouble(args[1]); } int successCount=0; double bestOverAll = 0; double runOut; shekelGBS pprob; ArrayList[] runLogs = new ArrayList[nTrials]; //initialize the min/max record for(int i=1; i <= nIterations; ++i) { if( vfreq!=0 && i%vfreq == 0 ) { minPerformance.add((Double)1000000.); maxPerformance.add((Double)0.); } } for( int i=0; i < nTrials; ++i) { if( i==0 ) pprob = new shekelGBS(pm,geoRate); else pprob = new shekelGBS(pm,geoRate,bestOverAll); runLogs[i] = new ArrayList(); runOut = pprob.runGA(runLogs[i]); if( runOut > bestOverAll ) bestOverAll = runOut; System.out.println("trial "+i+", result= "+runOut); //if( pprob.runGA() != 0 ) ++successCount; } System.out.println( "in "+nTrials+" trials, best overall= "+bestOverAll); for( int i=0; i < nTrials; ++i) { System.out.println("run "+i+" record"); for( int t=0; t < runLogs[0].size(); ++t) { System.out.format("t= %3d, best= %.3f\n", (t+1),((Double)runLogs[i].get(t)).doubleValue()); } } System.out.println( "min/max record every "+vfreq+" over "+nTrials+" runs"); for( int j=0; j < minPerformance.size(); ++j) { System.out.format( "j= %4d, min %.3f, max %.3f\n",(j+1)*vfreq, ((Double)minPerformance.get(j)).doubleValue(), ((Double)maxPerformance.get(j)).doubleValue()); } // System.out.println("geo. rate= "+geoRate); //", success rate: "+successCount/(double)nTrials); } } //kkk=== class critterSG //Shekel problem critter { //state holds the bits int state=0; //0..2^nBits-1 = nStates, divide to get the range double x; // x = range*(state/nStates) double fitness=0; shekelGBS sgb; int[] chromo; //no longer needed //ccc=== public critterSG(shekelGBS s) { sgb = s; state = 0; setFitness(); } //=== public critterSG(shekelGBS s,int k) { sgb = s; state = k; setFitness(); } //=== /** * decode: from chromosome to state * obsolete, no longer needed */ int decode() { state = chromo[0]; //System.out.println("starting state = chromo[0] = "+state); int base = 2; for( int i=1; i < shekelGBS.nBits; ++i) { state += base*chromo[i]; //System.out.println("chromo["+i+"]= "+chromo[i]+", state now= "+state); base *= 2; } return state; } //=== /** * encode: from state to chromosome * obsolete, no longer needed */ void encode() { int k = state; //from least significant to most significant for( int i=0; i < shekelGBS.nBits; ++i) { chromo[i] = k%2; k /= 2; //System.out.println("encode: k= "+k+", chromo["+i+"]]= "+chromo[i]); } } //=== void setFitness() { x = sgb.range*(state/(double)shekelGBS.nStates); fitness = sgb.objective(x); } }
Page 148
Java: Genetic Algorithms, Sorted Rank Style import java.io.*; import java.util.*; public class shekelRSS { static String[] helptext = { "Implementation of the RS style GA for the shekel problem.", "Usage:\n\t < invoke program>", ""}; //command line variables static int vfreq=5; //vfreq=0; //hold overs we may yet implement static final int NCEXIT=80000; // no change exit condition //pertains to all instances static int nIterations=50; static int nTrials = 6; static Random r; static long seed; static ArrayList minPerformance = new ArrayList(); static ArrayList maxPerformance = new ArrayList(); static final int BUGINVALID=-1; //mark popspace free static final double tempSTART=0.88; static final int STDZ=12; //population size static final int HALFSTDZ=STDZ/2; //half std pop size static final int THREEQSTD=3*STDZ/4; // 3 quarters std pop size static final int POPSPACE=3*STDZ; //space for critters static final int MAXMATE=THREEQSTD; //max number of matings static final int MAXMUTE=HALFSTDZ; // max number of mutations //=== problem specifics static final int nBits = 20; //chromo length static final int nStates = -1 + (int)Math.rint(Math.exp(nBits*Math.log(2))); //0..2^nBits-1 static final double range = 10; static double[][] S={ {7.382, 10.295, 0.1613}, {1.972, 4.722, 0.2327}, {8.111, 10.928, 0.2047}, {2.714, 11.052, 0.1579}, {4.022, 3.820, 0.1268}, {5.480, 12.911, 0.0519}, {8.316, 7.974, 0.1340}, {7.771, 8.085, 0.1040}, {1.618, 4.047, 0.1719}, {6.918, 5.310, 0.0665}, {8.571, 13.860, 0.0838}, {9.517, 6.163, 0.2204}}; //max value: 19.32926329141593 at 5.48 //ggg=== critterSP[] c0 = new critterSP[POPSPACE]; //ptrs to critters critterSP bestCrit = new critterSP(this); int[] role = new int[POPSPACE]; long fevals=0L; /* keep track of fcn evaluations */ boolean logProg = false; double logBase = 0; //only log fitnesses exceeding this //sss=== double runGA(ArrayList runRecord) { int t = 1; //algorithm time for cooling/stopping purposes int z=0; //current population size int noImprov=0; //no improvement count bestCrit.fitness = 0; double[] af = new double[1]; double temp; //temperature, using as RR living prob. //mark population slots free for( int i=0; i < POPSPACE; ++i ) { c0[i] = new critterSP(this); c0[i].fitness = BUGINVALID; } //INITIALIZATION, create the population af[0]=0; z=0; for(int i=0; i < STDZ; ++i ) { c0[i].state = r.nextInt(nStates+1); //random init c0[i].setFitness(); z = merge(-1,i,af,z); /* sense = -1 for maximization */ } //EVOLUTION LOOP int nmate = MAXMATE; //currently 6 int nmute = MAXMUTE; //current 6 int dltz=0; int ni, k; //int helpers int alIndex = 0; outerLoop: //block label for( t=1; t < = nIterations; ++t) { if( vfreq!=0 && t%vfreq == 0 ) { double min = ((Double)shekelRSS.minPerformance.get(alIndex)).doubleValue(); double max = ((Double)shekelRSS.maxPerformance.get(alIndex)).doubleValue(); //System.out.format( //"before: t= %2d, alIndex= %3d, min= %.3f, max= %.3f, best= %.3f\n", //t,alIndex,min,max,bestCrit.fitness); if( bestCrit.fitness < min ) shekelRSS.minPerformance.set(alIndex,(Double)bestCrit.fitness); if( bestCrit.fitness > max ) shekelRSS.maxPerformance.set(alIndex,(Double)bestCrit.fitness); /* min = ((Double)shekelRSS.minPerformance.get(alIndex)).doubleValue(); max = ((Double)shekelRSS.maxPerformance.get(alIndex)).doubleValue(); System.out.format( "after: t= %2d, alIndex= %3d, min= %.3f, max= %.3f, best= %.3f\n", t,alIndex,min,max,bestCrit.fitness); */ ++alIndex; } //hhh for( int i=0; i < nmute; ++i) { if( (ni = getslot()) < 0 ) break; //no free slots //pick random one to mutate k = r.nextInt(z); z = mutate(c0[role[k]],ni,af,z); } //mating (cross-over) step // mate top half, find mate at random (among current pop.) for( int m=0; m < nmate; ++m ) { if((ni = getslot()) < 0 ) break; //no free slots //random population member k = r.nextInt(z); if( m < nmate-1 ) { z = mate(c0[role[m]],c0[role[k]],ni,af,z); } else //do wrong-side-of-tracks for the last one z = mate(c0[role[m]],new critterSP(this),ni,af,z); } //check for improvement if( c0[role[0]].fitness > bestCrit.fitness ) { //copy c0[role[0]] into best bestCrit.state = c0[role[0]].state; bestCrit.x = c0[role[0]].x; bestCrit.fitness = c0[role[0]].fitness; noImprov=0; //check whether to print solution if( logProg && bestCrit.fitness > logBase ) { //report(1,0,t); //1=only print value, 0=only for best logBase = bestCrit.fitness; } } //check for no change exit if( ++noImprov == NCEXIT ) break; //select down the population size for( dltz=STDZ-z; dltz < 0; ++dltz) z = removal(gauntlet(tempSTART,z),af,z); runRecord.add((Double)bestCrit.fitness); } //report(2,0,t); //2=print value & matrix, 0=only for best //System.out.println( //"ending best: "+bestCrit.fitness+" @ x = "+bestCrit.x); return bestCrit.fitness; } //=== double objective( double x) { ++fevals; double y=0; for( int i=0; i < S.length; ++i ) { y += 1/(S[i][1]*S[i][1]*(x-S[i][0])*(x-S[i][0])+S[i][2]); //System.out.println("i= "+i+", y= "+y); } return y; } //ccc=== public shekelRSS() { } //ccc=== public shekelRSS(double logBase) { logProg = true; this.logBase = logBase; } //=== public int merge(int sense,int i, double[] af, int cs) /*:::::::: merge critter i into role according to rank via fitness sense= +1, small to big, i.e. minimization sense= -1, big to small, maximization i= index of this critter af= average fitness, cs= present population size return new population size :::::::*/ { int m, k, j; int z = cs; //insert newbug according to its fitness for( m=0; ; ++m) { if( m == z ) break; if( sense*c0[role[m]].fitness > sense*c0[i].fitness ) break; } //goes into slot m, see if room and update avg fitness af[0] *= z; //sum of fitnesses if( z < POPSPACE ) //have room, so add { ++z; af[0] = (af[0] + c0[i].fitness)/z; } else { //no room, knock off last af[0] += c0[i].fitness - c0[POPSPACE-1].fitness; af[0] = (af[0] + c0[i].fitness)/z; } for( j=z-2; j>=m; j--) role[j+1] = role[j]; role[m] = i; return z; } //=== public int getslot() { int i; for(i=0; i < POPSPACE; ++i ) if( c0[i].fitness == BUGINVALID ) return i; return -1; } //rrr=== void report( int rLevel, int todo, long its) { /*:::::: rLevel= extent to report: 0 minimal (just dots), 1 just fitness values 2 fitness values and entire matrix todo= # from top of gene pool to print its iteration count ::::::*/ if( rLevel == 0 ) { System.out.print("."); return;} if( rLevel == 1 ) { System.out.format( "best= %.3f, #its= %d\n",bestCrit.fitness,its); for( int i=0; i < todo; ++i) System.out.format("critter %4d fitness= %.3f\n",i,c0[i].fitness); return; } if( rLevel == 2 ) { System.out.format("best= %.3f, #its= %d\n",bestCrit.fitness,its); for( int i=0; i < todo; ++i) { System.out.format( "critter %4d fitness= %.3f, x= %.3f\n",i,c0[i].fitness,c0[i].x); } } } //mmm=== public static void main(String[] args) { seed = System.currentTimeMillis(); // seed = 1174741248177L; // uncomment for testing r = new Random(seed); System.out.println("\nseed: "+seed); int successCount=0; double bestOverAll = 0; double runOut; shekelRSS rss; ArrayList[] runLogs = new ArrayList[nTrials]; //initialize the min/max record for(int i=1; i <= nIterations; ++i) { if( vfreq!=0 && i%vfreq == 0 ) { minPerformance.add((Double)1000000.); maxPerformance.add((Double)0.); } } for( int i=0; i < nTrials; ++i) { if( i==0 ) rss = new shekelRSS(); else rss = new shekelRSS(bestOverAll); runLogs[i] = new ArrayList(); runOut = rss.runGA(runLogs[i]); if( runOut > bestOverAll ) bestOverAll = runOut; System.out.println("trial "+i+", result= "+runOut); } for( int i=0; i < nTrials; ++i) { System.out.println("run "+i+" record"); for( int t=0; t < runLogs[0].size(); ++t) { System.out.format("t= %3d, best= %.3f\n", t,((Double)runLogs[i].get(t)).doubleValue()); } } System.out.println( "min/max record every "+vfreq+" over "+nTrials+" runs"); for( int j=0; j < minPerformance.size(); ++j) { System.out.format( "j= %4d, min %.3f, max %.3f\n",(j+1)*vfreq, ((Double)minPerformance.get(j)).doubleValue(), ((Double)maxPerformance.get(j)).doubleValue()); } System.out.println( "in "+nTrials+" trials, best overall= "+bestOverAll); } //=== /** * crossover style mating, keep one offspring randomly */ int //return updated value of z mate( critterSP c1, critterSP c2, int ni, double[] af, int z) { int k, d, m, mc, x, y; //int helpers //select divide point, to right d = 1+r.nextInt(nBits-1); //d=0 or d=nBits just name change //bit mask and complement m = (~0 << d) & nStates; mc = ~m & nStates; //System.out.println( //"Xover at "+d+" mask: "+m+" complement: "+mc); x = c1.state; y = c2.state; //sometimes keep front half, sometimes the back half if( r.nextDouble() < 0.5 ) { c0[ni].state = (x & m) | (y & mc); } else { c0[ni].state = (x & mc) | (y & m); } c0[ni].setFitness(); //System.out.println( //"off1 state= "+c1[i].state+" fit: "+c1[i].fitness); //System.out.println( //"off2 state= "+c1[i+1].state+" fit: "+c1[i+1].fitness); return merge(-1,ni,af,z); } //=== /** * flip one bit at random */ int mutate(critterSP crit, int ni, double[] af, int z) { //copy crit into slot ni c0[ni].state = crit.state; for( int i=0; i < 1; ++i) { //bit to flip int k = r.nextInt(nBits); int m = (1 << k); c0[ni].state ^= m; } c0[ni].setFitness(); //merge rank return merge(-1,ni,af,z); } //=== int //return rank for reaping gauntlet(double livprob,int z) /*:::::: "Russian" roulette scheme, start at the bottom rank and work up. Independent of max/min sense ::::::*/ { int kr; //Establish bug at risk, start at bottom of role for( kr = z-1; ; ) { if( r.nextDouble() > livprob) break; //livprob= prob. of surviving if( kr == 0) { //cycled, tap random from bottom 2/3 kr = (int)(0.66*z*r.nextDouble()); //first top 2/3 break; } kr--; } return kr; } //=== int //return new population size removal(int kr, double[] af, int cs) /*::::: sense independent, works for maximization or minimization, uses rank according to the role. kr; rank for reaping cs; colony size :::::*/ { int ki,i; int z=cs; ki = role[kr]; // killed bug index, fitness rank kr //remove bug ki = role[kr] af[0] *= z; /* this is total fitness */ --z; //following should work even if fitness is integer af[0] = (af[0] - c0[ki].fitness)/z; //must re-merge c0[ki].fitness = BUGINVALID; //invalid mark for index ki for( i=kr; i < z; ++i ) role[i] = role[i+1]; return z; } } //kkk=== class critterSP //Shekel problem critter { //state holds the bits int state=0; //0..2^nBits-1 = nStates, divide to get the range double x; // x = range*(state/nStates) double fitness=0; shekelRSS srs; int[] chromo; //ccc=== public critterSP(shekelRSS s) { srs = s; state = 0; setFitness(); } //=== public critterSP(shekelRSS s,int k) { srs = s; state = k; setFitness(); } //=== /** * decode: from chromosome to state */ int decode() { state = chromo[0]; int base = 2; for( int i=1; i < shekelRSS.nBits; ++i) { state += base*chromo[i]; base *= 2; } return state; } //=== /** * encode: from state to chromosome */ void encode() { int k = state; //from least significant to most significant for( int i=0; i < shekelRSS.nBits; ++i) { chromo[i] = k%2; k /= 2; } //System.out.println("encode: k= "+k+", chromo["+i+"]]= "+chromo[i]); } //=== void setFitness() { x = srs.range*(state/(double)shekelRSS.nStates); fitness = srs.objective(x); } }
Page 154
Matlab: Computing the Permanent % mat is an nxn 0/1 matrix % used is an n-dim. array function y=permrecurse(level,n,used,mat,v) if level == n+1 y=v+1; else for i=1:n if used(i) == 0 & mat(level,i) ~= 0 used(i)=1; v = permrecurse(level+1,n,used,mat,v); used(i)=0; end end y=v; end
Page 155
Fortran: Non-recursive 0/1 Permanent Algorithm c23456789 PROGRAM PERMNR C INTEGER N,A(15,15) INTEGER PER, PERM(15), OD(15) COMMON A,PERM,OD,PER C N=3 DATA A(1,1),A(1,2),A(1,3)/1,0,1/ DATA A(2,1),A(2,2),A(2,3)/0,1,1/ DATA A(3,1),A(3,2),A(3,3)/1,1,1/ C DO 10, I=1,N 10 PERM(I)=I CALL ODOMETER(N) C the permanent of A is now in PER print *,'PER= ',PER STOP END C SUBROUTINE CP(N) INTEGER N,A(15,15) INTEGER PER, PERM(15), OD(15) COMMON A,PERM,OD,PER DO 10, I=1,N IF (A(I,PERM(I)).EQ.0) RETURN 10 CONTINUE PER = PER+1 RETURN END C SUBROUTINE ODOMETER(N) INTEGER N,A(15,15) INTEGER PER, PERM(15), OD(15) COMMON A,PERM,OD,PER DO 10, I=1,N 10 OD(I) = 0 I = N-1 20 CONTINUE IF (OD(I) .GT. N-I) THEN OD(I) = 0 I=I-1 IF (I .LT. 1) GOTO 100 ELSE K=PERM(I) PERM(I)=PERM(I+1) PERM(I+1)=K IF (OD(I) .EQ. N-I) THEN DO 30, J=I+1,N-I K=PERM(J) PERM(J) = PERM(J+1) 30 PERM(J+1) = K END IF CALL CP(N) I=N-1 END IF OD(I)=OD(I)+1 GOTO 20 100 RETURN END c234567