1 | /* |
---|
2 | Copyright 2006 by Sean Luke |
---|
3 | Licensed under the Academic Free License version 3.0 |
---|
4 | See the file "LICENSE" for more information |
---|
5 | */ |
---|
6 | |
---|
7 | |
---|
8 | package ec.gp; |
---|
9 | import ec.*; |
---|
10 | import ec.util.*; |
---|
11 | |
---|
12 | /* |
---|
13 | * GPType.java |
---|
14 | * |
---|
15 | * Created: Fri Aug 27 20:54:23 1999 |
---|
16 | * By: Sean Luke |
---|
17 | */ |
---|
18 | |
---|
19 | /** |
---|
20 | * GPType is a Clique which represents types in |
---|
21 | * Strongly-Typed Genetic Programming (STGP). |
---|
22 | * (David Montana, "Strongly-Typed Genetic Programming", |
---|
23 | * <i>Evolutionary Computation</i> 3(2), pp. 199-230). |
---|
24 | * |
---|
25 | * <p>In STGP, each function node has a <i>return-type</i>, and each of |
---|
26 | * its arguments also have assigned types. Furthermore, the tree |
---|
27 | * itself has a predefined "tree type". STGP permits crossover |
---|
28 | * and mutation of trees only with the constraint that each node's |
---|
29 | * return type "fits" with the corresponding argument type in the |
---|
30 | * node's parent; further, the root node's return type must "fit" with |
---|
31 | * the tree type. |
---|
32 | * |
---|
33 | * <p>The simplest definition of "fit" is that the types must be the same. |
---|
34 | * Montana calls this "Basic" STGP (see section 2.1). This is the form |
---|
35 | * of STGP that most implementations do, and it's not very powerful. |
---|
36 | * |
---|
37 | * <p>Montana further defined generic functions (ones with polymorphic |
---|
38 | * data types). Such beasts "fit" only if the trees involved can be |
---|
39 | * unified to make them fit, an expensive proceedure which ECJ does not |
---|
40 | * support. However, ECJ's does support a compromise between simple |
---|
41 | * "Basic" STGP and STGP with polymorphic types: providing both |
---|
42 | * <i>atomic types</i> (basic STGP) and a more powerful notion of |
---|
43 | * <i>set types</i>. |
---|
44 | * |
---|
45 | * <p>An atomic type is a basic GP type. Atomic types "fit" only |
---|
46 | * if they're the same object (this implementation uses == ). A problem |
---|
47 | * domain that only uses atomic types is essentially doing "Basic" STGP. |
---|
48 | * |
---|
49 | * <p>Set types are sets of atomic types. A set type "fits" with an |
---|
50 | * atomic type only if it contains the atomic type in its set. A set type |
---|
51 | * "fits" with another set type only if they share at least one atomic type |
---|
52 | * in common (that is, the intersection of their sets is nonempty). |
---|
53 | * |
---|
54 | * <p>Set types allow for types which can fit in several different generic |
---|
55 | * places -- an object can now say that it "fits" with types |
---|
56 | * A or B or C, but not D or E. |
---|
57 | * |
---|
58 | * <p>GPTypes are a Clique, and they set themselves up as a group; in general |
---|
59 | * you should not create any new GPTypes. You should also not attempt to |
---|
60 | * clone them, since type equivalence is determined partially by pointer |
---|
61 | * equivalence. |
---|
62 | * |
---|
63 | * <p><b>What Set and Atomic Types Can Do. </b> |
---|
64 | * Set and Atomic types can be used for most of the existing literature |
---|
65 | * (major exceptions: Tina Yu's work, and also work on multiplying |
---|
66 | * matricies with GP). For example, |
---|
67 | * I am fairly certain that atomic types and set types can be used to |
---|
68 | * implement any mechanism devisable using type inheritance along the lines |
---|
69 | * of (Thomas Haynes, Dale Schoenefeld, and Roger Wainwright, |
---|
70 | * "Type Inheritance in Strongly Typed Genetic Programming", |
---|
71 | * <i>Advances in Genetic Progrmming 2</i>, pp. 359-376. |
---|
72 | * Let's say that you wanted to define some classes a-la Haynes <i>et al</i> |
---|
73 | * with multiple inheritance, |
---|
74 | * say, a Vehicle, a Red-Thing, a Car (which is a Vehicle), a Truck (which |
---|
75 | * is a Vehicle), and a Fire-Truck (which is a Truck and a Red-Thing). Now, you |
---|
76 | * want to guarantee that children nodes fit with parents only if the return |
---|
77 | * value of the children node is a subclass of the parents' argument slot. |
---|
78 | * You can do this as follows: first, you create an atomic type for each |
---|
79 | * of the classes above. Then you create the set types: Vehicle-S = {Vehicle}, |
---|
80 | * Red-Thing-S = {Red-Thing}, Car-S = {Car,Vehicle}, Truck-S = {Truck,Vehicle}, |
---|
81 | * and Fire-Truck-S = {Fire-Truck,Truck,Red-Thing}. Then you set up your function |
---|
82 | * sets so that the return type of each node is an <i>atomic type</i>, and the |
---|
83 | * argument types of nodes are <i>set types</i>. For example, if the function |
---|
84 | * FOO is supposed to take a Fire Truck and a Car and return another Car, then |
---|
85 | * you set the return type to Car, the first argument type to Fire-Truck-S, and the |
---|
86 | * second return type to Car-S. The rest is left up to the reader as an excercise :-) |
---|
87 | * |
---|
88 | * <p>I also believe that set types and atomic types can handle most grammar-based |
---|
89 | * mechanisms I've seen, which in general appear reducable to STGP anyway; |
---|
90 | * for example, in Eric Jones and William Joines, "Genetic |
---|
91 | * Design of Electronic Circuits". <i>Late-Breaking Papers at the 1999 Genetic |
---|
92 | * and Evolutionary Computatiokn Conference</i>. 124-133. |
---|
93 | |
---|
94 | <p><b>Parameters</b><br> |
---|
95 | <table> |
---|
96 | <tr><td valign=top><i>base</i>.<tt>a.size</tt><br> |
---|
97 | <font size=-1>int >= 1</font></td> |
---|
98 | <td valign=top>(number of atomic types)</td></tr> |
---|
99 | |
---|
100 | <tr><td valign=top><i>base</i>.<tt>s.size</tt><br> |
---|
101 | <font size=-1>int >= 0</font></td> |
---|
102 | <td valign=top>(number of set types)</td></tr> |
---|
103 | |
---|
104 | <tr><td valign=top><i>base</i><tt>.a.</tt><i>n</i><tt>.name</tt><br> |
---|
105 | <font size=-1>String</font></td> |
---|
106 | <td valign=top>(name of atomic type <i>n</i>. Must be different from other GPType names)</td></tr> |
---|
107 | |
---|
108 | <tr><td valign=top><i>base</i><tt>.s.</tt><i>n</i><tt>.name</tt><br> |
---|
109 | <font size=-1>String</font></td> |
---|
110 | <td valign=top>(name of set type <i>n</i>. Must be different from other GPType names)</td></tr> |
---|
111 | |
---|
112 | <tr><td valign=top><i>base</i><tt>.s.</tt><i>n</i><tt>.size</tt><br> |
---|
113 | <font size=-1>int >= 1</font></td> |
---|
114 | <td valign=top>(number of atomic types in the set type <i>n</i>'s set)</td></tr> |
---|
115 | |
---|
116 | <tr><td valign=top><i>base</i><tt>.s.</tt><i>n</i><tt>.member.</tt><i>m</i><br> |
---|
117 | <font size=-1>String</font></td> |
---|
118 | <td valign=top>(name of atomic type member <i>m</i> in set type <i>n</i>)</td></tr> |
---|
119 | </table> |
---|
120 | |
---|
121 | |
---|
122 | * |
---|
123 | * @author Sean Luke |
---|
124 | * @version 1.0 |
---|
125 | */ |
---|
126 | |
---|
127 | public abstract class GPType implements Clique |
---|
128 | { |
---|
129 | public final static String P_NAME = "name"; |
---|
130 | |
---|
131 | /** The name of the type */ |
---|
132 | public String name; |
---|
133 | |
---|
134 | /** The preassigned integer value for the type */ |
---|
135 | public int type; |
---|
136 | |
---|
137 | /** Am I compatible with ("fit" with) <i>t</i>? For two atomic |
---|
138 | types, this is done by direct pointer equality. For |
---|
139 | two set types, this is done by determining if the intersection |
---|
140 | is nonempty. A set type is compatible with an atomic type |
---|
141 | if it contains the atomic type in its set. */ |
---|
142 | public abstract boolean compatibleWith(final GPInitializer initializer, final GPType t); |
---|
143 | |
---|
144 | /** Returns the type's name */ |
---|
145 | public String toString() { return name; } |
---|
146 | |
---|
147 | public void setup(final EvolutionState state, final Parameter base) |
---|
148 | { |
---|
149 | // What's my name? |
---|
150 | name = state.parameters.getString(base.push(P_NAME),null); |
---|
151 | if (name==null) |
---|
152 | state.output.fatal("No name was given for this GP type.", |
---|
153 | base.push(P_NAME)); |
---|
154 | |
---|
155 | // Register me |
---|
156 | GPType old_type = (GPType)(((GPInitializer)state.initializer).typeRepository.put(name,this)); |
---|
157 | if (old_type != null) |
---|
158 | state.output.fatal("The GP type \"" + name + "\" has been defined multiple times.", base.push(P_NAME)); |
---|
159 | } |
---|
160 | |
---|
161 | /** Returns a type for a given name. |
---|
162 | You must guarantee that after calling typeFor(...) one or |
---|
163 | several times, you call state.output.exitIfErrors() once. */ |
---|
164 | |
---|
165 | public static GPType typeFor(final String typeName, |
---|
166 | final EvolutionState state) |
---|
167 | { |
---|
168 | GPType myType = (GPType)(((GPInitializer)state.initializer).typeRepository.get(typeName)); |
---|
169 | if (myType==null) |
---|
170 | state.output.error("The GP type \"" + typeName + "\" could not be found."); |
---|
171 | return myType; |
---|
172 | } |
---|
173 | } |
---|