KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jgap > gp > CommandGene


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;
11
12 import java.io.*;
13 import org.jgap.*;
14 import org.jgap.gp.impl.*;
15
16 /**
17  * Abstract base class for all GP commands. A CommandGene can hold additional
18  * CommandGene's, it acts sort of like a Composite (also see CompositeGene for
19  * a smiliar characteristics, although for a GA).
20  *
21  * @author Klaus Meffert
22  * @since 3.0
23  */

24 public abstract class CommandGene
25     implements Comparable JavaDoc, Serializable {
26   /** String containing the CVS revision. Read out via reflection!*/
27   private final static String JavaDoc CVS_REVISION = "$Revision: 1.19 $";
28
29   /**
30    * Delta, useful for comparing doubles and floats.
31    */

32   public static final double DELTA = 0.0000001;
33
34   public final static Class JavaDoc BooleanClass = Boolean JavaDoc.class;
35
36   public final static Class JavaDoc IntegerClass = Integer JavaDoc.class;
37
38   public final static Class JavaDoc LongClass = Long JavaDoc.class;
39
40   public final static Class JavaDoc FloatClass = Float JavaDoc.class;
41
42   public final static Class JavaDoc DoubleClass = Double JavaDoc.class;
43
44   public final static Class JavaDoc VoidClass = Void JavaDoc.class;
45
46   private GPConfiguration m_configuration;
47
48   /**
49    * Should isValid() be called? True = no!
50    */

51   private boolean m_noValidation;
52
53   /**
54    * The return type of this node.
55    */

56   private Class JavaDoc m_returnType;
57
58   private int m_arity;
59
60   private boolean m_integerType;
61
62   private boolean m_floatType;
63
64   /** Energy of a gene, see RFE 1102206*/
65   private double m_energy;
66
67   /**
68    * Application-specific data that is attached to the Gene. This data may
69    * assist the application in labelling this Gene.
70    * JGAP ignores the data, aside from allowing it to be set and
71    * retrieved and considering it in clone() and compareTo().
72    *
73    * @since 3.0
74    */

75   private Object JavaDoc m_applicationData;
76
77   /**
78    * Method compareTo(): Should we also consider the application data when
79    * comparing? Default is "false" as "true" means a Gene's losing its
80    * identity when application data is set differently!
81    *
82    * @since 3.0
83    */

84   private boolean m_compareAppData;
85
86   private int m_subReturnType;
87
88   private int[] m_subChildTypes;
89
90   /**
91    * Initializations, called from each Constructor.
92    */

93   protected void init() {
94   }
95
96   public CommandGene(final GPConfiguration a_conf, final int a_arity,
97                      final Class JavaDoc a_returnType)
98       throws InvalidConfigurationException {
99     if (a_conf == null) {
100       throw new InvalidConfigurationException("Configuration must not be null!");
101     }
102     m_configuration = a_conf;
103     init();
104     m_arity = a_arity;
105     m_returnType = a_returnType;
106     if (a_returnType == Integer JavaDoc.class
107         || a_returnType == Long JavaDoc.class) {
108       m_integerType = true;
109     }
110     else if (a_returnType == Double JavaDoc.class
111              || a_returnType == Float JavaDoc.class) {
112       m_floatType = true;
113     }
114   }
115
116   /**
117    * Allows specifying a sub return type and sub child types.
118    *
119    * @param a_conf GPConfiguration
120    * @param a_arity int
121    * @param a_returnType Class
122    * @param a_subReturnType int
123    * @param a_childSubTypes int[]
124    * @throws InvalidConfigurationException
125    *
126    * @author Klaus Meffert
127    * @since 3.2
128    */

129   public CommandGene(final GPConfiguration a_conf, final int a_arity,
130                      final Class JavaDoc a_returnType, final int a_subReturnType,
131                      final int[] a_childSubTypes)
132       throws InvalidConfigurationException {
133     this(a_conf, a_arity, a_returnType);
134     if (a_childSubTypes != null) {
135       boolean specialCase = false;
136       // Special case from convenient construction.
137
// ------------------------------------------
138
if (a_childSubTypes.length == 1) {
139         if (a_childSubTypes[0] == 0) {
140           m_subChildTypes = null;
141           specialCase = true;
142         }
143       }
144       if (!specialCase) {
145         if (a_childSubTypes.length != a_arity) {
146           throw new IllegalArgumentException JavaDoc(
147               "Length of child sub types must equal"
148               + " the given arity (or set the former to null)");
149         }
150       }
151       else {
152         m_subChildTypes = a_childSubTypes;
153       }
154     }
155     else {
156       m_subChildTypes = a_childSubTypes;
157     }
158     m_subReturnType = a_subReturnType;
159   }
160
161   /**
162    * Command with one child: Allows specifying a sub return type and a sub child
163    * type. Convenience version of the called constructor.
164    *
165    * @param a_conf GPConfiguration
166    * @param a_arity int
167    * @param a_returnType Class
168    * @param a_subReturnType int
169    * @param a_childSubType int
170    * @throws InvalidConfigurationException
171    *
172    * @author Klaus Meffert
173    * @since 3.2
174    */

175   public CommandGene(final GPConfiguration a_conf, final int a_arity,
176                      final Class JavaDoc a_returnType, final int a_subReturnType,
177                      final int a_childSubType)
178       throws InvalidConfigurationException {
179     this(a_conf, a_arity, a_returnType, a_subReturnType,
180          new int[] {a_childSubType});
181   }
182
183   public void setAllele(Object JavaDoc a_newValue) {
184     throw new java.lang.UnsupportedOperationException JavaDoc(
185         "Method setAllele() not used.");
186   }
187
188   public Object JavaDoc getAllele() {
189     return null;
190   }
191
192   public String JavaDoc getPersistentRepresentation()
193       throws UnsupportedOperationException JavaDoc {
194     /**@todo Implement this org.jgap.Gene method*/
195     throw new java.lang.UnsupportedOperationException JavaDoc(
196         "Method getPersistentRepresentation() not yet implemented.");
197   }
198
199   public void setValueFromPersistentRepresentation(String JavaDoc a_representation)
200       throws UnsupportedOperationException JavaDoc, UnsupportedRepresentationException {
201     /**@todo Implement this org.jgap.Gene method*/
202     throw new java.lang.UnsupportedOperationException JavaDoc(
203         "Method setValueFromPersistentRepresentation() not yet implemented.");
204   }
205
206   public void setToRandomValue(RandomGenerator a_numberGenerator) {
207     // Do nothing here by default.
208
// ---------------------------
209
}
210
211   public void cleanup() {
212     // Do nothing here by default.
213
// ---------------------------
214
}
215
216   public int size() {
217     return m_arity;
218   }
219
220   /**
221    * Arity of the command. Override if necessary.
222    *
223    * @param a_indvividual the invididual the command's arity may depend on (in
224    * most cases the arity will not depend on the individual)
225    * @return arity of the command
226    *
227    * @author Klaus Meffert
228    * @since 3.0
229    */

230   public int getArity(IGPProgram a_indvividual) {
231     return m_arity;
232   }
233
234   public int compareTo(Object JavaDoc a_other) {
235     CommandGene o2 = (CommandGene) a_other;
236     if (size() != o2.size()) {
237       if (size() > o2.size()) {
238         return 1;
239       }
240       else {
241         return -1;
242       }
243     }
244     if (getClass() != o2.getClass()) {
245       /**@todo do it more precisely*/
246       return -1;
247     }
248     else {
249       return 0;
250     }
251   }
252
253   public boolean equals(Object JavaDoc a_other) {
254     if (a_other == null) {
255       return false;
256     }
257     else {
258       try {
259         /**@todo return type, input type*/
260         CommandGene other = (CommandGene) a_other;
261         if (getClass() == a_other.getClass()) {
262           if (getInternalValue() == null) {
263             if (other.getInternalValue() == null) {
264               return true;
265             }
266             else {
267               return false;
268             }
269           }
270           else {
271             if (other.getInternalValue() == null) {
272               return false;
273             }
274             else {
275               return true;
276             }
277           }
278         }
279         else {
280           return false;
281         }
282       } catch (ClassCastException JavaDoc cex) {
283         return false;
284       }
285     }
286   }
287
288   /**
289    * @return the string representation of the command. Especially usefull to
290    * output a resulting formula in human-readable form.
291    */

292   public abstract String JavaDoc toString();
293
294   /**
295    * Executes this node without knowing its return type.
296    *
297    * @param c the current Chromosome which is executing
298    * @param n the index of the Function in the Chromosome's Function array which
299    * is executing
300    * @param args the arguments to the current Chromosome which is executing
301    * @return the object which wraps the return value of this node, or null
302    * if the return type is null or unknown
303    * @throws UnsupportedOperationException if the type of this node is not
304    * boolean
305    *
306    * @author Klaus Meffert
307    * @since 3.0
308    */

309   public Object JavaDoc execute(ProgramChromosome c, int n, Object JavaDoc[] args) {
310     if (m_returnType == BooleanClass) {
311       return new Boolean JavaDoc(execute_boolean(c, n, args));
312     }
313     if (m_returnType == IntegerClass) {
314       return new Integer JavaDoc(execute_int(c, n, args));
315     }
316     if (m_returnType == LongClass) {
317       return new Long JavaDoc(execute_long(c, n, args));
318     }
319     if (m_returnType == FloatClass) {
320       return new Float JavaDoc(execute_float(c, n, args));
321     }
322     if (m_returnType == DoubleClass) {
323       return new Double JavaDoc(execute_double(c, n, args));
324     }
325     if (m_returnType == VoidClass) {
326       execute_void(c, n, args);
327     }
328     else {
329       return execute_object(c, n, args);
330     }
331     return null;
332   }
333
334   /**
335    * @return the return type of this node
336    *
337    * @author Klaus Meffert
338    * @since 3.0
339    */

340   public Class JavaDoc getReturnType() {
341     return m_returnType;
342   }
343
344   /**
345    * Sets the return type of this node.
346    *
347    * @param a_type the type to set the return type to
348    *
349    * @author Klaus Meffert
350    * @since 3.0
351    */

352   public void setReturnType(Class JavaDoc a_type) {
353     m_returnType = a_type;
354   }
355
356   /**
357    * Executes this node as a boolean. Override to implement.
358    *
359    * @param c ignored here
360    * @param n ignored here
361    * @param args ignored here
362    * @return nothing but exception
363    * @throws UnsupportedOperationException
364    *
365    * @author Klaus Meffert
366    * @since 3.0
367    */

368   public boolean execute_boolean(ProgramChromosome c, int n, Object JavaDoc[] args) {
369     throw new UnsupportedOperationException JavaDoc(getName() +
370         " cannot return boolean");
371   }
372
373   /**
374    * Executes this node, returning nothing. Override to implement.
375    *
376    * @param c ignored here
377    * @param n ignored here
378    * @param args ignored here
379    * @throws UnsupportedOperationException
380    *
381    * @author Klaus Meffert
382    * @since 3.0
383    */

384   public void execute_void(ProgramChromosome c, int n, Object JavaDoc[] args) {
385     throw new UnsupportedOperationException JavaDoc(getName() +
386         " cannot return void");
387   }
388
389   /**
390    * Executes this node as an integer. Override to implement.
391    *
392    * @param c ignored here
393    * @param n ignored here
394    * @param args ignored here
395    * @return nothing but exception
396    * @throws UnsupportedOperationException
397    *
398    * @author Klaus Meffert
399    * @since 3.0
400    */

401   public int execute_int(ProgramChromosome c, int n, Object JavaDoc[] args) {
402     throw new UnsupportedOperationException JavaDoc(getName() +
403         " cannot return int");
404   }
405
406   /**
407    * Executes this node as a long. Override to implement.
408    *
409    * @param c ignored here
410    * @param n ignored here
411    * @param args ignored here
412    * @return nothing but exception
413    * @throws UnsupportedOperationException
414    *
415    * @author Klaus Meffert
416    * @since 3.0
417    */

418   public long execute_long(ProgramChromosome c, int n, Object JavaDoc[] args) {
419     throw new UnsupportedOperationException JavaDoc(getName() +
420         " cannot return long");
421   }
422
423   /**
424    * Executes this node as a float. Override to implement.
425    *
426    * @param c ignored here
427    * @param n ignored here
428    * @param args ignored here
429    * @return nothing but exception
430    * @throws UnsupportedOperationException
431    *
432    * @author Klaus Meffert
433    * @since 3.0
434    */

435   public float execute_float(ProgramChromosome c, int n, Object JavaDoc[] args) {
436     throw new UnsupportedOperationException JavaDoc(getName() +
437         " cannot return float");
438   }
439
440   /**
441    * Executes this node as a double. Override to implement.
442    *
443    * @param c ignored here
444    * @param n ignored here
445    * @param args ignored here
446    * @return nothing but exception
447    * @throws UnsupportedOperationException
448    *
449    * @author Klaus Meffert
450    * @since 3.0
451    */

452   public double execute_double(ProgramChromosome c, int n, Object JavaDoc[] args) {
453     throw new UnsupportedOperationException JavaDoc(getName() +
454         " cannot return double");
455   }
456
457   /**
458    * Executes this node as an object. Override to implement.
459    *
460    * @param c ignored here
461    * @param n ignored here
462    * @param args ignored here
463    * @return nothing but exception
464    * @throws UnsupportedOperationException
465    *
466    * @author Klaus Meffert
467    * @since 3.0
468    */

469   public Object JavaDoc execute_object(ProgramChromosome c, int n, Object JavaDoc[] args) {
470     throw new UnsupportedOperationException JavaDoc(getName() +
471         " cannot return Object");
472   }
473
474   public String JavaDoc getName() {
475     return toString();
476   }
477
478   /**
479    * Gets the type of node allowed from the given child number. Should be
480    * overridden in subclasses.
481    *
482    * @param a_ind the individual the child belongs to
483    * @param a_chromNum the chromosome number
484    * @return the type of node allowed for that child, or null of no child
485    * exists
486    *
487    * @author Klaus Meffert
488    * @since 3.0
489    */

490   public Class JavaDoc getChildType(IGPProgram a_ind, int a_chromNum) {
491     if (m_arity == 0) {
492       return null;
493     }
494     else {
495       return getReturnType();
496     }
497   }
498
499   protected Object JavaDoc getInternalValue() {
500     return null;
501   }
502
503   /**
504    * Retrieves the hash code value for a CommandGene.
505    * Override if another hashCode() implementation is necessary or more
506    * appropriate than this default implementation.
507    *
508    * @return this Gene's hash code
509    *
510    * @author Klaus Meffert
511    * @since 3.0
512    */

513   public int hashCode() {
514     // If our internal value is null, then return zero. Otherwise,
515
// just return the hash code of the allele Object.
516
// -----------------------------------------------------------
517
if (getInternalValue() == null) {
518       return getClass().getName().hashCode();
519     }
520     else {
521       return getInternalValue().hashCode();
522     }
523   }
524
525   public boolean isIntegerType() {
526     return m_integerType;
527   }
528
529   public boolean isFloatType() {
530     return m_floatType;
531   }
532
533   /**
534    * @return true: command affects global state (i.e. stack or memory)
535    *
536    * @author Klaus Meffert
537    * @since 3.0
538    */

539   public boolean isAffectGlobalState() {
540     return false;
541   }
542
543   /**
544    * Subclasses capable of validating programs should overwrite this method.
545    * See PushCommand as a sample.
546    *
547    * @param a_program the ProgramChromosome to validate
548    * @return true: a_program is (superficially) valid with the current Command
549    *
550    * @author Klaus Meffert
551    * @since 3.0
552    */

553   public boolean isValid(ProgramChromosome a_program) {
554     return true;
555   }
556
557   public boolean isValid(ProgramChromosome a_program, int a_index) {
558     return true;
559   }
560
561   protected void check(ProgramChromosome a_program) {
562     if (m_noValidation) {
563       return;
564     }
565     if (!isValid(a_program)) {
566       throw new IllegalStateException JavaDoc("State for GP-command not valid");
567     }
568   }
569
570   protected void check(ProgramChromosome a_program, int a_index) {
571     if (m_noValidation) {
572       return;
573     }
574     if (!isValid(a_program, a_index)) {
575       throw new IllegalStateException JavaDoc("State for GP-command not valid");
576     }
577   }
578
579   public void setNoValidation(boolean a_noValidation) {
580     m_noValidation = a_noValidation;
581   }
582
583   /**
584    * @return the configuration set
585    *
586    * @author Klaus Meffert
587    * @since 3.0
588    */

589   public GPConfiguration getGPConfiguration() {
590     return m_configuration;
591   }
592
593   /**
594    * This sets the application-specific data that is attached to this Gene.
595    * Attaching application-specific data may be useful for some applications
596    * when it comes time to distinguish a Gene from another. JGAP ignores this
597    * data functionally.
598    *
599    * @param a_newData the new application-specific data to attach to this
600    * Gene
601    *
602    * @author Klaus Meffert
603    * @since 3.0
604    */

605   public void setApplicationData(final Object JavaDoc a_newData) {
606     m_applicationData = a_newData;
607   }
608
609   /**
610    * Retrieves the application-specific data that is attached to this Gene.
611    * Attaching application-specific data may be useful for
612    * some applications when it comes time to distinguish a Gene from another.
613    * JGAP ignores this data functionally.
614    *
615    * @return the application-specific data previously attached to this Gene,
616    * or null if there is no data attached
617    *
618    * @author Klaus Meffert
619    * @since 3.0
620    */

621   public Object JavaDoc getApplicationData() {
622     return m_applicationData;
623   }
624
625   /**
626    * Should we also consider the application data when comparing? Default is
627    * "false" as "true" means a Gene is losing its identity when
628    * application data is set differently!
629    *
630    * @param a_doCompare true: consider application data in method compareTo
631    *
632    * @author Klaus Meffert
633    * @since 2.4
634    */

635   public void setCompareApplicationData(final boolean a_doCompare) {
636     m_compareAppData = a_doCompare;
637   }
638
639   /*
640    * @return should we also consider the application data when comparing?
641    *
642    * @author Klaus Meffert
643    * @since 3.0
644    */

645   public boolean isCompareApplicationData() {
646     return m_compareAppData;
647   }
648
649   /**
650    * @return energy of the gene
651    *
652    * @author Klaus Meffert
653    * @since 2.3
654    */

655   public double getEnergy() {
656     return m_energy;
657   }
658
659   /**
660    * Sets the energy of the gene.
661    *
662    * @param a_energy the energy to set
663    *
664    * @author Klaus Meffert
665    * @since 2.3
666    */

667   public void setEnergy(final double a_energy) {
668     m_energy = a_energy;
669   }
670
671   /**
672    * @return sub return type
673    *
674    * @author Klaus Meffert
675    * @since 3.2
676    */

677   public int getSubReturnType() {
678     return m_subReturnType;
679   }
680
681   public int getSubChildType(int a_childNum) {
682     if (m_subChildTypes == null) {
683       return 0;
684     }
685     else {
686       return m_subChildTypes[a_childNum];
687     }
688   }
689
690   protected int[] getSubChildTypes() {
691     return m_subChildTypes;
692   }
693 }
694
Popular Tags