Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/vector/IntegerVectorIndividual.java @ 6703

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

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

File size: 15.8 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.vector;
9
10import ec.*;
11import ec.util.*;
12import java.io.*;
13
14/*
15 * IntegerVectorIndividual.java
16 * Created: Tue Mar 13 15:03:12 EST 2001
17 */
18
19/**
20 * IntegerVectorIndividual is a VectorIndividual whose genome is an array of ints.
21 * Gene values may range from species.mingene(x) to species.maxgene(x), inclusive.
22 * The default mutation method randomizes genes to new values in this range,
23 * with <tt>species.mutationProbability</tt>.
24 *
25
26 * <P><b>From ec.Individual:</b> 
27 * <p>In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways.
28 *
29 * <ul>
30 * <li><b>writeIndividual(...,DataOutput)/readIndividual(...,DataInput)</b>&nbsp;&nbsp;&nbsp;This method
31 * transmits or receives an individual in binary.  It is the most efficient approach to sending
32 * individuals over networks, etc.  These methods write the evaluated flag and the fitness, then
33 * call <b>readGenotype/writeGenotype</b>, which you must implement to write those parts of your
34 * Individual special to your functions-- the default versions of readGenotype/writeGenotype throw errors.
35 * You don't need to implement them if you don't plan on using read/writeIndividual.
36 *
37 * <li><b>printIndividual(...,PrintWriter)/readIndividual(...,LineNumberReader)</b>&nbsp;&nbsp;&nbsp;This
38 * approach transmits or receives an indivdual in text encoded such that the individual is largely readable
39 * by humans but can be read back in 100% by ECJ as well.  To do this, these methods will encode numbers
40 * using the <tt>ec.util.Code</tt> class.  These methods are mostly used to write out populations to
41 * files for inspection, slight modification, then reading back in later on.  <b>readIndividual</b> reads
42 * in the fitness and the evaluation flag, then calls <b>parseGenotype</b> to read in the remaining individual.
43 * You are responsible for implementing parseGenotype: the Code class is there to help you.
44 * <b>printIndividual</b> writes out the fitness and evaluation flag, then calls <b>genotypeToString</b>
45 * and printlns the resultant string. You are responsible for implementing the genotypeToString method in such
46 * a way that parseGenotype can read back in the individual println'd with genotypeToString.  The default form
47 * of genotypeToString simply calls <b>toString</b>, which you may override instead if you like.  The default
48 * form of <b>parseGenotype</b> throws an error.  You are not required to implement these methods, but without
49 * them you will not be able to write individuals to files in a simultaneously computer- and human-readable fashion.
50 *
51 * <li><b>printIndividualForHumans(...,PrintWriter)</b>&nbsp;&nbsp;&nbsp;This
52 * approach prints an individual in a fashion intended for human consumption only.
53 * <b>printIndividualForHumans</b> writes out the fitness and evaluation flag, then calls <b>genotypeToStringForHumans</b>
54 * and printlns the resultant string. You are responsible for implementing the genotypeToStringForHumans method.
55 * The default form of genotypeToStringForHumans simply calls <b>toString</b>, which you may override instead if you like
56 * (though note that genotypeToString's default also calls toString).  You should handle one of these methods properly
57 * to ensure individuals can be printed by ECJ.
58 * </ul>
59
60 * <p>In general, the various readers and writers do three things: they tell the Fitness to read/write itself,
61 * they read/write the evaluated flag, and they read/write the gene array.  If you add instance variables to
62 * a VectorIndividual or subclass, you'll need to read/write those variables as well.
63 <p><b>Default Base</b><br>
64 vector.int-vect-ind
65
66 * @author Sean Luke
67 * @version 1.0
68 */
69
70public class IntegerVectorIndividual extends VectorIndividual
71    {
72    public static final String P_INTEGERVECTORINDIVIDUAL = "int-vect-ind";
73    public int[] genome;
74   
75    public Parameter defaultBase()
76        {
77        return VectorDefaults.base().push(P_INTEGERVECTORINDIVIDUAL);
78        }
79
80    public Object clone()
81        {
82        IntegerVectorIndividual myobj = (IntegerVectorIndividual) (super.clone());
83
84        // must clone the genome
85        myobj.genome = (int[])(genome.clone());
86       
87        return myobj;
88        }
89
90    public void setup(final EvolutionState state, final Parameter base)
91        {
92        super.setup(state,base);  // actually unnecessary (Individual.setup() is empty)
93
94        Parameter def = defaultBase();
95       
96        if (!(species instanceof IntegerVectorSpecies))
97            state.output.fatal("IntegerVectorIndividual requires an IntegerVectorSpecies", base, def);
98        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
99       
100        genome = new int[s.genomeSize];
101        }
102       
103    public void defaultCrossover(EvolutionState state, int thread, VectorIndividual ind)
104        {
105        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
106        IntegerVectorIndividual i = (IntegerVectorIndividual) ind;
107        int tmp;
108        int point;
109
110        if (genome.length != i.genome.length)
111            state.output.fatal("Genome lengths are not the same for fixed-length vector crossover");
112        switch(s.crossoverType)
113            {
114            case VectorSpecies.C_ONE_POINT:
115                point = state.random[thread].nextInt((genome.length / s.chunksize)+1);
116                for(int x=0;x<point*s.chunksize;x++)
117                    {
118                    tmp = i.genome[x];
119                    i.genome[x] = genome[x];
120                    genome[x] = tmp;
121                    }
122                break;
123            case VectorSpecies.C_TWO_POINT:
124                int point0 = state.random[thread].nextInt((genome.length / s.chunksize)+1);
125                point = state.random[thread].nextInt((genome.length / s.chunksize)+1);
126                if (point0 > point) { int p = point0; point0 = point; point = p; }
127                for(int x=point0*s.chunksize;x<point*s.chunksize;x++)
128                    {
129                    tmp = i.genome[x];
130                    i.genome[x] = genome[x];
131                    genome[x] = tmp;
132                    }
133                break;
134            case VectorSpecies.C_ANY_POINT:
135                for(int x=0;x<genome.length/s.chunksize;x++)
136                    if (state.random[thread].nextBoolean(s.crossoverProbability))
137                        for(int y=x*s.chunksize;y<(x+1)*s.chunksize;y++)
138                            {
139                            tmp = i.genome[y];
140                            i.genome[y] = genome[y];
141                            genome[y] = tmp;
142                            }
143                break;
144            case VectorSpecies.C_LINE_RECOMB:
145            {
146            double alpha = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
147            double beta = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
148            long t,u;
149            long min, max;
150            for (int x = 0; x < genome.length; x++)
151                {
152                min = s.minGene(x);
153                max = s.maxGene(x);
154                t = (long) Math.floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5);
155                u = (long) Math.floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5);
156                if (!(t < min || t > max || u < min || u > max))
157                    {
158                    genome[x] = (int) t;
159                    i.genome[x] = (int) u;
160                    }
161                }
162            }
163            break;
164            case VectorSpecies.C_INTERMED_RECOMB:
165            {
166            long t,u;
167            long min, max;
168            for (int x = 0; x < genome.length; x++)
169                {
170                do
171                    {
172                    double alpha = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
173                    double beta = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
174                    min = s.minGene(x);
175                    max = s.maxGene(x);
176                    t = (long) Math.floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5);
177                    u = (long) Math.floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5);
178                    } while (t < min || t > max || u < min || u > max);
179                genome[x] = (int) t;
180                i.genome[x] = (int) u;
181                }
182            }
183            break;
184            }
185        }
186
187    /** Splits the genome into n pieces, according to points, which *must* be sorted.
188        pieces.length must be 1 + points.length */
189    public void split(int[] points, Object[] pieces)
190        {
191        int point0, point1;
192        point0 = 0; point1 = points[0];
193        for(int x=0;x<pieces.length;x++)
194            {
195            pieces[x] = new int[point1-point0];
196            System.arraycopy(genome,point0,pieces[x],0,point1-point0);
197            point0 = point1;
198            if (x >=pieces.length-2)
199                point1 = genome.length;
200            else point1 = points[x+1];
201            }
202        }
203   
204    /** Joins the n pieces and sets the genome to their concatenation.*/
205    public void join(Object[] pieces)
206        {
207        int sum=0;
208        for(int x=0;x<pieces.length;x++)
209            sum += ((int[])(pieces[x])).length;
210       
211        int runningsum = 0;
212        int[] newgenome = new int[sum];
213        for(int x=0;x<pieces.length;x++)
214            {
215            System.arraycopy(pieces[x], 0, newgenome, runningsum, ((int[])(pieces[x])).length);
216            runningsum += ((int[])(pieces[x])).length;
217            }
218        // set genome
219        genome = newgenome;
220        }
221
222
223    /** Returns a random value from between min and max inclusive.  This method handles
224        overflows that complicate this computation.  Does NOT check that
225        min is less than or equal to max.  You must check this yourself. */
226    public int randomValueFromClosedInterval(int min, int max, MersenneTwisterFast random)
227        {
228        if (max - min < 0) // we had an overflow
229            {
230            int l = 0;
231            do l = random.nextInt();
232            while(l < min || l > max);
233            return l;
234            }
235        else return min + random.nextInt(max - min + 1);
236        }
237
238
239    /** Destructively mutates the individual in some default manner.  The default form
240        simply randomizes genes to a uniform distribution from the min and max of the gene values. */
241    // notice that we bump to longs to avoid overflow errors
242    public void defaultMutate(EvolutionState state, int thread)
243        {
244        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
245        if (s.mutationProbability>0.0)
246            for(int x=0;x<genome.length;x++)
247                if (state.random[thread].nextBoolean(s.mutationProbability))
248                    genome[x] = randomValueFromClosedInterval((int)s.minGene(x), (int)s.maxGene(x), state.random[thread]);
249        }
250       
251   
252
253    /** Initializes the individual by randomly choosing Integers uniformly from mingene to maxgene. */
254    // notice that we bump to longs to avoid overflow errors
255    public void reset(EvolutionState state, int thread)
256        {
257        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
258        for(int x=0;x<genome.length;x++)
259            genome[x] = randomValueFromClosedInterval((int)s.minGene(x), (int)s.maxGene(x), state.random[thread]);
260        }
261
262    public int hashCode()
263        {
264        // stolen from GPIndividual.  It's a decent algorithm.
265        int hash = this.getClass().hashCode();
266
267        hash = ( hash << 1 | hash >>> 31 );
268        for(int x=0;x<genome.length;x++)
269            hash = ( hash << 1 | hash >>> 31 ) ^ genome[x];
270
271        return hash;
272        }
273
274    public String genotypeToStringForHumans()
275        {
276        String s = "";
277        for( int i = 0 ; i < genome.length ; i++ )
278            s = s + " " + genome[i];
279        return s;
280        }
281       
282    public String genotypeToString()
283        {
284        StringBuffer s = new StringBuffer();
285        s.append( Code.encode( genome.length ) );
286        for( int i = 0 ; i < genome.length ; i++ )
287            s.append( Code.encode( genome[i] ) );
288        return s.toString();
289        }
290               
291    protected void parseGenotype(final EvolutionState state,
292        final LineNumberReader reader) throws IOException
293        {
294        // read in the next line.  The first item is the number of genes
295        String s = reader.readLine();
296        DecodeReturn d = new DecodeReturn(s);
297        Code.decode( d );
298        int lll = (int)(d.l);
299
300        genome = new int[ lll ];
301
302        // read in the genes
303        for( int i = 0 ; i < genome.length ; i++ )
304            {
305            Code.decode( d );
306            genome[i] = (int)(d.l);
307            }
308        }
309
310    public boolean equals(Object ind)
311        {
312        if (!(this.getClass().equals(ind.getClass()))) return false; // SimpleRuleIndividuals are special.
313        IntegerVectorIndividual i = (IntegerVectorIndividual)ind;
314        if( genome.length != i.genome.length )
315            return false;
316        for( int j = 0 ; j < genome.length ; j++ )
317            if( genome[j] != i.genome[j] )
318                return false;
319        return true;
320        }
321
322    public Object getGenome()
323        { return genome; }
324    public void setGenome(Object gen)
325        { genome = (int[]) gen; }
326    public int genomeLength()
327        { return genome.length; }
328       
329    public void writeGenotype(final EvolutionState state,
330        final DataOutput dataOutput) throws IOException
331        {
332        dataOutput.writeInt(genome.length);
333        for(int x=0;x<genome.length;x++)
334            dataOutput.writeInt(genome[x]);
335        }
336
337    public void readGenotype(final EvolutionState state,
338        final DataInput dataInput) throws IOException
339        {
340        int len = dataInput.readInt();
341        if (genome==null || genome.length != len)
342            genome = new int[len];
343        for(int x=0;x<genome.length;x++)
344            genome[x] = dataInput.readInt();
345        }
346
347    /** Clips each gene value to be within its specified [min,max] range. */
348    public void clamp()
349        {
350        IntegerVectorSpecies _species = (IntegerVectorSpecies)species;
351        for (int i = 0; i < genomeLength(); i++)
352            {
353            int minGene = (int)_species.minGene(i);
354            if (genome[i] < minGene)
355                genome[i] = minGene;
356            else
357                {
358                int maxGene = (int)_species.maxGene(i);
359                if (genome[i] > maxGene)
360                    genome[i] = maxGene;
361                }
362            }
363        }
364               
365    public void setGenomeLength(int len)
366        {
367        int[] newGenome = new int[len];
368        System.arraycopy(genome, 0, newGenome, 0,
369            genome.length < newGenome.length ? genome.length : newGenome.length);
370        genome = newGenome;
371        }
372
373    /** Returns true if each gene value is within is specified [min,max] range. */
374    public boolean isInRange()
375        {
376        IntegerVectorSpecies _species = (IntegerVectorSpecies)species;
377        for (int i = 0; i < genomeLength(); i++)
378            if (genome[i] < _species.minGene(i) ||
379                genome[i] > _species.maxGene(i)) return false;
380        return true;
381        }
382
383    public double distanceTo(Individual otherInd)
384        {               
385        if (!(otherInd instanceof IntegerVectorIndividual))
386            return super.distanceTo(otherInd);  // will return infinity!
387               
388        IntegerVectorIndividual other = (IntegerVectorIndividual) otherInd;
389        int[] otherGenome = other.genome;
390        double sumSquaredDistance =0.0;
391        for(int i=0; i < other.genomeLength(); i++)
392            {
393            long dist = this.genome[i] - (long)otherGenome[i];
394            sumSquaredDistance += dist*dist;
395            }
396        return StrictMath.sqrt(sumSquaredDistance);
397        }
398    }
Note: See TracBrowser for help on using the repository browser.