// gpjpp example program // Copyright (c) 1997, Kim Kokkonen // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // Send comments, suggestions, problems to kimk@turbopower.com import java.io.*; import gpjpp.*; //Othello Result class GPOthello extends GPRun { //must override GPRun.createNodeSet to return // initialized set of functions & terminals protected GPAdfNodeSet createNodeSet(GPVariables cfg) { GPAdfNodeSet adfNs = new GPAdfNodeSet(); if (cfg.UseADFs) { /* adfNs.reserveSpace(2); GPNodeSet ns0 = new GPNodeSet(6); GPNodeSet ns1 = new GPNodeSet(4); adfNs.put(0, ns0); adfNs.put(1, ns1); //RPB has 4 functions plus ADF ns0.putNode(new GPNode('+', " + ", 2)); ns0.putNode(new GPNode('-', " - ", 2)); ns0.putNode(new GPNode('*', " * ", 2)); ns0.putNode(new GPNode('%', " / ", 2)); ns0.putNode(new GPNode('A', " ADF0 ", 2)); ns0.putNode(new GPNode('X', "x")); //ADF0 does only + and * functions ns1.putNode(new GPNode('+', "+", 2)); ns1.putNode(new GPNode('*', "*", 2)); ns1.putNode(new GPNode(1, "x1")); ns1.putNode(new GPNode(2, "x2")); */ } else { adfNs.reserveSpace(1); GPNodeSet ns0 = new GPNodeSet(25); adfNs.put(0, ns0); ns0.putNode(new GPNode('+', " + ", 2)); ns0.putNode(new GPNode('-', " - ", 2)); ns0.putNode(new GPNode('*', " * ", 2)); ns0.putNode(new GPNode('%', " / ", 2)); ns0.putNode(new GPNode('a', " a ")); ns0.putNode(new GPNode('A', " A ")); ns0.putNode(new GPNode('b', " b ")); ns0.putNode(new GPNode('B', " B ")); ns0.putNode(new GPNode('c', " c ")); ns0.putNode(new GPNode('C', " C ")); ns0.putNode(new GPNode('d', " d ")); ns0.putNode(new GPNode('D', " D ")); ns0.putNode(new GPNode('e', " e ")); ns0.putNode(new GPNode('E', " E ")); ns0.putNode(new GPNode('f', " f ")); ns0.putNode(new GPNode('F', " F ")); ns0.putNode(new GPNode('g', " g ")); ns0.putNode(new GPNode('G', " G ")); ns0.putNode(new GPNode('h', " h ")); ns0.putNode(new GPNode('H', " H ")); ns0.putNode(new GPNode('i', " i ")); ns0.putNode(new GPNode('I', " I ")); ns0.putNode(new GPNode('j', " j ")); ns0.putNode(new GPNode('J', " J ")); ns0.putNode(new GPNode(10, " 10 ")); } return adfNs; } //must override GPRun.createPopulation to return // SymbReg-specific population protected GPPopulation createPopulation(GPVariables cfg, GPAdfNodeSet adfNs) { return new GPOthelloPopulation(cfg, adfNs); } //construct this test case GPOthello(String baseName) { super(baseName, true); } //main application function public static void main(String[] args) { //compute base file name from command line parameter String baseName; if (args.length == 1) baseName = args[0]; else baseName = "GPOthello"; // GPOthelloGP.evaluatetest(); //construct the test case GPOthello test = new GPOthello(baseName); //run the test test.run(); //make sure all threads are killed System.exit(0); } } //===================================================================== //extend GPGene to evaluate equations class GPOthelloGene extends GPGene { // Overwritting to get our own testing data. // public void drawOn(GPDrawing ods, // String fname, // String title, // GPVariables cfg) throws IOException { // super.drawOn(ods,fname,title,cfg); // // System.out.println("We are HERE!"); //} //public null constructor required during stream loading only //this constructor called when new genes are created GPOthelloGene(GPNode gpo) { super(gpo); } //this constructor called when genes are cloned during reproduction GPOthelloGene(GPOthelloGene gpo) { super(gpo); } //called when genes are cloned during reproduction protected Object clone() { return new GPOthelloGene(this); } //ID routine isA() required only for streams //must override GPGene.createChild to create AntGene instances public GPGene createChild(GPNode gpo) { return new GPOthelloGene(gpo); } //protected divide, here protected by IEEE floating point standards double divide(double x, double y) { //return NaN or INF if y = 0 if (y==0) { return x; } else return x/y; } //called by OthelloGP.evaluate() for each branch of each GP //evaluate works with or without ADFs double evaluate( double aa, double AA, double bb, double BB, double cc, double CC, double dd, double DD, double ee, double EE, double ff, double FF, double gg, double GG, double hh, double HH, double ii, double II, double jj, double JJ, GPOthelloGP gp, double arg0, double arg1) { double ret = 0.0; //avoid compiler error if (isFunction()) { switch (node.value()) { case '*': ret = ((GPOthelloGene)get(0)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1) * ((GPOthelloGene)get(1)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1); break; case '+': ret = ((GPOthelloGene)get(0)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1) + ((GPOthelloGene)get(1)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1); break; case '-': ret = ((GPOthelloGene)get(0)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1) - ((GPOthelloGene)get(1)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1); break; case '%': //use protected divide function ret = divide(((GPOthelloGene)get(0)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1), ((GPOthelloGene)get(1)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1)); break; case 'Z': //ADF0 function call. We have access to that // subtree, as the GP gave us a reference to itself as // parameter. We first evaluate the subtrees, and then // call the adf with the parameters double a0 = ((GPOthelloGene)get(0)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1); double a1 = ((GPOthelloGene)get(1)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, arg0, arg1); ret = ((GPOthelloGene)gp.get(1)).evaluate(aa,AA,bb,BB,cc,CC,dd,DD,ee,EE,ff,FF,gg,GG,hh,HH,ii,II,jj,JJ, gp, a0, a1); break; default: throw new RuntimeException("Undefined function type "+node.value()); } } else { //is terminal switch (node.value()) { case 'a': ret = aa; break; case 'A': ret = AA; break; case 'b': ret = bb; break; case 'B': ret = BB; break; case 'c': ret = cc; break; case 'C': ret = CC; break; case 'd': ret = dd; break; case 'D': ret = DD; break; case 'e': ret = ee; break; case 'E': ret = EE; break; case 'f': ret = ff; break; case 'F': ret = FF; break; case 'g': ret = gg; break; case 'G': ret = GG; break; case 'h': ret = hh; break; case 'H': ret = HH; break; case 'i': ret = ii; break; case 'I': ret = II; break; case 'j': ret = jj; break; case 'J': ret = JJ; break; case 10: ret = 10; break; case 1: ret = arg0; break; case 2: ret = arg1; break; default: throw new RuntimeException("Undefined terminal type "+node.value()); } } return ret; } } //===================================================================== class GPOthelloGP extends GP { // define relevant parameters. static double[][] dataMoves = new double[200][8]; // The training data static int numMoves = 0; static double lowRank = - 1000000; //define fitness cases //initialize test case values This is for doing stuff before the // system starts training. Put code here if you want to do it. /* static { try { FileInputStream istream = new FileInputStream("traindata"); StreamTokenizer myTok = new StreamTokenizer(istream); myTok.parseNumbers(); int counter = 0; do { myTok.nextToken(); if (myTok.ttype == myTok.TT_NUMBER) { double thisNum = myTok.nval; dataMoves[counter / 8][counter % 8] = thisNum; counter++; } else { System.out.println("Read a string: " + myTok.sval + "at counter " + counter); } } while (myTok.ttype != myTok.TT_EOF); numMoves = counter / 8; System.out.println("Read data file. Number of moves = " + numMoves+ ". "); } catch (Exception e) {System.out.println("An Error Occured Reading the data file.");} }*/ //public null constructor required during stream loading only //this constructor called when new GPs are created GPOthelloGP(int genes) { super(genes); } //this constructor called when GPs are cloned during reproduction GPOthelloGP(GPOthelloGP gpo) { super(gpo); } //called when GPs are cloned during reproduction protected Object clone() { return new GPOthelloGP(this); } //must override GP.createGene to create GPOthelloGene instances public GPGene createGene(GPNode gpo) { return new GPOthelloGene(gpo); } //must override GP.evaluate to return standard fitness // Code is from evaluating the fitness measure. put your code here if you want. /* static void evaluatetest() { double rawFitness = 0.0; double lastValue = lowRank; double lastEdgarValue = lowRank; for (int i = 0; i < numMoves; i++) { //double rating = ((GPOthelloGene)get(0)).evaluate(dataMoves[i][2], // dataMoves[i][3], // dataMoves[i][4], // dataMoves[i][5], // dataMoves[i][6], // dataMoves[i][7], // this, 0, 0); double rating = dataMoves[i][2] - dataMoves[i][3] + 5*(dataMoves[i][4]*dataMoves[i][4]) - 5*(dataMoves[i][5]*dataMoves[i][5]) + 10*(dataMoves[i][6]*dataMoves[i][6]*dataMoves[i][6]) - 10*(dataMoves[i][7]*dataMoves[i][7]*dataMoves[i][7]); String output = "" + dataMoves[i][0] + ": " + dataMoves[i][2] + " " + dataMoves[i][3] + " " + dataMoves[i][4] + " " + dataMoves[i][5] + " " + dataMoves[i][6] + " " + dataMoves[i][7] + " Rating = " + rating + " "; // if (Double.isNaN(rating) || Double.isInfinite(rating)) { //set maximum error // return 1.0E30; //} if (dataMoves[i][0]==1) { lastValue = rating; } else if ((lastValue > rating) && (dataMoves[i][1] != lastEdgarValue)){ //add absolute error to rawFitness rawFitness += 1; output = output + "Fitness = " + rawFitness; } System.out.println(output); lastEdgarValue = dataMoves[i][1]; } double stdF = rawFitness; System.out.println("The test rating is " + stdF); }*/ // Fitness is actually evaluede here.evaluated here. public double evaluate(GPVariables cfg) { double rawFitness = 0.0; double stdF = 0.0; OthelloBoard board; OthelloPlayer blackPlayer = new OthelloGPTester(OthelloBoard.BLACK,this); OthelloPlayer whitePlayer = new OthelloEdgar(); Move currentMove; // Play some games and evaluate the board. int numGames = 1; for (int i=0; i board.score[OthelloBoard.WHITE]) { // we won so add .1 per piece System.out.println("Won " + board.score[OthelloBoard.BLACK] + " " + board.score[OthelloBoard.WHITE]); rawFitness = board.score[OthelloBoard.WHITE]/10; } else { // we lost so add 1 per piece System.out.println("Lost " + board.score[OthelloBoard.BLACK] + " " + board.score[OthelloBoard.WHITE]); rawFitness = board.score[OthelloBoard.WHITE]; } stdF += rawFitness; } // This boolean is set in the ini file. if (cfg.ComplexityAffectsFitness) //add .01 per unit length stdF += ((double)length()/100); System.out.println("Standard Fitness for individual after " + numGames + " game(s) = "+ stdF); return stdF; } } //===================================================================== //extend GPPopulation to create GPOthello GP trees class GPOthelloPopulation extends GPPopulation { //this constructor called when new populations are created GPOthelloPopulation(GPVariables gpVar, GPAdfNodeSet adfNs) { super(gpVar, adfNs); } //populations are not cloned in standard runs //GPOthelloPopulation(GPOthelloPopulation gpo) { super(gpo); } //protected Object clone() { return new GPOthelloPopulation(this); } //must override GPPopulation.createGP to create GPOthelloGP instances public GP createGP(int numOfGenes) { return new GPOthelloGP(numOfGenes); } }