Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/rule/breed/RuleCrossoverPipeline.java @ 9598

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

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

File size: 8.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.rule.breed;
9
10import ec.rule.*;
11import ec.*;
12import ec.util.*;
13
14/*
15 * RuleCrossoverPipeline.java
16 *
17 * Created: Tue Mar 13 15:03:12 EST 2001
18 * By: Sean Luke
19 */
20
21
22/**
23 *
24 RuleCrossoverPipeline is a BreedingPipeline which implements a simple default crossover
25 for RuleIndividuals.  Normally it takes two individuals and returns two crossed-over
26 child individuals.  Optionally, it can take two individuals, cross them over, but throw
27 away the second child (a one-child crossover).  RuleCrossoverPipeline works by iteratively taking rulesets
28 from each individual, and migrating rules from either to the other with a certain
29 per-rule probability.  Rule crossover preserves the min and max rule restrictions.
30 
31 <p><b>Typical Number of Individuals Produced Per <tt>produce(...)</tt> call</b><br>
32 1 or 2
33
34 <p><b>Number of Sources</b><br>
35 2
36
37 <p><b>Parameters</b><br>
38 <table>
39 <tr><td valign=top><i>base</i>.<tt>toss</tt><br>
40 <font size=-1>bool = <tt>true</tt> or <tt>false</tt> (default)</font>/td>
41 <td valign=top>(after crossing over with the first new individual, should its second sibling individual be thrown away instead of adding it to the population?)</td></tr>
42 <tr><td valign=top><i>base</i>.<tt>prob</tt><br>
43 <font size=-1>0.0 &lt;= float &lt; 1.0, or 0.5 (default)</font>/td>
44 <td valign=top>(probability that a rule will cross over from one individual to the other)</td></tr>
45 </table>
46
47 <p><b>Default Base</b><br>
48 rule.xover
49
50 * @author Sean Luke
51 * @version 1.0
52 */
53
54public class RuleCrossoverPipeline extends BreedingPipeline
55    {
56    public static final String P_TOSS = "toss";
57    public static final String P_CROSSOVER = "xover";
58    public static final String P_CROSSOVERPROB = "crossover-prob";
59    public static final int INDS_PRODUCED = 2;
60    public static final int NUM_SOURCES = 2;
61
62    /** Should the pipeline discard the second parent after crossing over? */
63    public boolean tossSecondParent;
64   
65    /** What is the probability of a rule migrating? */
66    public float ruleCrossProbability;
67
68    /** Temporary holding place for parents */
69    RuleIndividual parents[];
70
71    public RuleCrossoverPipeline() { parents = new RuleIndividual[2]; }
72    public Parameter defaultBase() { return RuleDefaults.base().push(P_CROSSOVER); }
73
74    /** Returns 2 */
75    public int numSources() { return NUM_SOURCES; }
76
77    public Object clone()
78        {
79        RuleCrossoverPipeline c = (RuleCrossoverPipeline)(super.clone());
80
81        // deep-cloned stuff
82        c.parents = (RuleIndividual[]) parents.clone();
83
84        return c;
85        }
86
87    public void setup(final EvolutionState state, final Parameter base)
88        {
89        super.setup(state,base);
90        Parameter def = defaultBase();
91        tossSecondParent = state.parameters.getBoolean(base.push(P_TOSS),
92            def.push(P_TOSS),false);
93        ruleCrossProbability = state.parameters.getFloatWithDefault(base.push(P_CROSSOVERPROB),
94            def.push(P_CROSSOVERPROB),0.5f);
95        if (ruleCrossProbability > 1.0 || ruleCrossProbability < 0.0)
96            state.output.fatal("Rule cross probability must be between 0 and 1",base.push(P_CROSSOVERPROB),
97                def.push(P_CROSSOVERPROB));
98        }
99       
100    /** Returns 2 (unless tossing the second sibling, in which case it returns 1) */
101    public int typicalIndsProduced() { return (tossSecondParent? 1: INDS_PRODUCED); }
102
103    public int produce(final int min,
104        final int max,
105        final int start,
106        final int subpopulation,
107        final Individual[] inds,
108        final EvolutionState state,
109        final int thread)
110
111        {
112        // how many individuals should we make?
113        int n = (tossSecondParent? 1 : INDS_PRODUCED);
114        if (n < min) n = min;
115        if (n > max) n = max;
116
117        // should we bother?
118        if (!state.random[thread].nextBoolean(likelihood))
119            return reproduce(n, start, subpopulation, inds, state, thread, true);  // DO produce children from source -- we've not done so already
120
121
122        RuleInitializer initializer = ((RuleInitializer)state.initializer);
123   
124        for(int q=start;q<n+start; /* no increment */)  // keep on going until we're filled up
125            {
126            // grab two individuals from our sources
127            if (sources[0]==sources[1])  // grab from the same source
128                {
129                sources[0].produce(2,2,0,subpopulation,parents,state,thread);
130                if (!(sources[0] instanceof BreedingPipeline))  // it's a selection method probably
131                    {
132                    parents[0] = (RuleIndividual)(parents[0].clone());
133                    parents[1] = (RuleIndividual)(parents[1].clone());
134                    }
135                }
136            else // grab from different sources
137                {
138                sources[0].produce(1,1,0,subpopulation,parents,state,thread);
139                sources[1].produce(1,1,1,subpopulation,parents,state,thread);
140                if (!(sources[0] instanceof BreedingPipeline))  // it's a selection method probably
141                    parents[0] = (RuleIndividual)(parents[0].clone());
142                if (!(sources[1] instanceof BreedingPipeline)) // it's a selection method probably
143                    parents[1] = (RuleIndividual)(parents[1].clone());
144                }
145
146            // at this point, parents[] contains our two selected individuals,
147            // AND they're copied so we own them and can make whatever modifications
148            // we like on them.
149
150            // so we'll cross them over now.
151
152            parents[0].preprocessIndividual(state,thread);
153            parents[1].preprocessIndividual(state,thread);
154
155            if( parents[0].rulesets.length != parents[1].rulesets.length )
156                {
157                state.output.fatal( "The number of rule sets should be identical in both parents ( " +
158                    parents[0].rulesets.length + " : " +
159                    parents[1].rulesets.length + " )." );
160                }
161
162            // for each set of rules (assume both individuals have the same number of rule sets)
163            for( int x = 0 ; x < parents[0].rulesets.length ; x++ )
164                {
165                RuleSet[] temp = new RuleSet[2];
166                while(true)
167                    {
168                    // create two new rulesets (initially empty)
169                    for( int i = 0 ; i < 2 ; i++ )
170                        temp[i] = new RuleSet();
171                    // split the ruleset indexed x in parent 1
172                    temp = parents[0].rulesets[x].splitIntoTwo( state, thread, temp,ruleCrossProbability);
173                    // now temp[0] contains rules to that must go to parent[1]
174                                       
175                    // split the ruleset indexed x in parent 2 (append after the split results from previous operation)
176                    temp = parents[1].rulesets[x].splitIntoTwo( state, thread, temp, 1 - ruleCrossProbability);
177                    // now temp[1] contains rules that must go to parent[0]
178                   
179                    // ensure that there are enough rules
180                    if (temp[0].numRules >= parents[0].rulesets[x].constraints(initializer).minSize &&
181                        temp[0].numRules <= parents[0].rulesets[x].constraints(initializer).maxSize &&
182                        temp[1].numRules >= parents[1].rulesets[x].constraints(initializer).minSize &&
183                        temp[1].numRules <= parents[1].rulesets[x].constraints(initializer).maxSize)
184                        break;
185                       
186                    temp = new RuleSet[2];
187                    }
188                   
189                // copy the results in the rulesets of the parents
190                parents[0].rulesets[x].copyNoClone(temp[1]);
191                parents[1].rulesets[x].copyNoClone(temp[0]);
192                }
193           
194            parents[0].postprocessIndividual(state,thread);
195            parents[1].postprocessIndividual(state,thread);
196   
197            parents[0].evaluated=false;
198            parents[1].evaluated=false;
199           
200            // add 'em to the population
201            inds[q] = parents[0];
202            q++;
203            if (q<n+start && !tossSecondParent)
204                {
205                inds[q] = parents[1];
206                q++;
207                }
208            }
209        return n;
210        }
211    }
212   
213   
214   
215   
216   
217   
218   
Note: See TracBrowser for help on using the repository browser.