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 | package ec.multiobjective; |
---|
8 | |
---|
9 | import java.io.*; |
---|
10 | import ec.util.DecodeReturn; |
---|
11 | import ec.util.Parameter; |
---|
12 | import ec.util.Code; |
---|
13 | import ec.Fitness; |
---|
14 | import ec.EvolutionState; |
---|
15 | import java.util.*; |
---|
16 | import ec.*; |
---|
17 | |
---|
18 | /* |
---|
19 | * MultiObjectiveFitness.java |
---|
20 | * |
---|
21 | * Created: Tue Aug 10 20:27:38 1999 |
---|
22 | * By: Sean Luke |
---|
23 | */ |
---|
24 | |
---|
25 | /** |
---|
26 | * MultiObjectiveFitness is a subclass of Fitness which implements basic |
---|
27 | * multi-objective mechanisms suitable for being used with a variety of |
---|
28 | * multi-objective selection mechanisms, including ones using pareto-optimality. |
---|
29 | * |
---|
30 | * <p> |
---|
31 | * The object contains two items: an array of floating point values representing |
---|
32 | * the various multiple fitnesses, and a flag (maximize) indicating whether |
---|
33 | * higher is considered better. By default, isIdealFitness() always returns |
---|
34 | * false; you might want to override that, though it'd be unusual -- what is the |
---|
35 | * ideal fitness from the perspective of a pareto front? |
---|
36 | * |
---|
37 | * <p> |
---|
38 | * The object also contains maximum and minimum fitness values suggested for the |
---|
39 | * problem, on a per-objective basis. By default the maximum values are all 1.0 |
---|
40 | * and the minimum values are all 0.0, but you can change these. Note that |
---|
41 | * maximum does not mean "best" unless maximize is true. |
---|
42 | * |
---|
43 | * <p>The class also contains utility methods or computing pareto dominance, |
---|
44 | * Pareto Fronts and Pareto Front Ranks, and distance in multiobjective space. |
---|
45 | * The default comparison operators use Pareto Dominance, though this is often |
---|
46 | * overridden by subclasses. |
---|
47 | * |
---|
48 | * <p>The fitness() method returns the maximum of the fitness values, which is |
---|
49 | * clearly nonsensical: you should not be using this method. |
---|
50 | * |
---|
51 | * <p>Subclasses of this class may add certain auxiliary fitness measures which |
---|
52 | * are printed out by MultiObjectiveStatistics along with the multiple objectives. |
---|
53 | * To have these values printed out, override the getAuxiliaryFitnessNames() |
---|
54 | * and getAuxiliaryFitnessValues() methods. |
---|
55 | * |
---|
56 | * <p> |
---|
57 | * <b>Parameters</b><br> |
---|
58 | * <table> |
---|
59 | * <tr> |
---|
60 | * <td valign=top><i>base</i>.<tt>num-objectives</tt><br> |
---|
61 | * (else)<tt>multi.num-objectives</tt><br> |
---|
62 | * <font size=-1>int >= 1</font></td> |
---|
63 | * <td valign=top>(the number of fitnesses in the objectives array)</td> |
---|
64 | * </tr> |
---|
65 | * |
---|
66 | * <tr> |
---|
67 | * <td valign=top><i>base</i>.<tt>maximize</tt><br> |
---|
68 | * <font size=-1> bool = <tt>true</tt> (default) or <tt>false</tt></font></td> |
---|
69 | * <td valign=top>(are higher values considered "better"?) |
---|
70 | * </table> |
---|
71 | * |
---|
72 | * <tr> |
---|
73 | * <td valign=top><i>base</i>.<tt>max</tt><br> |
---|
74 | * <font size=-1> float (<tt>1.0</tt> default)</font></td> |
---|
75 | * <td valign=top>(maximum fitness value for all objectives)</table> |
---|
76 | * |
---|
77 | * <tr> |
---|
78 | * <td valign=top><i>base</i>.<tt>max</tt>.<i>i</i><br> |
---|
79 | * <font size=-1> float (<tt>1.0</tt> default)</font></td> |
---|
80 | * <td valign=top>(maximum fitness value for objective <i>i</i>. Overrides the |
---|
81 | * all-objective maximum fitness.)</table> |
---|
82 | * |
---|
83 | * <tr> |
---|
84 | * <td valign=top><i>base</i>.<tt>min</tt><br> |
---|
85 | * <font size=-1> float (<tt>0.0</tt> (default)</font></td> |
---|
86 | * <td valign=top>(minimum fitness value for all objectives)</table> |
---|
87 | * |
---|
88 | * <tr> |
---|
89 | * <td valign=top><i>base</i>.<tt>min</tt>.<i>i</i><br> |
---|
90 | * <font size=-1> float = <tt>0.0</tt> (default)</font></td> |
---|
91 | * <td valign=top>(minimum fitness value for objective <i>i</i>. Overrides the |
---|
92 | * all-objective minimum fitness.)</table> |
---|
93 | * |
---|
94 | * <p> |
---|
95 | * <b>Default Base</b><br> |
---|
96 | * multi.fitness |
---|
97 | * |
---|
98 | * @author Sean Luke |
---|
99 | * @version 1.1 |
---|
100 | */ |
---|
101 | |
---|
102 | public class MultiObjectiveFitness extends Fitness |
---|
103 | { |
---|
104 | public static final String MULTI_FITNESS_POSTAMBLE = "["; |
---|
105 | public static final String FITNESS_POSTAMBLE = "]"; |
---|
106 | |
---|
107 | /** parameter for size of objectives */ |
---|
108 | public static final String P_NUMOBJECTIVES = "num-objectives"; |
---|
109 | |
---|
110 | /** parameter for max fitness values */ |
---|
111 | public static final String P_MAXOBJECTIVES = "max"; |
---|
112 | |
---|
113 | /** parameter for min fitness values */ |
---|
114 | public static final String P_MINOBJECTIVES = "min"; |
---|
115 | |
---|
116 | /** Is higher better? */ |
---|
117 | public static final String P_MAXIMIZE = "maximize"; |
---|
118 | |
---|
119 | /** Desired maximum fitness values. By default these are 1.0. Shared. */ |
---|
120 | public float[] maxObjective; |
---|
121 | |
---|
122 | /** Desired minimum fitness values. By default these are 0.0. Shared. */ |
---|
123 | public float[] minObjective; |
---|
124 | |
---|
125 | /** The various fitnesses. */ |
---|
126 | protected float[] objectives; // values range from 0 (worst) to 1 INCLUSIVE |
---|
127 | protected boolean maximize = true; |
---|
128 | |
---|
129 | /** Returns auxilliary fitness value names to be printed by the statistics object. |
---|
130 | By default, an empty array is returned, but various algorithms may override this to provide additional columns. |
---|
131 | */ |
---|
132 | public String[] getAuxilliaryFitnessNames() { return new String[] { }; } |
---|
133 | |
---|
134 | /** Returns auxilliary fitness values to be printed by the statistics object. |
---|
135 | By default, an empty array is returned, but various algorithms may override this to provide additional columns. |
---|
136 | */ |
---|
137 | public double[] getAuxilliaryFitnessValues() { return new double[] { }; } |
---|
138 | |
---|
139 | public boolean isMaximizing() |
---|
140 | { |
---|
141 | return maximize; |
---|
142 | } |
---|
143 | |
---|
144 | |
---|
145 | public int getNumObjectives() { return objectives.length; } |
---|
146 | |
---|
147 | /** |
---|
148 | * Returns the objectives as an array. Note that this is the *actual array*. |
---|
149 | * Though you could set values in this array, you should NOT do this -- |
---|
150 | * rather, set them using setObjectives(). |
---|
151 | */ |
---|
152 | public float[] getObjectives() |
---|
153 | { |
---|
154 | return objectives; |
---|
155 | } |
---|
156 | |
---|
157 | public float getObjective(int i) |
---|
158 | { |
---|
159 | return objectives[i]; |
---|
160 | } |
---|
161 | |
---|
162 | public void setObjectives(final EvolutionState state, float[] newObjectives) |
---|
163 | { |
---|
164 | if (newObjectives == null) |
---|
165 | { |
---|
166 | state.output.fatal("Null objective array provided to MultiObjectiveFitness."); |
---|
167 | } |
---|
168 | if (newObjectives.length != objectives.length) |
---|
169 | { |
---|
170 | state.output.fatal("New objective array length does not match current length."); |
---|
171 | } |
---|
172 | for (int i = 0; i < newObjectives.length; i++) |
---|
173 | { |
---|
174 | float _f = newObjectives[i]; |
---|
175 | if (_f == Float.POSITIVE_INFINITY || _f == Float.NEGATIVE_INFINITY || Float.isNaN(_f)) |
---|
176 | { |
---|
177 | state.output.warning("Bad objective #" + i + ": " + _f + ", setting to worst value for that objective."); |
---|
178 | if (maximize) |
---|
179 | newObjectives[i] = minObjective[i]; |
---|
180 | else |
---|
181 | newObjectives[i] = maxObjective[i]; |
---|
182 | } |
---|
183 | } |
---|
184 | objectives = newObjectives; |
---|
185 | } |
---|
186 | |
---|
187 | public Parameter defaultBase() |
---|
188 | { |
---|
189 | return MultiObjectiveDefaults.base().push(P_FITNESS); |
---|
190 | } |
---|
191 | |
---|
192 | public Object clone() |
---|
193 | { |
---|
194 | MultiObjectiveFitness f = (MultiObjectiveFitness) (super.clone()); |
---|
195 | f.objectives = (float[]) (objectives.clone()); // cloning an array |
---|
196 | |
---|
197 | // note that we do NOT clone max and min fitness -- they're shared |
---|
198 | return f; |
---|
199 | } |
---|
200 | |
---|
201 | /** |
---|
202 | * Returns the Max() of objectives, which adheres to Fitness.java's protocol |
---|
203 | * for this method. Though you should not rely on a selection or statistics |
---|
204 | * method which requires this. |
---|
205 | */ |
---|
206 | public float fitness() |
---|
207 | { |
---|
208 | float fit = objectives[0]; |
---|
209 | for (int x = 1; x < objectives.length; x++) |
---|
210 | if (fit < objectives[x]) |
---|
211 | fit = objectives[x]; |
---|
212 | return fit; |
---|
213 | } |
---|
214 | |
---|
215 | /** |
---|
216 | * Sets up. This must be called at least once in the prototype before |
---|
217 | * instantiating any fitnesses that will actually be used in evolution. |
---|
218 | */ |
---|
219 | |
---|
220 | public void setup(EvolutionState state, Parameter base) |
---|
221 | { |
---|
222 | super.setup(state, base); // unnecessary really |
---|
223 | |
---|
224 | Parameter def = defaultBase(); |
---|
225 | int numFitnesses; |
---|
226 | |
---|
227 | numFitnesses = state.parameters.getInt(base.push(P_NUMOBJECTIVES), def.push(P_NUMOBJECTIVES), 0); |
---|
228 | if (numFitnesses <= 0) |
---|
229 | state.output.fatal("The number of objectives must be an integer >= 1.", base.push(P_NUMOBJECTIVES), def.push(P_NUMOBJECTIVES)); |
---|
230 | |
---|
231 | maximize = state.parameters.getBoolean(base.push(P_MAXIMIZE), def.push(P_MAXIMIZE), true); |
---|
232 | |
---|
233 | objectives = new float[numFitnesses]; |
---|
234 | maxObjective = new float[numFitnesses]; |
---|
235 | minObjective = new float[numFitnesses]; |
---|
236 | |
---|
237 | for (int i = 0; i < numFitnesses; i++) |
---|
238 | { |
---|
239 | // load default globals |
---|
240 | minObjective[i] = state.parameters.getFloatWithDefault(base.push(P_MINOBJECTIVES), def.push(P_MINOBJECTIVES), 0.0f); |
---|
241 | maxObjective[i] = state.parameters.getFloatWithDefault(base.push(P_MAXOBJECTIVES), def.push(P_MAXOBJECTIVES), 1.0f); |
---|
242 | |
---|
243 | // load specifics if any |
---|
244 | minObjective[i] = state.parameters.getFloatWithDefault(base.push(P_MINOBJECTIVES).push("" + i), def.push(P_MINOBJECTIVES).push("" + i), minObjective[i]); |
---|
245 | maxObjective[i] = state.parameters.getFloatWithDefault(base.push(P_MAXOBJECTIVES).push("" + i), def.push(P_MAXOBJECTIVES).push("" + i), maxObjective[i]); |
---|
246 | |
---|
247 | // test for validity |
---|
248 | if (minObjective[i] >= maxObjective[i]) |
---|
249 | state.output.error("For objective " + i + "the min fitness must be strictly less than the max fitness."); |
---|
250 | } |
---|
251 | state.output.exitIfErrors(); |
---|
252 | } |
---|
253 | |
---|
254 | /** |
---|
255 | * Returns true if this fitness is the "ideal" fitness. Default always |
---|
256 | * returns false. You may want to override this. |
---|
257 | */ |
---|
258 | public boolean isIdealFitness() |
---|
259 | { |
---|
260 | return false; |
---|
261 | } |
---|
262 | |
---|
263 | /** |
---|
264 | * Returns true if I'm equivalent in fitness (neither better nor worse) to |
---|
265 | * _fitness. The rule I'm using is this: If one of us is better in one or |
---|
266 | * more criteria, and we are equal in the others, then equivalentTo is |
---|
267 | * false. If each of us is better in one or more criteria each, or we are |
---|
268 | * equal in all criteria, then equivalentTo is true. Multiobjective optimization algorithms may |
---|
269 | * choose to override this to do something else. |
---|
270 | */ |
---|
271 | |
---|
272 | public boolean equivalentTo(Fitness _fitness) |
---|
273 | { |
---|
274 | MultiObjectiveFitness other = (MultiObjectiveFitness) _fitness; |
---|
275 | boolean abeatsb = false; |
---|
276 | boolean bbeatsa = false; |
---|
277 | |
---|
278 | if (maximize != other.maximize) |
---|
279 | throw new RuntimeException( |
---|
280 | "Attempt made to compare two multiobjective fitnesses; but one expects higher values to be better and the other expectes lower values to be better."); |
---|
281 | if (objectives.length != other.objectives.length) |
---|
282 | throw new RuntimeException("Attempt made to compare two multiobjective fitnesses; but they have different numbers of objectives."); |
---|
283 | if (maximize) |
---|
284 | { |
---|
285 | for (int x = 0; x < objectives.length; x++) |
---|
286 | { |
---|
287 | if (objectives[x] > other.objectives[x]) |
---|
288 | abeatsb = true; |
---|
289 | if (objectives[x] < other.objectives[x]) |
---|
290 | bbeatsa = true; |
---|
291 | if (abeatsb && bbeatsa) |
---|
292 | return true; |
---|
293 | } |
---|
294 | } |
---|
295 | else |
---|
296 | // lower is better |
---|
297 | { |
---|
298 | for (int x = 0; x < objectives.length; x++) |
---|
299 | { |
---|
300 | if (objectives[x] < other.objectives[x]) |
---|
301 | abeatsb = true; |
---|
302 | if (objectives[x] > other.objectives[x]) |
---|
303 | bbeatsa = true; |
---|
304 | if (abeatsb && bbeatsa) |
---|
305 | return true; |
---|
306 | } |
---|
307 | } |
---|
308 | if (abeatsb || bbeatsa) |
---|
309 | return false; |
---|
310 | return true; |
---|
311 | } |
---|
312 | |
---|
313 | /** |
---|
314 | * Returns true if I'm better than _fitness. The DEFAULT rule I'm using is this: if |
---|
315 | * I am better in one or more criteria, and we are equal in the others, then |
---|
316 | * betterThan is true, else it is false. Multiobjective optimization algorithms may |
---|
317 | * choose to override this to do something else. |
---|
318 | */ |
---|
319 | |
---|
320 | public boolean betterThan(Fitness fitness) |
---|
321 | { |
---|
322 | return paretoDominates((MultiObjectiveFitness)fitness); |
---|
323 | } |
---|
324 | |
---|
325 | /** |
---|
326 | * Returns true if I'm better than _fitness. The rule I'm using is this: if |
---|
327 | * I am better in one or more criteria, and we are equal in the others, then |
---|
328 | * betterThan is true, else it is false. |
---|
329 | */ |
---|
330 | |
---|
331 | public boolean paretoDominates(MultiObjectiveFitness other) |
---|
332 | { |
---|
333 | boolean abeatsb = false; |
---|
334 | if (maximize != other.maximize) |
---|
335 | throw new RuntimeException( |
---|
336 | "Attempt made to compare two multiobjective fitnesses; but one expects higher values to be better and the other expectes lower values to be better."); |
---|
337 | if (objectives.length != other.objectives.length) |
---|
338 | throw new RuntimeException("Attempt made to compare two multiobjective fitnesses; but they have different numbers of objectives."); |
---|
339 | if (maximize) |
---|
340 | { |
---|
341 | for (int x = 0; x < objectives.length; x++) |
---|
342 | { |
---|
343 | if (objectives[x] > other.objectives[x]) |
---|
344 | abeatsb = true; |
---|
345 | else if (objectives[x] < other.objectives[x]) |
---|
346 | return false; |
---|
347 | } |
---|
348 | } |
---|
349 | else |
---|
350 | { |
---|
351 | for (int x = 0; x < objectives.length; x++) |
---|
352 | { |
---|
353 | if (objectives[x] < other.objectives[x]) |
---|
354 | abeatsb = true; |
---|
355 | else if (objectives[x] > other.objectives[x]) |
---|
356 | return false; |
---|
357 | } |
---|
358 | } |
---|
359 | return abeatsb; |
---|
360 | } |
---|
361 | |
---|
362 | // Remove an individual from the ArrayList, shifting the topmost |
---|
363 | // individual in his place |
---|
364 | static void yank(int val, ArrayList list) |
---|
365 | { |
---|
366 | int size = list.size(); |
---|
367 | list.set(val, list.get(size - 1)); |
---|
368 | list.remove(size - 1); |
---|
369 | } |
---|
370 | |
---|
371 | /** |
---|
372 | * Divides an array of Individuals into the Pareto front and the "nonFront" (everyone else). |
---|
373 | * The Pareto front is returned. You may provide ArrayLists for the front and a nonFront. |
---|
374 | * If you provide null for the front, an ArrayList will be created for you. If you provide |
---|
375 | * null for the nonFront, non-front individuals will not be added to it. This algorithm is |
---|
376 | * O(n^2). |
---|
377 | */ |
---|
378 | public static ArrayList partitionIntoParetoFront(Individual[] inds, ArrayList front, ArrayList nonFront) |
---|
379 | { |
---|
380 | if (front == null) |
---|
381 | front = new ArrayList(); |
---|
382 | |
---|
383 | // put the first guy in the front |
---|
384 | front.add(inds[0]); |
---|
385 | |
---|
386 | // iterate over all the remaining individuals |
---|
387 | for (int i = 1; i < inds.length; i++) |
---|
388 | { |
---|
389 | Individual ind = (Individual) (inds[i]); |
---|
390 | |
---|
391 | boolean noOneWasBetter = true; |
---|
392 | int frontSize = front.size(); |
---|
393 | |
---|
394 | // iterate over the entire front |
---|
395 | for (int j = 0; j < frontSize; j++) |
---|
396 | { |
---|
397 | Individual frontmember = (Individual) (front.get(j)); |
---|
398 | |
---|
399 | // if the front member is better than the individual, dump the individual and go to the next one |
---|
400 | if (((MultiObjectiveFitness) (frontmember.fitness)).paretoDominates((MultiObjectiveFitness) (ind.fitness))) |
---|
401 | { |
---|
402 | if (nonFront != null) nonFront.add(ind); |
---|
403 | noOneWasBetter = false; |
---|
404 | break; // failed. He's not in the front |
---|
405 | } |
---|
406 | // if the individual was better than the front member, dump the front member. But look over the |
---|
407 | // other front members (don't break) because others might be dominated by the individual as well. |
---|
408 | else if (((MultiObjectiveFitness) (ind.fitness)).paretoDominates((MultiObjectiveFitness) (frontmember.fitness))) |
---|
409 | { |
---|
410 | yank(j, front); |
---|
411 | // a front member is dominated by the new individual. Replace him |
---|
412 | frontSize--; // member got removed |
---|
413 | j--; // because there's another guy we now need to consider in his place |
---|
414 | if (nonFront != null) nonFront.add(frontmember); |
---|
415 | } |
---|
416 | } |
---|
417 | if (noOneWasBetter) |
---|
418 | front.add(ind); |
---|
419 | } |
---|
420 | return front; |
---|
421 | } |
---|
422 | |
---|
423 | |
---|
424 | /** Divides inds into pareto front ranks (each an ArrayList), and returns them, in order, |
---|
425 | stored in an ArrayList. */ |
---|
426 | public static ArrayList partitionIntoRanks(Individual[] inds) |
---|
427 | { |
---|
428 | Individual[] dummy = new Individual[0]; |
---|
429 | ArrayList frontsByRank = new ArrayList(); |
---|
430 | |
---|
431 | while(inds.length > 0) |
---|
432 | { |
---|
433 | ArrayList front = new ArrayList(); |
---|
434 | ArrayList nonFront = new ArrayList(); |
---|
435 | MultiObjectiveFitness.partitionIntoParetoFront(inds, front, nonFront); |
---|
436 | |
---|
437 | // build inds out of remainder |
---|
438 | inds = (Individual[]) nonFront.toArray(dummy); |
---|
439 | frontsByRank.add(front); |
---|
440 | } |
---|
441 | return frontsByRank; |
---|
442 | } |
---|
443 | |
---|
444 | |
---|
445 | /** |
---|
446 | * Returns the sum of the squared difference between two Fitnesses in Objective space. |
---|
447 | */ |
---|
448 | public double sumSquaredObjectiveDistance(MultiObjectiveFitness other) |
---|
449 | { |
---|
450 | double s = 0; |
---|
451 | for (int i = 0; i < objectives.length; i++) |
---|
452 | { |
---|
453 | double a = (objectives[i] - other.objectives[i]); |
---|
454 | s += a * a; |
---|
455 | } |
---|
456 | return s; |
---|
457 | } |
---|
458 | |
---|
459 | |
---|
460 | /** |
---|
461 | * Returns the Manhattan difference between two Fitnesses in Objective space. |
---|
462 | */ |
---|
463 | public double manhattanObjectiveDistance(MultiObjectiveFitness other) |
---|
464 | { |
---|
465 | double s = 0; |
---|
466 | for (int i = 0; i < objectives.length; i++) |
---|
467 | { |
---|
468 | s += Math.abs(objectives[i] - other.objectives[i]); |
---|
469 | } |
---|
470 | return s; |
---|
471 | } |
---|
472 | |
---|
473 | |
---|
474 | public String fitnessToString() |
---|
475 | { |
---|
476 | String s = FITNESS_PREAMBLE + MULTI_FITNESS_POSTAMBLE; |
---|
477 | for (int x = 0; x < objectives.length; x++) |
---|
478 | { |
---|
479 | if (x > 0) |
---|
480 | s = s + " "; |
---|
481 | s = s + Code.encode(objectives[x]); |
---|
482 | } |
---|
483 | s = s + " "; |
---|
484 | s = s + Code.encode(maximize); |
---|
485 | return s + FITNESS_POSTAMBLE; |
---|
486 | } |
---|
487 | |
---|
488 | |
---|
489 | public String fitnessToStringForHumans() |
---|
490 | { |
---|
491 | String s = FITNESS_PREAMBLE + MULTI_FITNESS_POSTAMBLE; |
---|
492 | for (int x = 0; x < objectives.length; x++) |
---|
493 | { |
---|
494 | if (x > 0) |
---|
495 | s = s + " "; |
---|
496 | s = s + objectives[x]; |
---|
497 | } |
---|
498 | s = s + " "; |
---|
499 | s = s + (maximize ? "max" : "min"); |
---|
500 | return s + FITNESS_POSTAMBLE; |
---|
501 | } |
---|
502 | |
---|
503 | public void readFitness(final EvolutionState state, final LineNumberReader reader) throws IOException |
---|
504 | { |
---|
505 | DecodeReturn d = Code.checkPreamble(FITNESS_PREAMBLE + MULTI_FITNESS_POSTAMBLE, state, reader); |
---|
506 | for (int x = 0; x < objectives.length; x++) |
---|
507 | { |
---|
508 | Code.decode(d); |
---|
509 | if (d.type != DecodeReturn.T_FLOAT) |
---|
510 | state.output.fatal("Reading Line " + d.lineNumber + ": " + "Bad Fitness (objectives value #" + x + ")."); |
---|
511 | objectives[x] = (float) d.d; |
---|
512 | } |
---|
513 | Code.decode(d); |
---|
514 | if (d.type != DecodeReturn.T_BOOLEAN) |
---|
515 | state.output.fatal("Reading Line " + d.lineNumber + ": " + "Information missing about whether higher is better"); |
---|
516 | maximize = (boolean) (d.l != 0); |
---|
517 | } |
---|
518 | |
---|
519 | public void writeFitness(final EvolutionState state, final DataOutput dataOutput) throws IOException |
---|
520 | { |
---|
521 | dataOutput.writeInt(objectives.length); |
---|
522 | for (int x = 0; x < objectives.length; x++) |
---|
523 | dataOutput.writeFloat(objectives[x]); |
---|
524 | dataOutput.writeBoolean(maximize); |
---|
525 | } |
---|
526 | |
---|
527 | public void readFitness(final EvolutionState state, final DataInput dataInput) throws IOException |
---|
528 | { |
---|
529 | int len = dataInput.readInt(); |
---|
530 | if (objectives == null || objectives.length != len) |
---|
531 | objectives = new float[len]; |
---|
532 | for (int x = 0; x < objectives.length; x++) |
---|
533 | objectives[x] = dataInput.readFloat(); |
---|
534 | maximize = dataInput.readBoolean(); |
---|
535 | } |
---|
536 | } |
---|