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 | |
---|
9 | package ec.steadystate; |
---|
10 | import ec.simple.*; |
---|
11 | import ec.*; |
---|
12 | import ec.util.Parameter; |
---|
13 | import java.util.*; |
---|
14 | import ec.eval.MasterProblem; |
---|
15 | |
---|
16 | /* |
---|
17 | * SteadyStateEvaluator.java |
---|
18 | * |
---|
19 | */ |
---|
20 | |
---|
21 | /** |
---|
22 | * This subclass of Evaluator performs the evaluation portion of Steady-State Evolution and (in distributed form) |
---|
23 | * Asynchronous Evolution. The procedure is as follows. We begin with an empty Population and one by |
---|
24 | * one create new Indivdiuals and send them off to be evaluated. In basic Steady-State Evolution the |
---|
25 | * individuals are immediately evaluated and we wait for them; but in Asynchronous Evolution the individuals are evaluated |
---|
26 | * for however long it takes and we don't wait for them to finish. When individuals return they are |
---|
27 | * added to the Population until it is full. No duplicate individuals are allowed. |
---|
28 | * |
---|
29 | * <p>At this point the system switches to its "steady state": individuals are bred from the population |
---|
30 | * one by one, and sent off to be evaluated. Once again, in basic Steady-State Evolution the |
---|
31 | * individuals are immediately evaluated and we wait for them; but in Asynchronous Evolution the individuals are evaluated |
---|
32 | * for however long it takes and we don't wait for them to finish. When an individual returns, we |
---|
33 | * mark an individual in the Population for death, then replace it with the new returning individual. |
---|
34 | * Note that during the steady-state, Asynchronous Evolution could be still sending back some "new" individuals |
---|
35 | * created during the initialization phase, not "bred" individuals. |
---|
36 | * |
---|
37 | * <p>The determination of how an individual is marked for death is done by the SteadyStateBreeder. |
---|
38 | * |
---|
39 | * <p>When SteadyStateEvaluator sends indivduals off to be evaluated, it stores them in an internal queue, along |
---|
40 | * with the subpopulation in which they were destined. This tuple is defined by QueueIndividual.java |
---|
41 | * |
---|
42 | * |
---|
43 | * @author Sean Luke |
---|
44 | * @version 1.0 |
---|
45 | */ |
---|
46 | |
---|
47 | public class SteadyStateEvaluator extends SimpleEvaluator |
---|
48 | { |
---|
49 | LinkedList queue = new LinkedList(); |
---|
50 | |
---|
51 | /** Holds the subpopulation currently being evaluated. */ |
---|
52 | int subpopulationBeingEvaluated = -1; |
---|
53 | |
---|
54 | /** Our problem. */ |
---|
55 | SimpleProblemForm problem; |
---|
56 | |
---|
57 | public void setup(final EvolutionState state, final Parameter base) |
---|
58 | { |
---|
59 | super.setup(state,base); |
---|
60 | } |
---|
61 | |
---|
62 | public void prepareToEvaluate(EvolutionState state, int thread) |
---|
63 | { |
---|
64 | problem = (SimpleProblemForm)p_problem.clone(); |
---|
65 | |
---|
66 | /* |
---|
67 | We only call prepareToEvaluate during Asynchronous Evolution. |
---|
68 | */ |
---|
69 | if (problem instanceof MasterProblem) |
---|
70 | ((MasterProblem)problem).prepareToEvaluate(state, thread); |
---|
71 | } |
---|
72 | |
---|
73 | /** Submits an individual to be evaluated by the Problem, and adds it and its subpopulation to the queue. */ |
---|
74 | public void evaluateIndividual(final EvolutionState state, Individual ind, int subpop) |
---|
75 | { |
---|
76 | problem.evaluate(state, ind, subpop, 0); |
---|
77 | queue.addLast(new QueueIndividual(ind, subpop)); |
---|
78 | } |
---|
79 | |
---|
80 | /** Returns true if we're ready to evaluate an individual. Ordinarily this is ALWAYS true, |
---|
81 | except in the asynchronous evolution situation, where we may not have a processor ready yet. */ |
---|
82 | public boolean canEvaluate() |
---|
83 | { |
---|
84 | if (problem instanceof MasterProblem) |
---|
85 | return ((MasterProblem)problem).canEvaluate(); |
---|
86 | else return true; |
---|
87 | } |
---|
88 | |
---|
89 | /** Returns an evaluated individual is in the queue and ready to come back to us. |
---|
90 | Ordinarily this is ALWAYS true at the point that we call it, except in the asynchronous |
---|
91 | evolution situation, where we may not have a job completed yet, in which case NULL is |
---|
92 | returned. Once an individual is returned by this function, no other individual will |
---|
93 | be returned until the system is ready to provide us with another one. NULL will |
---|
94 | be returned otherwise. */ |
---|
95 | public Individual getNextEvaluatedIndividual() |
---|
96 | { |
---|
97 | QueueIndividual qind = null; |
---|
98 | |
---|
99 | if (problem instanceof MasterProblem) |
---|
100 | { |
---|
101 | if (((MasterProblem)problem).evaluatedIndividualAvailable()) |
---|
102 | qind = ((MasterProblem)problem).getNextEvaluatedIndividual(); |
---|
103 | } |
---|
104 | else |
---|
105 | { |
---|
106 | qind = (QueueIndividual)(queue.removeFirst()); |
---|
107 | } |
---|
108 | |
---|
109 | if (qind == null) return null; |
---|
110 | |
---|
111 | subpopulationBeingEvaluated = qind.subpop; |
---|
112 | return qind.ind; |
---|
113 | } |
---|
114 | |
---|
115 | /** Returns the subpopulation of the last evaluated individual returned by getNextEvaluatedIndividual, or potentially -1 if |
---|
116 | getNextEvaluatedIndividual was never called or hasn't returned an individual yet. */ |
---|
117 | public int getSubpopulationOfEvaluatedIndividual() |
---|
118 | { |
---|
119 | return subpopulationBeingEvaluated; |
---|
120 | } |
---|
121 | } |
---|
122 | |
---|
123 | |
---|