Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/vector/ByteVectorIndividual.java @ 13067

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

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

File size: 15.3 KB
Line 
1/*
2  Copyright 2006 by Sean Luke and George Mason University
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 * ByteVectorIndividual.java
16 * Created: Tue Mar 13 15:03:12 EST 2001
17 */
18
19/**
20 * ByteVectorIndividual is a VectorIndividual whose genome is an array of bytes.
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 * <P><b>From ec.Individual:</b> 
26 *
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.byte-vect-ind
65
66 * @author Liviu Panait
67 * @author Sean Luke
68 * @version 1.0
69 */
70
71public class ByteVectorIndividual extends VectorIndividual
72    {
73    public static final String P_BYTEVECTORINDIVIDUAL = "byte-vect-ind";
74    public byte[] genome;
75   
76    public Parameter defaultBase()
77        {
78        return VectorDefaults.base().push(P_BYTEVECTORINDIVIDUAL);
79        }
80
81    public Object clone()
82        {
83        ByteVectorIndividual myobj = (ByteVectorIndividual) (super.clone());
84
85        // must clone the genome
86        myobj.genome = (byte[])(genome.clone());
87       
88        return myobj;
89        }
90
91    public void setup(final EvolutionState state, final Parameter base)
92        {
93        super.setup(state,base);  // actually unnecessary (Individual.setup() is empty)
94
95        // since IntegerVectorSpecies set its constraint values BEFORE it called
96        // super.setup(...) [which in turn called our setup(...)], we know that
97        // stuff like genomeSize has already been set...
98       
99        Parameter def = defaultBase();
100       
101        if (!(species instanceof IntegerVectorSpecies))
102            state.output.fatal("ByteVectorIndividual requires an IntegerVectorSpecies", base, def);
103        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
104       
105        genome = new byte[s.genomeSize];
106        }
107       
108    public void defaultCrossover(EvolutionState state, int thread, VectorIndividual ind)
109        {
110        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
111        ByteVectorIndividual i = (ByteVectorIndividual) ind;
112        byte tmp;
113        int point;
114
115        if (genome.length != i.genome.length)
116            state.output.fatal("Genome lengths are not the same for fixed-length vector crossover");
117        switch(s.crossoverType)
118            {
119            case VectorSpecies.C_ONE_POINT:
120                point = state.random[thread].nextInt((genome.length / s.chunksize)+1);
121                for(int x=0;x<point*s.chunksize;x++)
122                    {
123                    tmp = i.genome[x];
124                    i.genome[x] = genome[x];
125                    genome[x] = tmp;
126                    }
127                break;
128            case VectorSpecies.C_TWO_POINT:
129                int point0 = state.random[thread].nextInt((genome.length / s.chunksize)+1);
130                point = state.random[thread].nextInt((genome.length / s.chunksize)+1);
131                if (point0 > point) { int p = point0; point0 = point; point = p; }
132                for(int x=point0*s.chunksize;x<point*s.chunksize;x++)
133                    {
134                    tmp = i.genome[x];
135                    i.genome[x] = genome[x];
136                    genome[x] = tmp;
137                    }
138                break;
139            case VectorSpecies.C_ANY_POINT:
140                for(int x=0;x<genome.length/s.chunksize;x++)
141                    if (state.random[thread].nextBoolean(s.crossoverProbability))
142                        for(int y=x*s.chunksize;y<(x+1)*s.chunksize;y++)
143                            {
144                            tmp = i.genome[y];
145                            i.genome[y] = genome[y];
146                            genome[y] = tmp;
147                            }
148                break;
149            case VectorSpecies.C_LINE_RECOMB:
150            {
151            double alpha = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
152            double beta = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
153            long t,u;
154            long min, max;
155            for (int x = 0; x < genome.length; x++)
156                {
157                min = s.minGene(x);
158                max = s.maxGene(x);
159                t = (long) Math.floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5);
160                u = (long) Math.floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5);
161                if (!(t < min || t > max || u < min || u > max))
162                    {
163                    genome[x] = (byte) t;
164                    i.genome[x] = (byte) u;
165                    }
166                }
167            }
168            break;
169            case VectorSpecies.C_INTERMED_RECOMB:
170            {
171            long t,u;
172            long min, max;
173            for (int x = 0; x < genome.length; x++)
174                {
175                do
176                    {
177                    double alpha = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
178                    double beta = state.random[thread].nextDouble() * (1 + 2*s.lineDistance) - s.lineDistance;
179                    min = s.minGene(x);
180                    max = s.maxGene(x);
181                    t = (long) Math.floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5);
182                    u = (long) Math.floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5);
183                    } while (t < min || t > max || u < min || u > max);
184                genome[x] = (byte) t;
185                i.genome[x] = (byte) u;
186                }
187            }
188            break;
189            }
190        }
191
192    /** Splits the genome into n pieces, according to points, which *must* be sorted.
193        pieces.length must be 1 + points.length */
194    public void split(int[] points, Object[] pieces)
195        {
196        int point0, point1;
197        point0 = 0; point1 = points[0];
198        for(int x=0;x<pieces.length;x++)
199            {
200            pieces[x] = new byte[point1-point0];
201            System.arraycopy(genome,point0,pieces[x],0,point1-point0);
202            point0 = point1;
203            if (x >=pieces.length-2)
204                point1 = genome.length;
205            else point1 = points[x+1];
206            }
207        }
208   
209    /** Joins the n pieces and sets the genome to their concatenation.*/
210    public void join(Object[] pieces)
211        {
212        int sum=0;
213        for(int x=0;x<pieces.length;x++)
214            sum += ((byte[])(pieces[x])).length;
215       
216        int runningsum = 0;
217        byte[] newgenome = new byte[sum];
218        for(int x=0;x<pieces.length;x++)
219            {
220            System.arraycopy(pieces[x], 0, newgenome, runningsum, ((byte[])(pieces[x])).length);
221            runningsum += ((byte[])(pieces[x])).length;
222            }
223        // set genome
224        genome = newgenome;
225        }
226
227    /** Destructively mutates the individual in some default manner.  The default form
228        simply randomizes genes to a uniform distribution from the min and max of the gene values. */
229    public void defaultMutate(EvolutionState state, int thread)
230        {
231        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
232        if (s.mutationProbability>0.0)
233            for(int x=0;x<genome.length;x++)
234                if (state.random[thread].nextBoolean(s.mutationProbability))
235                    genome[x] = (byte)((int)s.minGene(x) + state.random[thread].nextInt((int)s.maxGene(x)-(int)s.minGene(x)+1));
236        }
237       
238   
239
240    /** Initializes the individual by randomly choosing Bytes uniformly from mingene to maxgene. */
241    public void reset(EvolutionState state, int thread)
242        {
243        IntegerVectorSpecies s = (IntegerVectorSpecies) species;
244        for(int x=0;x<genome.length;x++)
245            genome[x] = (byte)((int)s.minGene(x) + state.random[thread].nextInt((int)s.maxGene(x)-(int)s.minGene(x)+1));
246        }
247
248    public int hashCode()
249        {
250        // stolen from GPIndividual.  It's a decent algorithm.
251        int hash = this.getClass().hashCode();
252
253        hash = ( hash << 1 | hash >>> 31 );
254        for(int x=0;x<genome.length;x++)
255            hash = ( hash << 1 | hash >>> 31 ) ^ genome[x];
256
257        return hash;
258        }
259
260    public String genotypeToStringForHumans()
261        {
262        String s = "";
263        for( int i = 0 ; i < genome.length ; i++ )
264            s = s + " " + genome[i];
265        return s;
266        }
267       
268    public String genotypeToString()
269        {
270        StringBuffer s = new StringBuffer();
271        s.append( Code.encode( genome.length ) );
272        for( int i = 0 ; i < genome.length ; i++ )
273            s.append( Code.encode( genome[i] ) );
274        return s.toString();
275        }
276               
277    protected void parseGenotype(final EvolutionState state,
278        final LineNumberReader reader) throws IOException
279        {
280        // read in the next line.  The first item is the number of genes
281        String s = reader.readLine();
282        DecodeReturn d = new DecodeReturn(s);
283        Code.decode( d );
284        int lll = (int)(d.l);
285
286        genome = new byte[ lll ];
287
288        // read in the genes
289        for( int i = 0 ; i < genome.length ; i++ )
290            {
291            Code.decode( d );
292            genome[i] = (byte)(d.l);
293            }
294        }
295
296    public boolean equals(Object ind)
297        {
298        if (!(this.getClass().equals(ind.getClass()))) return false; // SimpleRuleIndividuals are special.
299        ByteVectorIndividual i = (ByteVectorIndividual)ind;
300        if( genome.length != i.genome.length )
301            return false;
302        for( int j = 0 ; j < genome.length ; j++ )
303            if( genome[j] != i.genome[j] )
304                return false;
305        return true;
306        }
307
308    public Object getGenome()
309        { return genome; }
310    public void setGenome(Object gen)
311        { genome = (byte[]) gen; }
312    public int genomeLength()
313        { return genome.length; }
314
315    public void writeGenotype(final EvolutionState state,
316        final DataOutput dataOutput) throws IOException
317        {
318        dataOutput.writeInt(genome.length);
319        for(int x=0;x<genome.length;x++)
320            dataOutput.writeByte(genome[x]);
321        }
322
323    public void readGenotype(final EvolutionState state,
324        final DataInput dataInput) throws IOException
325        {
326        int len = dataInput.readInt();
327        if (genome==null || genome.length != len)
328            genome = new byte[len];
329        for(int x=0;x<genome.length;x++)
330            genome[x] = dataInput.readByte();
331        }
332
333    /** Clips each gene value to be within its specified [min,max] range. */
334    public void clamp()
335        {
336        IntegerVectorSpecies _species = (IntegerVectorSpecies)species;
337        for (int i = 0; i < genomeLength(); i++)
338            {
339            byte minGene = (byte)_species.minGene(i);
340            if (genome[i] < minGene)
341                genome[i] = minGene;
342            else
343                {
344                byte maxGene = (byte)_species.maxGene(i);
345                if (genome[i] > maxGene)
346                    genome[i] = maxGene;
347                }
348            }
349        }
350               
351    public void setGenomeLength(int len)
352        {
353        byte[] newGenome = new byte[len];
354        System.arraycopy(genome, 0, newGenome, 0,
355            genome.length < newGenome.length ? genome.length : newGenome.length);
356        genome = newGenome;
357        }
358
359    /** Returns true if each gene value is within is specified [min,max] range. */
360    public boolean isInRange()
361        {
362        IntegerVectorSpecies _species = (IntegerVectorSpecies)species;
363        for (int i = 0; i < genomeLength(); i++)
364            if (genome[i] < _species.minGene(i) ||
365                genome[i] > _species.maxGene(i)) return false;
366        return true;
367        }
368
369    public double distanceTo(Individual otherInd)
370        {               
371        if (!(otherInd instanceof ByteVectorIndividual))
372            return super.distanceTo(otherInd);  // will return infinity!
373               
374        ByteVectorIndividual other = (ByteVectorIndividual) otherInd;
375        byte[] otherGenome = other.genome;
376        double sumSquaredDistance =0.0;
377        for(int i=0; i < other.genomeLength(); i++)
378            {
379            long dist = this.genome[i] - (long)otherGenome[i];
380            sumSquaredDistance += dist*dist;
381            }
382        return StrictMath.sqrt(sumSquaredDistance);
383        }
384    }
Note: See TracBrowser for help on using the repository browser.