[6152] | 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.rule; |
---|
| 9 | import ec.*; |
---|
| 10 | import ec.util.*; |
---|
| 11 | import java.io.*; |
---|
| 12 | |
---|
| 13 | /* |
---|
| 14 | * RuleIndividual.java |
---|
| 15 | * |
---|
| 16 | * Created: Tue May 29 18:20:20 EDT 2001 |
---|
| 17 | * By: Sean Luke |
---|
| 18 | */ |
---|
| 19 | |
---|
| 20 | /** |
---|
| 21 | * RuleIndividual is an Individual with an array of RuleSets, each of which |
---|
| 22 | * is a set of Rules. RuleIndividuals belong to some subclass of RuleSpecies |
---|
| 23 | * (or just RuleSpecies itself). |
---|
| 24 | * |
---|
| 25 | * <p>RuleIndividuals really have basically one parameter: the number |
---|
| 26 | * of RuleSets to use. This is determined by the <tt>num-rulesets</tt> |
---|
| 27 | * parameter. |
---|
| 28 | |
---|
| 29 | * <P><b>From ec.Individual:</b> |
---|
| 30 | * |
---|
| 31 | * <p>In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways. |
---|
| 32 | * |
---|
| 33 | * <ul> |
---|
| 34 | * <li><b>writeIndividual(...,DataOutput)/readIndividual(...,DataInput)</b> This method |
---|
| 35 | * transmits or receives an individual in binary. It is the most efficient approach to sending |
---|
| 36 | * individuals over networks, etc. These methods write the evaluated flag and the fitness, then |
---|
| 37 | * call <b>readGenotype/writeGenotype</b>, which you must implement to write those parts of your |
---|
| 38 | * Individual special to your functions-- the default versions of readGenotype/writeGenotype throw errors. |
---|
| 39 | * You don't need to implement them if you don't plan on using read/writeIndividual. |
---|
| 40 | * |
---|
| 41 | * <li><b>printIndividual(...,PrintWriter)/readIndividual(...,LineNumberReader)</b> This |
---|
| 42 | * approach transmits or receives an indivdual in text encoded such that the individual is largely readable |
---|
| 43 | * by humans but can be read back in 100% by ECJ as well. To do this, these methods will encode numbers |
---|
| 44 | * using the <tt>ec.util.Code</tt> class. These methods are mostly used to write out populations to |
---|
| 45 | * files for inspection, slight modification, then reading back in later on. <b>readIndividual</b>reads |
---|
| 46 | * in the fitness and the evaluation flag, then calls <b>parseGenotype</b> to read in the remaining individual. |
---|
| 47 | * You are responsible for implementing parseGenotype: the Code class is there to help you. |
---|
| 48 | * <b>printIndividual</b> writes out the fitness and evaluation flag, then calls <b>genotypeToString<b> |
---|
| 49 | * and printlns the resultant string. You are responsible for implementing the genotypeToString method in such |
---|
| 50 | * a way that parseGenotype can read back in the individual println'd with genotypeToString. The default form |
---|
| 51 | * of genotypeToString simply calls <b>toString</b>, which you may override instead if you like. The default |
---|
| 52 | * form of <b>parseGenotype</b> throws an error. You are not required to implement these methods, but without |
---|
| 53 | * them you will not be able to write individuals to files in a simultaneously computer- and human-readable fashion. |
---|
| 54 | * |
---|
| 55 | * <li><b>printIndividualForHumans(...,PrintWriter)</b> This |
---|
| 56 | * approach prints an individual in a fashion intended for human consumption only. |
---|
| 57 | * <b>printIndividualForHumans</b> writes out the fitness and evaluation flag, then calls <b>genotypeToStringForHumans<b> |
---|
| 58 | * and printlns the resultant string. You are responsible for implementing the genotypeToStringForHumans method. |
---|
| 59 | * The default form of genotypeToStringForHumans simply calls <b>toString</b>, which you may override instead if you like |
---|
| 60 | * (though note that genotypeToString's default also calls toString). You should handle one of these methods properly |
---|
| 61 | * to ensure individuals can be printed by ECJ. |
---|
| 62 | * </ul> |
---|
| 63 | |
---|
| 64 | * <p>In general, the various readers and writers do three things: they tell the Fitness to read/write itself, |
---|
| 65 | * they read/write the evaluated flag, and they read/write the Rulesets. If you add instance variables to |
---|
| 66 | * a RuleIndividual or subclass, you'll need to read/write those variables as well. |
---|
| 67 | |
---|
| 68 | <p><b>Parameters</b><br> |
---|
| 69 | <table> |
---|
| 70 | <tr><td valign=top><i>base</i>.<tt>num-rulesets</tt><br> |
---|
| 71 | <font size=-1>int >= 1</font></td> |
---|
| 72 | <td valign=top>(number of rulesets used)</td></tr> |
---|
| 73 | <tr><td valign=top><i>base</i>.<tt>ruleset</tt>.<i>n</i><br> |
---|
| 74 | <font size=-1>Classname, subclass of or = ec.rule.RuleSet</font></td> |
---|
| 75 | <td valign=top>(class of ruleset <i>n</i>)</td></tr> |
---|
| 76 | </table> |
---|
| 77 | |
---|
| 78 | <p><b>Parameter bases</b><br> |
---|
| 79 | <table> |
---|
| 80 | <tr><td valign=top><i>base</i>.<tt>ruleset</tt>.<i>n</i><br> |
---|
| 81 | <td>RuleSet <i>n</i></td></tr> |
---|
| 82 | </table> |
---|
| 83 | |
---|
| 84 | <p><b>Default Base</b><br> |
---|
| 85 | rule.individual |
---|
| 86 | |
---|
| 87 | * @author Sean Luke |
---|
| 88 | * @version 1.0 |
---|
| 89 | */ |
---|
| 90 | public class RuleIndividual extends Individual |
---|
| 91 | { |
---|
| 92 | public static final String P_RULESET = "ruleset"; |
---|
| 93 | public static final String P_NUMRULESETS = "num-rulesets"; |
---|
| 94 | |
---|
| 95 | /** The individual's rulesets. */ |
---|
| 96 | public RuleSet[] rulesets; |
---|
| 97 | |
---|
| 98 | public Parameter defaultBase() |
---|
| 99 | { |
---|
| 100 | return RuleDefaults.base().push(P_INDIVIDUAL); |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | public Object clone() |
---|
| 104 | { |
---|
| 105 | RuleIndividual myobj = (RuleIndividual) (super.clone()); |
---|
| 106 | myobj.rulesets = new RuleSet[rulesets.length]; |
---|
| 107 | for(int x=0;x<rulesets.length;x++) |
---|
| 108 | myobj.rulesets[x] = (RuleSet)(rulesets[x].clone()); |
---|
| 109 | return myobj; |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | /** Called by pipelines before they've modified the individual and |
---|
| 113 | it might need to be "fixed" -- basically a hook for you to override. |
---|
| 114 | By default, calls validateRules on each ruleset. */ |
---|
| 115 | public void preprocessIndividual(final EvolutionState state, final int thread) |
---|
| 116 | { |
---|
| 117 | for (int x=0;x<rulesets.length;x++) |
---|
| 118 | rulesets[x].preprocessRules(state,thread); |
---|
| 119 | } |
---|
| 120 | |
---|
| 121 | /** Called by pipelines after they've modified the individual and |
---|
| 122 | it might need to be "fixed" -- basically a hook for you to override. |
---|
| 123 | By default, calls validateRules on each ruleset. */ |
---|
| 124 | public void postprocessIndividual(final EvolutionState state, final int thread) |
---|
| 125 | { |
---|
| 126 | for (int x=0;x<rulesets.length;x++) |
---|
| 127 | rulesets[x].postprocessRules(state,thread); |
---|
| 128 | } |
---|
| 129 | |
---|
| 130 | public boolean equals(Object ind) |
---|
| 131 | { |
---|
| 132 | // My loose definition: ind must be a |
---|
| 133 | if (!getClass().equals(ind.getClass())) // not the same class, I'm conservative that way |
---|
| 134 | return false; |
---|
| 135 | |
---|
| 136 | RuleIndividual other = (RuleIndividual)ind; |
---|
| 137 | if (rulesets.length != other.rulesets.length) return false; |
---|
| 138 | for(int x=0;x<rulesets.length;x++) |
---|
| 139 | if (!rulesets[x].equals(other.rulesets[x])) return false; |
---|
| 140 | return true; |
---|
| 141 | } |
---|
| 142 | |
---|
| 143 | public int hashCode() |
---|
| 144 | { |
---|
| 145 | int hash = this.getClass().hashCode(); |
---|
| 146 | for(int x=0;x<rulesets.length;x++) |
---|
| 147 | // rotate hash and XOR |
---|
| 148 | hash = |
---|
| 149 | (hash << 1 | hash >>> 31 ) ^ rulesets[x].hashCode(); |
---|
| 150 | return hash; |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | public void setup(final EvolutionState state, final Parameter base) |
---|
| 154 | { |
---|
| 155 | super.setup(state,base); // actually unnecessary (Individual.setup() is empty) |
---|
| 156 | |
---|
| 157 | // I'm the top-level setup, I guess |
---|
| 158 | int numrulesets = state.parameters.getInt( |
---|
| 159 | base.push(P_NUMRULESETS), defaultBase().push(P_NUMRULESETS), |
---|
| 160 | 1); // need at least 1 ruleset! |
---|
| 161 | if (numrulesets == 0) |
---|
| 162 | state.output.fatal("RuleIndividual needs at least one RuleSet!", |
---|
| 163 | base.push(P_NUMRULESETS), defaultBase().push(P_NUMRULESETS)); |
---|
| 164 | |
---|
| 165 | rulesets = new RuleSet[numrulesets]; |
---|
| 166 | |
---|
| 167 | for(int x=0;x<numrulesets;x++) |
---|
| 168 | { |
---|
| 169 | rulesets[x] = (RuleSet)(state.parameters.getInstanceForParameterEq( |
---|
| 170 | base.push(P_RULESET).push(""+x),defaultBase().push(P_RULESET), |
---|
| 171 | RuleSet.class)); |
---|
| 172 | rulesets[x].setup(state,base.push(P_RULESET).push(""+x)); |
---|
| 173 | } |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | public void printIndividualForHumans(final EvolutionState state, |
---|
| 177 | final int log) |
---|
| 178 | { |
---|
| 179 | state.output.println(EVALUATED_PREAMBLE + (evaluated ? "true" : "false"), log); |
---|
| 180 | fitness.printFitnessForHumans(state,log); |
---|
| 181 | for(int x=0;x<rulesets.length;x++) |
---|
| 182 | { |
---|
| 183 | state.output.println("Ruleset " + x + ":", log); |
---|
| 184 | rulesets[x].printRuleSetForHumans(state, log); |
---|
| 185 | } |
---|
| 186 | } |
---|
| 187 | |
---|
| 188 | public void printIndividual(final EvolutionState state, |
---|
| 189 | final int log) |
---|
| 190 | { |
---|
| 191 | state.output.println(EVALUATED_PREAMBLE + Code.encode(evaluated), log); |
---|
| 192 | fitness.printFitness(state, log); |
---|
| 193 | for(int x=0;x<rulesets.length;x++) |
---|
| 194 | { |
---|
| 195 | state.output.println("Ruleset " + x + ":", log); |
---|
| 196 | rulesets[x].printRuleSet(state,log); |
---|
| 197 | } |
---|
| 198 | } |
---|
| 199 | |
---|
| 200 | /** Overridden for the RuleIndividual genotype, writing each ruleset in turn. */ |
---|
| 201 | public void printIndividual(final EvolutionState state, |
---|
| 202 | final PrintWriter writer) |
---|
| 203 | { |
---|
| 204 | writer.println(EVALUATED_PREAMBLE + Code.encode(evaluated)); |
---|
| 205 | fitness.printFitness(state,writer); |
---|
| 206 | for(int x=0;x<rulesets.length;x++) |
---|
| 207 | { |
---|
| 208 | writer.println("Ruleset " + x + ":"); |
---|
| 209 | rulesets[x].printRuleSet(state,writer); |
---|
| 210 | } |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | /** Overridden for the RuleIndividual genotype, writing each ruleset in turn. */ |
---|
| 214 | public void writeGenotype(final EvolutionState state, |
---|
| 215 | final DataOutput dataOutput) throws IOException |
---|
| 216 | { |
---|
| 217 | dataOutput.writeInt(rulesets.length); |
---|
| 218 | for(int x=0;x<rulesets.length;x++) |
---|
| 219 | rulesets[x].writeRuleSet(state,dataOutput); |
---|
| 220 | } |
---|
| 221 | |
---|
| 222 | /** Overridden for the RuleIndividual genotype. */ |
---|
| 223 | public void readGenotype(final EvolutionState state, |
---|
| 224 | final DataInput dataInput) throws IOException |
---|
| 225 | { |
---|
| 226 | int len = dataInput.readInt(); |
---|
| 227 | if (rulesets==null || rulesets.length != len) |
---|
| 228 | state.output.fatal("Number of RuleSets differ in RuleIndividual when reading from readGenotype(EvolutionState, DataInput)."); |
---|
| 229 | for(int x=0;x<rulesets.length;x++) |
---|
| 230 | rulesets[x].readRuleSet(state,dataInput); |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | |
---|
| 234 | /** Overridden for the RuleIndividual genotype. */ |
---|
| 235 | public void parseGenotype(final EvolutionState state, |
---|
| 236 | final LineNumberReader reader) |
---|
| 237 | throws IOException |
---|
| 238 | { |
---|
| 239 | // read my ruleset |
---|
| 240 | for(int x=0;x<rulesets.length;x++) |
---|
| 241 | { |
---|
| 242 | reader.readLine(); // throw it away -- it's the ruleset# indicator |
---|
| 243 | rulesets[x].readRuleSet(state,reader); |
---|
| 244 | } |
---|
| 245 | } |
---|
| 246 | |
---|
| 247 | public long size() |
---|
| 248 | { |
---|
| 249 | long size=0; |
---|
| 250 | for(int x=0;x<rulesets.length;x++) |
---|
| 251 | size+= rulesets[x].numRules(); |
---|
| 252 | return size; |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | public void reset(EvolutionState state, int thread) |
---|
| 256 | { |
---|
| 257 | for(int x=0;x<rulesets.length;x++) |
---|
| 258 | rulesets[x].reset(state,thread); |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | /** Mutates the Individual. The default implementation simply calls mutate(...) on each of |
---|
| 262 | the RuleSets. */ |
---|
| 263 | public void mutate(EvolutionState state, int thread) |
---|
| 264 | { |
---|
| 265 | for(int x=0;x<rulesets.length;x++) |
---|
| 266 | rulesets[x].mutate(state,thread); |
---|
| 267 | } |
---|
| 268 | } |
---|
| 269 | |
---|