IslandEv adopts a client server model. The clients connect to the server, downloads the code for running a single evolutionary process and starts running it. These evolving islands then connect regularly to the server to inform it of their progress and to exchange migratory individuals with their neighbours. In the case that the evolutionary process you want to distribute uses multiple coevolving populations then each island will hold all these populations and migration across islands will occur only between populations of the same type.
If you will use IslandEv to distribute JaGa then you can skip the next section. Otherwise read on to find out how to plug in your evolutionary package to IslandEv.
islandev
package:
Individual
: This interface must be implemented by whatever object represenbts a member of your population. An individual is assumed to have a fitness value represented as a double. It is also possible for an Individual
object to hold more information in the form of Objects returned by the getProperty
method. Providing these properties is not essential but you may find it useful to do so since their values will be printed and logged by the server. The Individual
interface has the following methods to be implemented by your object representing a member of your population:
double getFitness
: This should return the fitness value of this individual.Object getProperty( int index )
: This should return the index
th property of this individual. Eg. properties could be Double
objects representing other fitness values, or tracing information referencing the individual's parents.int compareTo( Object o )
: Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
By implementing the java.lang.Comparable
interface we can now know which is the fittest of two individuals. This is needed for finding out which is the fittest solution found so far and if it has reached target fitness. If your individuals only have a single fitness value then you may want something like return new Double( getFitness() ).compareTo( new Double( ( ( Individual ) o ).getFitness() ) );
. If your individuals have multiple fitness values then the comparison may be more complex.EvolutionaryInteractiveTask
: This interface should be implemented by an object in your evolutionary process which has access to information about the current state of evolution. The following methods must be implemented:
int[] getPopulationSizes
: Should return an array of ints holding the sizes of the populations in your evolutionary process. For a single population setup use int[] rv = { popSize }; return rv;
where popSize
is a variable in your code holding the population size.Individual getSolutionTemplate
: Should return an Individual
object sol
such that, if for any other Individual
object ind
, the expression sol.compareTo( ind ) <= 0
is true, then ind
is considered a solution to the problem being tackled by evolution.SnapshotPainter getSnapshotPainter
: A SnapshotPainter
object is simply one capable of returning a JComponent
. This component will be placed into the GUI displayed on the client's screen so they have a graphical view of the progress of their island. For an empty panel use return new EmptySnapshotPainter();
.void set( Object params )
: This method inherited from the distrit.InteractiveTask
interface is used to send information to this evolutionary process from the server. The server will do this in two cases:
params
equal to a String
object holding the name of the population log file. The index of the population to load must be appended to the end of this file name so for population 0 the file name is ( ( String ) params ) + "0"
. If you do nothing in this case by if !( params instanceof String )
then all islands will start from the initial population.
params
equal to a Vector
holding Individual
objects to be inserted into each population. For a single population process then the vector will only contain one individual.Object get( Object params )
: This method is called regularly by the server to check on the progress of this evolutionary process and to get migrating individuals. This method should return a Vector
holding the following in index order:
Vector
holding the best individual of each population. One
Individual
object per population.Vector
holding the number of generations elapsed for each population. One Integer
object per population.Vector
holding the average fitness of each population. One
Double
object per population.Vector
holding an individual selected for outbound migration for each population. One Individual
object per population.Vector
holding arrays of populations to be logged. For single population setups these arrays will be of size one. These populations will be logged to a file in the order they appear in the vector by calling their toString
method. The last population will be saved in a special file whose name will be given to the set
method when the server wants this process to load it.REPORT_BEST_IND, REPORT_GENERATION, ...
constants refer to these indeces used when sending information to the server.
Once you've made your evolutionary package implement these interfaces you can start distributing it with IslandEv. Read the next section to find out how.
This section will assume that you know how to create an object of type EvolutionaryInteractiveTask
. If you are using JaGa then this will be the Monica
object, see the code in the JaGa Getting Started guide to find out how to create a Monica object. If you are using a custom evolutionary package then this is the object implementing the EvolutionaryInteractiveTask
as mentioned in the previous section.
The Islands Evolutionary Server can be given a queue of evolutionary tasks to go through in order. As soon as an individual is found superior or equal to the solution template, the server moves on to the next task and updates all clients. The server keeps log files showing when it starts a problem, when it finds a solution, when clients connect, etc.. The migration rate between islands is configurable by setting the probability that a migration event will succeed. You can think of this as specifying how far apart islands are.
Here goes an example code setting up a server class using the IslandsEvolutionServerWrapper
helper class included with IslandEv:
import islandev.*;
import distrit.*;
import java.util.Vector;
public class IslandEvExample extends IslandsEvolutionServerWrapper
{
public IslandEvExample()
{
EvolutionaryInteractiveTask evoTask = getEvoTask();
String evoTaskName = "MyEvoTask";
Vector taskQ = new Vector();
Vector taskQNames = new Vector();
taskQ.add( evoTask );
taskQNames.add( evoTaskName );
String logDir = "/home/username/log/";
String logFileName = "evoLog.txt";
double migrationRate = 0.5; // roughly half migration events succeed
ies = new IslandsEvolutionServer( taskQ, taskQNames, logDir, logFileName, migrationRate );
}
protected static EvolutionaryInteractiveTask getEvoTask()
{
... // code that creates an EvolutionaryInteractiveTask.
}
}
Now that we have our server class IslandEvExample
.
IslandEv uses RMI. What we first need is to configure our Java Security Policy. This is done with a policy file such as java.policy which allows the server to use various sockets and to have file access to the /home/username/log directory.
Now every time we want to start our server we must do the following things:
rmiregistry
at the command line. Important you must do this from a directory without direct access to your class files.host
on port port
then http://host:port/islandev/Individual.class
should point to the class file.SingleServerWrapper
class included with DistrIT by typing at the command line: java -Djava.rmi.codebase=http://host:port/ -Djava.rmi.server.hostname=host -Djava.security.policy=java.policy distrit.server.SingleServerWrapper IslandEvExample IES
IES
is the RMI binding name and can be changed to whatever you choose.
Now the islands evolution server will be up and running waiting for clients to connect.
All the clients need to have is the 5Kb DistrIT client and a java.policy file. You must replace host
in the policy file by the hostname of the server. Now you can launch the client with:
java -Djava.security.policy=java.policy -jar ITClient.jar host IES clientName
where clientName
is a unique name used by the server to refer to this client.
Now this client should connect to your Islands Evolution Server, download the evolutionary process and start running it. You can check what's happening at the server console.
Please do not hesitate to contact the project administrator for troubleshooting or advice on using IslandEv.