Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/Subpopulation.java @ 10187

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

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

File size: 14.2 KB
RevLine 
[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
9package ec;
10import java.util.*;
11import java.io.*;
12import ec.util.*;
13
14/*
15 * Subpopulation.java
16 *
17 * Created: Tue Aug 10 20:34:14 1999
18 * By: Sean Luke
19 */
20
21/**
22 * Subpopulation is a group which is basically an array of Individuals.
23 * There is always one or more Subpopulations in the Population.  Each
24 * Subpopulation has a Species, which governs the formation of the Individuals
25 * in that Subpopulation.  Subpopulations also contain a Fitness prototype
26 * which is cloned to form Fitness objects for individuals in the subpopulation.
27 *
28 * <p>An initial subpopulation is populated with new random individuals
29 * using the populate(...) method.  This method typically populates
30 * by filling the array with individuals created using the Subpopulations'
31 * species' emptyClone() method, though you might override this to create
32 * them with other means, by loading from text files for example.
33 *
34 * <p>In a multithreaded area of a run, Subpopulations should be considered
35 * immutable.  That is, once they are created, they should not be modified,
36 * nor anything they contain.  This protocol helps ensure read-safety under
37 * multithreading race conditions.
38 *
39
40 <p><b>Parameters</b><br>
41 <table>
42 <tr><td valign=top><i>base</i>.<tt>size</tt><br>
43 <font size=-1>int &gt;= 1</font></td>
44 <td valign=top>(total number of individuals in the subpopulation)</td></tr>
45
46 <tr><td valign=top><i>base</i>.<tt>species</tt><br>
47 <font size=-1>classname, inherits and != ec.Species</font></td>
48 <td valign=top>(the class of the subpopulations' Species)</td></tr>
49
50 <tr><td valign=top><i>base</i>.<tt>fitness</tt><br>
51 <font size=-1>classname, inherits and != ec.Fitness</font></td>
52 <td valign=top>(the class for the prototypical Fitness for individuals in this subpopulation)</td></tr>
53
54 <tr><td valign=top><i>base</i>.<tt>file</tt><br>
55 <font size=-1>String</font></td>
56 <td valign=top>(pathname of file from which the population is to be loaded.  If not defined, or empty, then the population will be initialized at random in the standard manner)</td></tr>
57
58 <tr><td valign=top><i>base</i>.<tt>duplicate-retries</tt><br>
59 <font size=-1>int &gt;= 0</font></td>
60 <td valign=top>(during initialization, when we produce an individual which already exists in the subpopulation, the number of times we try to replace it with something unique.  Ignored if we're loading from a file.)</td></tr>
61 </table>
62
63 <p><b>Default Base</b><br>
64 ec.subpop
65
66 <p><b>Parameter bases</b><br>
67 <table>
68 <tr><td valign=top><i>base</i>.<tt>species</tt></td>
69 <td>species (the subpopulations' species)</td></tr>
70
71 </table>
72
73
74 * @author Sean Luke
75 * @version 1.0
76 */
77
78
79public class Subpopulation implements Group
80    {
81    /** A new subpopulation should be loaded from this file if it is non-null;
82        otherwise they should be created at random.  */
83    public File loadInds;
84
85    /** The species for individuals in this subpopulation. */
86    public Species species;
87
88    /** The subpopulation's individuals. */
89    public Individual[] individuals;
90
91    /** Do we allow duplicates? */
92    public int numDuplicateRetries;
93   
94    public static final String P_SUBPOPULATION = "subpop";
95    public static final String P_FILE = "file";
96    public static final String P_SUBPOPSIZE = "size";  // parameter for number of subpops or pops
97    public static final String P_SPECIES = "species";
98    public static final String P_RETRIES = "duplicate-retries";
99
100    public static final String NUM_INDIVIDUALS_PREAMBLE = "Number of Individuals: ";
101    public static final String INDIVIDUAL_INDEX_PREAMBLE = "Individual Number: ";
102
103    public Parameter defaultBase()
104        {
105        return ECDefaults.base().push(P_SUBPOPULATION);
106        }
107
108    /** Returns an instance of Subpopulation just like it had been before it was
109        populated with individuals. You may need to override this if you override
110        Subpopulation.   <b>IMPORTANT NOTE</b>: if the size of the array in
111        Subpopulation has been changed, then the clone will take on the new array
112        size.  This helps some evolution strategies.
113        @see Group#emptyClone()
114    */
115   
116    public Group emptyClone()
117        {
118        try
119            {
120            Subpopulation p = (Subpopulation)clone();
121            p.species = species;  // don't throw it away...maybe this is a bad idea...
122            p.individuals = new Individual[individuals.length];  // empty
123            return p;   
124            }
125        catch (CloneNotSupportedException e) { throw new InternalError(); } // never happens
126        }
127
128    public void setup(final EvolutionState state, final Parameter base)
129        {
130        Parameter def = defaultBase();
131
132        int size;
133
134        // do we load from a file?
135        loadInds = state.parameters.getFile(
136            base.push(P_FILE),null);
137
138        // what species do we use?
139
140        species = (Species) state.parameters.getInstanceForParameter(
141            base.push(P_SPECIES),def.push(P_SPECIES),
142            Species.class);
143        species.setup(state,base.push(P_SPECIES));
144
145        // how big should our subpopulation be?
146       
147        size = state.parameters.getInt(
148            base.push(P_SUBPOPSIZE),def.push(P_SUBPOPSIZE),1);
149        if (size<=0)
150            state.output.fatal(
151                "Subpopulation size must be an integer >= 1.\n",
152                base.push(P_SUBPOPSIZE),def.push(P_SUBPOPSIZE));
153       
154        // How often do we retry if we find a duplicate?
155        numDuplicateRetries = state.parameters.getInt(
156            base.push(P_RETRIES),def.push(P_RETRIES),0);
157        if (numDuplicateRetries < 0) state.output.fatal(
158            "The number of retries for duplicates must be an integer >= 0.\n",
159            base.push(P_RETRIES),def.push(P_RETRIES));
160       
161        individuals = new Individual[size];
162        }
163
164
165
166    public void populate(EvolutionState state, int thread)
167        {
168        // should we load individuals from a file? -- duplicates are permitted
169        if (loadInds!=null)
170            {
171            try { readSubpopulation(state, new LineNumberReader(new FileReader(loadInds))); }
172            catch (IOException e) { state.output.fatal("An IOException occurred when trying to read from the file " + loadInds + ".  The IOException was: \n" + e); }
173            }
174        else
175            {
176            Hashtable h = null;
177            if (numDuplicateRetries >= 1)
178                h = new Hashtable(individuals.length / 2);  // seems reasonable
179
180            for(int x=0;x<individuals.length;x++)
181                {
182                for(int tries=0;
183                    tries <= /* Yes, I see that*/ numDuplicateRetries;
184                    tries++)
185                    {
186                    individuals[x] = species.newIndividual(state, thread);
187
188                    if (numDuplicateRetries >= 1)
189                        {
190                        // check for duplicates
191                        Object o = h.get(individuals[x]);
192                        if (o == null) // found nothing, we're safe
193                            // hash it and go
194                            {
195                            h.put(individuals[x],individuals[x]);
196                            break;
197                            }
198                        }
199                    }  // oh well, we tried to cut down the duplicates
200                }
201            }
202        }
203       
204    /** Prints an entire subpopulation in a form readable by humans.
205        @deprecated Verbosity no longer has meaning
206    */
207    public final void printSubpopulationForHumans(final EvolutionState state,
208        final int log,
209        final int verbosity)
210        {
211        printSubpopulationForHumans(state, log);
212        }
213       
214    /** Prints an entire subpopulation in a form readable by humans but also parseable by the computer using readSubpopulation(EvolutionState, LineNumberReader).
215        @deprecated Verbosity no longer has meaning
216    */
217    public final void printSubpopulation(final EvolutionState state,
218        final int log,
219        final int verbosity)
220        {
221        printSubpopulation(state, log);
222        }
223       
224    /** Prints an entire subpopulation in a form readable by humans, with a verbosity of Output.V_NO_GENERAL. */
225    public void printSubpopulationForHumans(final EvolutionState state,
226        final int log)
227        {
228        state.output.println(NUM_INDIVIDUALS_PREAMBLE + individuals.length, log);
229        for(int i = 0 ; i < individuals.length; i++)
230            {
231            state.output.println(INDIVIDUAL_INDEX_PREAMBLE + Code.encode(i), log);
232            individuals[i].printIndividualForHumans(state, log);
233            }
234        }
235       
236    /** Prints an entire subpopulation in a form readable by humans but also parseable by the computer using readSubpopulation(EvolutionState, LineNumberReader) with a verbosity of Output.V_NO_GENERAL. */
237    public void printSubpopulation(final EvolutionState state,
238        final int log)
239        {
240        state.output.println(NUM_INDIVIDUALS_PREAMBLE + Code.encode(individuals.length), log);
241        for(int i = 0 ; i < individuals.length; i++)
242            {
243            state.output.println(INDIVIDUAL_INDEX_PREAMBLE + Code.encode(i), log);
244            individuals[i].printIndividual(state, log);
245            }
246        }
247       
248    /** Prints an entire subpopulation in a form readable by humans but also parseable by the computer using readSubpopulation(EvolutionState, LineNumberReader). */
249    public void printSubpopulation(final EvolutionState state,
250        final PrintWriter writer)
251        {
252        writer.println(NUM_INDIVIDUALS_PREAMBLE + Code.encode(individuals.length));
253        for(int i = 0 ; i < individuals.length; i++)
254            {
255            writer.println(INDIVIDUAL_INDEX_PREAMBLE + Code.encode(i));
256            individuals[i].printIndividual(state, writer);
257            }
258        }
259   
260    /** Reads a subpopulation from the format generated by printSubpopulation(....).  If the number of individuals is not identical, the individuals array will
261        be deleted and replaced with a new array, and a warning will be generated as individuals will have to be created using newIndividual(...) rather
262        than readIndividual(...). */
263    public void readSubpopulation(final EvolutionState state,
264        final LineNumberReader reader) throws IOException
265        {
266        // read in number of individuals and check to see if this appears to be a valid subpopulation
267        int numIndividuals = Code.readIntegerWithPreamble(NUM_INDIVIDUALS_PREAMBLE, state, reader);
268
269        // read in individuals
270        if (numIndividuals != individuals.length)
271            {
272            state.output.warnOnce("On reading subpopulation from text stream, the subpopulation size didn't match.\n" +
273                "Had to resize and use newIndividual() instead of readIndividual().");
274            individuals = new Individual[numIndividuals];
275            for(int i = 0 ; i < individuals.length; i++)
276                {
277                int j = Code.readIntegerWithPreamble(INDIVIDUAL_INDEX_PREAMBLE, state, reader);
278                // sanity check
279                if (j!=i) state.output.warnOnce("On reading subpopulation from text stream, some individual indexes in the subpopulation did not match.");
280                individuals[i] = species.newIndividual(state, reader);
281                }
282            }
283        else for(int i = 0 ; i < individuals.length; i++)
284                 {
285                 int j = Code.readIntegerWithPreamble(INDIVIDUAL_INDEX_PREAMBLE, state, reader);
286                 // sanity check
287                 if (j!=i) state.output.warnOnce("On reading subpopulation from text stream, some individual indexes in the subpopulation did not match.");
288                 if (individuals[i] != null)
289                     individuals[i].readIndividual(state, reader);
290                 else
291                     {
292                     state.output.warnOnce("On reading subpopulation from text stream, some of the preexisting subpopulation's slots were null.\n" +
293                         "Had to use newIndividual() instead of readIndividual().  If you're starting an evolutionary run by reading an\n" +
294                         "existing population from a file, this is expected -- ignore this message.");
295                     individuals[i] = species.newIndividual(state, reader);
296                     }
297                 }
298        }
299       
300    /** Writes a subpopulation in binary form, in a format readable by readSubpopulation(EvolutionState, DataInput). */
301    public void writeSubpopulation(final EvolutionState state,
302        final DataOutput dataOutput) throws IOException
303        {
304        dataOutput.writeInt(individuals.length);
305        for(int i = 0 ; i < individuals.length; i++)
306            individuals[i].writeIndividual(state, dataOutput);
307        }
308   
309    /** Reads a subpopulation in binary form, from the format generated by writeSubpopulation(...).  If the number of individuals is not identical, the individuals array will
310        be deleted and replaced with a new array, and a warning will be generated as individuals will have to be created using newIndividual(...) rather
311        than readIndividual(...) */
312    public void readSubpopulation(final EvolutionState state,
313        final DataInput dataInput) throws IOException
314        {
315        int numIndividuals = dataInput.readInt();
316        if (numIndividuals != individuals.length)
317            {
318            state.output.warnOnce("On reading subpopulation from binary stream, the subpopulation size was incorrect.\n" +
319                "Had to resize and use newIndividual() instead of readIndividual().");
320            individuals = new Individual[numIndividuals];
321            for(int i = 0 ; i < individuals.length; i++)
322                individuals[i] = species.newIndividual(state, dataInput);
323            }
324        else for(int i = 0 ; i < individuals.length; i++)
325                 individuals[i].readIndividual(state, dataInput);
326        }
327    }
Note: See TracBrowser for help on using the repository browser.