Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/gp/breed/MutateOneNodePipeline.java @ 6152

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

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

File size: 9.9 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 * MutateOneNodePipeline.java
15 *
16 * Created: Wed Dec 15 21:41:30 1999
17 * By: Sean Luke
18 */
19
20/**
21 * MutateOneNodesPipeline implements the OneNode mutation algorithm described
22 * in Kumar Chellapilla,
23 * "A Preliminary Investigation into Evolving Modular Programs without Subtree
24 * Crossover", GP98.
25 *
26 * <p>MutateOneNodesPipeline chooses a single node in an individual and
27 * replaces it with a randomly-chosen node of the same arity and type
28 * constraints.  Thus the original topological structure is
29 * the same but that one node is different.
30 *
31
32 <p><b>Typical Number of Individuals Produced Per <tt>produce(...)</tt> call</b><br>
33 ...as many as the source produces
34
35 <p><b>Number of Sources</b><br>
36 1
37
38 <p><b>Parameters</b><br>
39 <table>
40 <tr><td valign=top><i>base</i>.<tt>ns</tt>.0<br>
41 <font size=-1>classname, inherits and != GPNodeSelector</font></td>
42 <td valign=top>(GPNodeSelector for tree)</td></tr>
43
44 <tr><td valign=top><i>base</i>.<tt>tree.0</tt><br>
45 <font size=-1>0 &lt; int &lt; (num trees in individuals), if exists</font></td>
46 <td valign=top>(tree chosen for mutation; if parameter doesn't exist, tree is picked at random)</td></tr>
47
48 </table>
49
50 <p><b>Default Base</b><br>
51 gp.breed.mutate-one-node
52
53 <p><b>Parameter bases</b><br>
54 <table>
55 <tr><td valign=top><i>base</i>.<tt>ns</tt><br>
56 <td>The GPNodeSelector selector</td></tr>
57 </table>
58
59 * @author Sean Luke
60 * @version 1.0
61 */
62
63public class MutateOneNodePipeline extends GPBreedingPipeline
64    {
65    public static final String P_MUTATEONENODE = "mutate-one-node";
66    public static final int NUM_SOURCES = 1;
67   
68    /** How the pipeline chooses a subtree to mutate */
69    public GPNodeSelector nodeselect;   
70
71    /** Is our tree fixed?  If not, this is -1 */
72    int tree;
73
74    public Parameter defaultBase() { return GPBreedDefaults.base().push(P_MUTATEONENODE); }
75
76    public int numSources() { return NUM_SOURCES; }
77
78    public Object clone()
79        {
80        MutateOneNodePipeline c = (MutateOneNodePipeline)(super.clone());
81       
82        // deep-cloned stuff
83        c.nodeselect = (GPNodeSelector)(nodeselect.clone());
84        return c;
85        }
86
87    public void setup(final EvolutionState state, final Parameter base)
88        {
89        super.setup(state,base);
90
91        Parameter p = base.push(P_NODESELECTOR).push(""+0);
92        Parameter def = defaultBase();
93
94        nodeselect = (GPNodeSelector)
95            (state.parameters.getInstanceForParameter(
96                p,def.push(P_NODESELECTOR).push(""+0),GPNodeSelector.class));
97        nodeselect.setup(state,p);
98
99
100        tree = TREE_UNFIXED;
101        if (state.parameters.exists(base.push(P_TREE).push(""+0),
102                def.push(P_TREE).push(""+0)))
103            {
104            tree = state.parameters.getInt(base.push(P_TREE).push(""+0),
105                def.push(P_TREE).push(""+0),0);
106            if (tree==-1)
107                state.output.fatal("Tree fixed value, if defined, must be >= 0");
108            }
109        }
110
111
112
113
114    /** Returns a node which is swap-compatible with returntype, and whose arguments are swap-compatible with the current children of original.  You need to clone this node. */
115
116
117    private GPNode pickCompatibleNode(final GPNode original, final GPFunctionSet set, final EvolutionState state, final GPType returntype, final int thread)
118        {
119        // an expensive procedure: we will linearly search for a valid node
120        int numValidNodes = 0;
121       
122        int type = returntype.type;
123        GPInitializer initializer = ((GPInitializer)state.initializer);
124        int len = original.constraints(initializer).childtypes.length;
125        boolean failed;
126
127        if (initializer.numAtomicTypes + initializer.numSetTypes == 1)  // easy
128            numValidNodes = set.nodesByArity[type][len].length;
129        else for(int x=0;x<set.nodesByArity[type][len].length;x++) // ugh, the hard way -- nodes swap-compatible with type, and of arity len
130                 {
131                 failed = false;
132                 for(int y=0;y<set.nodesByArity[type][len][x].constraints(initializer).childtypes.length;y++)
133                     if (!set.nodesByArity[type][len][x].constraints(initializer).
134                         childtypes[y].compatibleWith(initializer,original.children[y].
135                             constraints(initializer).returntype))
136                         { failed = true; break; }
137                 if (!failed) numValidNodes++;
138                 }
139       
140        // we must have at least success -- the node itself.  Otherwise we're
141        // in deep doo-doo.
142
143        // now pick a random node number
144        int nodenum = state.random[thread].nextInt(numValidNodes);
145
146        // find and return that node
147        int prosnode = 0;
148       
149        if (numValidNodes == set.nodesByArity[type][len].length) // easy
150            return set.nodesByArity[type][len][nodenum];
151        else for(int x=0;x<set.nodesByArity[type][len].length;x++) // ugh, the hard way -- nodes swap-compatible with type, and of arity len
152                 {
153                 failed = false;
154                 for(int y=0;y<set.nodesByArity[type][len][x].constraints(initializer).childtypes.length;y++)
155                     if (!set.nodesByArity[type][len][x].constraints(initializer).
156                         childtypes[y].compatibleWith(initializer,original.children[y].
157                             constraints(initializer).returntype))
158                         { failed = true; break; }
159                 if (!failed)
160                     {
161                     if (prosnode == nodenum)  // got it!
162                         return set.nodesByArity[type][len][x];
163                     prosnode++;
164                     }
165                 }
166
167        // should never be able to get here
168        throw new InternalError();  // whoops!
169        }
170
171
172    public int produce(final int min,
173        final int max,
174        final int start,
175        final int subpopulation,
176        final Individual[] inds,
177        final EvolutionState state,
178        final int thread)
179        {
180        // grab n individuals from our source and stick 'em right into inds.
181        // we'll modify them from there
182        int n = sources[0].produce(min,max,start,subpopulation,inds,state,thread);
183
184        // should we bother?
185        if (!state.random[thread].nextBoolean(likelihood))
186            return reproduce(n, start, subpopulation, inds, state, thread, false);  // DON'T produce children from source -- we already did
187
188
189        GPInitializer initializer = ((GPInitializer)state.initializer);
190
191        // now let's mutate 'em
192        for(int q=start; q < n+start; q++)
193            {
194            GPIndividual i = (GPIndividual)inds[q];
195           
196            if (tree!=TREE_UNFIXED && (tree<0 || tree >= i.trees.length))
197                // uh oh
198                state.output.fatal("MutateOneNodePipeline 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");
199
200            int t;
201            // pick random tree
202            if (tree==TREE_UNFIXED)
203                if (i.trees.length>1) t = state.random[thread].nextInt(i.trees.length);
204                else t = 0;
205            else t = tree;
206                   
207            // prepare the nodeselector
208            nodeselect.reset();
209           
210            // pick a node
211           
212            GPNode p1=null;  // the node we pick
213            GPNode p2=null;
214           
215            // pick a node in individual 1
216            p1 = nodeselect.pickNode(state,subpopulation,thread,i,i.trees[t]);
217           
218            // generate a tree with a new root but the same children,
219            // which we will replace p1 with
220           
221            GPType type;
222            type = p1.parentType(initializer);
223           
224            p2 = (GPNode)(pickCompatibleNode(p1,i.trees[t].constraints(initializer).functionset,state,type,thread)).lightClone();
225
226            // if it's an ERC, let it set itself up
227            p2.resetNode(state,thread);
228           
229            // p2's parent and argposition will be set automatically below
230
231            GPIndividual j;
232
233            if (sources[0] instanceof BreedingPipeline)
234                // it's already a copy, so just smash the tree in
235                {
236                j=i;
237                p1.replaceWith(p2);
238                j.evaluated = false;
239                }
240            else
241                {
242                j = (GPIndividual)(i.lightClone());
243               
244                // Fill in various tree information that didn't get filled in there
245                j.trees = new GPTree[i.trees.length];
246               
247                for(int x=0;x<j.trees.length;x++)
248                    {
249                    if (x==t)  // we've got a tree with a kicking cross position!
250                        {
251                        j.trees[x] = (GPTree)(i.trees[x].lightClone());
252                        j.trees[x].owner = j;
253                        j.trees[x].child = i.trees[x].child.cloneReplacingAtomic(p2,p1);
254                        j.trees[x].child.parent = j.trees[x];
255                        j.trees[x].child.argposition = 0;
256                        j.evaluated = false;
257                        } // it's changed
258                    else
259                        {
260                        j.trees[x] = (GPTree)(i.trees[x].lightClone());
261                        j.trees[x].owner = j;
262                        j.trees[x].child = (GPNode)(i.trees[x].child.clone());
263                        j.trees[x].child.parent = j.trees[x];
264                        j.trees[x].child.argposition = 0;
265                        }
266                    }
267                }
268
269            // add the new individual, replacing its previous source
270            inds[q] = j;
271            }
272        return n;
273        }
274    }
Note: See TracBrowser for help on using the repository browser.