Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/gp/GPIndividual.java @ 12147

Last change on this file since 12147 was 6152, checked in by bfarka, 14 years ago

added ecj and custom statistics to communicate with the okb services #1441

File size: 12.1 KB
Line 
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
8package ec.gp;
9import ec.*;
10import ec.util.*;
11import java.io.*;
12
13/*
14 * GPIndividual.java
15 *
16 * Created: Fri Aug 27 17:07:45 1999
17 * By: Sean Luke
18 */
19
20/**
21 * GPIndividual is an Individual used for GP evolution runs.
22 * GPIndividuals contain, at the very least, a nonempty array of GPTrees.
23 * You can use GPIndividual directly, or subclass it to extend it as
24 * you see fit.
25 
26 * <P>GPIndividuals have two clone methods: clone() and lightClone().  clone() is
27 * a deep clone method as usual.  lightClone() is a light clone which does not copy
28 * the trees.
29 *
30 * <p>In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways.
31 *
32 * <ul>
33 * <li><b>writeIndividual(...,DataOutput)/readIndividual(...,DataInput)</b>&nbsp;&nbsp;&nbsp;This method
34 * transmits or receives an individual in binary.  It is the most efficient approach to sending
35 * individuals over networks, etc.  These methods write the evaluated flag and the fitness, then
36 * call <b>readGenotype/writeGenotype</b>, which you must implement to write those parts of your
37 * Individual special to your functions-- the default versions of readGenotype/writeGenotype throw errors.
38 * You don't need to implement them if you don't plan on using read/writeIndividual.
39 *
40 * <li><b>printIndividual(...,PrintWriter)/readIndividual(...,LineNumberReader)</b>&nbsp;&nbsp;&nbsp;This
41 * approach transmits or receives an indivdual in text encoded such that the individual is largely readable
42 * by humans but can be read back in 100% by ECJ as well.  Because GPIndividuals are often very large,
43 * <b>GPIndividual has overridden these methods -- they work differently than in Individual (the superclass).</b>  In specific:
44 * <b>readIndividual</b> by default reads in the fitness and the evaluation flag, then calls <b>parseGenotype</b>
45 * to read in the trees (via GPTree.readTree(...)).
46 * However <b>printIndividual</b> by default prints the fitness and evaluation flag, and prints all the trees
47 * by calling GPTree.printTree(...).  It does not call <b>genotypeToString</b> at all.  This
48 * is because it's very wasteful to build up a large string holding the printed form of the GPIndividual
49 * just to pump it out a stream once.
50 *
51 * <li><b>printIndividualForHumans(...,PrintWriter)</b>&nbsp;&nbsp;&nbsp;This
52 * approach prints an individual in a fashion intended for human consumption only. Because GPIndividuals are often very large,
53 * <b>GPIndividual has overridden this methods -- it works differently than in Individual (the superclass).</b>  In specific:
54 * <b>printIndividual</b> by default prints the fitness and evaluation flag, and prints all the trees
55 * by calling GPTree.printTreeForHumans(...).  It does not call <b>genotypeToStringForHumans</b> at all.  This
56 * is because it's very wasteful to build up a large string holding the printed form of the GPIndividual
57 * just to pump it out a stream once.
58 *
59 * <p>In general, the various readers and writers do three things: they tell the Fitness to read/write itself,
60 * they read/write the evaluated flag, and they read/write the GPTree array (by having each GPTree read/write
61 * itself).  If you add instance variables to GPIndividual, you'll need to read/write those variables as well.
62
63
64 <p><b>Parameters</b><br>
65 <table>
66 <tr><td valign=top><i>base</i>.<tt>numtrees</tt><br>
67 <font size=-1>int &gt;= 1</font></td>
68 <td valign=top>(number of trees in the GPIndividual)</td></tr>
69
70 <tr><td valign=top><i>base</i>.<tt>tree.</tt><i>n</i><br>
71 <font size=-1>classname, inherits or = ec.gp.GPTree</font></td>
72 <td valign=top>(class of tree <i>n</i> in the individual)</td></tr>
73 </table>
74
75 <p><b>Default Base</b><br>
76 gp.individual
77
78 <p><b>Parameter bases</b><br>
79 <table>
80 <tr><td valign=top><i>base</i>.<tt>tree.</tt><i>n</i></td>
81 <td>tree <i>n</i> in the individual</td></tr>
82 </table>
83
84 *
85 * @author Sean Luke
86 * @version 1.0
87 */
88
89public class GPIndividual extends Individual
90    {
91    public static final String P_NUMTREES = "numtrees";
92    public static final String P_TREE = "tree";
93   
94    public GPTree[] trees;
95   
96    public Parameter defaultBase()
97        {
98        return GPDefaults.base().push(P_INDIVIDUAL);
99        }
100
101    public boolean equals(Object ind)
102        {
103        if (!(this.getClass().equals(ind.getClass()))) return false;  // GPIndividuals are special.
104        GPIndividual i = (GPIndividual)ind;
105        if (trees.length != i.trees.length) return false;
106        // this default version works fine for most GPIndividuals.
107        for(int x=0;x<trees.length;x++)
108            if (!(trees[x].treeEquals(i.trees[x]))) return false;
109        return true;
110        }
111   
112    public int hashCode()
113        {
114        // stolen from GPNode.  It's a decent algorithm.
115        int hash = this.getClass().hashCode();
116       
117        for(int x=0;x<trees.length;x++)
118            hash =
119                // Rotate hash and XOR
120                (hash << 1 | hash >>> 31 ) ^
121                trees[x].treeHashCode();
122        return hash;
123        }
124
125    /** Sets up a prototypical GPIndividual with those features which it
126        shares with other GPIndividuals in its species, and nothing more. */
127
128    public void setup(final EvolutionState state, final Parameter base)
129        {
130        super.setup(state,base);  // actually unnecessary (Individual.setup() is empty)
131
132        Parameter def = defaultBase();
133
134        // set my evaluation to false
135        evaluated = false;
136
137        // how many trees?
138        int t = state.parameters.getInt(base.push(P_NUMTREES),def.push(P_NUMTREES),1);  // at least 1 tree for GP!
139        if (t <= 0)
140            state.output.fatal("A GPIndividual must have at least one tree.",
141                base.push(P_NUMTREES),def.push(P_NUMTREES));
142       
143        // load the trees
144        trees = new GPTree[t];
145
146        for (int x=0;x<t;x++)
147            {
148            Parameter p = base.push(P_TREE).push(""+x);
149            trees[x] = (GPTree)(state.parameters.getInstanceForParameterEq(
150                    p,def.push(P_TREE).push(""+x),GPTree.class));
151            trees[x].owner = this;
152            trees[x].setup(state,p);
153            }
154       
155        // now that our function sets are all associated with trees,
156        // give the nodes a chance to determine whether or not this is
157        // going to work for them (especially the ADFs).
158        GPInitializer initializer = ((GPInitializer)state.initializer);
159        for (int x=0;x<t;x++)
160            {
161            for(int w = 0;w < trees[x].constraints(initializer).functionset.nodes.length;w++)
162                {
163                GPNode[] gpfi = trees[x].constraints(initializer).functionset.nodes[w];
164                for (int y = 0;y<gpfi.length;y++)
165                    gpfi[y].checkConstraints(state,x,this,base);
166                }
167            }
168        // because I promised with checkConstraints(...)
169        state.output.exitIfErrors();
170        }
171
172
173    /** Verification of validity of the GPIndividual -- strictly for debugging purposes only */
174    public final void verify(EvolutionState state)
175        {
176        if (!(state.initializer instanceof GPInitializer))
177            { state.output.error("Initializer is not a GPInitializer"); return; }
178           
179        GPInitializer initializer = (GPInitializer)(state.initializer);
180
181        if (trees==null)
182            { state.output.error("Null trees in GPIndividual."); return; }
183        for(int x=0;x<trees.length;x++) if (trees[x]==null)
184                                            { state.output.error("Null tree (#"+x+") in GPIndividual."); return; }
185        for(int x=0;x<trees.length;x++)
186            trees[x].verify(state);
187        state.output.exitIfErrors();
188        }
189
190    /** Prints just the trees of the GPIndividual.  Broken out like this to be used by GEIndividual to avoid
191        re-printing the fitness and evaluated premables. */
192    public void printTrees(final EvolutionState state, final int log)
193        {
194        for(int x=0;x<trees.length;x++)
195            {
196            state.output.println("Tree " + x + ":",log);
197            trees[x].printTreeForHumans(state,log);
198            }
199        }
200
201    public void printIndividualForHumans(final EvolutionState state, final int log)
202        {
203        state.output.println(EVALUATED_PREAMBLE + (evaluated ? "true" : "false"), log);
204        fitness.printFitnessForHumans(state,log);
205        printTrees(state,log);
206        }
207
208    public void printIndividual(final EvolutionState state, final int log)
209        {
210        state.output.println(EVALUATED_PREAMBLE + Code.encode(evaluated), log);
211        fitness.printFitness(state,log);
212        for(int x=0;x<trees.length;x++)
213            {
214            state.output.println("Tree " + x + ":",log);
215            trees[x].printTree(state,log);
216            }   
217        }
218           
219    public void printIndividual(final EvolutionState state,
220        final PrintWriter writer)
221        {
222        writer.println(EVALUATED_PREAMBLE + Code.encode(evaluated));
223        fitness.printFitness(state,writer);
224        for(int x=0;x<trees.length;x++)
225            {
226            writer.println("Tree " + x + ":");
227            trees[x].printTree(state,writer);
228            }   
229        }
230       
231    /** Overridden for the GPIndividual genotype. */
232    public void writeGenotype(final EvolutionState state,
233        final DataOutput dataOutput) throws IOException
234        {
235        dataOutput.writeInt(trees.length);
236        for(int x=0;x<trees.length;x++)
237            trees[x].writeTree(state,dataOutput);
238        }
239
240    /** Overridden for the GPIndividual genotype. */
241    public void readGenotype(final EvolutionState state,
242        final DataInput dataInput) throws IOException
243        {
244        int treelength = dataInput.readInt();
245        if (trees == null || treelength != trees.length) // wrong size!
246            state.output.fatal("Number of trees differ in GPIndividual when reading from readGenotype(EvolutionState, DataInput).");
247        for(int x=0;x<trees.length;x++)
248            trees[x].readTree(state,dataInput);
249        }
250
251    public void parseGenotype(final EvolutionState state,
252        final LineNumberReader reader) throws IOException
253        {
254        // Read my trees
255        for(int x=0;x<trees.length;x++)
256            {
257            reader.readLine();  // throw it away -- it's the tree indicator
258            trees[x].readTree(state,reader);
259            }
260        }
261
262    /** Deep-clones the GPIndividual.  Note that you should not deep-clone the prototypical GPIndividual
263        stored in GPSpecies: they contain blank GPTrees with null roots, and this method,
264        which calls GPTree.clone(), will produce a NullPointerException as a result. Instead, you probably
265        want to use GPSpecies.newIndividual(...) if you're thinking of playing with the prototypical
266        GPIndividual. */
267       
268    public Object clone()
269        {
270        // a deep clone
271               
272        GPIndividual myobj = (GPIndividual)(super.clone());
273
274        // copy the tree array
275        myobj.trees = new GPTree[trees.length];
276        for(int x=0;x<trees.length;x++)
277            {
278            myobj.trees[x] = (GPTree)(trees[x].clone());  // force a deep clone
279            myobj.trees[x].owner = myobj;  // reset owner away from me
280            }
281        return myobj;
282        }
283
284    /** Like clone(), but doesn't force the GPTrees to deep-clone themselves. */
285    public GPIndividual lightClone()
286        {
287        // a light clone
288        GPIndividual myobj = (GPIndividual)(super.clone());
289       
290        // copy the tree array
291        myobj.trees = new GPTree[trees.length];
292        for(int x=0;x<trees.length;x++)
293            {
294            myobj.trees[x] = (GPTree)(trees[x].lightClone());  // note light-cloned!
295            myobj.trees[x].owner = myobj;  // reset owner away from me
296            }
297        return myobj;
298        }
299
300    /** Returns the "size" of the individual, namely, the number of nodes
301        in all of its subtrees.  */
302    public long size()
303        {
304        long size = 0;
305        for(int x=0;x<trees.length;x++)
306            size += trees[x].child.numNodes(GPNode.NODESEARCH_ALL);
307        return size;
308        }
309
310    }
Note: See TracBrowser for help on using the repository browser.