KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgap > gp > impl > GPGenotype


1 /*
2  * This file is part of JGAP.
3  *
4  * JGAP offers a dual license model containing the LGPL as well as the MPL.
5  *
6  * For licencing information please see the file license.txt included with JGAP
7  * or have a look at the top of class org.jgap.Chromosome which representatively
8  * includes the JGAP license policy applicable for any file delivered with JGAP.
9  */

10 package org.jgap.gp.impl;
11
12 import java.io.*;
13 import java.util.*;
14 import org.jgap.*;
15 import org.jgap.gp.*;
16 import org.jgap.gp.terminal.*;
17 import org.jgap.event.*;
18 import org.jgap.util.*;
19
20 /**
21  * Genotype for GP Programs.
22  *
23  * @author Klaus Meffert
24  * @since 3.0
25  */

26 public class GPGenotype
27     implements Runnable JavaDoc, Serializable, Comparable JavaDoc {
28   /** String containing the CVS revision. Read out via reflection!*/
29   private final static String JavaDoc CVS_REVISION = "$Revision: 1.22 $";
30
31   /**
32    * The array of GPProgram's that makeup the GPGenotype's population.
33    */

34   private GPPopulation m_population;
35
36   /**
37    * The current configuration instance.
38    */

39   private transient GPConfiguration m_configuration;
40
41   private transient static GPConfiguration m_staticConfiguration;
42
43   /**
44    * Fitness value of the best solution.
45    */

46   private transient double m_bestFitness;
47
48   /**
49    * Sum of fitness values over all chromosomes.
50    */

51   private transient double m_totalFitness;
52
53   /**
54    * Best solution found.
55    */

56   private transient IGPProgram m_allTimeBest;
57
58   private transient double m_allTimeBestFitness;
59
60   /**
61    * Is full mode with program construction allowed?
62    */

63   private boolean m_fullModeAllowed[];
64
65   /**
66    * Return type per chromosome.
67    */

68   private Class JavaDoc[] m_types;
69
70   /**
71    * Argument types for ADF's
72    */

73   private Class JavaDoc[][] m_argTypes;
74
75   /**
76    * Available GP-functions.
77    */

78   private CommandGene[][] m_nodeSets;
79
80   /**
81    * Minimum depth per each chromosome
82    */

83   private int[] m_minDepths;
84
85   /**
86    * Maximum depth per each chromosome
87    */

88   private int[] m_maxDepths;
89
90   /**
91    * Maximum number of nodes allowed per chromosome (when exceeded program
92    * aborts)
93    */

94   private int m_maxNodes;
95
96   /**
97    * True: Output status information to console
98    */

99   private boolean m_verbose;
100
101   private Map m_variables;
102
103   private IGPProgram m_fittestToAdd;
104
105   private boolean m_cloneWarningGPProgramShown;
106
107   /**
108    * Default constructor. Ony use with dynamic instantiation.
109    * @throws InvalidConfigurationException
110    *
111    * @author Klaus Meffert
112    * @since 3.0
113    */

114   public GPGenotype()
115       throws InvalidConfigurationException {
116   }
117
118   /**
119    * Preferred constructor to use, if not randomInitialGenotype.
120    *
121    * @param a_configuration the configuration to use
122    * @param a_population the initialized population to use
123    * @param a_types the type for each chromosome, the length of the array
124    * represents the number of chromosomes
125    * @param a_argTypes the types of the arguments to each chromosome, must be an
126    * array of arrays, the first dimension of which is the number of chromosomes
127    * and the second dimension of which is the number of arguments to the
128    * chromosome
129    * @param a_nodeSets the nodes which are allowed to be used by each chromosome,
130    * must be an array of arrays, the first dimension of which is the number of
131    * chromosomes and the second dimension of which is the number of nodes
132    * @param a_minDepths contains the minimum depth allowed for each chromosome
133    * @param a_maxDepths contains the maximum depth allowed for each chromosome
134    * @param a_maxNodes reserve space for a_maxNodes number of nodes
135    *
136    * @throws InvalidConfigurationException
137    *
138    * @author Klaus Meffert
139    * @since 3.0
140    */

141   public GPGenotype(GPConfiguration a_configuration, GPPopulation a_population,
142                     Class JavaDoc[] a_types, Class JavaDoc[][] a_argTypes,
143                     CommandGene[][] a_nodeSets, int[] a_minDepths,
144                     int[] a_maxDepths, int a_maxNodes)
145       throws InvalidConfigurationException {
146     // Sanity checks: Make sure neither the Configuration, the array
147
// of Chromosomes, nor any of the Genes inside the array are null.
148
// ---------------------------------------------------------------
149
if (a_configuration == null) {
150       throw new IllegalArgumentException JavaDoc(
151           "The configuration instance may not be null.");
152     }
153     if (a_population == null) {
154       throw new IllegalArgumentException JavaDoc(
155           "The population may not be null.");
156     }
157     for (int i = 0; i < a_population.size(); i++) {
158       if (a_population.getGPProgram(i) == null) {
159         throw new IllegalArgumentException JavaDoc(
160             "The GPProgram instance at index " + i + " in population" +
161             " is null, which is forbidden in general.");
162       }
163     }
164     m_types = a_types;
165     m_argTypes = a_argTypes;
166     m_nodeSets = a_nodeSets;
167     m_maxDepths = a_maxDepths;
168     m_minDepths = a_minDepths;
169     m_maxNodes = a_maxNodes;
170     setGPPopulation(a_population);
171     setGPConfiguration(a_configuration);
172     m_variables = new Hashtable();
173     m_allTimeBestFitness = FitnessFunction.NO_FITNESS_VALUE;
174     // Lock the settings of the configuration object so that it cannot
175
// be altered.
176
// ---------------------------------------------------------------
177
getGPConfiguration().lockSettings();
178   }
179
180   /**
181    * Creates a genotype with initial population for the world set.
182    *
183    * @param a_conf the configuration to use
184    * @param a_types the type of each chromosome, the length is the number of
185    * chromosomes
186    * @param a_argTypes the types of the arguments to each chromosome, must be an
187    * array of arrays, the first dimension of which is the number of chromosomes
188    * and the second dimension of which is the number of arguments to the
189    * chromosome
190    * @param a_nodeSets the nodes which are allowed to be used by each
191    * chromosome, must be an array of arrays, the first dimension of which is the
192    * number of chromosomes and the second dimension of which is the number of
193    * nodes. Note that it is not necessary to include the arguments of a
194    * chromosome as terminals in the chromosome's node set. This is done
195    * automatically
196    * @param a_maxNodes reserve space for a_maxNodes number of nodes
197    * @param a_verboseOutput true: output status information to console
198    *
199    * @return created population
200    *
201    * @throws InvalidConfigurationException
202    *
203    * @author Klaus Meffert
204    * @since 3.0
205    */

206   public static GPGenotype randomInitialGenotype(final GPConfiguration a_conf,
207       Class JavaDoc[] a_types, Class JavaDoc[][] a_argTypes, CommandGene[][] a_nodeSets,
208       int a_maxNodes, boolean a_verboseOutput)
209       throws InvalidConfigurationException {
210     int[] minDepths = null;
211     int[] maxDepths = null;
212     return randomInitialGenotype(a_conf, a_types, a_argTypes, a_nodeSets,
213                                  minDepths, maxDepths, a_maxNodes,
214                                  a_verboseOutput);
215   }
216
217   /**
218    * Creates a genotype with initial population for the world set.
219    *
220    * @param a_conf the configuration to use
221    * @param a_types the type of each chromosome, the length is the number of
222    * chromosomes
223    * @param a_argTypes the types of the arguments to each chromosome, must be an
224    * array of arrays, the first dimension of which is the number of chromosomes
225    * and the second dimension of which is the number of arguments to the
226    * chromosome
227    * @param a_nodeSets the nodes which are allowed to be used by each
228    * chromosome, must be an array of arrays, the first dimension of which is the
229    * number of chromosomes and the second dimension of which is the number of
230    * nodes. Note that it is not necessary to include the arguments of a
231    * chromosome as terminals in the chromosome's node set. This is done
232    * automatically
233    * @param a_minDepths array of minimum depths to use: for each chromosome
234    * one entry
235    * @param a_maxDepths array of maximum depths to use: for each chromosome
236    * one entry
237    * @param a_maxNodes reserve space for a_maxNodes number of nodes
238    * @param a_verboseOutput true: output status information to console
239    *
240    * @return created population
241    *
242    * @throws InvalidConfigurationException
243    *
244    * @author Klaus Meffert
245    * @since 3.0
246    */

247   public static GPGenotype randomInitialGenotype(final GPConfiguration a_conf,
248       Class JavaDoc[] a_types, Class JavaDoc[][] a_argTypes, CommandGene[][] a_nodeSets,
249       int[] a_minDepths, int[] a_maxDepths, int a_maxNodes,
250       boolean a_verboseOutput)
251       throws InvalidConfigurationException {
252     boolean[] fullModeAllowed = new boolean[a_types.length];
253     for (int i = 0; i < a_types.length; i++) {
254       fullModeAllowed[i] = true;
255     }
256     return randomInitialGenotype(a_conf, a_types, a_argTypes, a_nodeSets,
257                                  a_minDepths, a_maxDepths, a_maxNodes,
258                                  fullModeAllowed, a_verboseOutput);
259   }
260
261   /**
262    * Creates a genotype with initial population for the world set.
263    *
264    * @param a_conf the configuration to use
265    * @param a_types the type of each chromosome, the length is the number of
266    * chromosomes
267    * @param a_argTypes the types of the arguments to each chromosome, must be an
268    * array of arrays, the first dimension of which is the number of chromosomes
269    * and the second dimension of which is the number of arguments to the
270    * chromosome
271    * @param a_nodeSets the nodes which are allowed to be used by each
272    * chromosome, must be an array of arrays, the first dimension of which is the
273    * number of chromosomes and the second dimension of which is the number of
274    * nodes. Note that it is not necessary to include the arguments of a
275    * chromosome as terminals in the chromosome's node set. This is done
276    * automatically
277    * @param a_minDepths array of minimum depths to use: for each chromosome
278    * one entry
279    * @param a_maxDepths array of maximum depths to use: for each chromosome
280    * one entry
281    * @param a_maxNodes reserve space for a_maxNodes number of nodes
282    * @param a_fullModeAllowed array of boolean values. For each chromosome there
283    * is one value indicating whether the full mode for creating chromosome
284    * generations during evolution is allowed (true) or not (false)
285    * @param a_verboseOutput true: output status information to console
286    *
287    * @return created population
288    *
289    * @throws InvalidConfigurationException
290    *
291    * @author Klaus Meffert
292    * @since 3.0
293    */

294   public static GPGenotype randomInitialGenotype(final GPConfiguration a_conf,
295       Class JavaDoc[] a_types, Class JavaDoc[][] a_argTypes, CommandGene[][] a_nodeSets,
296       int[] a_minDepths, int[] a_maxDepths, int a_maxNodes,
297       boolean[] a_fullModeAllowed, boolean a_verboseOutput)
298       throws InvalidConfigurationException {
299     if (a_argTypes.length != a_fullModeAllowed.length
300         || (a_minDepths != null && a_argTypes.length != a_minDepths.length)
301         || (a_maxDepths != null && a_argTypes.length != a_maxDepths.length)
302         || a_argTypes.length != a_types.length) {
303       throw new IllegalArgumentException JavaDoc("a_argTypes must have same length"
304           + " as a_types, a_minDepths, a_maxDepths and a_fullModeAllowed");
305     }
306     System.gc();
307     if (a_verboseOutput) {
308       System.out.println("Creating initial population");
309       System.out.println("Memory consumed before creating population: "
310                          + SystemKit.getTotalMemoryMB() + "MB");
311     }
312     GPPopulation pop = new GPPopulation(a_conf, a_conf.getPopulationSize());
313     // Create initial population.
314
// --------------------------
315
pop.create(a_types, a_argTypes, a_nodeSets, a_minDepths, a_maxDepths,
316                a_maxNodes, a_fullModeAllowed);
317     System.gc();
318     if (a_verboseOutput) {
319       System.out.println("Memory used after creating population: "
320                          + SystemKit.getTotalMemoryMB() + "MB");
321     }
322     GPGenotype gp = new GPGenotype(a_conf, pop, a_types, a_argTypes, a_nodeSets,
323                                    a_minDepths, a_maxDepths, a_maxNodes);
324     gp.m_fullModeAllowed = a_fullModeAllowed;
325     return gp;
326   }
327
328   public GPConfiguration getGPConfiguration() {
329     return m_configuration;
330   }
331
332   /**
333    * @return the static configuration to use with the Genetic Programming
334    *
335    * @author Klaus Meffert
336    * @since 3.2
337    */

338   public static GPConfiguration getStaticGPConfiguration() {
339     return m_staticConfiguration;
340   }
341
342   /**
343    * Sets the static configuration to use with the Genetic Programming.
344    *
345    * @param a_configuration the static configuration to use
346    *
347    * @author Klaus Meffert
348    * @since 3.2
349    */

350   public static void setStaticGPConfiguration(GPConfiguration a_configuration) {
351     m_staticConfiguration = a_configuration;
352   }
353
354   static class GPFitnessComparator
355       implements Comparator {
356     public int compare(Object JavaDoc o1, Object JavaDoc o2) {
357       if (! (o1 instanceof IGPProgram) ||
358           ! (o2 instanceof IGPProgram))
359         throw new ClassCastException JavaDoc(
360             "FitnessComparator must operate on IGPProgram instances");
361       double f1 = ( (IGPProgram) o1).getFitnessValue();
362       double f2 = ( (IGPProgram) o2).getFitnessValue();
363       if (f1 > f2) {
364         return 1;
365       }
366       else if (Math.abs(f1 - f2) < 0.000001) {
367         return 0;
368       }
369       else {
370         return -1;
371       }
372     }
373   }
374   /**
375    * Evolves the population n times.
376    *
377    * @param a_evolutions number of evolution
378    *
379    * @author Klaus Meffert
380    * @since 3.0
381    */

382   public void evolve(int a_evolutions) {
383     getGPPopulation().sort(new GPFitnessComparator());
384     // Here, we could do threading.
385
for (int i = 0; i < a_evolutions; i++) {
386       calcFitness();
387       if (m_bestFitness < 0.000001) {
388         // Optimal solution found, quit.
389
// -----------------------------
390
return;
391       }
392       if (m_verbose) {
393         if (i % 25 == 0) {
394           System.out.println("Evolving generation "
395                              + i
396                              + ", memory free: "
397                              + SystemKit.getFreeMemoryMB()
398                              + " MB");
399         }
400       }
401       evolve();
402     }
403     calcFitness();
404   }
405
406   /**
407    * Calculates the fitness value of all programs, of the best solution as
408    * well as the total fitness (sum of all fitness values).
409    *
410    * @author Klaus Meffert
411    * @since 3.0
412    */

413   public void calcFitness() {
414     double totalFitness = 0.0d;
415     GPPopulation pop = getGPPopulation();
416     IGPProgram best = null;
417     IGPFitnessEvaluator evaluator = getGPConfiguration().getGPFitnessEvaluator();
418     m_bestFitness = FitnessFunction.NO_FITNESS_VALUE;
419     for (int i = 0; i < pop.size() && pop.getGPProgram(i) != null; i++) {
420       IGPProgram program = pop.getGPProgram(i);
421       double fitness = program.getFitnessValue();
422       if (best == null || evaluator.isFitter(fitness, m_bestFitness)) {
423         best = program;
424         m_bestFitness = fitness;
425       }
426       totalFitness += fitness;
427     }
428     m_totalFitness = totalFitness;
429 // best = pop.determineFittestProgram();
430
// m_bestFitness = best.getFitnessValue();
431
/**@todo do something similar here as with Genotype.preserveFittestChromosome*/
432     if (m_allTimeBest == null
433         || evaluator.isFitter(m_bestFitness, m_allTimeBestFitness)) {
434       pop.setChanged(true);
435       try {
436         ICloneHandler cloner = getGPConfiguration().getJGAPFactory().
437             getCloneHandlerFor(best, null);
438         if (cloner == null) {
439           m_allTimeBest = best;
440           if (!m_cloneWarningGPProgramShown) {
441             System.out.println("Warning: cannot clone instance of " +
442                                best.getClass());
443             m_cloneWarningGPProgramShown = true;
444           }
445         }
446         else {
447           m_allTimeBest = (IGPProgram) cloner.perform(best, null, null);
448         }
449       } catch (Exception JavaDoc ex) {
450         m_allTimeBest = best;
451         ex.printStackTrace();
452       }
453       m_allTimeBestFitness = m_bestFitness;
454       // Fire an event to indicate a new best solution.
455
// ----------------------------------------------
456
getGPConfiguration().getEventManager().fireGeneticEvent(
457           new GeneticEvent(GeneticEvent.GPGENOTYPE_NEW_BEST_SOLUTION, this));
458       if (m_verbose) {
459         // Output the new best solution found.
460
// -----------------------------------
461
outputSolution(m_allTimeBest);
462       }
463     }
464   }
465
466   /**
467    * @return the all-time best solution found
468    *
469    * @author Klaus Meffert
470    * @since 3.0
471    */

472   public IGPProgram getAllTimeBest() {
473     return m_allTimeBest;
474   }
475
476   /**
477    * Outputs the best solution currently found.
478    * @param a_best the fittest ProgramChromosome
479    *
480    * @author Klaus Meffert
481    * @since 3.0
482    */

483   public void outputSolution(IGPProgram a_best) {
484     System.out.println(" Best solution fitness: " + a_best.getFitnessValue());
485     System.out.println(" Best solution: " + a_best.toStringNorm(0));
486     String JavaDoc depths = "";
487     int size = a_best.size();
488     for (int i = 0; i < size; i++) {
489       if (i > 0) {
490         depths += " / ";
491       }
492       depths += a_best.getChromosome(i).getDepth(0);
493     }
494     if (size == 1) {
495       System.out.println(" Depth of chromosome: " + depths);
496     }
497     else {
498       System.out.println(" Depths of chromosomes: " + depths);
499     }
500     System.out.println(" --------");
501   }
502
503   /**
504    * Evolve the population by one generation. Probabilistically reproduces
505    * and crosses individuals into a new population which then overwrites the
506    * original population.
507    *
508    * @author Klaus Meffert
509    * @since 3.0
510    */

511   public void evolve() {
512     try {
513       int popSize = getGPConfiguration().getPopulationSize();
514       GPPopulation oldPop = getGPPopulation();
515       GPPopulation newPopulation = new GPPopulation(oldPop, false);
516       if (m_fittestToAdd != null) {
517         newPopulation.addFittestProgram(m_fittestToAdd);
518         m_fittestToAdd = null;
519       }
520       float val;
521       RandomGenerator random = getGPConfiguration().getRandomGenerator();
522       GPConfiguration conf = getGPConfiguration();
523       // Determine how many new individuals will be added to the new generation.
524
// -----------------------------------------------------------------------
525
int popSize1 = (int) Math.round(popSize * (1 - conf.getNewChromsPercent()));
526       for (int i = 0; i < popSize1; i++) {
527         // Clear the stack for each GP program (=ProgramChromosome).
528
// ---------------------------------------------------------
529
getGPConfiguration().clearStack();
530         val = random.nextFloat();
531         // Note that if we only have one slot left to fill, we don't do
532
// crossover, but fall through to reproduction.
533
// ------------------------------------------------------------
534
if (i < popSize - 1 && val < conf.getCrossoverProb()) {
535           // Do crossover.
536
// -------------
537
IGPProgram i1 = conf.getSelectionMethod().select(this);
538 // newPopulation.checkIfFittest(i1);
539
IGPProgram i2 = conf.getSelectionMethod().select(this);
540 // newPopulation.checkIfFittest(i2);
541
int tries = 0;
542           do {
543             try {
544               IGPProgram[] newIndividuals = conf.getCrossMethod().operate(i1,
545                   i2);
546               newPopulation.setGPProgram(i, newIndividuals[0]);
547               newPopulation.setGPProgram(i + 1, newIndividuals[1]);
548               i++;
549               break;
550             } catch (IllegalStateException JavaDoc iex) {
551               tries++;
552               if (tries >= getGPConfiguration().getProgramCreationMaxtries()) {
553                 if (!getGPConfiguration().isMaxNodeWarningPrinted()) {
554                   System.err.println(
555                       "Warning: Maximum number of nodes allowed may be too small");
556                   getGPConfiguration().flagMaxNodeWarningPrinted();
557                   // Try cloning a previously generated valid program.
558
// -------------------------------------------------
559
IGPProgram program = cloneProgram(getGPConfiguration().
560                       getPrototypeProgram());
561                   if (program != null) {
562                     newPopulation.setGPProgram(i++, program);
563                     program = cloneProgram(getGPConfiguration().
564                         getPrototypeProgram());
565                     newPopulation.setGPProgram(i, program);
566                     break;
567                   }
568                   else {
569                     throw new IllegalStateException JavaDoc(iex.getMessage());
570                   }
571                 }
572               }
573             }
574           } while (true);
575         }
576         else if (val < conf.getCrossoverProb() + conf.getReproductionProb()) {
577           // Reproduction only.
578
// ------------------
579
newPopulation.setGPProgram(i, conf.getSelectionMethod().select(this));
580         }
581       }
582       // Add new chromosomes randomly.
583
// -----------------------------
584
for (int i = popSize1; i < popSize; i++) {
585         // Determine depth randomly and between minInitDepth and maxInitDepth.
586
// -------------------------------------------------------------------
587
int depth = conf.getMinInitDepth()
588             + random.nextInt(conf.getMaxInitDepth() - conf.getMinInitDepth()
589                              + 1);
590         int tries = 0;
591         do {
592           try {
593             IGPProgram program = newPopulation.create(m_types, m_argTypes,
594                 m_nodeSets, m_minDepths, m_maxDepths, depth, (i % 2) == 0,
595                 m_maxNodes, m_fullModeAllowed);
596             newPopulation.setGPProgram(i, program);
597             break;
598           } catch (IllegalStateException JavaDoc iex) {
599             tries++;
600             if (tries > getGPConfiguration().getProgramCreationMaxtries()) {
601               // Try cloning a previously generated valid program.
602
// -------------------------------------------------
603
IGPProgram program = cloneProgram(getGPConfiguration().
604                   getPrototypeProgram());
605               if (program != null) {
606                 newPopulation.setGPProgram(i, program);
607                 break;
608               }
609               else {
610                 throw new IllegalStateException JavaDoc(iex.getMessage());
611               }
612             }
613           }
614         } while (true);
615       }
616       // Now set the new population as the active one.
617
// ---------------------------------------------
618
setGPPopulation(newPopulation);
619       // Increase number of generation.
620
// ------------------------------
621
conf.incrementGenerationNr();
622       // Fire an event to indicate we've performed an evolution.
623
// -------------------------------------------------------
624
conf.getEventManager().fireGeneticEvent(
625           new GeneticEvent(GeneticEvent.GPGENOTYPE_EVOLVED_EVENT, this));
626     } catch (InvalidConfigurationException iex) {
627       // This should never happen.
628
// -------------------------
629
throw new IllegalStateException JavaDoc(iex.getMessage());
630     }
631   }
632
633   public GPPopulation getGPPopulation() {
634     return m_population;
635   }
636
637   /**
638    * @return the total fitness, that is the fitness over all chromosomes
639    *
640    * @author Klaus Meffert
641    * @since 3.0
642    */

643   public double getTotalFitness() {
644     return m_totalFitness;
645   }
646
647   /**
648    * Default implementation of method to run GPGenotype as a thread.
649    *
650    * @author Klaus Meffert
651    * @since 3.0
652    */

653   public void run() {
654     try {
655       while (!Thread.currentThread().interrupted()) {
656         evolve();
657         calcFitness();
658         // Pause between evolutions to avoid 100% CPU load.
659
// ------------------------------------------------
660
Thread.sleep(10);
661       }
662     } catch (Exception JavaDoc ex) {
663       ex.printStackTrace();
664       System.exit(1);
665     }
666   }
667
668   /**
669    * Retrieves the GPProgram in the population with the highest fitness
670    * value.
671    *
672    * @return the GPProgram with the highest fitness value, or null if there
673    * are no programs in this Genotype
674    *
675    * @author Klaus Meffert
676    * @since 3.0
677    */

678   public synchronized IGPProgram getFittestProgram() {
679     double fittest;
680     if (m_allTimeBest != null) {
681       fittest = m_allTimeBest.getFitnessValue();
682     }
683     else {
684       fittest = FitnessFunction.NO_FITNESS_VALUE;
685     }
686     IGPProgram fittestPop = getGPPopulation().determineFittestProgram();
687     if (fittestPop == null) {
688       return m_allTimeBest;
689     }
690     if (getGPConfiguration().getGPFitnessEvaluator().isFitter(fittest,
691         fittestPop.getFitnessValue())) {
692       return m_allTimeBest;
693     }
694     else {
695 // m_allTimeBest = fittestPop;/**@todo*/
696
return fittestPop;
697     }
698   }
699   /**
700    * Retrieves the GPProgram in the population with the highest fitness
701    * value. Only considers programs for which the fitness value has already
702    * been computed.
703    *
704    * @return the GPProgram with the highest fitness value, or null if there
705    * are no programs with known fitness value in this Genotype
706    *
707    * @author Klaus Meffert
708    * @since 3.2
709    */

710   public synchronized IGPProgram getFittestProgramComputed() {
711     return getGPPopulation().determineFittestProgramComputed();
712   }
713
714   protected void setGPPopulation(GPPopulation a_pop) {
715     m_population = a_pop;
716   }
717
718   /**
719    * Sets the configuration to use with the Genetic Algorithm.
720    * @param a_configuration the configuration to use
721    *
722    * @author Klaus Meffert
723    * @since 3.0
724    */

725   public void setGPConfiguration(GPConfiguration a_configuration) {
726     m_configuration = a_configuration;
727   }
728
729   /**
730    * Compares this entity against the specified object.
731    *
732    * @param a_other the object to compare against
733    * @return true: if the objects are the same, false otherwise
734    *
735    * @author Klaus Meffert
736    * @since 3.0
737    */

738   public boolean equals(Object JavaDoc a_other) {
739     try {
740       return compareTo(a_other) == 0;
741     } catch (ClassCastException JavaDoc cex) {
742       return false;
743     }
744   }
745
746   /**
747    * Compares this Genotype against the specified object. The result is true
748    * if the argument is an instance of the Genotype class, has exactly the
749    * same number of programs as the given Genotype, and, for each
750    * GPProgram in this Genotype, there is an equal program in the
751    * given Genotype. The programs do not need to appear in the same order
752    * within the populations.
753    *
754    * @param a_other the object to compare against
755    * @return a negative number if this genotype is "less than" the given
756    * genotype, zero if they are equal to each other, and a positive number if
757    * this genotype is "greater than" the given genotype
758    *
759    * @author Klaus Meffert
760    * @since 3.0
761    */

762   public int compareTo(Object JavaDoc a_other) {
763     try {
764       // First, if the other Genotype is null, then they're not equal.
765
// -------------------------------------------------------------
766
if (a_other == null) {
767         return 1;
768       }
769       GPGenotype otherGenotype = (GPGenotype) a_other;
770       // First, make sure the other Genotype has the same number of
771
// chromosomes as this one.
772
// ----------------------------------------------------------
773
int size1 = getGPPopulation().size();
774       int size2 = otherGenotype.getGPPopulation().size();
775       if (size1 != size2) {
776         if (size1 > size2) {
777           return 1;
778         }
779         else {
780           return -1;
781         }
782       }
783       // Next, prepare to compare the programs of the other Genotype
784
// against the programs of this Genotype. To make this a lot
785
// simpler, we first sort the programs in both this Genotype
786
// and the one we're comparing against. This won't affect the
787
// genetic algorithm (it doesn't care about the order), but makes
788
// it much easier to perform the comparison here.
789
// --------------------------------------------------------------
790
Arrays.sort(getGPPopulation().getGPPrograms());
791       Arrays.sort(otherGenotype.getGPPopulation().getGPPrograms());
792       for (int i = 0; i < getGPPopulation().size(); i++) {
793         int result = (getGPPopulation().getGPProgram(i).compareTo(
794             otherGenotype.getGPPopulation().getGPProgram(i)));
795         if (result != 0) {
796           return result;
797         }
798       }
799       return 0;
800     } catch (ClassCastException JavaDoc e) {
801       return -1;
802     }
803   }
804
805   /***
806    * Hashcode function for the genotype, tries to create a unique hashcode for
807    * the chromosomes within the population. The logic for the hashcode is
808    *
809    * Step Result
810    * ---- ------
811    * 1 31*0 + hashcode_0 = y(1)
812    * 2 31*y(1) + hashcode_1 = y(2)
813    * 3 31*y(2) + hashcode_2 = y(3)
814    * n 31*y(n-1) + hashcode_n-1 = y(n)
815    *
816    * Each hashcode is a number and the binary equivalent is computed and
817    * returned.
818    * @return the computed hashcode
819    *
820    * @author Klaus Meffert
821    * @since 3.0
822    */

823   public int hashCode() {
824     int i, size = getGPPopulation().size();
825     IGPProgram prog;
826     int twopower = 1;
827     // For empty genotype we want a special value different from other hashcode
828
// implementations.
829
// ------------------------------------------------------------------------
830
int localHashCode = -573;
831     for (i = 0; i < size; i++, twopower = 2 * twopower) {
832       prog = getGPPopulation().getGPProgram(i);
833       localHashCode = 31 * localHashCode + prog.hashCode();
834     }
835     return localHashCode;
836   }
837
838   /**
839    * @param a_verbose true: output status information to console
840    *
841    * @author Klaus Meffert
842    * @since 3.0
843    */

844   public void setVerboseOutput(boolean a_verbose) {
845     m_verbose = a_verbose;
846   }
847
848   private IGPProgram cloneProgram(IGPProgram a_original) {
849     IGPProgram validProgram = getGPConfiguration().
850         getPrototypeProgram();
851     ICloneHandler cloner = getGPConfiguration().getJGAPFactory().
852         getCloneHandlerFor(validProgram, null);
853     if (cloner != null) {
854       try {
855         IGPProgram program = (IGPProgram) cloner.perform(
856             validProgram, null, null);
857         return program;
858       } catch (Exception JavaDoc ex) {
859         return null;
860       }
861     }
862     return null;
863   }
864
865   /**
866    * Stores a Variable
867    * @param a_var the Variable to store
868    *
869    * @author Klaus Meffert
870    * @since 3.2
871    */

872   public void putVariable(Variable a_var) {
873     m_variables.put(a_var.getName(), a_var);
874   }
875
876   /**
877    * @param a_varName name of variable to retriebe
878    * @return Variable instance or null, if not found
879    *
880    * @author Klaus Meffert
881    * @since 3.2
882    */

883   public Variable getVariable(String JavaDoc a_varName) {
884     return (Variable) m_variables.get(a_varName);
885   }
886
887   /**
888    * Adds a GP program to this Genotype. Does nothing when given null.
889    * The injection is actually executed in method create(..) of GPPopulation.
890    *
891    * @param a_toAdd the program to add
892    *
893    * @author Klaus Meffert
894    * @since 3.2
895    */

896   public void addFittestProgram(final IGPProgram a_toAdd) {
897     if (a_toAdd != null) {
898       m_fittestToAdd = a_toAdd;
899     }
900   }
901 }
902
Popular Tags