| 1 | // galib-queens.C - N Queens w/galib -*- C++ -*- |
|---|
| 2 | // |
|---|
| 3 | // N-Queens solution search by Genetic Algorithms. This demo code was |
|---|
| 4 | // used to show how tabu search is much faster on this problem. Tabu |
|---|
| 5 | // search is also a simpler to implement right because it has fewer |
|---|
| 6 | // variables to act on. |
|---|
| 7 | // |
|---|
| 8 | // Copyright (C) 2006 Mirko Maischberger <mirko.maischberger@gmail.com>, |
|---|
| 9 | // Paolo Vaccari <paoz at lilik dot it> |
|---|
| 10 | // |
|---|
| 11 | // This program is free software; you can redistribute it and/or modify |
|---|
| 12 | // it under the terms of the GNU General Public License as published by |
|---|
| 13 | // the Free Software Foundation; either version 2 of the License, or |
|---|
| 14 | // (at your option) any later version. |
|---|
| 15 | // |
|---|
| 16 | // This program is distributed in the hope that it will be useful, |
|---|
| 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 19 | // GNU General Public License for more details. |
|---|
| 20 | // |
|---|
| 21 | // You should have received a copy of the GNU General Public License |
|---|
| 22 | // along with this program; if not, write to the Free Software |
|---|
| 23 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 24 | // |
|---|
| 25 | // |
|---|
| 26 | // Notes: to compile this program you can simply copyt the file in |
|---|
| 27 | // the examples path of your galib sources and add it to the |
|---|
| 28 | // examples/Makefile |
|---|
| 29 | |
|---|
| 30 | #include <stdio.h> |
|---|
| 31 | #include <stdlib.h> |
|---|
| 32 | #include <ga/ga.h> |
|---|
| 33 | //#include <ga/std_stream.h> |
|---|
| 34 | |
|---|
| 35 | #define cout STD_COUT |
|---|
| 36 | #define endl STD_ENDL |
|---|
| 37 | //#define ostream STD_OSTREAM |
|---|
| 38 | |
|---|
| 39 | int dim = 100; |
|---|
| 40 | int popsize = 50; |
|---|
| 41 | int ngen = 100000; |
|---|
| 42 | float pcross = 0.795; |
|---|
| 43 | float pmut = 0.10; |
|---|
| 44 | float mutq = 0.25; |
|---|
| 45 | float preplace = 0.78; |
|---|
| 46 | |
|---|
| 47 | float objective(GAGenome &); |
|---|
| 48 | void init(GAGenome &); |
|---|
| 49 | int mutate(GAGenome &, float); |
|---|
| 50 | GABoolean stopwhenzero(GAGeneticAlgorithm &); |
|---|
| 51 | |
|---|
| 52 | void print(const GAGenome &); |
|---|
| 53 | |
|---|
| 54 | int main(int argc, char *argv[]) |
|---|
| 55 | { |
|---|
| 56 | GA1DArrayGenome<int> genome(dim, objective); |
|---|
| 57 | genome.initializer(init); |
|---|
| 58 | genome.mutator(mutate); |
|---|
| 59 | genome.crossover(GA1DArrayGenome<int>::PartialMatchCrossover); |
|---|
| 60 | |
|---|
| 61 | GASteadyStateGA ga(genome); |
|---|
| 62 | ga.pReplacement(preplace); |
|---|
| 63 | /* |
|---|
| 64 | GASimpleGA ga(genome); |
|---|
| 65 | gasimplega.elitist(); |
|---|
| 66 | */ |
|---|
| 67 | //GAIncrementalGA ga(genome); |
|---|
| 68 | |
|---|
| 69 | ga.populationSize(popsize); |
|---|
| 70 | ga.nGenerations(ngen); |
|---|
| 71 | ga.pMutation(pmut); |
|---|
| 72 | ga.pCrossover(pcross); |
|---|
| 73 | ga.terminator(stopwhenzero); |
|---|
| 74 | ga.minimize(); |
|---|
| 75 | |
|---|
| 76 | ga.initialize(clock()); |
|---|
| 77 | |
|---|
| 78 | // initial population |
|---|
| 79 | GAPopulation pop = ga.population(); |
|---|
| 80 | cout << "pop. size = " << pop.size() << endl; |
|---|
| 81 | for (int i = 0; i < pop.size(); i++) |
|---|
| 82 | { |
|---|
| 83 | cout << "pop(" << i << ") = " << pop.individual(i) << |
|---|
| 84 | " (" << pop.individual(i).score() << ")" << endl; |
|---|
| 85 | } |
|---|
| 86 | cout << "\nbest = " << pop.best()<< |
|---|
| 87 | " (" << pop.best().score() << ")" << endl; |
|---|
| 88 | //print(pop.best()); |
|---|
| 89 | cout << "worst = " << pop.worst() << |
|---|
| 90 | " (" << pop.worst().score() << ")" << endl; |
|---|
| 91 | //print(pop.worst()); |
|---|
| 92 | |
|---|
| 93 | cout << "evolving..."; |
|---|
| 94 | while(!ga.done()){ |
|---|
| 95 | ga.step(); |
|---|
| 96 | if(ga.generation() % 50 == 0) { |
|---|
| 97 | cout << "." << ga.statistics().bestIndividual().score(); |
|---|
| 98 | cout.flush(); |
|---|
| 99 | } |
|---|
| 100 | } |
|---|
| 101 | cout << "\n\n"; |
|---|
| 102 | |
|---|
| 103 | cout << "best generated @ generation #" << ga.generation() << ":\n" << |
|---|
| 104 | ga.statistics().bestIndividual() << |
|---|
| 105 | " (" << ga.statistics().bestIndividual().score() << ")" << endl; |
|---|
| 106 | print(ga.statistics().bestIndividual()); |
|---|
| 107 | return 0; |
|---|
| 108 | } |
|---|
| 109 | |
|---|
| 110 | |
|---|
| 111 | void init(GAGenome& c) |
|---|
| 112 | { |
|---|
| 113 | GA1DArrayGenome<int> & genome = (GA1DArrayGenome<int> &)c; |
|---|
| 114 | |
|---|
| 115 | for(int i = 0; i < dim; i++) |
|---|
| 116 | genome.gene(i, i); |
|---|
| 117 | |
|---|
| 118 | for(int i = 0; i < dim; i++) |
|---|
| 119 | { |
|---|
| 120 | int r = GARandomInt(0, dim - 1); |
|---|
| 121 | genome.swap(i, r); |
|---|
| 122 | } |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | |
|---|
| 126 | int mutate(GAGenome& c, float mutprob) |
|---|
| 127 | { |
|---|
| 128 | GA1DArrayGenome<int>& genome = (GA1DArrayGenome<int>&)c; |
|---|
| 129 | |
|---|
| 130 | if(mutprob <= 0.0) |
|---|
| 131 | return(0); |
|---|
| 132 | |
|---|
| 133 | int i, j; |
|---|
| 134 | float mut = GARandomFloat(0.0, 1.0); |
|---|
| 135 | |
|---|
| 136 | if(mut < mutprob) |
|---|
| 137 | { |
|---|
| 138 | for(int d = 0; d < dim; d++) { |
|---|
| 139 | mut = GARandomFloat(0.0, 1.0); |
|---|
| 140 | if(mut < mutq/dim) { |
|---|
| 141 | i = GARandomInt(0, dim - 1); |
|---|
| 142 | j = GARandomInt(0, dim - 1); |
|---|
| 143 | genome.swap(i, j); |
|---|
| 144 | } |
|---|
| 145 | } |
|---|
| 146 | return(1); |
|---|
| 147 | } |
|---|
| 148 | else |
|---|
| 149 | return(0); |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | |
|---|
| 153 | float objective(GAGenome& c) |
|---|
| 154 | { |
|---|
| 155 | GA1DArrayGenome<int> & genome = (GA1DArrayGenome<int> &)c; |
|---|
| 156 | |
|---|
| 157 | float cost = 0; |
|---|
| 158 | for(int i = 0; i < dim - 1; i++) |
|---|
| 159 | for(int j = 1; j < dim - i; j++) |
|---|
| 160 | { |
|---|
| 161 | if( genome.gene(i + j) == genome.gene(i) - j |
|---|
| 162 | or |
|---|
| 163 | genome.gene(i + j) == genome.gene(i) + j ) |
|---|
| 164 | { |
|---|
| 165 | cost+=1.0; |
|---|
| 166 | //break; |
|---|
| 167 | } |
|---|
| 168 | } |
|---|
| 169 | return cost; |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | |
|---|
| 173 | GABoolean stopwhenzero(GAGeneticAlgorithm & ga) |
|---|
| 174 | { |
|---|
| 175 | if (ga.statistics().bestIndividual().score() == 0 or ga.generation() == ngen ) |
|---|
| 176 | return gaTrue; |
|---|
| 177 | else |
|---|
| 178 | return gaFalse; |
|---|
| 179 | } |
|---|
| 180 | |
|---|
| 181 | |
|---|
| 182 | void print(const GAGenome& c) |
|---|
| 183 | { |
|---|
| 184 | GA1DArrayGenome<int> & genome = (GA1DArrayGenome<int> &)c; |
|---|
| 185 | |
|---|
| 186 | for(int i = 0; i < dim; i++) |
|---|
| 187 | { |
|---|
| 188 | for(int j = 0; j < dim; j++) |
|---|
| 189 | { |
|---|
| 190 | if (genome.gene(j) == i) |
|---|
| 191 | cout << "@ "; |
|---|
| 192 | else |
|---|
| 193 | cout << "x "; |
|---|
| 194 | } |
|---|
| 195 | cout << endl; |
|---|
| 196 | } |
|---|
| 197 | cout << endl; |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | |
|---|
| 201 | // force instantiations for compilers that do not do auto instantiation |
|---|
| 202 | // for some compilers (e.g. metrowerks) this must come after any |
|---|
| 203 | // specializations or you will get 'multiply-defined errors when you compile. |
|---|
| 204 | #if !defined(GALIB_USE_AUTO_INST) |
|---|
| 205 | //#include <ga/GAAllele.C> |
|---|
| 206 | #include <ga/GA1DArrayGenome.C> |
|---|
| 207 | GALIB_INSTANTIATION_PREFIX GAArray<int>; |
|---|
| 208 | GALIB_INSTANTIATION_PREFIX GA1DArrayGenome<int>; |
|---|
| 209 | #endif |
|---|
| 210 | |
|---|