Mercurial > projects > aid
diff trunk/ga_maze.d @ 0:4b2e8e8a633e
Repository setup.
author | revcompgeek |
---|---|
date | Mon, 03 Mar 2008 19:28:10 -0700 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trunk/ga_maze.d Mon Mar 03 19:28:10 2008 -0700 @@ -0,0 +1,331 @@ +/++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + Genetic Algorithm Maze Test + + + Author: Matt P. + + + Version: 0.5 + + + + + + Runs a genetic algorithm test using a maze generation + + + and guessing algorithm. + + + + + + Usage: ga_maze [options] + + + Options: + + + -h + + + Prints this information. + + + -v + + + Turns on verbose output. + + + -m float + + + Specifies the mutation rate for each generation. + + + Default: 0.05 + + + + + + -d float + + + Specifies the survival rate for each generation. + + + Default: 0.5 + + + + + + -p integer + + + Specifies the population for each generation. + + + Default: 1000 + + + + + + -l integer + + + Specifies the maximum length of the solution code.+ + + Default: 20 + + + + + + -r integer + + + Specifies the number of times to repeat the test. + + + Default: 20 + + + + + + -c char + + + Specifies the crossover type + + + s / 1 - One point crossover + + + t / 2 - Two point crossover + + + u / 3 - Uniform crossover + + + Default: s + + + + + + -s integer integer + + + Specifies the size of the maze + + + Default: 7 7 + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/ + + +module ga_maze; + +import aid.ga; +import tango.math.Random; +import tango.math.Math; +import tango.io.Stdout; +//import tango.text.String; +import Float = tango.text.convert.Float; +import Integer = tango.text.convert.Integer; + +import bcd.sys.times; + +char[] chars = "NESW"; + +//int numChars = 20; +int stringLen = 28; + +bool[][] maze; +int w = 7; +int h = 7; + +double average(double[] array){ + double avg = 0; + foreach (double v; array) + avg += v; + avg /= array.length; + return avg; +} + +double stdDev(double[] array){ + double avg = average(array); + double stddev = 0; + foreach (double v; array){ + stddev += (v - avg) * (v - avg); + } + stddev = sqrt(stddev/array.length); + return stddev; +} + +bool[][] generateMaze(uint width, uint height){ + bool[][] maze; + + maze.length = width; + + for (auto i = 0; i < width; i++){ + maze[i].length = height; + } + + bool rowStart = true; + bool vertical; + for (auto i = 1; i < width; i+=2){ + vertical = rowStart; + rowStart = !rowStart; + + for (auto j = 1; j < height; j+=2){ + maze[i][j] = true; + if (vertical) + maze[i + ((Random.shared.next(2)-1)?-1:1)][j] = true; + else + maze[i][j + ((Random.shared.next(2)-1)?-1:1)] = true; + vertical = !vertical; + } + } + + return maze; +} + +void printMaze(bool[][] m, bool[][] trail = null,char e = '.', char f = 'X', bool outline = true){ + if (outline){ + Stdout("+"); + for (auto j = 0; j < m[0].length; j++){ + Stdout("-"); + } + Stdout("+").newline; + } + + for (auto i = 0; i < m.length; i++){ + if (outline) Stdout("|"); + for (auto j = 0; j < m[i].length; j++){ + if(m[i][j]) Stdout(""~f); + else if(trail && trail[i][j]) Stdout("+"); + else Stdout(""~e); + } + if (outline) Stdout("|").newline; + } + if (outline){ + Stdout("+"); + for (auto j = 0; j < m[0].length; j++){ + Stdout("-"); + } + Stdout("+").newline; + } +} + +/++++++++++++++++++++++++++ Foo ++++++++++++++++++++++++++++++/ + +class Foo { + int count = 0; + public double calculateFitness(char[] gene){ + + bool canMove(int x, int y){ + return ((x >= 0) && (x < w) && (y >= 0) && (y < h) && (!maze[x][y])); + } + + double square(int v){ + return v*v; + } + + /*bool[][] trail; + + trail.length = w; + for(uint i = 0; i < w; i++){ + trail[i].length = h; + }*/ + + double fitness=0; + int x = 0; + int y = 0; + for (uint i = 0; i < gene.length; i++){ + //trail[x][y] = true; + //Stdout(""~gene[i]); + if(gene[i] == 'N' && canMove(x,y-1)) y--; + if(gene[i] == 'E' && canMove(x+1,y)) x++; + if(gene[i] == 'S' && canMove(x,y+1)) y++; + if(gene[i] == 'W' && canMove(x-1,y)) x--; + + if (x == w-1 && y == h-1){ + return 100; + } + } + + fitness = 100 - sqrt(square(x-(w-1)) + square(y-(h-1))); + /*if(count < 20){ + Stdout.format("{} {:.4}",gene,fitness).newline; + //printMaze(maze,trail); + count++; + }*/ + return fitness; + } + + public char[] getRandomGenotype(){ + char[] t; + t.length = stringLen; + for (int i = 0; i < stringLen; i++){ + t[i] = chars[Random.shared.next(chars.length)]; + } + return t; + } + + public char getRandomChar(uint index){ + return chars[Random.shared.next(chars.length)]; + } +} + +/++++++++++++++++++++++ End Foo ++++++++++++++++++++++++++++++/ + +void usage(){ + auto s = + "Usage: ga_maze [options] \n" + "Options: \n" + "-h \n" + " Prints this information. \n" + "-v \n" + " Turns on verbose output. \n" + "-m float \n" + " Specifies the mutation rate for each generation. \n" + " Default: 0.05 \n" + " \n" + "-d float \n" + " Specifies the survival rate for each generation. \n" + " Default: 0.5 \n" + " \n" + "-p integer \n" + " Specifies the population for each generation. \n" + " Default: 1000 \n" + " \n" + "-l integer \n" + " Specifies the maximum length of the solution code.\n" + " Default: 20 \n" + " \n" + "-n integer \n" + " Specifies how many possibilities there are for \n" + " each character of the code string. \n" + " Default: 20 \n" + " \n" + "-r integer \n" + " Specifies the number of times to repeat the test. \n" + " Default: 20 \n" + " \n" + "-c char \n" + " Specifies the crossover type \n" + " s / 1 - One point crossover \n" + " t / 2 - Two point crossover \n" + " u / 3 - Uniform crossover \n" + " Default: s "; + Stdout(s).newline; +} + +void main(char[][] args){ + Foo f = new Foo(); + GeneticAlgorithm ga = new GeneticAlgorithm(); + ga.calculateFitness = &f.calculateFitness; + ga.getRandomGenotype = &f.getRandomGenotype; + ga.getRandomChar = &f.getRandomChar; + ga.fitnessThreshold = 100; + int rep = 20; + bool dotime = true; + + + for (auto i = 1; i < args.length; i++){ + char[] arg = args[i]; + switch (arg){ + case "-h": + usage(); + return; + case "-m": + ga.mutationRate = Float.parse(args[++i]); + break; + case "-d": + ga.survivalRate = Float.parse(args[++i]); + break; + case "-p": + ga.startPopulation = Integer.parse(args[++i]); + break; + case "-l": + stringLen = Integer.parse(args[++i]); + //ga.fitnessThreshold = stringLen; + break; + case "-r": + rep = Integer.parse(args[++i]); + break; + case "-v": + ga.verbose = true; + break; + case "-s": + w = Integer.parse(args[++i]); + h = Integer.parse(args[++i]); + stringLen = 2*(w+h); + break; + case "-c": + auto t = args[++i]; + switch (t){ + case "s","1": + ga.crossoverType = 1; + break; + case "t","2": + ga.crossoverType = 2; + break; + default: + ga.crossoverType = 3; + } + break; + case "-b": + ga.bailout = Integer.parse(args[++i]); + break; + case "-t": + dotime = false; + break; + default: + Stdout.format("Unknown parameter: {}",arg).newline; + usage(); + return; + } + } + + double[] time; + double[] gens; + long start,end; + double generations; + + for(auto i = 0; i < rep; i++){ + maze=generateMaze(w,h); + + if(dotime) start = iutime(); + generations = ga.run(); + if(dotime) end = iutime() - start; + + if(dotime) time ~= end; + gens ~= generations; + } + + if(dotime) Stdout.format("{0}, {1:.5}, {2}, {3:.5}", average(gens),stdDev(gens),average(time),stdDev(time)).newline; + else Stdout.format("{0}, {1:.5}", average(gens),stdDev(gens)).newline; //", {2}, {3:.5}" ,average(time),stdDev(time) +} \ No newline at end of file