Print

Print


Okay Zheng, rather than build a test harness, I decided instead to  
describe the procedure to you here.

First you need to output the individual.  This can be done with

	Individual.printIndividual(EvolutionState, Writer)

For example, I modified the Artificial Ant example (Ant.java) to  
insert the following code as the very first code in the describe(...)  
function:

try
	{
	Parameter p = new Parameter("output-to");
	if (state.parameters.exists(p))
		{
		PrintWriter pw = new PrintWriter(new  
FileWriter(state.parameters.getFile(p, null)));
		ind.printIndividual(state, pw);
		pw.close();
		}
	}
catch (IOException e)
	{
	state.output.message("Unable to output best individual because of " +  
e);
	}


The describe(...) function is called on the best individual of run, so  
this code will write the best individual of the run out to the file I  
specify with the parameter "output-to".

Then I run the Artificial Ant example for, say, 10 generations like  
this:

	java ec.Evolve -file ant.params -p generations=10 -p output-to=\$here

If you're on Windows you may be able to say $here rather than \$here,  
but I'm on a Mac, which is a UNIX box, and my shell requires that $ be  
escaped.  In ECJ parlance, the phrase "$here" means "this shall be a  
file name placed right where I ran the script, as opposed to right  
next to the ant.params file" (which would be plain old "here").

So anyway, ECJ dutifully scribbles a file called "here", and here it is:

Evaluated: T
Fitness: f1107558400|33.0|i56|
Tree 0:
  (if-food-ahead (if-food-ahead (progn2 (if-food-ahead move move)  
(progn3 move move move)) (progn2 right move)) (progn3 left move right))


This is a computer-readable version of the best-so-far individual.   
The lines are:

1. Has the individual already had its fitness evaluated?

2. What was the fitness?  This is two numbers, a float followed by an  
int.  The Float is f1107558400|33.0| which means "1107558400 is the  
raw bits of the float if they were interpreted as an integer" and  
"33.0 is the print representation of the float for humans."  The Int  
is i56| which means "the int is 56".

3. Coming up is the first tree in the individual.

4 and on: the individual proper.


We need to convert this into a tiny little subpopulation because we're  
going to read it back into ECJ as a subpopulation to evaluate.  To do  
this we edit this file to add two additional headers: the number of  
individuals in the subpopulation (we'll make it a subpopulation of 1  
individual) and an indicator that the next individual is individual  
number 0.  The revised file looks like this:


Number of Individuals: i1|
Individual Number: i0|
Evaluated: F
Fitness: f1107558400|33.0|i56|
Tree 0:
  (if-food-ahead (if-food-ahead (progn2 (if-food-ahead move move)  
(progn3 move move move)) (progn2 right move)) (progn3 left move right))


Notice that I changed the "T" to an "F" also.  This tells ECJ that the  
fitness is not valid and it should reevaluate the individual when it  
gets the chance.

Now copy the Ant.java file to Ant2.java, and modify evaluate(...)  
function in the Java file Ant2.java to evaluate the individual as  
you'd like to do "offline".  That's up to you to do.  Get rid of the  
describe(...) function in the Ant2.java file.  Remember to change the  
classname to "Ant2".  Compile the Ant2.java file when you're done.   
For example, let's say that all I care about is printing out the  
individual just to prove it got loaded and evaluate(...) got called on  
it.  I could do:


package ec.app.ant;
import ec.util.*;
import ec.*;
import ec.gp.*;
import ec.simple.*;

public class Ant2 extends GPProblem implements SimpleProblemForm
     {
     public void evaluate(final EvolutionState state,
         final Individual ind,
         final int subpopulation,
         final int threadnum)
         {
	// obviously you'd do something more interesting with the individual  
than
	// just print it out!!

	state.output.println("Here's the individual: ", 3000, Log.D_STDERR);
	ind.printIndividual(state, Log.D_STDERR, 3000);
         }
     }


Now we can run this sucker like this:

	java ec.Evolve -file ant.params -p generations=1 -p pop.subpop. 
0.file=here -p pop.subpop.0.size=1 -p eval.problem=ec.app.ant.Ant2

Note that this says that population 0 has size 1, and it's consisting  
of individuals loaded from the file "here", and that instead of the  
Ant class we're using the Ant2 class for out Problem class.

Running this we get:

| ECJ
| An evolutionary computation system (version 19)
| By Sean Luke
| Contributors: L. Panait, G. Balan, S. Paus, Z. Skolicki, R.  
Kicinger, E. Popovici,
|               K. Sullivan, J. Harrison, J. Bassett, R. Hubley, A.  
Desai, A. Chircop,
|               J. Compton, W. Haddon, S. Donnelly, B. Jamil, and J.  
O'Beirne
| URL: http://cs.gmu.edu/~eclab/projects/ecj/
| Mail: [log in to unmask]
|       (better: join ECJ-INTEREST at URL above)
| Date: July 10, 2009
| Current Java: 1.5.0_19 / Java HotSpot(TM) Client VM-1.5.0_19-137
| Required Minimum Java: 1.4


Threads:  breed/1 eval/1
Seed: 4357
Job: 0
Setting up
Processing GP Types
Processing GP Node Constraints
Processing GP Function Sets
Processing GP Tree Constraints
Initializing Generation 0
ONCE-ONLY WARNING:
On reading subpopulation from text stream, some of the preexisting  
subpopulation's slots were null.
Had to use newIndividual() instead of readIndividual().  If you're  
starting an evolutionary run by reading an
existing population from a file, this is expected -- ignore this  
message.
Here's the individual:
Evaluated: T
Fitness: f1107558400|33.0|i56|
Tree 0:
  (if-food-ahead (if-food-ahead (progn2 (if-food-ahead move move)  
(progn3 move move move)) (progn2 right move)) (progn3 left move right))
Subpop 0 best fitness of generation: Fitness: Raw=33.0  
Adjusted=0.029411765 Hits=56
Subpop 0 best fitness of run: Fitness: Raw=33.0 Adjusted=0.029411765  
Hits=56


And there you go!  It loaded the file, creating a spurious warning  
(ignore it as it stated you should), and called our  
Problem.evaluate(...) function with the individual, which printed out  
the individual as we coded it to.


I hope that's useful enough for you to go on.  I realize that ECJ  
isn't the simplest of systems to be using if you're a Java newbie, so  
feel free to write in again if there's stuff you don't understand.


Sean