Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/gp/breed/InternalCrossoverPipeline.java @ 9449

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

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

File size: 13.4 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.breed;
9import ec.*;
10import ec.util.*;
11import ec.gp.*;
12
13/*
14 * InternalCrossoverPipeline.java
15 *
16 * Created: Wed Dec 15 21:41:30 1999
17 * By: Sean Luke
18 */
19
20/**
21 * InternalCrossoverPipeline picks two subtrees from somewhere within an individual,
22 * and crosses them over.  Before doing so, it checks to make sure that the
23 * subtrees come from trees with the same tree constraints, that the subtrees
24 * are swap-compatible with each other, that the new individual does not violate
25 * depth constraints, and that one subtree does not contain the other.  It tries
26 * <tt>tries</tt> times to find a valid subtree pair to cross over.  Failing this,
27 * it just copies the individual.
28 *
29
30 <p><b>Typical Number of Individuals Produced Per <tt>produce(...)</tt> call</b><br>
31 ...as many as the source produces
32
33 <p><b>Number of Sources</b><br>
34 1
35
36 <p><b>Parameters</b><br>
37 <table>
38 <tr><td valign=top><i>base</i>.<tt>tries</tt><br>
39 <font size=-1>int &gt;= 1</font></td>
40 <td valign=top>(number of times to try finding valid pairs of nodes)</td></tr>
41
42 <tr><td valign=top><i>base</i>.<tt>maxdepth</tt><br>
43 <font size=-1>int &gt;= 1</font></td>
44 <td valign=top>(maximum valid depth of the crossed-over individual's trees)</td></tr>
45 
46 <tr><td valign=top><i>base</i>.<tt>ns.</tt>0<br>
47 <font size=-1>classname, inherits and != GPNodeSelector</font></td>
48 <td valign=top>(GPNodeSelector for subtree 0.  </td></tr>
49
50 <tr><td valign=top><i>base</i>.<tt>ns.</tt>1<br>
51 <font size=-1>classname, inherits and != GPNodeSelector,<br>
52 or String <tt>same<tt></font></td>
53 <td valign=top>(GPNodeSelector for subtree 1.  If value is <tt>same</tt>, then <tt>ns.1</tt> a copy of whatever <tt>ns.0</tt> is)</td></tr>
54
55 <tr><td valign=top><i>base</i>.<tt>tree.0</tt><br>
56 <font size=-1>0 &lt; int &lt; (num trees in individuals), if exists</font></td>
57 <td valign=top>(first tree for the crossover; if parameter doesn't exist, tree is picked at random)</td></tr>
58
59 <tr><td valign=top><i>base</i>.<tt>tree.1</tt><br>
60 <font size=-1>0 &lt; int &lt; (num trees in individuals), if exists</font></td>
61 <td valign=top>(second tree for the crossover; if parameter doesn't exist, tree is picked at random.  This tree <b>must</b> have the same GPTreeConstraints as <tt>tree.0</tt>, if <tt>tree.0</tt> is defined.)</td></tr>
62
63 </table>
64
65 <p><b>Default Base</b><br>
66 gp.breed.internal-xover
67
68 <p><b>Parameter bases</b><br>
69 <table>
70 <tr><td valign=top><i>base</i>.<tt>ns.</tt><i>n</i><br>
71 <td>nodeselect<i>n</i> (<i>n</i> is 0 or 1)</td></tr>
72 </table>
73
74 </table>
75
76
77 * @author Sean Luke
78 * @version 1.0
79 */
80
81public class InternalCrossoverPipeline extends GPBreedingPipeline
82    {
83    public static final String P_INTERNALCROSSOVER = "internal-xover";
84    public static final String P_NUM_TRIES = "tries";
85    public static final String P_MAXDEPTH = "maxdepth";
86    public static final int NUM_SOURCES = 1;
87
88   
89    /** How the pipeline chooses the first subtree */
90    public GPNodeSelector nodeselect0;
91
92    /** How the pipeline chooses the second subtree */
93    public GPNodeSelector nodeselect1;
94
95    /** How many times the pipeline attempts to pick nodes until it gives up. */
96    public int numTries;
97
98    /** The deepest tree the pipeline is allowed to form.  Single terminal trees are depth 1. */
99    public int maxDepth;
100
101    /** Is the first tree fixed?  If not, this is -1 */
102    public int tree1;
103
104    /** Is the second tree fixed?  If not, this is -1 */
105    public int tree2;
106
107
108    public Parameter defaultBase() { return GPBreedDefaults.base().push(P_INTERNALCROSSOVER); }
109
110    public int numSources() { return NUM_SOURCES; }
111
112    public Object clone()
113        {
114        InternalCrossoverPipeline c = (InternalCrossoverPipeline)(super.clone());
115       
116        // deep-cloned stuff
117        c.nodeselect0 = (GPNodeSelector)(nodeselect0.clone());
118        c.nodeselect1 = (GPNodeSelector)(nodeselect1.clone());
119        return c;
120        }
121
122    public void setup(final EvolutionState state, final Parameter base)
123        {
124        super.setup(state,base);
125
126        Parameter def = defaultBase();
127        Parameter p = base.push(P_NODESELECTOR).push("0");
128        Parameter d = def.push(P_NODESELECTOR).push("0");
129
130        nodeselect0 = (GPNodeSelector)
131            (state.parameters.getInstanceForParameter(
132                p,d, GPNodeSelector.class));
133        nodeselect0.setup(state,p);
134
135        p = base.push(P_NODESELECTOR).push("1");
136        d = def.push(P_NODESELECTOR).push("1");
137
138        if (state.parameters.exists(p,d) &&
139            state.parameters.getString(p,d).equals(V_SAME))
140            // can't just copy it this time; the selectors
141            // use internal caches.  So we have to clone it no matter what
142            nodeselect1 = (GPNodeSelector)(nodeselect0.clone());
143        else
144            {
145            nodeselect1 = (GPNodeSelector)
146                (state.parameters.getInstanceForParameter(
147                    p,d, GPNodeSelector.class));
148            nodeselect1.setup(state,p);
149            }
150
151        numTries = state.parameters.getInt(base.push(P_NUM_TRIES),
152            def.push(P_NUM_TRIES),1);
153        if (numTries == 0)
154            state.output.fatal("InternalCrossover Pipeline has an invalid number of tries (it must be >= 1).",base.push(P_NUM_TRIES),def.push(P_NUM_TRIES));
155
156        maxDepth = state.parameters.getInt(base.push(P_MAXDEPTH),def.push(P_MAXDEPTH),1);
157        if (maxDepth==0)
158            state.output.fatal("InternalCrossover Pipeline has an invalid maximum depth (it must be >= 1).",base.push(P_MAXDEPTH),def.push(P_MAXDEPTH));
159
160        tree1 = TREE_UNFIXED;
161        if (state.parameters.exists(base.push(P_TREE).push(""+0),
162                def.push(P_TREE).push(""+0)))
163            {
164            tree1 = state.parameters.getInt(base.push(P_TREE).push(""+0),
165                def.push(P_TREE).push(""+0),0);
166            if (tree1==-1)
167                state.output.fatal("Tree fixed value, if defined, must be >= 0");
168            }
169
170        tree2 = TREE_UNFIXED;
171        if (state.parameters.exists(base.push(P_TREE).push(""+1),
172                def.push(P_TREE).push(""+1)))
173            {
174            tree2 = state.parameters.getInt(base.push(P_TREE).push(""+1),
175                def.push(P_TREE).push(""+1),0);
176            if (tree2==-1)
177                state.output.fatal("Tree fixed value, if defined, must be >= 0");
178            }
179        }
180
181
182
183    /** Returns true if inner1 and inner2 do not contain one another */
184    private boolean noContainment(GPNode inner1, GPNode inner2)
185        {
186        GPNodeParent current = inner1;
187        while(current != null && current instanceof GPNode)
188            {
189            if (current==inner2) return false;  // inner2 contains inner1
190            current = ((GPNode)current).parent;
191            }
192        current = inner2;
193        while(current != null && current instanceof GPNode)
194            {
195            if (current==inner1) return false;  // inner1 contains inner2
196            current = ((GPNode)current).parent;
197            }
198        return true;
199        }
200
201    /** Returns true if inner1 can feasibly be swapped into inner2's position. */
202
203    boolean verifyPoints(GPInitializer initializer, GPNode inner1, GPNode inner2)
204        {
205        // first check to see if inner1 is swap-compatible with inner2
206        // on a type basis
207        if (!inner1.swapCompatibleWith(initializer, inner2)) return false;
208
209        // next check to see if inner1 can fit in inner2's spot
210        if (inner1.depth()+inner2.atDepth() > maxDepth) return false;
211
212        // checks done!
213        return true;
214        }
215
216
217    public int produce(final int min,
218        final int max,
219        final int start,
220        final int subpopulation,
221        final Individual[] inds,
222        final EvolutionState state,
223        final int thread)
224
225        {
226        // grab n individuals from our source and stick 'em right into inds.
227        // we'll modify them from there
228        int n = sources[0].produce(min,max,start,subpopulation,inds,state,thread);
229
230
231        // should we bother?
232        if (!state.random[thread].nextBoolean(likelihood))
233            return reproduce(n, start, subpopulation, inds, state, thread, false);  // DON'T produce children from source -- we already did
234
235
236
237        GPInitializer initializer = ((GPInitializer)state.initializer);
238
239        for(int q=start;q<n+start; q++)
240            {
241            GPIndividual i = (GPIndividual)inds[q];
242                   
243            if (tree1!=TREE_UNFIXED && (tree1<0 || tree1 >= i.trees.length))
244                // uh oh
245                state.output.fatal("Internal Crossover Pipeline attempted to fix tree.0 to a value which was out of bounds of the array of the individual's trees.  Check the pipeline's fixed tree values -- they may be negative or greater than the number of trees in an individual");
246               
247            if (tree2!=TREE_UNFIXED && (tree2<0 || tree2 >= i.trees.length))
248                // uh oh
249                state.output.fatal("Internal Crossover Pipeline attempted to fix tree.0 to a value which was out of bounds of the array of the individual's trees.  Check the pipeline's fixed tree values -- they may be negative or greater than the number of trees in an individual");
250
251            GPIndividual j;
252            if (sources[0] instanceof BreedingPipeline)
253                // it's already a copy, so just smash the tree in
254                {
255                j=i;
256                }
257            else // need to copy it
258                {
259                j = (GPIndividual)(i.lightClone());
260               
261                // Fill in various tree information that didn't get filled in there
262                j.trees = new GPTree[i.trees.length];
263               
264                for(int x=0;x<j.trees.length;x++)
265                    {
266                    j.trees[x] = (GPTree)(i.trees[x].lightClone());  // light clone
267                    j.trees[x].owner = j;
268                    j.trees[x].child = (GPNode)(i.trees[x].child.clone());
269                    j.trees[x].child.parent = j.trees[x];
270                    j.trees[x].child.argposition = 0;
271                    }
272                }
273
274
275            int t1=0; int t2=0;
276            if (tree1==TREE_UNFIXED || tree2==TREE_UNFIXED)
277                {
278                do
279                    // pick random trees  -- their GPTreeConstraints must be the same
280                    {
281                    if (tree1==TREE_UNFIXED)
282                        if (i.trees.length > 1)
283                            t1 = state.random[thread].nextInt(i.trees.length);
284                        else t1 = 0;
285                    else t1 = tree1;
286                   
287                    if (tree2==TREE_UNFIXED)
288                        if (i.trees.length > 1)
289                            t2 = state.random[thread].nextInt(i.trees.length);
290                        else t2 = 0;
291                    else t2 = tree2;
292                    } while (i.trees[t1].constraints(initializer) != i.trees[t2].constraints(initializer));
293                }
294            else
295                {
296                t1 = tree1;
297                t2 = tree2;
298                // make sure the constraints are okay
299                if (i.trees[t1].constraints(initializer)
300                    != i.trees[t2].constraints(initializer)) // uh oh
301                    state.output.fatal("GP Crossover Pipeline's two tree choices are both specified by the user -- but their GPTreeConstraints are not the same");
302                }
303
304           
305            // prepare the nodeselectors
306            nodeselect0.reset();
307            nodeselect1.reset();
308           
309           
310            // pick some nodes
311           
312            GPNode p1=null;
313            GPNode p2=null;
314            boolean res = false;
315
316            for(int x=0;x<numTries;x++)
317                {
318                // pick a node in individual 1
319                p1 = nodeselect0.pickNode(state,subpopulation,thread,j,j.trees[t1]);
320               
321                // pick a node in individual 2
322                p2 = nodeselect1.pickNode(state,subpopulation,thread,j,j.trees[t2]);
323               
324                // make sure they're not the same node
325                res = (p1!=p2 &&
326                    // check for containment
327                    (t1!=t2 || noContainment(p1,p2)) &&
328                    // check for validity
329                    verifyPoints(initializer,p1,p2) &&   // 1 goes into 2
330                    verifyPoints(initializer,p2,p1));    // 2 goes into 1
331                if (res) break; // got one
332                }
333
334            // if res, then it's time to cross over!
335            if (res)
336                {
337                GPNodeParent oldparent = p1.parent;
338                byte oldargposition = p1.argposition;
339                p1.parent = p2.parent;
340                p1.argposition = p2.argposition;
341                p2.parent = oldparent;
342                p2.argposition = oldargposition;
343               
344                if (p1.parent instanceof GPNode)
345                    ((GPNode)(p1.parent)).children[p1.argposition] = p1;
346                else ((GPTree)(p1.parent)).child = p1;
347
348                if (p2.parent instanceof GPNode)
349                    ((GPNode)(p2.parent)).children[p2.argposition] = p2;
350                else ((GPTree)(p2.parent)).child = p2;
351
352                j.evaluated = false;  // we've modified it
353                }
354           
355            // add the individuals to the population
356            inds[q] = j;
357            }
358        return n;
359        }
360
361    }
Note: See TracBrowser for help on using the repository browser.