Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/vector/BitVectorIndividual.java @ 10501

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

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

File size: 11.9 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 * BitVectorIndividual.java
16 * Created: Tue Mar 13 15:03:12 EST 2001
17 */
18
19/**
20 * BitVectorIndividual is a VectorIndividual whose genome is an array of booleans.
21 * The default mutation method simply flips bits with <tt>mutationProbability</tt>.
22 *
23 * <P><b>From ec.Individual:</b> 
24 *
25 * <p>In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways.
26 *
27 * <ul>
28 * <li><b>writeIndividual(...,DataOutput)/readIndividual(...,DataInput)</b>&nbsp;&nbsp;&nbsp;This method
29 * transmits or receives an individual in binary.  It is the most efficient approach to sending
30 * individuals over networks, etc.  These methods write the evaluated flag and the fitness, then
31 * call <b>readGenotype/writeGenotype</b>, which you must implement to write those parts of your
32 * Individual special to your functions-- the default versions of readGenotype/writeGenotype throw errors.
33 * You don't need to implement them if you don't plan on using read/writeIndividual.
34 *
35 * <li><b>printIndividual(...,PrintWriter)/readIndividual(...,LineNumberReader)</b>&nbsp;&nbsp;&nbsp;This
36 * approach transmits or receives an indivdual in text encoded such that the individual is largely readable
37 * by humans but can be read back in 100% by ECJ as well.  To do this, these methods will encode numbers
38 * using the <tt>ec.util.Code</tt> class.  These methods are mostly used to write out populations to
39 * files for inspection, slight modification, then reading back in later on.  <b>readIndividual</b> reads
40 * in the fitness and the evaluation flag, then calls <b>parseGenotype</b> to read in the remaining individual.
41 * You are responsible for implementing parseGenotype: the Code class is there to help you.
42 * <b>printIndividual</b> writes out the fitness and evaluation flag, then calls <b>genotypeToString</b>
43 * and printlns the resultant string. You are responsible for implementing the genotypeToString method in such
44 * a way that parseGenotype can read back in the individual println'd with genotypeToString.  The default form
45 * of genotypeToString simply calls <b>toString</b>, which you may override instead if you like.  The default
46 * form of <b>parseGenotype</b> throws an error.  You are not required to implement these methods, but without
47 * them you will not be able to write individuals to files in a simultaneously computer- and human-readable fashion.
48 *
49 * <li><b>printIndividualForHumans(...,PrintWriter)</b>&nbsp;&nbsp;&nbsp;This
50 * approach prints an individual in a fashion intended for human consumption only.
51 * <b>printIndividualForHumans</b> writes out the fitness and evaluation flag, then calls <b>genotypeToStringForHumans</b>
52 * and printlns the resultant string. You are responsible for implementing the genotypeToStringForHumans method.
53 * The default form of genotypeToStringForHumans simply calls <b>toString</b>, which you may override instead if you like
54 * (though note that genotypeToString's default also calls toString).  You should handle one of these methods properly
55 * to ensure individuals can be printed by ECJ.
56 * </ul>
57
58 * <p>In general, the various readers and writers do three things: they tell the Fitness to read/write itself,
59 * they read/write the evaluated flag, and they read/write the gene array.  If you add instance variables to
60 * a VectorIndividual or subclass, you'll need to read/write those variables as well.
61 <p><b>Default Base</b><br>
62 vector.bit-vect-ind
63
64 * @author Sean Luke
65 * @version 1.0
66 */
67
68public class BitVectorIndividual extends VectorIndividual
69    {
70    public static final String P_BITVECTORINDIVIDUAL = "bit-vect-ind";
71    public boolean[] genome;
72   
73    public Parameter defaultBase()
74        {
75        return VectorDefaults.base().push(P_BITVECTORINDIVIDUAL);
76        }
77
78    public Object clone()
79        {
80        BitVectorIndividual myobj = (BitVectorIndividual) (super.clone());
81       
82        // must clone the genome
83        myobj.genome = (boolean[])(genome.clone());
84       
85        return myobj;
86        }
87
88    public void setup(final EvolutionState state, final Parameter base)
89        {
90        super.setup(state,base);  // actually unnecessary (Individual.setup() is empty)
91
92        VectorSpecies s = (VectorSpecies)species;  // where my default info is stored
93        genome = new boolean[s.genomeSize];
94        }
95
96    public void defaultCrossover(EvolutionState state, int thread, VectorIndividual ind)
97        {
98        VectorSpecies s = (VectorSpecies)species;  // where my default info is stored
99        BitVectorIndividual i = (BitVectorIndividual) ind;
100        boolean tmp;
101        int point;
102
103        if (genome.length != i.genome.length)
104            state.output.fatal("Genome lengths are not the same for fixed-length vector crossover");
105        switch(s.crossoverType)
106            {
107            case VectorSpecies.C_ONE_POINT:
108                point = state.random[thread].nextInt((genome.length / s.chunksize)+1);
109                for(int x=0;x<point*s.chunksize;x++)
110                    {
111                    tmp = i.genome[x];
112                    i.genome[x] = genome[x];
113                    genome[x] = tmp;
114                    }
115                break;
116            case VectorSpecies.C_TWO_POINT:
117                int point0 = state.random[thread].nextInt((genome.length / s.chunksize)+1);
118                point = state.random[thread].nextInt((genome.length / s.chunksize)+1);
119                if (point0 > point) { int p = point0; point0 = point; point = p; }
120                for(int x=point0*s.chunksize;x<point*s.chunksize;x++)
121                    {
122                    tmp = i.genome[x];
123                    i.genome[x] = genome[x];
124                    genome[x] = tmp;
125                    }
126                break;
127            case VectorSpecies.C_ANY_POINT:
128                for(int x=0;x<genome.length/s.chunksize;x++)
129                    if (state.random[thread].nextBoolean(s.crossoverProbability))
130                        for(int y=x*s.chunksize;y<(x+1)*s.chunksize;y++)
131                            {
132                            tmp = i.genome[y];
133                            i.genome[y] = genome[y];
134                            genome[y] = tmp;
135                            }
136                break;
137            }
138        }
139
140    /** Splits the genome into n pieces, according to points, which *must* be sorted.
141        pieces.length must be 1 + points.length */
142    public void split(int[] points, Object[] pieces)
143        {
144        int point0, point1;
145        point0 = 0; point1 = points[0];
146        for(int x=0;x<pieces.length;x++)
147            {
148            pieces[x] = new boolean[point1-point0];
149            System.arraycopy(genome,point0,pieces[x],0,point1-point0);
150            point0 = point1;
151            if (x >=pieces.length-2)
152                point1 = genome.length;
153            else point1 = points[x+1];
154            }
155        }
156   
157    /** Joins the n pieces and sets the genome to their concatenation.*/
158    public void join(Object[] pieces)
159        {
160        int sum=0;
161        for(int x=0;x<pieces.length;x++)
162            sum += ((boolean[])(pieces[x])).length;
163       
164        int runningsum = 0;
165        boolean[] newgenome = new boolean[sum];
166        for(int x=0;x<pieces.length;x++)
167            {
168            System.arraycopy(pieces[x], 0, newgenome, runningsum, ((boolean[])(pieces[x])).length);
169            runningsum += ((boolean[])(pieces[x])).length;
170            }
171        // set genome
172        genome = newgenome;
173        }
174
175    /** Destructively mutates the individual in some default manner.  The default form
176        does a bit-flip with a probability depending on parameters. */
177    public void defaultMutate(EvolutionState state, int thread)
178        {
179        VectorSpecies s = (VectorSpecies)species;  // where my default info is stored
180        if (s.mutationProbability>0.0)
181            for(int x=0;x<genome.length;x++)
182                if (state.random[thread].nextBoolean(s.mutationProbability))
183                    genome[x] = !genome[x];
184        }
185       
186    /** Initializes the individual by randomly flipping the bits */
187    public void reset(EvolutionState state, int thread)
188        {
189        for(int x=0;x<genome.length;x++)
190            genome[x] = state.random[thread].nextBoolean();
191        }
192
193    public int hashCode()
194        {
195        // stolen from GPIndividual.  It's a decent algorithm.
196        int hash = this.getClass().hashCode();
197
198        hash = ( hash << 1 | hash >>> 31 ) ^ genome.hashCode();
199
200        return hash;
201        }
202
203    public String genotypeToStringForHumans()
204        {
205        String s = "";
206        for( int i = 0 ; i < genome.length ; i++ )
207            {
208            if( genome[i] )
209                s = s + " 1";
210            else
211                s = s + " 0";
212            }
213        return s;
214        }
215       
216    public String genotypeToString()
217        {
218        StringBuffer s = new StringBuffer();
219        s.append( Code.encode( genome.length ) );
220        for( int i = 0 ; i < genome.length ; i++ )
221            s.append( Code.encode( genome[i] ) );
222        return s.toString();
223        }
224               
225    protected void parseGenotype(final EvolutionState state,
226        final LineNumberReader reader) throws IOException
227        {
228        // read in the next line.  The first item is the number of genes
229        String s = reader.readLine();
230        DecodeReturn d = new DecodeReturn(s);
231        Code.decode( d );
232        int lll = (int)(d.l);
233
234        genome = new boolean[ lll ];
235
236        // read in the genes
237        for( int i = 0 ; i < genome.length ; i++ )
238            {
239            Code.decode( d );
240            genome[i] = (boolean)(d.l!=0);
241            }
242        }
243
244    public boolean equals(Object ind)
245        {
246        if (!(this.getClass().equals(ind.getClass()))) return false; // SimpleRuleIndividuals are special.
247        BitVectorIndividual i = (BitVectorIndividual)ind;
248        if( genome.length != i.genome.length )
249            return false;
250        for( int j = 0 ; j < genome.length ; j++ )
251            if( genome[j] != i.genome[j] )
252                return false;
253        return true;
254        }
255
256    public Object getGenome()
257        { return genome; }
258    public void setGenome(Object gen)
259        { genome = (boolean[]) gen; }
260    public int genomeLength()
261        { return genome.length; }
262
263    public void setGenomeLength(int len)
264        {
265        boolean[] newGenome = new boolean[len];
266        System.arraycopy(genome, 0, newGenome, 0,
267            genome.length < newGenome.length ? genome.length : newGenome.length);
268        genome = newGenome;
269        }
270
271    public void writeGenotype(final EvolutionState state,
272        final DataOutput dataOutput) throws IOException
273        {
274        dataOutput.writeInt(genome.length);
275        for(int x=0;x<genome.length;x++)
276            dataOutput.writeBoolean(genome[x]);  // inefficient: booleans are written out as bytes
277        }
278
279    public void readGenotype(final EvolutionState state,
280        final DataInput dataInput) throws IOException
281        {
282        int len = dataInput.readInt();
283        if (genome==null || genome.length != len)
284            genome = new boolean[len];
285        for(int x=0;x<genome.length;x++)
286            genome[x] = dataInput.readBoolean();
287        }
288
289    /** Implements distance as hamming distance. */
290    public double distanceTo(Individual otherInd)
291        {
292        if (!(otherInd instanceof BitVectorIndividual))
293            return super.distanceTo(otherInd);  // will return infinity!
294               
295        BitVectorIndividual other = (BitVectorIndividual) otherInd;
296        boolean[] otherGenome = other.genome;
297        double hammingDistance =0;
298        for(int i=0; i < other.genomeLength(); i++)
299            {
300            if(genome[i] ^ otherGenome[i])  //^ is xor
301                hammingDistance++;
302            }
303
304        return hammingDistance;
305        }
306
307    }
Note: See TracBrowser for help on using the repository browser.