public class MasterProblem extends Problem implements SimpleProblemForm, GroupedProblemForm, ec.co.ConstructiveProblemForm
The MasterProblem is a special ECJ problem that performs evaluations by sending them to a remote Slave process to be evaluated. As it implements both the SimpleProblemForm and the GroupedProblemForm interfaces, the MasterProblem can perform both traditional EC evaluations as well as coevolutionary evaluations.
When a MasterProblem is specified by the Evaluator, the Problem is set up as usual, but then the MasterProblem replaces it. The Problem is not garbage collected -- instead, it's hung off the MasterProblem's problem variable. In some sense the Problem is "pushed aside".
If the Evaluator begins by calling prepareToEvaluate(), and we're not doing coevolution, then the MasterProblem does not evaluate individuals immediately. Instead, it waits for at most jobSize individuals be submitted via evaluate(), and then sends them all off in a group, called a job, to the remote slave. In other situations (coevolution, or no prepareToEvaluate()) the MasterProblem sends off individuals immediately.
It may be the case that no Slave has space in its queue to accept a new job containing, among others, your new individual. In this case, calling evaluate() will block until one comes available. You can avoid this by testing for availability first by calling canEvaluate(). Note that canEvaluate() and evaluate() together are not atomic and so you should not rely on this facility if your system uses multiple threads.
When the individuals or their fitnesses return, they are immediately updated in place. You have three options to wait for them:
You can wait for all the individuals to finish evaluation by calling finishEvaluating(). If you call this method before a job is entirely filled, it will be sent in truncated format (which generally is perfectly fine). You then block until all the jobs have been completed and the individuals updated.
You can block until at least one individual is available, by calling getNextEvaluatedIndividual(), which blocks and then returns the individual that was just completed.
You can test in non-blocking fashion to see if an individual is available, by calling evaluatedIndividualAvailable(). If this returns true, you may then call getNextEvaluatedIndividual() to get the individual. Note that this isn't atomic, so don't use it if you have multiple threads.
Parameters
base.debug-info boolean |
(whether the system should display information useful for debugging purposes) |
base.job-size integer > 0 |
(how large should a job be at most?) |
eval.master.port int |
(the port where the slaves will connect) |
eval.compression boolean |
(whether the communication with the slaves should be compressed or not) |
eval.masterproblem.max-jobs-per-slave int |
(the maximum load (number of jobs) per slave at any point in time) |
Modifier and Type | Field and Description |
---|---|
boolean |
batchMode |
SlaveMonitor |
monitor |
static java.lang.String |
P_DEBUG_INFO |
static java.lang.String |
P_JOB_SIZE |
Problem |
problem |
Constructor and Description |
---|
MasterProblem() |
Modifier and Type | Method and Description |
---|---|
boolean |
canEvaluate()
Asynchronous Steady-State EC only: Returns true if the problem is ready to evaluate.
|
java.lang.Object |
clone()
Creates a new individual cloned from a prototype,
and suitable to begin use in its own evolutionary
context.
|
void |
closeContacts(EvolutionState state,
int result)
Gracefully close contacts with the slaves
|
void |
describe(EvolutionState state,
Individual ind,
int subpopulation,
int threadnum,
int log)
Part of SimpleProblemForm.
|
void |
evaluate(EvolutionState state,
Individual[] inds,
boolean[] updateFitness,
boolean countVictoriesOnly,
int[] subpops,
int threadnum)
Evaluates the individuals found in ind together.
|
void |
evaluate(EvolutionState state,
Individual ind,
int subpopulation,
int threadnum)
Evaluates the individual in ind, if necessary (perhaps
not evaluating them if their evaluated flags are true),
and sets their fitness appropriately.
|
boolean |
evaluatedIndividualAvailable()
This will only return true if (1) the EvolutionState is a SteadyStateEvolutionState and
(2) an individual has returned from the system.
|
void |
finishEvaluating(EvolutionState state,
int threadnum)
Will be called by the Evaluator after prepareToEvaluate(...) is called
and then a series of individuals are evaluated.
|
java.util.List<ec.co.Component> |
getAllComponents() |
java.util.List<ec.co.Component> |
getAllowedComponents(ec.co.ConstructiveIndividual partialSolution)
Return the allowable "neighborhood" of components that
|
ec.co.Component |
getArbitraryComponent(EvolutionState state,
int thread)
Chooses an arbitrary component from the problem domain.
|
ec.co.Component |
getComponentFromString(java.lang.String s)
Decode a String representation of a solution component.
|
QueueIndividual |
getNextEvaluatedIndividual()
This method blocks until an individual is available from the slaves (which will cause evaluatedIndividualAvailable()
to return true), at which time it returns the individual.
|
void |
initializeContacts(EvolutionState state)
Initialize contacts with the slaves
|
boolean |
isCompleteSolution(ec.co.ConstructiveIndividual solution)
Determine whether a given specifies a complete solution to this problem.
|
boolean |
isViolated(ec.co.ConstructiveIndividual partialSolution,
ec.co.Component component) |
int |
numComponents() |
int |
postprocessPopulation(EvolutionState state,
Population pop,
boolean[] assessFitness,
boolean countVictoriesOnly)
Finish processing the population (such as fitness information) after evaluation.
|
void |
prepareToEvaluate(EvolutionState state,
int threadnum)
May be called by the Evaluator prior to a series of individuals to
evaluate, and then ended with a finishEvaluating(...).
|
void |
preprocessPopulation(EvolutionState state,
Population pop,
boolean[] prepareForFitnessAssessment,
boolean countVictoriesOnly)
Set up the population pop (such as fitness information) prior to evaluation.
|
void |
receiveAdditionalData(EvolutionState state,
java.io.DataInputStream dataIn)
This method is called on a MasterProblem by the Slave.
|
void |
reinitializeContacts(EvolutionState state)
Reinitialize contacts with the slaves
|
void |
sendAdditionalData(EvolutionState state,
java.io.DataOutputStream dataOut)
This method is called from the SlaveMonitor's accept() thread to optionally send additional data to the
Slave via the dataOut stream.
|
void |
setup(EvolutionState state,
Parameter base)
Sets up the object by reading it from the parameters stored
in state, built off of the parameter base base.
|
void |
transferAdditionalData(EvolutionState state)
This method is called by a Slave to transfer data previously loaded via receiveAdditionalData() to
a running EvolutionState at the beginning of evolution.
|
defaultBase, describe
public static final java.lang.String P_DEBUG_INFO
public static final java.lang.String P_JOB_SIZE
public boolean batchMode
public transient SlaveMonitor monitor
public Problem problem
public java.lang.Object clone()
Prototype
Typically this should be a full "deep" clone. However, you may share certain elements with other objects rather than clone hem, depending on the situation:
Implementations.
public Object clone()
{
try
{
return super.clone();
}
catch ((CloneNotSupportedException e)
{ throw new InternalError(); } // never happens
}
public Object clone()
{
try
{
MyObject myobj = (MyObject) (super.clone());
// put your deep-cloning code here...
}
catch ((CloneNotSupportedException e)
{ throw new InternalError(); } // never happens
return myobj;
}
public Object clone()
{
MyObject myobj = (MyObject) (super.clone());
// put your deep-cloning code here...
return myobj;
}
public void setup(EvolutionState state, Parameter base)
Prototype
For prototypes, setup(...) is typically called once for the prototype instance; cloned instances do not receive the setup(...) call. setup(...) may be called more than once; the only guarantee is that it will get called at least once on an instance or some "parent" object from which it was ultimately cloned.
public void prepareToEvaluate(EvolutionState state, int threadnum)
Problem
prepareToEvaluate
in class Problem
public void finishEvaluating(EvolutionState state, int threadnum)
Problem
finishEvaluating
in class Problem
public void evaluate(EvolutionState state, Individual ind, int subpopulation, int threadnum)
SimpleProblemForm
evaluate
in interface SimpleProblemForm
public void describe(EvolutionState state, Individual ind, int subpopulation, int threadnum, int log)
Problem
describe
in interface SimpleProblemForm
describe
in class Problem
public void preprocessPopulation(EvolutionState state, Population pop, boolean[] prepareForFitnessAssessment, boolean countVictoriesOnly)
GroupedProblemForm
countVictoriesOnly will be set if Individuals' fitness is to be based on whether they're the winner of a test, instead of based on the specifics of the scores in the tests. This really only happens for Single-Elimination Tournament one-population competitive coevolution.
prepareForFitnessAssessment will indicate which subpopulations will have their fitness values updated this time around, during postprocessPopulation. It may not be the same as updateFitness[] in evaluate(...).
If you are basing fitness on trials, this method should create the initial trials if the prepareForFitnessAssessment[...] is true for that subpopulation.
preprocessPopulation
in interface GroupedProblemForm
public int postprocessPopulation(EvolutionState state, Population pop, boolean[] assessFitness, boolean countVictoriesOnly)
GroupedProblemForm
countVictoriesOnly will be set if Individuals' fitness is to be based on whether they're the winner of a test, instead of based on the specifics of the scores in the tests. This really only happens for Single-Elimination Tournament one-population competitive coevolution. If this is set, probably would leave the Fitnesses as they are here (they've been set and incremented in evaluate(...)), but if it's not set, you may want to set the Fitnesses to the maximum or average or the various trials performed.
assessFitness will indicate which subpopulations should have their final fitness values assessed. You should not clear the trials of individuals for which assessFitness[] is false. Instead allow trials to accumulate and ultimately update the fitnesses later when the flag is set. assessFitness[] may not be the same as updateFitness[] in evaluate(...).
Should return the number of individuals evaluated (not tested: but actually had their fitnesses modified -- or would have if the evaluated flag wasn't set).
postprocessPopulation
in interface GroupedProblemForm
public void evaluate(EvolutionState state, Individual[] inds, boolean[] updateFitness, boolean countVictoriesOnly, int[] subpops, int threadnum)
GroupedProblemForm
countVictoriesOnly will be set if Individuals' fitness is to be based on whether they're the winner of a test, instead of based on the specifics of the scores in the tests. This really only happens for Single-Elimination Tournament one-population competitive coevolution. If this is set, you should increment the Fitness of the winner each time. If it's not set, you should update Fitness as you see fit, then set the final Fitness in preprocessPopulation.
evaluate
in interface GroupedProblemForm
public void initializeContacts(EvolutionState state)
initializeContacts
in class Problem
public void reinitializeContacts(EvolutionState state)
reinitializeContacts
in class Problem
public void closeContacts(EvolutionState state, int result)
closeContacts
in class Problem
public boolean canEvaluate()
Problem
canEvaluate
in class Problem
public boolean evaluatedIndividualAvailable()
public QueueIndividual getNextEvaluatedIndividual()
public void sendAdditionalData(EvolutionState state, java.io.DataOutputStream dataOut)
public void receiveAdditionalData(EvolutionState state, java.io.DataInputStream dataIn)
public void transferAdditionalData(EvolutionState state)
public int numComponents()
numComponents
in interface ec.co.ConstructiveProblemForm
public boolean isCompleteSolution(ec.co.ConstructiveIndividual solution)
ec.co.ConstructiveProblemForm
isCompleteSolution
in interface ec.co.ConstructiveProblemForm
solution
- A partial or complete solution to this ConstructiveProblemForm.public boolean isViolated(ec.co.ConstructiveIndividual partialSolution, ec.co.Component component)
isViolated
in interface ec.co.ConstructiveProblemForm
partialSolution
- A partial solution to this ConstructiveProblemForm.component
- A component that we may wish to add to the partial solution.public java.util.List<ec.co.Component> getAllComponents()
getAllComponents
in interface ec.co.ConstructiveProblemForm
public java.util.List<ec.co.Component> getAllowedComponents(ec.co.ConstructiveIndividual partialSolution)
ec.co.ConstructiveProblemForm
getAllowedComponents
in interface ec.co.ConstructiveProblemForm
partialSolution
- A collection of components that represent a
partial solution that we wish to add a component to.public ec.co.Component getComponentFromString(java.lang.String s)
ec.co.ConstructiveProblemForm
getComponentFromString
in interface ec.co.ConstructiveProblemForm
s
- A String representing a component.public ec.co.Component getArbitraryComponent(EvolutionState state, int thread)
ec.co.ConstructiveProblemForm
getArbitraryComponent
in interface ec.co.ConstructiveProblemForm
state
- The state (used, for example, to access the simulation's PRNGs)thread
- The thread the caller is operating on. If the caller is single-threaded, just set this to zero.