KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.*;
13 import org.apache.commons.lang.builder.CompareToBuilder;
14 import org.jgap.*;
15 import org.jgap.impl.*;
16 import org.jgap.distr.*;
17 import org.jgap.event.*;
18 import org.jgap.gp.*;
19
20 /**
21  * Configuration for a GP.
22  *
23  * @author Klaus Meffert
24  * @since 3.0
25  */

26 public class GPConfiguration
27     extends Configuration {
28   /** String containing the CVS revision. Read out via reflection!*/
29   private final static String JavaDoc CVS_REVISION = "$Revision: 1.25 $";
30
31   /**
32    * References the current fitness function that will be used to evaluate
33    * chromosomes during the natural selection process.
34    */

35   private GPFitnessFunction m_objectiveFunction;
36
37   /**
38    * Internal stack, see PushCommand for example.
39    */

40   private Stack m_stack = new Stack();
41
42   /**
43    * Internal memory, see StoreTerminalCommand for example.
44    */

45   private Culture m_memory = new Culture(50); /**@todo make 50 configurable*/
46
47   /**
48    * The probability that a crossover operation is chosen during evolution. Must
49    * be between 0.0d and 1.0d, inclusive.
50    */

51   private double m_crossoverProb = 0.9d;
52
53   /**
54    * The probability that a reproduction operation is chosen during evolution.
55    * Must be between 0.0d and 1.0d. crossoverProb + reproductionProb must equal
56    * 1.0d.
57    */

58   private double m_reproductionProb = 0.1d;
59
60   /**
61    * Percentage of the population that will be filled with new individuals
62    * during evolution. Must be between 0.0d and 1.0d.
63    */

64   private double m_newChromsPercent = 0.3d;
65
66   /**
67    * In crossover: If random number (0..1) < this value, then choose a function
68    * otherwise a terminal
69    */

70   private double m_functionProb = 0.9d;
71
72   /**
73    * The maximum depth of an individual resulting from crossover.
74    */

75   private int m_maxCrossoverDepth = 17;
76
77   /**
78    * The maximum depth of an individual when the world is created.
79    */

80   private int m_maxInitDepth = 7;
81
82   /**
83    * The minimum depth of an individual when the world is created.
84    */

85   private int m_minInitDepth = 3;
86
87   /**
88    * The method of choosing an individual to perform an evolution operation on.
89    */

90   private INaturalGPSelector m_selectionMethod;
91
92   /**
93    * The method of crossing over two individuals during evolution.
94    */

95   private CrossMethod m_crossMethod;
96
97   /**
98    * True: Set of available functions must contain any "type of function" that
99    * may be needed during construction of a new program. A "type of function"
100    * is, for instance, a terminal with return type
101    * <code>CommandGene.IntegerClass</code>.
102    */

103   private boolean m_strictProgramCreation;
104
105   /**
106    * If m_strictProgramCreation is false: Maximum number of tries to construct
107    * a valid program.
108    */

109   private int m_programCreationMaxTries = 5;
110
111   /**
112    * The fitness evaluator. See interface IGPFitnessEvaluator for details.
113    */

114   private IGPFitnessEvaluator m_fitnessEvaluator;
115
116   private INodeValidator m_nodeValidator;
117
118   /**
119    * Internal flag to display a warning only once, in case a program could not
120    * be evolved with the allowed maximum number of nodes.
121    *
122    * @since 3.2
123    */

124   private boolean m_warningPrinted;
125
126   /**
127    * Prototype of a valid program. May be cloned if needed (do not reference
128    * it!)
129    *
130    * @since 3.2
131    */

132   private IGPProgram m_prototypeProgram;
133
134   private transient Map m_programCache;
135
136   private boolean m_useProgramCache = false;
137
138   /**
139    * Constructor utilizing the FitnessProportionateSelection.
140    *
141    * @throws InvalidConfigurationException
142    *
143    * @author Klaus Meffert
144    * @since 3.0
145    */

146   public GPConfiguration()
147       throws InvalidConfigurationException {
148     this("", null);
149   }
150
151   public GPConfiguration(String JavaDoc a_id, String JavaDoc a_name)
152       throws InvalidConfigurationException {
153     super(a_id, a_name);
154     init();
155     m_selectionMethod = new FitnessProportionateSelection();
156   }
157
158   /**
159    * Sets a GP fitness evaluator, such as
160    * org.jgap.gp.impl.DefaultGPFitnessEvaluator.
161    *
162    * @param a_evaluator the fitness evaluator to set
163    *
164    * @author Klaus Meffert
165    * @since 3.1
166    */

167   public void setGPFitnessEvaluator(IGPFitnessEvaluator a_evaluator) {
168     m_fitnessEvaluator = a_evaluator;
169   }
170
171   /**
172    * Helper for construction.
173    *
174    * @throws InvalidConfigurationException
175    *
176    * @author Klaus Meffert
177    * @since 3.1
178    */

179   protected void init()
180       throws InvalidConfigurationException {
181     m_crossMethod = new BranchTypingCross(this);
182     setEventManager(new EventManager());
183     setRandomGenerator(new StockRandomGenerator());
184     setGPFitnessEvaluator(new DefaultGPFitnessEvaluator());
185     m_programCache = new HashMap(50);
186   }
187
188   /**
189    * Constructor utilizing the FitnessProportionateSelection.
190    *
191    * @param a_selectionMethod the selection method to use
192    * @throws InvalidConfigurationException
193    *
194    * @author Klaus Meffert
195    * @since 3.1
196    */

197   public GPConfiguration(INaturalGPSelector a_selectionMethod)
198       throws InvalidConfigurationException {
199     super();
200     init();
201     m_selectionMethod = a_selectionMethod;
202   }
203
204   /**
205    * Sets the selection method to use.
206    * @param a_method the selection method to use
207    *
208    * @author Klaus Meffert
209    * @since 3.1
210    */

211   public void setSelectionMethod(INaturalGPSelector a_method) {
212     if (a_method == null) {
213       throw new IllegalArgumentException JavaDoc("Selection method must not be null");
214     }
215     m_selectionMethod = a_method;
216   }
217
218   /**
219    * Sets the crossover method to use.
220    * @param a_method the crossover method to use
221    *
222    * @author Klaus Meffert
223    * @since 3.1
224    */

225   public void setCrossoverMethod(CrossMethod a_method) {
226     if (a_method == null) {
227       throw new IllegalArgumentException JavaDoc("Crossover method must not be null");
228     }
229     m_crossMethod = a_method;
230   }
231
232   public synchronized void verifyStateIsValid()
233       throws InvalidConfigurationException {
234     // Do nothing in here.
235
// -------------------
236
}
237
238   public synchronized void addGeneticOperator(GeneticOperator a_operatorToAdd)
239       throws InvalidConfigurationException {
240     throw new UnsupportedOperationException JavaDoc(
241         "Use addGeneticOperator(GPGeneticOperator) instead!");
242   }
243
244 // /**@todo implement something like that*/
245
// public synchronized void addGeneticOperator(IGPGeneticOperator a_operatorToAdd)
246
// throws InvalidConfigurationException {
247
// }
248

249   public double getCrossoverProb() {
250     return m_crossoverProb;
251   }
252
253   public void setCrossoverProb(float a_crossoverProb) {
254     m_crossoverProb = a_crossoverProb;
255   }
256
257   public double getReproductionProb() {
258     return m_reproductionProb;
259   }
260
261   public void setReproductionProb(float a_reproductionProb) {
262     m_reproductionProb = a_reproductionProb;
263   }
264
265   /**
266    * @param a_functionProb probability that a function is choosen in crossing
267    * over (between 0 and 1)
268    *
269    * @author Klaus Meffert
270    * @since 3.2
271    */

272   public void setFunctionProb(double a_functionProb) {
273     m_functionProb = a_functionProb;
274   }
275
276   /**
277    * @return probability that a function is choosen in crossing over
278    *
279    * @author Klaus Meffert
280    * @since 3.2
281    */

282   public double getFunctionProb() {
283     return m_functionProb;
284   }
285
286   public void setNewChromsPercent(double a_newChromsPercent) {
287     m_newChromsPercent = a_newChromsPercent;
288   }
289
290   public double getNewChromsPercent() {
291     return m_newChromsPercent;
292   }
293
294   public int getMaxCrossoverDepth() {
295     return m_maxCrossoverDepth;
296   }
297
298   public void setMaxCrossoverDepth(int a_maxCrossoverDepth) {
299     m_maxCrossoverDepth = a_maxCrossoverDepth;
300   }
301
302   public INaturalGPSelector getSelectionMethod() {
303     return m_selectionMethod;
304   }
305
306   public CrossMethod getCrossMethod() {
307     return m_crossMethod;
308   }
309
310   public int getMaxInitDepth() {
311     return m_maxInitDepth;
312   }
313
314   public void setMaxInitDepth(int a_maxDepth) {
315     m_maxInitDepth = a_maxDepth;
316   }
317
318   public int getMinInitDepth() {
319     return m_minInitDepth;
320   }
321
322   public void setMinInitDepth(int a_minDepth) {
323     m_minInitDepth = a_minDepth;
324   }
325
326   public void pushToStack(Object JavaDoc a_value) {
327     m_stack.push(a_value);
328   }
329
330   public Object JavaDoc popFromStack() {
331     return m_stack.pop();
332   }
333
334   public Object JavaDoc peekStack() {
335     return m_stack.peek();
336   }
337
338   public int stackSize() {
339     return m_stack.size();
340   }
341
342   public void clearStack() {
343     m_stack.clear();
344   }
345
346   /**
347    * Stores a value in the internal memory.
348    *
349    * @param a_name named index of the memory cell
350    * @param a_value the value to store
351    *
352    * @author Klaus Meffert
353    * @since 3.0
354    */

355   public void storeInMemory(String JavaDoc a_name, Object JavaDoc a_value) {
356     m_memory.set(a_name, a_value, -1);
357   }
358
359   /**
360    * Stores a value in the internal matrix memory.
361    *
362    * @param a_x the first coordinate of the matrix (width)
363    * @param a_y the second coordinate of the matrix (height)
364    * @param a_value the value to store
365    * @return created or used memory cell
366    *
367    * @author Klaus Meffert
368    * @since 3.2
369    */

370   public CultureMemoryCell storeMatrixMemory(int a_x, int a_y, Object JavaDoc a_value) {
371     return m_memory.setMatrix(a_x, a_y, a_value);
372   }
373
374   /**
375    * Reads a value from the internal matrix memory.
376    *
377    * @param a_x the first coordinate of the matrix (width)
378    * @param a_y the second coordinate of the matrix (height)
379    * @return read value
380    *
381    * @author Klaus Meffert
382    * @since 3.2
383    */

384   public Object JavaDoc readMatrixMemory(int a_x, int a_y) {
385     return m_memory.getMatrix(a_x, a_y).getCurrentValue();
386   }
387
388   /**
389    * Reads a value from the internal memory.
390    *
391    * @param a_name named index of the memory cell to read out
392    * @return read value
393    *
394    * @author Klaus Meffert
395    * @since 3.0
396    */

397   public Object JavaDoc readFromMemory(String JavaDoc a_name) {
398     return m_memory.get(a_name).getCurrentValue();
399   }
400
401   /**
402    * @param a_name the name of the cell to evaluate
403    * @return the value of a memory cell, if it exsists. Otherwise returns null.
404    *
405    * @author Klaus Meffert
406    * @since 3.2
407    */

408   public Object JavaDoc readFromMemoryIfExists(String JavaDoc a_name) {
409     CultureMemoryCell cell = null;
410     try {
411       cell = m_memory.get(a_name);
412     } catch (IllegalArgumentException JavaDoc iex) {
413       // Memory name not found: OK.
414
// --------------------------
415
;
416     }
417     if (cell == null) {
418       return null;
419     }
420     return cell.getCurrentValue();
421   }
422
423   /**
424    * Stores a value in the internal indexed memory.
425    *
426    * @param a_index index of the cell
427    * @param a_value the value to store
428    * @return created or used memory cell
429    *
430    * @author Klaus Meffert
431    * @since 3.2
432    */

433   public CultureMemoryCell storeIndexedMemory(int a_index, Object JavaDoc a_value) {
434     return m_memory.set(a_index, a_value, -1, "noname");
435   }
436
437   /**
438    * Reads a value from the internal indexed memory.
439    *
440    * @param a_index index of the cell
441    * @return read value (maybe null )
442    *
443    * @author Klaus Meffert
444    * @since 3.2
445    */

446   public Object JavaDoc readIndexedMemory(int a_index) {
447     CultureMemoryCell cell = m_memory.get(a_index);
448     if (cell == null) {
449       return null;
450     }
451     else {
452       return cell.getCurrentValue();
453     }
454   }
455
456   /**
457    * Clears the memory.
458    *
459    * @author Klaus Meffert
460    * @since 3.0
461    */

462   public void clearMemory() {
463     m_memory.clear();
464   }
465
466   public GPFitnessFunction getGPFitnessFunction() {
467     return m_objectiveFunction;
468   }
469
470   /**
471    * Sets the fitness function to be used for this genetic algorithm.
472    * The fitness function is responsible for evaluating a given
473    * Chromosome and returning a positive integer that represents its
474    * worth as a candidate solution. These values are used as a guide by the
475    * natural to determine which Chromosome instances will be allowed to move
476    * on to the next round of evolution, and which will instead be eliminated.
477    *
478    * @param a_functionToSet fitness function to be used
479    *
480    * @throws InvalidConfigurationException if the fitness function is null, or
481    * if this Configuration object is locked.
482    *
483    * @author Neil Rotstan
484    * @since 1.1
485    */

486   public synchronized void setFitnessFunction(GPFitnessFunction a_functionToSet)
487       throws InvalidConfigurationException {
488     verifyChangesAllowed();
489     // Sanity check: Make sure that the given fitness function isn't null.
490
// -------------------------------------------------------------------
491
if (a_functionToSet == null) {
492       throw new InvalidConfigurationException(
493           "The FitnessFunction instance may not be null.");
494     }
495     // Ensure that no other fitness function has been set in a different
496
// configuration object within the same thread!
497
// -----------------------------------------------------------------
498
checkProperty(PROPERTY_FITFUNC_INST, a_functionToSet,
499                   "Fitness function has already been set differently.");
500     m_objectiveFunction = a_functionToSet;
501   }
502
503   public boolean isStrictProgramCreation() {
504     return m_strictProgramCreation;
505   }
506
507   public void setStrictProgramCreation(boolean a_strict) {
508     m_strictProgramCreation = a_strict;
509   }
510
511   public int getProgramCreationMaxtries() {
512     return m_programCreationMaxTries;
513   }
514
515   public void setProgramCreationMaxTries(int a_maxtries) {
516     m_programCreationMaxTries = a_maxtries;
517   }
518
519   /**
520    * @return the fitness evaluator set
521    *
522    * @author Klaus Meffert
523    * @since 3.0
524    */

525   public IGPFitnessEvaluator getGPFitnessEvaluator() {
526     return m_fitnessEvaluator;
527   }
528
529   /**
530    * Validates a_node in the context of a_chrom. Considers the recursion level
531    * (a_recursLevel), the type needed (a_type) for the node, the functions
532    * available (a_functionSet) and the depth of the whole chromosome needed
533    * (a_depth), and whether grow mode is used (a_grow is true) or not.
534    *
535    * @param a_chrom the chromosome that will contain the node, if valid
536    * @param a_node the node selected and to be validated
537    * @param a_rootNode root node of the node to be validated (may be null)
538    * @param a_tries number of times the validator has been called, useful for
539    * stopping by returning true if the number exceeds a limit
540    * @param a_num the chromosome's index in the individual of this chromosome
541    * @param a_recurseLevel level of recursion
542    * @param a_type the return type of the node needed
543    * @param a_functionSet the array of available functions
544    * @param a_depth the needed depth of the program chromosome
545    * @param a_grow true: use grow mode, false: use full mode
546    * @param a_childIndex index of the child in the parent node to which it
547    * belongs (-1 if node is root node)
548    *
549    * @return true: node is valid; false: node is invalid
550    *
551    * @author Klaus Meffert
552    * @since 3.0
553    */

554   public boolean validateNode(ProgramChromosome a_chrom, CommandGene a_node,
555                               CommandGene a_rootNode, int a_tries, int a_num,
556                               int a_recurseLevel, Class JavaDoc a_type,
557                               CommandGene[] a_functionSet, int a_depth,
558                               boolean a_grow, int a_childIndex) {
559     if (m_nodeValidator == null) {
560       return true;
561     }
562     return m_nodeValidator.validate(a_chrom, a_node, a_rootNode, a_tries, a_num,
563                                     a_recurseLevel, a_type, a_functionSet,
564                                     a_depth, a_grow, a_childIndex);
565   }
566
567   /**
568    * Sets the node validator. Also see method validateNode.
569    *
570    * @param a_nodeValidator sic
571    *
572    * @author Klaus Meffert
573    * @since 3.0
574    */

575   public void setNodeValidator(INodeValidator a_nodeValidator) {
576     m_nodeValidator = a_nodeValidator;
577   }
578
579   /**
580    * @return the node validator set
581    *
582    * @author Klaus Meffert
583    * @since 3.0
584    */

585   public INodeValidator getNodeValidator() {
586     return m_nodeValidator;
587   }
588
589   /**
590    * Compares this entity against the specified object.
591    *
592    * @param a_other the object to compare against
593    * @return true: if the objects are the same, false otherwise
594    *
595    * @author Klaus Meffert
596    * @since 3.1
597    */

598   public boolean equals(Object JavaDoc a_other) {
599     try {
600       return compareTo(a_other) == 0;
601     } catch (ClassCastException JavaDoc cex) {
602       return false;
603     }
604   }
605
606   public int compareTo(Object JavaDoc a_other) {
607     if (a_other == null) {
608       return 1;
609     }
610     else {
611       GPConfiguration other = (GPConfiguration) a_other;
612       return new CompareToBuilder()
613           .append(m_objectiveFunction, other.m_objectiveFunction)
614           .append(m_crossoverProb, other.m_crossoverProb)
615           .append(m_reproductionProb, other.m_reproductionProb)
616           .append(m_newChromsPercent, other.m_newChromsPercent)
617           .append(m_maxCrossoverDepth, other.m_maxCrossoverDepth)
618           .append(m_maxInitDepth, other.m_maxInitDepth)
619           .append(m_selectionMethod.getClass(),
620                   other.m_selectionMethod.getClass())
621           .append(m_crossMethod.getClass(), other.m_crossMethod.getClass())
622           .append(m_programCreationMaxTries, other.m_programCreationMaxTries)
623           .append(m_strictProgramCreation, other.m_strictProgramCreation)
624           .append(m_fitnessEvaluator.getClass(),
625                   other.m_fitnessEvaluator.getClass())
626           .toComparison();
627     }
628   }
629
630   /**
631    *
632    * @return see ProgramChromosome.growOrFull(...) and GPGenotype.evolve()
633    *
634    * @author Klaus Meffert
635    * @since 3.2
636    */

637   public boolean isMaxNodeWarningPrinted() {
638     return m_warningPrinted;
639   }
640
641   /**
642    * See ProgramChromosome.growOrFull(...) and GPGenotype.evolve().
643    *
644    * @author Klaus Meffert
645    * @since 3.2
646    */

647   public void flagMaxNodeWarningPrinted() {
648     m_warningPrinted = true;
649   }
650
651   /**
652    *
653    * @param a_program IGPProgram
654    *
655    * @author Klaus Meffert
656    * @since 3.2
657    */

658   public void setPrototypeProgram(IGPProgram a_program) {
659     m_prototypeProgram = a_program;
660   }
661
662   /**
663    * @return prototype program set (maybe null if not setted previously)
664    *
665    * @author Klaus Meffert
666    * @since 3.2
667    */

668   public IGPProgram getPrototypeProgram() {
669     return m_prototypeProgram;
670   }
671
672   /**
673    * @return capacity of the memory in cells
674    *
675    * @author Klaus Meffert
676    * @since 3.2
677    */

678   public int getMemorySize() {
679     return m_memory.size();
680   }
681
682   public GPProgramInfo readProgramCache(GPProgram a_prog) {
683     GPProgramInfo pci = new GPProgramInfo(a_prog, true);
684     pci.setFound(false);
685     return (GPProgramInfo)m_programCache.get(pci.getToStringNorm());
686   }
687
688   public GPProgramInfo putToProgramCache(GPProgram a_prog) {
689     GPProgramInfo pci = new GPProgramInfo(a_prog, true);
690     return (GPProgramInfo)m_programCache.put(pci.getToStringNorm(), pci);
691   }
692
693   public boolean isUseProgramCache() {
694     return m_useProgramCache;
695   }
696
697   public void setUseProgramCache(boolean a_useCache) {
698     m_useProgramCache = a_useCache;
699   }
700 }
701 /**@todo introduce lock for configuration*/
702
Popular Tags