Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/de/DEBreeder.java @ 10216

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

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

File size: 8.2 KB
Line 
1package ec.de;
2
3import ec.*;
4import ec.util.*;
5import ec.vector.*;
6
7/*
8 * DEBreeder.java
9 *
10 * Created: Wed Apr 26 17:37:59 2006
11 * By: Liviu Panait
12 */
13
14/**
15 * DEBreeder provides a straightforward Differential Evolution (DE) breeder
16 * for the ECJ system.  The code is derived from the "classic" DE algorithm, known as DE/rand/1/bin, found on page 140 of
17 * "Differential Evolution: A Practical Approach to Global Optimization"
18 * by Kenneth Price, Rainer Storn, and Jouni Lampinen.
19 *
20 * <p>DEBreeder requires that all individuals be DoubleVectorIndividuals.
21 *
22 * <p>In short, the algorithm is as follows.  For each individual in the population, we produce a child
23 * by selecting three (different) individuals, none the original individual, called r0, r1, and r2.
24 * We then create an individal c, defined as c = r0 + F * (r1 - r2).  Last, we cross over c with the
25 * original individual and produce a single child, using uniform crossover with gene-independent
26 * crossover probability "Cr".
27 *
28 * <p>This class should be used in conjunction with
29 * DEEvaluator, which allows the children to enter the population only if they're superior to their
30 * parents (the original individuals).  If so, they replace their parents.
31 *
32 * <p><b>Parameters</b><br>
33 * <table>
34 * <tr><td valign=top><i>base.</i><tt>f</tt><br>
35 * <font size=-1>0.0 &lt;= double &lt;= 1.0 </font></td>
36 * <td valign=top>The "F" mutation scaling factor</td></tr>
37 *
38 * <tr><td valign=top><i>base.</i><tt>cr</tt><br>
39 * <font size=-1>0.0 &lt;= double &lt;= 1.0 </font></td>
40 * <td valign=top>The "Cr" probability of crossing over genes</td></tr>
41 * </table>
42 *
43 * @author Liviu Panait and Sean Luke
44 * @version 2.0
45 */
46
47public class DEBreeder extends Breeder
48    {
49    public static final double CR_UNSPECIFIED = -1;
50
51    /** Scaling factor for mutation */
52    public double F = 0.0;
53    /** Probability of crossover per gene */
54    public double Cr = CR_UNSPECIFIED;
55       
56    public static final String P_F = "f";
57    public static final String P_Cr = "cr";
58       
59    /** the previous population is stored in order to have parents compete directly with their children */
60    public Population previousPopulation = null;
61
62    /** the best individuals in each population (required by some DE breeders).  It's not required by DEBreeder's algorithm */
63    public int[] bestSoFarIndex = null;
64
65    public void setup(final EvolutionState state, final Parameter base)
66        {
67        if (!state.parameters.exists(base.push(P_Cr), null))  // it wasn't specified -- hope we know what we're doing
68            Cr = CR_UNSPECIFIED;
69        else
70            {
71            Cr = state.parameters.getDouble(base.push(P_Cr),null,0.0);
72            if ( Cr < 0.0 || Cr > 1.0 )
73                state.output.fatal( "Parameter not found, or its value is outside of [0.0,1.0].", base.push(P_Cr), null );
74            }
75                       
76        F = state.parameters.getDouble(base.push(P_F),null,0.0);
77        if ( F < 0.0 || F > 1.0 )
78            state.output.fatal( "Parameter not found, or its value is outside of [0.0,1.0].", base.push(P_F), null );
79        }
80
81    // this function is called just before chldren are to be bred
82    public void prepareDEBreeder(EvolutionState state)
83        {
84        // update the bestSoFar for each population
85        if( bestSoFarIndex == null || state.population.subpops.length != bestSoFarIndex.length )
86            bestSoFarIndex = new int[state.population.subpops.length];
87
88        for( int subpop = 0 ; subpop < state.population.subpops.length ; subpop++ )
89            {
90            Individual[] inds = state.population.subpops[subpop].individuals;
91            bestSoFarIndex[subpop] = 0;
92            for( int j = 1 ; j < inds.length ; j++ )
93                if( inds[j].fitness.betterThan(inds[bestSoFarIndex[subpop]].fitness) )
94                    bestSoFarIndex[subpop] = j;
95            }
96        }
97
98    public Population breedPopulation(EvolutionState state)
99        {
100        // double check that we're using DEEvaluator
101        if (!(state.evaluator instanceof DEEvaluator))
102            state.output.warnOnce("DEEvaluator not used, but DEBreeder used.  This is almost certainly wrong.");
103               
104        // prepare the breeder (some global statistics might need to be computed here)
105        prepareDEBreeder(state);
106
107        // create the new population
108        Population newpop = (Population) state.population.emptyClone();
109
110        // breed the children
111        for( int subpop = 0 ; subpop < state.population.subpops.length ; subpop++ )
112            {
113            if (state.population.subpops[subpop].individuals.length < 4)  // Magic number, sorry.  createIndividual() requires at least 4 individuals in the pop
114                state.output.fatal("Subpopulation " + subpop + " has fewer than four individuals, and so cannot be used with DEBreeder.");
115           
116            Individual[] inds = newpop.subpops[subpop].individuals;
117            for( int i = 0 ; i < inds.length ; i++ )
118                {
119                newpop.subpops[subpop].individuals[i] = createIndividual( state, subpop, i, 0);  // unthreaded for now
120                }
121            }
122
123        // store the current population for competition with the new children
124        previousPopulation = state.population;
125        return newpop;
126        }
127
128    /** Tests the Individual to see if its values are in range. */
129    public boolean valid(DoubleVectorIndividual ind)
130        {
131        FloatVectorSpecies species = (FloatVectorSpecies)(ind.species);
132        return (!(species.mutationIsBounded && !ind.isInRange()));
133        }
134
135    public DoubleVectorIndividual createIndividual(EvolutionState state,
136        int subpop,
137        int index,
138        int thread)
139        {
140        Individual[] inds = state.population.subpops[subpop].individuals;
141
142        DoubleVectorIndividual v = (DoubleVectorIndividual)(inds[index].clone());
143        do
144            {
145            // select three indexes different from each other and from that of the current parent
146            int r0, r1, r2;
147            do
148                {
149                r0 = state.random[thread].nextInt(inds.length);
150                }
151            while( r0 == index );
152            do
153                {
154                r1 = state.random[thread].nextInt(inds.length);
155                }
156            while( r1 == r0 || r1 == index );
157            do
158                {
159                r2 = state.random[thread].nextInt(inds.length);
160                }
161            while( r2 == r1 || r2 == r0 || r2 == index );
162
163            DoubleVectorIndividual g0 = (DoubleVectorIndividual)(inds[r0]);
164            DoubleVectorIndividual g1 = (DoubleVectorIndividual)(inds[r1]);
165            DoubleVectorIndividual g2 = (DoubleVectorIndividual)(inds[r2]);
166
167            for(int i = 0; i < v.genome.length; i++)
168                v.genome[i] = g0.genome[i] + F * (g1.genome[i] - g2.genome[i]);
169            }
170        while(!valid(v));
171
172        return crossover(state, (DoubleVectorIndividual)(inds[index]), v, thread);
173        }
174
175
176    /** Crosses over child with target, storing the result in child and returning it.  The default
177        procedure copies each value from the target, with independent probability CROSSOVER, into
178        the child.  The crossover guarantees that at least one child value, chosen at random, will
179        not be overwritten.  Override this method to perform some other kind of crossover. */
180               
181    public DoubleVectorIndividual crossover(EvolutionState state, DoubleVectorIndividual target, DoubleVectorIndividual child, int thread)
182        {
183        if (Cr == CR_UNSPECIFIED)
184            state.output.warnOnce("Differential Evolution Parameter cr unspecified.  Assuming cr = 0.5");
185                       
186        // first, hold one value in abeyance
187        int index = state.random[thread].nextInt(child.genome.length);
188        double val = child.genome[index];
189               
190        // do the crossover
191        for(int i = 0; i < child.genome.length; i++)
192            {
193            if (state.random[thread].nextDouble() < Cr)
194                child.genome[i] = target.genome[i];
195            }
196               
197        // reset the one value so it's not just a duplicate copy
198        child.genome[index] = val;
199       
200        return child;
201        }
202                       
203    }
Note: See TracBrowser for help on using the repository browser.