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 | |
---|
8 | package ec.vector; |
---|
9 | |
---|
10 | import ec.*; |
---|
11 | |
---|
12 | /* |
---|
13 | * VectorIndividual.java |
---|
14 | * Created: Tue Mar 13 15:03:12 EST 2001 |
---|
15 | */ |
---|
16 | |
---|
17 | /** |
---|
18 | * VectorIndividual is the abstract superclass of simple individual representations |
---|
19 | * which consist of vectors of values (booleans, integers, floating-point, etc.) |
---|
20 | * |
---|
21 | * <p>This class contains two methods, defaultCrossover and defaultMutate, which can |
---|
22 | * be overridden if all you need is a simple crossover and a simple mutate mechanism. |
---|
23 | * the VectorCrossoverPipeline and VectorMutationPipeline classes use these methods to do their |
---|
24 | * handiwork. For more sophisticated crossover and mutation, you'll need to write |
---|
25 | * a custom breeding pipeline. |
---|
26 | * |
---|
27 | * <p>The <i>kind</i> of default crossover and mutation, and associated information, |
---|
28 | * is stored in the VectorIndividual's VectorSpecies object, which is obtained through |
---|
29 | * the <tt>species</tt> variable. For example, |
---|
30 | * VectorIndividual assumes three common types of crossover as defined in VectorSpecies |
---|
31 | * which you should implement in your defaultCrossover method: one-point, |
---|
32 | * two-point, and any-point (otherwise known as "uniform") crossover. |
---|
33 | * |
---|
34 | * <p>VectorIndividual is typically used for fixed-length vector representations; |
---|
35 | * however, it can also be used with variable-length representations. Two methods have |
---|
36 | * been provided in all subclasses of VectorIndividual to help you there: split and |
---|
37 | * join, which you can use to break up and reconnect VectorIndividuals in a variety |
---|
38 | * of ways. Note that you may want to override the reset() method to create individuals |
---|
39 | * with different initial lengths. |
---|
40 | * |
---|
41 | * <p>VectorIndividuals must belong to the species VectorSpecies (or some subclass of it). |
---|
42 | * |
---|
43 | |
---|
44 | * <P><b>From ec.Individual:</b> |
---|
45 | * |
---|
46 | * <p>In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways. |
---|
47 | * |
---|
48 | * <ul> |
---|
49 | * <li><b>writeIndividual(...,DataOutput)/readIndividual(...,DataInput)</b> This method |
---|
50 | * transmits or receives an individual in binary. It is the most efficient approach to sending |
---|
51 | * individuals over networks, etc. These methods write the evaluated flag and the fitness, then |
---|
52 | * call <b>readGenotype/writeGenotype</b>, which you must implement to write those parts of your |
---|
53 | * Individual special to your functions-- the default versions of readGenotype/writeGenotype throw errors. |
---|
54 | * You don't need to implement them if you don't plan on using read/writeIndividual. |
---|
55 | * |
---|
56 | * <li><b>printIndividual(...,PrintWriter)/readIndividual(...,LineNumberReader)</b> This |
---|
57 | * approach transmits or receives an indivdual in text encoded such that the individual is largely readable |
---|
58 | * by humans but can be read back in 100% by ECJ as well. To do this, these methods will encode numbers |
---|
59 | * using the <tt>ec.util.Code</tt> class. These methods are mostly used to write out populations to |
---|
60 | * files for inspection, slight modification, then reading back in later on. <b>readIndividual</b> reads |
---|
61 | * in the fitness and the evaluation flag, then calls <b>parseGenotype</b> to read in the remaining individual. |
---|
62 | * You are responsible for implementing parseGenotype: the Code class is there to help you. |
---|
63 | * <b>printIndividual</b> writes out the fitness and evaluation flag, then calls <b>genotypeToString</b> |
---|
64 | * and printlns the resultant string. You are responsible for implementing the genotypeToString method in such |
---|
65 | * a way that parseGenotype can read back in the individual println'd with genotypeToString. The default form |
---|
66 | * of genotypeToString simply calls <b>toString</b>, which you may override instead if you like. The default |
---|
67 | * form of <b>parseGenotype</b> throws an error. You are not required to implement these methods, but without |
---|
68 | * them you will not be able to write individuals to files in a simultaneously computer- and human-readable fashion. |
---|
69 | * |
---|
70 | * <li><b>printIndividualForHumans(...,PrintWriter)</b> This |
---|
71 | * approach prints an individual in a fashion intended for human consumption only. |
---|
72 | * <b>printIndividualForHumans</b> writes out the fitness and evaluation flag, then calls <b>genotypeToStringForHumans</b> |
---|
73 | * and printlns the resultant string. You are responsible for implementing the genotypeToStringForHumans method. |
---|
74 | * The default form of genotypeToStringForHumans simply calls <b>toString</b>, which you may override instead if you like |
---|
75 | * (though note that genotypeToString's default also calls toString). You should handle one of these methods properly |
---|
76 | * to ensure individuals can be printed by ECJ. |
---|
77 | * </ul> |
---|
78 | |
---|
79 | * <p>In general, the various readers and writers do three things: they tell the Fitness to read/write itself, |
---|
80 | * they read/write the evaluated flag, and they read/write the gene array. If you add instance variables to |
---|
81 | * a VectorIndividual or subclass, you'll need to read/write those variables as well. |
---|
82 | |
---|
83 | * @author Sean Luke |
---|
84 | * @version 1.0 |
---|
85 | */ |
---|
86 | |
---|
87 | public abstract class VectorIndividual extends Individual |
---|
88 | { |
---|
89 | /** Destructively crosses over the individual with another in some default manner. In most |
---|
90 | implementations provided in ECJ, one-, two-, and any-point crossover is done with a |
---|
91 | for loop, rather than a possibly more efficient approach like arrayCopy(). The disadvantage |
---|
92 | is that arrayCopy() takes advantage of a CPU's bulk copying. The advantage is that arrayCopy() |
---|
93 | would require a scratch array, so you'd be allocing and GCing an array for every crossover. |
---|
94 | Dunno which is more efficient. */ |
---|
95 | public void defaultCrossover(EvolutionState state, int thread, |
---|
96 | VectorIndividual ind) { } |
---|
97 | |
---|
98 | /** Destructively mutates the individual in some default manner. The default version calls reset()*/ |
---|
99 | public void defaultMutate(EvolutionState state, int thread) { reset(state,thread); } |
---|
100 | |
---|
101 | /** Initializes the individual. */ |
---|
102 | public abstract void reset(EvolutionState state, int thread); |
---|
103 | |
---|
104 | /** Returns the gene array. If you know the type of the array, you can cast it and work on |
---|
105 | it directly. Otherwise, you can still manipulate it in general, because arrays (like |
---|
106 | all objects) respond to clone() and can be manipulated with arrayCopy without bothering |
---|
107 | with their type. This might be useful in creating special generalized crossover operators |
---|
108 | -- we apologize in advance for the fact that Java doesn't have a template system. :-( |
---|
109 | The default version returns null. */ |
---|
110 | public Object getGenome() { return null; } |
---|
111 | |
---|
112 | /** Sets the gene array. See getGenome(). The default version does nothing. |
---|
113 | */ |
---|
114 | public void setGenome(Object gen) { } |
---|
115 | |
---|
116 | /** Returns the length of the gene array. By default, this method returns 0. */ |
---|
117 | public int genomeLength() { return 0; } |
---|
118 | |
---|
119 | /** Initializes the individual to a new size. Only use this if you need to initialize variable-length individuals. */ |
---|
120 | public void reset(EvolutionState state, int thread, int newSize) |
---|
121 | { |
---|
122 | setGenomeLength(newSize); |
---|
123 | reset(state, thread); |
---|
124 | } |
---|
125 | |
---|
126 | /** Sets the genome length. If the length is longer, then it is filled with a default value (likely 0 or false). |
---|
127 | This may or may not be a valid value -- you will need to set appropriate values here. |
---|
128 | The default implementation does nothing; but all subclasses in ECJ implement a subset of this. */ |
---|
129 | public void setGenomeLength(int len) { } |
---|
130 | |
---|
131 | /** Splits the genome into n pieces, according to points, which *must* be sorted. |
---|
132 | pieces.length must be 1 + points.length. The default form does nothing -- be careful |
---|
133 | not to use this method if it's not implemented! It should be trivial to implement it |
---|
134 | for your genome -- just like at the other implementations. */ |
---|
135 | public void split(int[] points, Object[] pieces) { } |
---|
136 | |
---|
137 | /** Joins the n pieces and sets the genome to their concatenation. The default form does nothing. |
---|
138 | It should be trivial to implement it |
---|
139 | for your genome -- just like at the other implementations. */ |
---|
140 | public void join(Object[] pieces) { } |
---|
141 | |
---|
142 | /** Clones the genes in pieces, and replaces the genes with their copies. Does NOT copy the array, but modifies it in place. |
---|
143 | If the VectorIndividual holds numbers or booleans etc. instead of genes, nothing is cloned |
---|
144 | (why bother?). */ |
---|
145 | public void cloneGenes(Object piece) { } // default does nothing. |
---|
146 | |
---|
147 | public long size() { return genomeLength(); } |
---|
148 | } |
---|