Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/gp/build/RandTree.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: 13.3 KB
Line 
1/*
2  Copyright 2006 by Alexander Chircop
3  Licensed under the Academic Free License version 3.0
4  See the file "LICENSE" for more information
5*/
6
7
8/*
9 *  RandTree as described by Hitoshi Iba
10 *  Author: Alexander Chircop
11 *  Date:   28th Nov 2000
12 */
13 
14package ec.gp.build;
15import ec.gp.*;
16import ec.*;
17import ec.util.*;
18import java.util.*;
19
20public class RandTree extends GPNodeBuilder
21    {
22    public static final String P_RANDOMBRANCH = "randtree";
23    int[] arities;
24    boolean aritySetupDone=false;
25
26    LinkedList permutations;
27
28    private class ArityObject extends Object
29        {
30        public int arity;
31        public ArityObject(int a) { arity=a; }
32        }
33
34    public Parameter defaultBase()
35        {
36        return GPBuildDefaults.base().push(P_RANDOMBRANCH);
37        }
38
39    public void setup(final EvolutionState state, final Parameter base)
40        {
41        super.setup(state,base);
42
43        // we use size distributions -- did the user specify any?
44        if (!canPick())
45            state.output.fatal("RandTree requires some kind of size distribution set, either with " + P_MINSIZE + "/" + P_MAXSIZE + ", or with " + P_NUMSIZES + ".",
46                base, defaultBase());
47        }
48
49    // Added method to enhance linked list functionality with ArityObject
50    private boolean contains(LinkedList initArities,int a)
51        {
52        boolean truth=false;
53        int counter=0;
54        ArityObject b;
55
56        if (initArities.size()!=0)
57            while ((counter<initArities.size()) && (!truth))
58                {
59                b=(ArityObject)initArities.get(counter);
60                if (b.arity==a) {truth=true;}
61                counter++;
62                }
63        return truth;
64        }
65
66    private void remove(LinkedList initArities,int a)
67        {
68        int counter=0;
69        boolean removed=false;
70        while((counter<initArities.size()) && (!removed))
71            {
72            ArityObject b=(ArityObject)initArities.get(counter);
73            if (b.arity==a)
74                {
75                initArities.remove(counter);
76                removed=true;
77                }
78            counter++;
79            }
80        }
81
82    public void setupArities(final EvolutionState state,final GPFunctionSet set)
83        {
84        int noOfArities=0,current=0,marker=0,counter=0,a;
85        LinkedList initArities=new LinkedList();
86        GPInitializer initializer = ((GPInitializer)state.initializer);
87        // count available arities and place on linked list
88        while(current<set.nodes[0].length)
89            {
90                {
91                a=set.nodes[0][current].constraints(initializer).childtypes.length;
92                if((!contains(initArities,a)) && (a!=0))
93                    {
94                    initArities.add(new ArityObject(a));
95                    noOfArities++;
96                    }
97                }
98            current++;
99            }
100
101        if (initArities.size()==0) {state.output.fatal("Arity count failed... counted 0.");}
102
103        // identify different available arities and place on array
104        arities=new int[noOfArities];
105        current=0;
106
107        while(current<noOfArities)
108            {
109            // finds maximum arity on the list
110            marker=0;
111            for (counter=0;counter<initArities.size();counter++)
112                {
113                ArityObject max=(ArityObject) initArities.get(counter);
114                if (max.arity > marker)
115                    {
116                    marker=max.arity;
117                    }
118                }
119
120            // Place maximum found on the array
121            arities[current]=marker;
122            remove(initArities,marker);
123            current++;
124            }
125
126        aritySetupDone=true;
127        }
128
129    private long fact(long num)
130        {
131        if (num==0) { return 1; }
132        else { return num*fact(num-1); }
133        }
134
135    private int[] select(LinkedList permutations,int size)
136        {
137        int counter1,counter2,total=0;
138        long residue,denominator=1;
139        int selection;
140        int[] current;
141        int[] quantity=new int[permutations.size()];
142
143        for (counter1=0;counter1<permutations.size();counter1++)
144            {
145            current=(int[])permutations.get(counter1);
146            residue=size;
147            // Quick internal calculations
148            for (counter2=0;counter2<current.length;counter2++)
149                {
150                residue -= current[counter2];
151                denominator *= fact(current[counter2]);
152                }
153            quantity[counter1] = (int) (fact(size-1)/(denominator * fact(residue)));
154            total += quantity[counter1];
155            }
156
157        double[] prob=new double[quantity.length];
158        // quantities found... now build array for probabilities
159        for (counter1=0;counter1<quantity.length;counter1++)
160            {
161            prob[counter1] = (double)quantity[counter1]/(double)total;
162            // I don't think we need to check for negative values here -- Sean
163            }
164        RandomChoice.organizeDistribution(prob);
165        double s=0.0;
166        selection = RandomChoice.pickFromDistribution(prob,s);
167
168        return (int[])permutations.get(selection);
169        }
170
171    public GPNode newRootedTree(final EvolutionState state,
172        final GPType type,
173        final int thread,
174        final GPNodeParent parent,
175        final GPFunctionSet set,
176        final int argposition,
177        final int requestedSize)
178        {
179        int treeSize;
180        boolean valid=false;
181        String word=new String();
182
183        treeSize=pickSize(state,thread);
184
185        if (!aritySetupDone) { setupArities(state,set); }
186
187        int[] temp=new int[arities.length];
188        permutations=new LinkedList();
189        Permute(0,temp,treeSize-1);
190        if (permutations.size()==0) { state.output.fatal("Not able to build combination of nodes."); }
191        int[] scheme=select(permutations,treeSize);
192        word=buildDyckWord(treeSize,arities,scheme,state,thread);
193        int cycle=0;
194        while(!valid)
195            {
196            valid=checkDyckWord(word);
197            if (!valid)
198                {
199                word=word.substring(word.length()-1,word.length()).concat(word.substring(0,word.length()-1));
200                cycle++;
201                if (cycle>=(treeSize*2)-1) {state.output.fatal("Not able to find valid permutation for generated Dyck word: "+word);}
202                }
203            }
204        return buildTree(state,thread,parent,argposition,set,word);
205        }
206
207    // recursive function to work out all combinations and push them onto ArrayList
208    private void Permute(int current,int[] sol,int size)
209        {
210        int counter=0,result=0;
211        // base case
212        if (current==arities.length-1) /* set last one to maximum allowable */
213            {
214            while(result<=size)
215                {
216                counter++;
217                result=result+arities[current];
218                }
219            result=result-arities[current];
220            counter--;
221            if (result<0)
222                {
223                result=0;
224                counter=0;
225                }
226            sol[current]=counter;
227
228            //Adding this solution to the list.
229            permutations.add(sol);
230            }
231        // end of base case
232        else
233            {
234            while(result<=size)
235                {
236                if (result<=size)
237                    {
238                    sol[current]=counter;
239                    Permute(current+1,sol,size-result);
240                    }
241                result=result+arities[current];
242                counter++;
243                }
244            }
245        }
246
247    public String buildDyckWord(int requestedSize,int[] arities,int[] s,EvolutionState state,int thread)
248        {
249        int counter,choices,choice,pos,arity=0,checksum=0,size=0;
250        int[] scheme=new int[s.length];
251
252        String dyck=new String("");
253        String addStr=new String();
254
255        scheme=s;
256        for(counter=0;counter<scheme.length;counter++)
257            {
258            checksum += scheme[counter]*arities[counter];
259            }
260
261        size=checksum+1;
262        if (size!=requestedSize) { state.output.message("A tree of the requested size could not be built.  Using smaller size.");}
263        choices=size;
264
265        for(counter=0;counter<size;counter++)
266            {
267            dyck=dyck.concat("x*");
268            }
269
270        // Find a non-0 arity to insert
271        counter=0;
272        while((arity==0) && (counter<scheme.length))
273            {
274            if (scheme[counter]>0)
275                {
276                arity=arities[counter];
277                scheme[counter]--;
278                }
279            counter++;
280            }
281
282        while(arity!=0)
283            {
284            choice=state.random[thread].nextInt(choices--)+1;
285            pos=-1;
286            counter=0;
287            // find insertion position within the string
288            while(counter!=choice)
289                {
290                pos++;
291                if (dyck.charAt(pos)=='*') { counter++; }
292                }
293            // building no of y's in string
294            addStr="";
295            while (addStr.length()<arity) { addStr=addStr.concat("y"); }
296
297            // finally put the string together again
298            dyck=dyck.substring(0,pos).concat(addStr).concat(dyck.substring(pos+1,dyck.length()));
299
300            // Find another non-0 arity to insert
301            counter=0;
302            arity=0;
303            while((arity==0) && (counter<scheme.length))
304                {
305                if (scheme[counter]>0)
306                    {
307                    arity=arities[counter];
308                    scheme[counter]--;
309                    }
310                counter++;
311                }
312            }
313        //Clean up leftover *'s
314        for (counter=0;counter<dyck.length();counter++)
315            {
316            if(dyck.charAt(counter)=='*')
317                {
318                dyck=dyck.substring(0,counter).concat(dyck.substring(counter+1,dyck.length()));
319                }
320            }
321        return dyck;
322        }
323
324    // function to check validity of Dyck word
325    public boolean checkDyckWord(String dyck)
326        {
327        int counter=0;
328        boolean underflow=false;
329        String stack=new String();
330        while ((counter<dyck.length()) && (!underflow))
331            {
332            switch (dyck.charAt(counter))
333                {
334                case 'x':
335                {
336                stack=stack.concat("x");
337                break;
338                }
339                case 'y':
340                {
341                if (stack.length()<=1)
342                    {
343                    underflow=true;
344                    stack="";
345                    }
346                else
347                    {
348                    stack=stack.substring(0,stack.length()-1);
349                    }
350                break;
351                }
352                }
353            counter++;
354            }
355        if (stack.length()!=1)
356            {
357            return false;
358            }
359        else
360            {
361            return true;
362            }
363        }
364
365    // This function parses the dyck word and puts random nodes into their slots.
366    private GPNode buildTree(final EvolutionState state,
367        final int thread,
368        final GPNodeParent parent,
369        final int argposition,
370        final GPFunctionSet set,
371        final String dyckWord)
372        {
373        int counter=0;
374        Stack s=new Stack();
375        char nextChar;
376
377        // Parsing dyck word from left to right and building tree
378        for (counter=0;counter<dyckWord.length();counter++)
379            {
380            if (counter<dyckWord.length()-1) { nextChar=dyckWord.charAt(counter+1);} else { nextChar='*'; }
381            if ((nextChar=='x') || (nextChar=='*')) /* terminal node */
382                {
383                GPNode[] nn = set.terminals[0];
384                GPNode n = (GPNode)(nn[state.random[thread].nextInt(nn.length)].lightClone());
385                n.resetNode(state,thread);  // give ERCs a chance to randomize
386                s.push(n);
387                }
388            else if (nextChar=='y') /* non-terminal */
389                {
390                // finding arity of connection
391                int Ycount=0; /* arity */
392                boolean nextCharY;
393                nextCharY=(nextChar=='y');
394                counter++;
395                while ((counter<dyckWord.length()) && (nextCharY))
396                    {
397                    if (dyckWord.charAt(counter)=='y') { Ycount++; }
398                    if (counter<dyckWord.length()-1) { nextCharY=(dyckWord.charAt(counter+1)=='y'); }
399                    counter++;
400                    }
401
402                //Arity found.  Now just choose non terminal at random.
403                GPNode[] nonTerms=set.nodesByArity[0][Ycount];
404                GPNode nT=(GPNode) (nonTerms[state.random[thread].nextInt(nonTerms.length)].lightClone());
405                // Non terminal chosen, now attaching children
406                int childcount=Ycount;
407                while (childcount>0)
408                    {
409                    childcount--;
410                    if (s.size()==0) { state.output.fatal("Stack underflow when building tree."); }
411                    GPNode child=(GPNode) s.pop();
412                    child.parent=nT;
413                    child.argposition=(byte)childcount;
414                    nT.children[childcount]=child;
415                    }
416                nT.argposition=0;
417                nT.parent=null;
418                s.push(nT);
419                if (counter!=dyckWord.length()) counter--;
420                }
421            }
422        return (GPNode) s.pop();
423        }
424    }
Note: See TracBrowser for help on using the repository browser.