/*
* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/
package org.jgap.audit;
import java.util.*;
import org.jgap.*;
import org.jgap.eval.*;
/**
* Monitors the evolution progress extensively.
* Keeps track of the population development for each single generation during
* the whole evolution process.
* Monitors chromosomes as well as genes. For each chromosome the originating
* chromosome is monitored (applies for natural selectors as well as for genetic
* operators that transform a single chromosome, like MutationOperator).
* For more complex genetic operators, like CrossoverOperator, all originating
* chromosomes are monitored (in crossover there are two).
* For genes an analogue monitoring is supported as for chromosomes.
*
* TO ACTIVATE MONITORING:
* Configuration.setMonitor(new EvolutionMonitor());
*
* Each chromosome and gene itself has a unique ID. This ID is set by method
* setUniqueID. A unique ID is a String value that, in best case, is unique
* worldwide.
*
* A chromosome's or gene's originator is set by method setUniqueIDTemplate.
* This method accepts an index, as there could be more than one originator
* (see below).
*
* --------------------------------------------------------------------------
*
* To give a better view, here are the population snapshots that are taken
* during a single evolution generation (chromosomes are given by *,+,-,.):
*
* |-------| |-------| |-------| |-------| |-------|
* | ** * | | ** | | * | | + | | + |
* |* * * | => |* * * | => |* * | => |* - | => |* . |
* | * ** | | ** | | ** | | ** | | -* |
* |-------| |-------| |-------| |-------| |-------|
* Update Natural Natural Genetic Genetic
* Chromosomes Selector 1 Selector i Operator 1 Operator j
* (Fitness calc.)
*
* |-------| |-------| |-------| |-------| |-------|
* | + | | + | | +** | | +** | | + * |
* => |* . | => |* . | => |* . | => |* * . | => |* * . |
* | -* | | -* | |* -* | |* -* | |* - |
* |-------| |-------| |-------| |-------| |-------|
* Bulk Fitness Update Add new Re-add Natural
* Function Chromosomes Chromosomes Fittest Selector k
* (optional) Chromosome (Post-Sel.)
*
* |-------|
* | + * |
* => |* * . |
* |* - |
* |-------|
* End of cycle
*
* For each single evolution cycle, these population states are kept separately.
*
* --------------------------------------------------------------------------
*
* For each chromosome the originating chromosomes are tracked. Here are examples:
*
* Natural Selection, e.g. WeightedRouletteSelector:
* Chromosome 4715 has originator Chromosome 4711 (different ID because of
* cloning)
*
* Genetic Operation, e.g. MutationOperator:
* Chromosome 5512 has originator Chromosome 1139
*
* Genetic Operation, e.g. CrossoverOperator:
* Chromosome 7119 has originator Chromosomes 807 and 5703
* Chromosome 7120 has originator Chromosomes 807 and 5703
* => two resulting Chromosomes have the same originators!
*
* Genetic, Operation, e.g. YourOperator:
* There can be as many originating Chromosomes as your operator regards
*
* --------------------------------------------------------------------------
*
* For each gene the originating genes are tracked. Examples:
*
* Natural Selection, e.g. WeightedRouletteSelector:
* All Genes in Chromosome 4711 have the same originating genes as
* Chromosome 4711's originating Chromosome's genes.
* => Chromosome is selected only, not modified, thus the Genes stick to the
* Chromosome they belong to. Genes unique ID of template is not set.
*
* Genetic Operation, e.g. MutationOperator:
* Each mutated Gene originates from exactly one other Gene
*
* Genetic Operation, e.g. CrossoverOperator:
* Each crossed over Gene A has one originating Gene B.
* In turn, Gene B has one originating Gene A, as their alleles are swapped.
* All uncrossed Genes have the same originator as the Chromosome they
* belong to, thus their unique ID of template is not set.
*
* Genetic, Operation, e.g. YourOperator:
* A Gene could virtually have any number of originators.
*
* @author Klaus Meffert
* @since 3.5
*/
public class EvolutionMonitor
implements IEvolutionMonitor {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.3 $";
public static final int CONTEXT_UPDATE_CHROMOSOMES1 = 0;
public static final int CONTEXT_OFFSET_NATURAL_SELECTOR1 = 1;
public static final int CONTEXT_OFFSET_AFTER_OPERATE = 10;
public static final int CONTEXT_AFTER_BULK_EVALUATION = 20;
public static final int CONTEXT_UPDATE_CHROMOSOMES2 = 22;
public static final int CONTEXT_NEW_CHROMOSOME = 22;
public static final int CONTEXT_READD_FITTEST = 23;
public static final int CONTEXT_OFFSET_NATURAL_SELECTOR2 = 30;
public static final int CONTEXT_END_OF_CYCLE = 999;
private int m_checks;
private PopulationHistoryIndexed m_popHist;
private int m_selectorIndex;
private int m_operatorIndex;
public EvolutionMonitor() {
init();
}
protected void init() {
m_popHist = new PopulationHistoryIndexed();
}
/**
* Called after another evolution cycle has been executed.
*
* @param a_pop the currently evolved population
* @param a_messages the monitor can append messages to indicate why it asks
* evolution to stop
* @return true: continue with the evolution; false: stop evolution
*
* @author Klaus Meffert
* @since 3.4.4
*/
public boolean nextCycle(Population a_pop, List<String> a_messages) {
// Let's verify the progress since our last check.
// -----------------------------------------------
IChromosome best = a_pop.determineFittestChromosome();
if (best != null) {
// A best solution exists.
// -----------------------
}
else {
// No solution exists at all.
// --------------------------
}
// Store the population
Population popClone = (Population) a_pop.clone();
// m_evaluator.storePopulation(CONTEXT_END_OF_CYCLE, m_checks, popClone);
PopulationContext context = new PopulationContext(popClone);
context.setChromosome(best);
m_popHist.addPopulation(m_checks, CONTEXT_END_OF_CYCLE, context);
m_checks++;
initCounters();
// No continouos processing as in this example there is an outer main loop.
// ------------------------------------------------------------------------
return false;
}
/**
* Called just before the evolution starts.
*
* @param a_config the configuration used
*
* @author Klaus Meffert
* @since 3.5
*/
public void start(Configuration a_config) {
initCounters();
}
private void initCounters() {
m_selectorIndex = 0;
m_operatorIndex = 0;
}
/**
* Called whenever it's worth monitoring.
*
* @param a_monitorEvent see constants at top of class IEvolutionMonitor
* @param a_evolutionNo the index of the evolution round (1, 2, ...)
* @param a_information event-specific information
*
* @author Klaus Meffert
* @since 3.5
*/
public void event(String a_monitorEvent, int a_evolutionNo,
Object[] a_information) {
if (a_monitorEvent == null) {
// Should never happen.
// --------------------
return;
}
if (a_information == null) {
return;
}
PopulationContext context;
// The events are queried in the chronological order they do appear.
// -----------------------------------------------------------------
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_REMOVE_CHROMOSOME)) {
// Initiated by Population.keepPopSizeConstant()
Population pop = (Population) a_information[0];
Integer chromosomeIndex = (Integer) a_information[1];
IChromosome chrom = pop.getChromosome(chromosomeIndex);
}
if (a_monitorEvent.equals(IEvolutionMonitor.
MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES1)) {
// Initiated by GABreeder.evolve before calling updateChromosomes(..)
Population pop = (Population) a_information[0];
}
if (a_monitorEvent.equals(IEvolutionMonitor.
MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1)) {
// Initiated by GABreeder.evolve after calling updateChromosomes(..)
Population pop = (Population) ( (Population) a_information[0]).clone();
// Record population as now each chromosome has a fitness value assigned.
// ----------------------------------------------------------------------
// m_evaluator.storePopulation(CONTEXT_UPDATE_CHROMOSOMES1, m_checks, pop);
context = new PopulationContext(pop);
m_popHist.addPopulation(m_checks, CONTEXT_UPDATE_CHROMOSOMES1, context);
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_BEFORE_SELECT)) {
NaturalSelector selector = (NaturalSelector) a_information[0];
Population pop = (Population) a_information[1];
int selectionSize = (Integer) a_information[2];
boolean a_processBeforeGeneticOperators = (Boolean) a_information[3];
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_SELECT)) {
NaturalSelector selector = (NaturalSelector) a_information[0];
Population pop = (Population) ( (Population) a_information[1]).clone();
Population newPop = (Population) ( (Population) a_information[2]).clone();
int selectionSize = (Integer) a_information[3];
boolean a_processBeforeGeneticOperators = (Boolean) a_information[4];
if (a_processBeforeGeneticOperators) {
// Selection executed before genetic operators.
// --------------------------------------------
// Store data for each selector subsequently.
// ------------------------------------------
context = new PopulationContext(pop);
context.setSelector(selector);
m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR1 +
m_selectorIndex * 2 + 0, context);
context = new PopulationContext(newPop);
context.setSelector(selector);
m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR1 +
m_selectorIndex * 2 + 1, context);
m_selectorIndex++;
}
else {
// Selection executed after genetic operators.
// -------------------------------------------
context = new PopulationContext(pop);
context.setSelector(selector);
// Store data for each selector subsequently.
// ------------------------------------------
m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR2 +
m_selectorIndex * 2 + 0, context);
context = new PopulationContext(newPop);
context.setSelector(selector);
m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR2 +
m_selectorIndex * 2 + 1, context);
}
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_BEFORE_OPERATE)) {
GeneticOperator operator = (GeneticOperator) a_information[0];
Population pop = (Population) a_information[1];
List<IChromosome> chromosomes = (List<IChromosome>) a_information[2];
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_OPERATE)) {
GeneticOperator operator = (GeneticOperator) a_information[0];
Population pop = (Population) a_information[1];
List<IChromosome> chromosomes = (List<IChromosome>) a_information[2];
// Store data for each selector subsequently.
// ------------------------------------------
context = new PopulationContext(pop);
context.setOperator(operator);
m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_AFTER_OPERATE +
m_operatorIndex, context);
m_operatorIndex++;
m_selectorIndex = 0;
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_BEFORE_BULK_EVAL)) {
BulkFitnessFunction bulkFitnessFunction = (BulkFitnessFunction)
a_information[0];
Population pop = (Population) a_information[1];
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_BULK_EVAL)) {
BulkFitnessFunction bulkFitnessFunction = (BulkFitnessFunction)
a_information[0];
Population pop = (Population) ( (Population) a_information[1]).clone();
context = new PopulationContext(pop);
context.setBulkFitnessFunction(bulkFitnessFunction);
m_popHist.addPopulation(m_checks, CONTEXT_AFTER_BULK_EVALUATION, context);
}
if (a_monitorEvent.equals(IEvolutionMonitor.
MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES2)) {
Population pop = (Population) a_information[0];
}
if (a_monitorEvent.equals(IEvolutionMonitor.
MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES2)) {
Population pop = (Population) a_information[0];
context = new PopulationContext(pop);
m_popHist.addPopulation(m_checks, CONTEXT_UPDATE_CHROMOSOMES2, context);
}
if (a_monitorEvent.equals(IEvolutionMonitor.
MONITOR_EVENT_BEFORE_ADD_CHROMOSOME)) {
Population pop = (Population) a_information[0];
IChromosome newChromosome = (IChromosome) ( (IChromosome) a_information[1]).
clone();
context = new PopulationContext(pop);
context.setChromosome(newChromosome);
m_popHist.addPopulation(m_checks, CONTEXT_NEW_CHROMOSOME, context);
}
if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_READD_FITTEST)) {
Population pop = (Population) a_information[0];
IChromosome fittest = (IChromosome) ( (IChromosome) a_information[1]).
clone();
context = new PopulationContext(pop);
context.setChromosome(fittest);
m_popHist.addPopulation(m_checks, CONTEXT_READD_FITTEST, context);
}
}
public PopulationHistoryIndexed getPopulations() {
return m_popHist;
}
}