Free cookie consent management tool by TermsFeed Policy Generator

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