KickJava   Java API By Example, From Geeks To Geeks.

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


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.function.*;
16 import org.jgap.gp.*;
17 import org.jgap.util.*;
18
19 /**
20  * A GP program contains 1..n ProgramChromosome's.
21  *
22  * @author Klaus Meffert
23  * @since 3.0
24  */

25 public class GPProgram
26     extends GPProgramBase implements Serializable, Comparable JavaDoc, ICloneable {
27   /** String containing the CVS revision. Read out via reflection!*/
28   private final static String JavaDoc CVS_REVISION = "$Revision: 1.10 $";
29
30   /**
31    * Holds the chromosomes contained in this program.
32    */

33   private ProgramChromosome[] m_chromosomes;
34
35   /**
36    * Constructor.
37    *
38    * @param a_conf the configuration to use
39    * @param a_types the type of each chromosome, the length is the number of
40    * chromosomes
41    * @param a_argTypes the types of the arguments to each chromosome, must be an
42    * array of arrays, the first dimension of which is the number of chromosomes
43    * and the second dimension of which is the number of arguments to the
44    * chromosome
45    * @param a_nodeSets the nodes which are allowed to be used by each chromosome,
46    * must be an array of arrays, the first dimension of which is the number of
47    * chromosomes and the second dimension of which is the number of nodes
48    * @param a_minDepths contains the minimum depth allowed for each chromosome
49    * @param a_maxDepths contains the maximum depth allowed for each chromosome
50    * @param a_maxNodes reserve space for a_maxNodes number of nodes
51    * @throws InvalidConfigurationException
52    *
53    * @author Klaus Meffert
54    * @since 3.0
55    */

56   public GPProgram(GPConfiguration a_conf, Class JavaDoc[] a_types,
57                    Class JavaDoc[][] a_argTypes, CommandGene[][] a_nodeSets,
58                    int[] a_minDepths, int[] a_maxDepths, int a_maxNodes)
59       throws InvalidConfigurationException {
60     super(a_conf);
61     m_chromosomes = new ProgramChromosome[a_types.length];
62     setTypes(a_types);
63     setArgTypes(a_argTypes);
64     setNodeSets(a_nodeSets);
65     setMaxDepths(a_maxDepths);
66     setMinDepths(a_minDepths);
67     setMaxNodes(a_maxNodes);
68   }
69
70   /**
71    * Constructor to initialize a GPProgram with values of another GPProgram.
72    *
73    * @param a_prog the GPProgram to read the initialization values from
74    * @throws InvalidConfigurationException
75    *
76    * @author Klaus Meffert
77    * @since 3.0
78    */

79   public GPProgram(IGPProgram a_prog)
80       throws InvalidConfigurationException {
81     super(a_prog);
82     m_chromosomes = new ProgramChromosome[getTypes().length];
83   }
84
85   /**
86    * Sort of minimalistic constructor. Use only if you are aware of what you do.
87    *
88    * @param a_conf the configuration to use
89    * @param a_numChromosomes the number of chromosomes to use with this program.
90    * @throws InvalidConfigurationException
91    *
92    * @author Klaus Meffert
93    * @since 3.0
94    */

95   public GPProgram(GPConfiguration a_conf, int a_numChromosomes)
96       throws InvalidConfigurationException {
97     super(a_conf);
98     m_chromosomes = new ProgramChromosome[a_numChromosomes];
99   }
100
101   /**
102    * @param a_index the chromosome to get
103    * @return the ProgramChromosome with the given index
104    *
105    * @author Klaus Meffert
106    * @since 3.0
107    */

108   public ProgramChromosome getChromosome(int a_index) {
109     return m_chromosomes[a_index];
110   }
111
112   /**
113    * Sets the given chromosome at the given index.
114    *
115    * @param a_index sic
116    * @param a_chrom sic
117    *
118    * @author Klaus Meffert
119    * @since 3.0
120    */

121   public void setChromosome(int a_index, ProgramChromosome a_chrom) {
122     m_chromosomes[a_index] = a_chrom;
123   }
124
125   public void growOrFull(int a_depth, boolean a_grow, int a_maxNodes,
126                          boolean[] a_fullModeAllowed) {
127     GPConfiguration conf = getGPConfiguration();
128     int size = m_chromosomes.length;
129     for (int i = 0; i < size; i++) {
130       try {
131         // Construct a chromosome with place for a_maxNodes nodes.
132
// -------------------------------------------------------
133
m_chromosomes[i] = new ProgramChromosome(conf, a_maxNodes, this);
134       } catch (InvalidConfigurationException iex) {
135         throw new RuntimeException JavaDoc(iex);
136       }
137       m_chromosomes[i].setArgTypes(getArgTypes()[i]);
138       // If there are ADF's in the nodeSet, then set their type according to
139
// the chromosome it references.
140
// -------------------------------------------------------------------
141
int len = getNodeSets()[i].length;
142       for (int j = 0; j < len; j++) {
143         if (getNodeSets()[i][j] instanceof ADF) {
144           ( (ADF) getNodeSets()[i][j]).setReturnType(
145               getTypes()[ ( (ADF) getNodeSets()[i][j]).getChromosomeNum()]);
146         }
147       }
148     }
149     int depth;
150     for (int i = 0; i < size; i++) {
151       // Restrict depth to input params.
152
// -------------------------------
153
if (getMaxDepths() != null && a_depth > getMaxDepths()[i]) {
154         depth = getMaxDepths()[i];
155       }
156       else {
157         if (getMinDepths() != null && a_depth < getMinDepths()[i]) {
158           depth = getMinDepths()[i];
159         }
160         else {
161           depth = a_depth;
162         }
163       }
164       // Decide whether to use grow mode or full mode.
165
// ---------------------------------------------
166
if (a_grow || !a_fullModeAllowed[i]) {
167         m_chromosomes[i].growOrFull(i, depth, getType(i), getArgType(i),
168                                     getNodeSet(i), true);
169       }
170       else {
171         m_chromosomes[i].growOrFull(i, depth, getType(i), getArgType(i),
172                                     getNodeSet(i), false);
173       }
174     }
175     if (getGPConfiguration().isUseProgramCache()) {
176       // Cache fitness value by checking if a program with same
177
// representation was computed before.
178
GPProgramInfo pcInfo = getGPConfiguration().readProgramCache(this);
179       if (pcInfo == null) {
180         /**@todo add listener for event "same program evolved again"*/
181         pcInfo = getGPConfiguration().putToProgramCache(this);
182       }
183       else {
184         setFitnessValue(pcInfo.getFitnessValue());
185       }
186     }
187   }
188
189   /**
190    * @return the number of chromosomes in the program
191    *
192    * @author Klaus Meffert
193    * @since 3.0
194    */

195   public int size() {
196     return m_chromosomes.length;
197   }
198
199   /**
200    * Builds a String that represents the output of the GPProgram in
201    * left-hand-notion.
202    * @param a_startNode the node to start with
203    * @return output in left-hand notion
204    *
205    * @author Klaus Meffert
206    * @since 3.0
207    */

208   public String JavaDoc toString(int a_startNode) {
209     if (a_startNode < 0) {
210       return "";
211     }
212     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
213     for (int i = 0; i < m_chromosomes.length; i++) {
214       if (i > 0) {
215         sb.append(" ==> ");
216       }
217       sb.append(m_chromosomes[i].toString(a_startNode));
218     }
219     return sb.toString();
220   }
221
222   /**
223    * Builds a String that represents the normalized output of the GPProgram.
224    * @param a_startNode the node to start with
225    * @return output in normalized notion
226    *
227    * @author Klaus Meffert
228    * @since 3.0
229    */

230   public String JavaDoc toStringNorm(int a_startNode) {
231     if (a_startNode < 0) {
232       return "";
233     }
234     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
235     for (int i = 0; i < m_chromosomes.length; i++) {
236       if (i > 0) {
237         sb.append(" ==> ");
238       }
239       sb.append(m_chromosomes[i].toStringNorm(a_startNode));
240     }
241     return sb.toString();
242   }
243
244   /**
245    * Executes the given chromosome as an integer function.
246    *
247    * @param a_chromosomeNum the index of the chromosome to execute
248    * @param a_args the arguments to use
249    * @return the integer return value
250    *
251    * @author Klaus Meffert
252    * @since 3.0
253    */

254   public int execute_int(int a_chromosomeNum, Object JavaDoc[] a_args) {
255     m_chromosomes[a_chromosomeNum].setIndividual(this);
256     return m_chromosomes[a_chromosomeNum].execute_int(a_args);
257   }
258
259   /**
260    * Executes the given chromosome as a float function.
261    *
262    * @param a_chromosomeNum the index of the chromosome to execute
263    * @param a_args the arguments to use
264    * @return the floar return value
265    *
266    * @author Klaus Meffert
267    * @since 3.0
268    */

269   public float execute_float(int a_chromosomeNum, Object JavaDoc[] a_args) {
270     m_chromosomes[a_chromosomeNum].setIndividual(this);
271     return m_chromosomes[a_chromosomeNum].execute_float(a_args);
272   }
273
274   /**
275    * Executes the given chromosome as a double function.
276    *
277    * @param a_chromosomeNum the index of the chromosome to execute
278    * @param a_args the arguments to use
279    * @return the double return value
280    *
281    * @author Klaus Meffert
282    * @since 3.0
283    */

284   public double execute_double(int a_chromosomeNum, Object JavaDoc[] a_args) {
285     m_chromosomes[a_chromosomeNum].setIndividual(this);
286     return m_chromosomes[a_chromosomeNum].execute_double(a_args);
287   }
288
289   /**
290    * Executes the given chromosome as an object function.
291    *
292    * @param a_chromosomeNum the index of the chromosome to execute
293    * @param a_args the arguments to use
294    * @return the object return value
295    *
296    * @author Klaus Meffert
297    * @since 3.0
298    */

299   public Object JavaDoc execute_object(int a_chromosomeNum, Object JavaDoc[] a_args) {
300     m_chromosomes[a_chromosomeNum].setIndividual(this);
301     return m_chromosomes[a_chromosomeNum].execute_object(a_args);
302   }
303
304   /**
305    * Executes the given chromosome as an object function.
306    *
307    * @param a_chromosomeNum the index of the chromosome to execute
308    * @param a_args the arguments to use
309    *
310    * @author Klaus Meffert
311    * @since 3.0
312    */

313   public void execute_void(int a_chromosomeNum, Object JavaDoc[] a_args) {
314     m_chromosomes[a_chromosomeNum].setIndividual(this);
315     m_chromosomes[a_chromosomeNum].execute_void(a_args);
316   }
317
318   /**
319    * Searches for a chromosome that has the given class and returns its index.
320    *
321    * @param a_chromosomeNum the index of the chromosome to start the search with
322    * @param a_class the class to find
323    * @return the index of the first chromosome found that is of a_class, or -1
324    *
325    * @author Klaus Meffert
326    * @since 3.0
327    */

328   public int getCommandOfClass(int a_chromosomeNum, Class JavaDoc a_class) {
329     for (int i = a_chromosomeNum; i < m_chromosomes.length; i++) {
330       int j = m_chromosomes[i].getCommandOfClass(0, a_class);
331       if (j >= 0) {
332         return j;
333       }
334     }
335     return -1;
336   }
337
338   /**
339    * Compares the given program to this program.
340    *
341    * @param a_other the program against which to compare this program
342    * @return a negative number if this program is "less than" the given
343    * program, zero if they are equal to each other, and a positive number if
344    * this program is "greater than" the given program
345    *
346    * @author Klaus Meffert
347    * @since 3.0
348    */

349   public int compareTo(Object JavaDoc a_other) {
350     // First, if the other Chromosome is null, then this chromosome is
351
// automatically the "greater" Chromosome.
352
// ---------------------------------------------------------------
353
if (a_other == null) {
354       return 1;
355     }
356     int size = size();
357     GPProgram other = (GPProgram) a_other;
358     ProgramChromosome[] otherChroms = other.m_chromosomes;
359     // If the other Chromosome doesn't have the same number of genes,
360
// then whichever has more is the "greater" Chromosome.
361
// --------------------------------------------------------------
362
if (other.size() != size) {
363       return size() - other.size();
364     }
365     // Next, compare the gene values (alleles) for differences. If
366
// one of the genes is not equal, then we return the result of its
367
// comparison.
368
// ---------------------------------------------------------------
369
Arrays.sort(m_chromosomes);
370     Arrays.sort(otherChroms);
371     for (int i = 0; i < size; i++) {
372       int comparison = m_chromosomes[i].compareTo(otherChroms[i]);
373       if (comparison != 0) {
374         return comparison;
375       }
376     }
377     // Everything is equal. Return zero.
378
// ---------------------------------
379
return 0;
380   }
381
382   /**
383    * @return deep clone of the object instance
384    *
385    * @author Klaus Meffert
386    * @since 3.2
387    */

388   public Object JavaDoc clone() {
389     try {
390       // Min and max depths can be null.
391
// -------------------------------
392
int[] minDepthsClone;
393       if (getMinDepths() != null) {
394         minDepthsClone = (int[]) getMinDepths().clone();
395       }
396       else {
397         minDepthsClone = null;
398       }
399       int[] maxDepthsClone;
400       if (getMaxDepths() != null) {
401         maxDepthsClone = (int[]) getMaxDepths().clone();
402       }
403       else {
404         maxDepthsClone = null;
405       }
406       GPProgram result = new GPProgram(getGPConfiguration(),
407                                        (Class JavaDoc[]) getTypes().clone(),
408                                        (Class JavaDoc[][]) getArgTypes().clone(),
409                                        (CommandGene[][]) getNodeSets().clone(),
410                                        minDepthsClone,
411                                        maxDepthsClone,
412                                        getMaxNodes());
413       result.setFitnessValue(getFitnessValueDirectly());
414       // Try to clone application data.
415
// ------------------------------
416
Object JavaDoc appData = getApplicationData();
417       if (appData != null) {
418         ICloneHandler cloner = getGPConfiguration().getJGAPFactory().getCloneHandlerFor(appData,null);
419         if (cloner != null) {
420           result.setApplicationData(cloner.perform(appData,null,null));
421         }
422         else {
423           result.setApplicationData(appData);
424         }
425       }
426       for (int i = 0; i < m_chromosomes.length; i++) {
427         if (m_chromosomes[i] == null) {
428           break;
429         }
430         result.m_chromosomes[i] = (ProgramChromosome) m_chromosomes[i].clone();
431       }
432       return result;
433     } catch (Exception JavaDoc ex) {
434       throw new CloneException(ex);
435     }
436   }
437 }
438
Popular Tags