/*
* 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.*;
//import examples.*;
/**
* Evaluates evolution progress thas has previously been tracked by
* EvolutionMonitor (or a similar instance).
* This class regards a complete evolution, not just a single round. This is an
* optional way, another would be to just gather data per round and then display
* or evaluate the round-specific data.
* This class considers global (complete evolution) data because computations
* are executed on this data, like tracking chromosomes, evaluating the progress
* of selectors or genetic operators, etc.
*
* @author Klaus Meffert
* @since 3.5
*/
public class EvolutionEvaluator {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.3 $";
private PopulationHistoryIndexed m_monitorData;
private List<Integer> evolutionIndexes;
public EvolutionEvaluator(PopulationHistoryIndexed a_monitorData) {
if (a_monitorData == null) {
throw new IllegalArgumentException("Data must not be null!");
}
m_monitorData = a_monitorData;
evolutionIndexes = new Vector();
}
public void evaluate() {
Map<Integer, Map> data = m_monitorData.getPopulationsHistory();
Iterator<Integer> evolutions = data.keySet().iterator();
Population pop1, pop2;
// Gather all evolution indexes.
// -----------------------------
int evNo;
while (evolutions.hasNext()) {
evNo = evolutions.next();
evolutionIndexes.add(evNo);
}
// Gather a list of unique IDs for all chromosomes within all populations
// of all recorded states in all generations.
// ----------------------------------------------------------------------
Map<String, Map<IChromosome, List<Integer>>> chromIDs =
gatherChromosomesIDs(data);
// Track all chromosomes.
// ----------------------
Map<IChromosome, Map<Integer, List<IChromosome>>> chromTrack =
trackChromosomes(data);
/**@todo use chromIDs and chromTrack*/
int size = evolutionIndexes.size();
for (int i = 0; i < size; i++) {
evNo = evolutionIndexes.get(i);
Map<Integer, PopulationContext>
eventsPops = m_monitorData.getPopulations(evNo);
// Care about all executed Selectors per generation.
// -------------------------------------------------
int index = 0;
do {
PopulationContext ctx1 = eventsPops.get(EvolutionMonitor.
CONTEXT_OFFSET_NATURAL_SELECTOR1 + index * 2 + 0);
if (ctx1 == null) {
break;
}
pop1 = ctx1.getPopulation();
NaturalSelector selector = ctx1.getSelector();
PopulationContext ctx2 = eventsPops.get(EvolutionMonitor.
CONTEXT_OFFSET_NATURAL_SELECTOR1 + index * 2 + 1);
pop2 = ctx2.getPopulation();
// Evaluate average fitness of selection
// Track which individuals contributed to the top n solutions
/**@todo */
} while (true);
// Executed Operators per generation.
// Fitness progress intra-generation.
// Fitness progress over generations.
}
}
/**
* Tracks the originator chain of each chromosome in the final population.
* The originator chain potentially begins with the first generation.
* A chromosome could virtually have as many originators as there are
* evolutions (minus one), or it could have zero originators. The latter case
* means the chromosome was just created in the final population.
*
* @param a_data population (evolution) data
* @return the result of the investigation
*
* @author Klaus Meffert
* @since 3.5
*/
private Map<IChromosome, Map<Integer, List<IChromosome>>>
trackChromosomes(Map<Integer, Map> a_data) {
int size = evolutionIndexes.size() - 1;
Map<Integer, PopulationContext> contextMap = a_data.get(size);
PopulationContext context = contextMap.get(EvolutionMonitor.
CONTEXT_END_OF_CYCLE);
Population finalPop = context.getPopulation();
return trackChromosomes(a_data, finalPop);
}
/**
*
* @param a_data Map
* @param a_pop Population
* @return the result of the investigation
*
* @author Klaus Meffert
* @since 3.5
*/
private Map<IChromosome, Map<Integer, List<IChromosome>>>
trackChromosomes(Map<Integer, Map> a_data, Population a_pop) {
// A track is a list of chromosomes, with each of them having a list
// of originators:
// A Chromosome has originators, possibly from several different evolutions.
// -------------------------------------------------------------------------
Map<IChromosome, Map<Integer, List<IChromosome>>> chromosomesTrack
= new Hashtable();
int evNo;
int currentIndex = evolutionIndexes.size();
if (currentIndex < 1) {
return chromosomesTrack;
}
// Retrieve predecessing population.
// ---------------------------------
evNo = evolutionIndexes.get(currentIndex - 1);
Map<Integer, PopulationContext> contextMap = a_data.get(evNo);
PopulationContext context = contextMap.get(EvolutionMonitor.
CONTEXT_END_OF_CYCLE);
Population previousPop = context.getPopulation();
Map<Integer, List<IChromosome>> evoMap = new Hashtable();
// Find originators for all chromosomes in given population.
// ---------------------------------------------------------
for (int i = 0; i < a_pop.size(); i++) {
IChromosome chrom = a_pop.getChromosome(i);
int uindex = 1;
List<IChromosome> uids = new Vector();
// Gather originators for current chromosome in population.
// --------------------------------------------------------
do {
String uid = chrom.getUniqueIDTemplate(uindex++);
IChromosome chrom0 = null;
if (uid != null || uindex == 2) {
// Find chromosome instance for unique ID.
// ---------------------------------------
for (int k = 0; k < previousPop.size(); k++) {
chrom0 = previousPop.getChromosome(k);
if (chrom0.getUniqueID().equals(uid)) {
break;
}
}
uids.add(chrom0);
evoMap.put(evNo, uids);
chromosomesTrack.put(chrom, evoMap);
}
if (uid == null) {
break;
}
} while (true);
}
return chromosomesTrack;
}
/**
* For all chromosomes: Gather their IDs and the list of indexes of the
* evolution rounds they appeared in. Normally, a chromosome with a specific
* unique ID just appears within one single generation. The reason is, that,
* normally, in selection and genetic operator, the chromosomes' IDs change,
* because the chromosomes are cloned.
*
* @param a_data monitoring data
* @return result of investigation
*/
private Map<String, Map<IChromosome, List<Integer>>> gatherChromosomesIDs(
Map<Integer, Map> a_data) {
int size = evolutionIndexes.size() - 1;
Map<Integer, PopulationContext> contextMap;
// Gather all chromosomes' unique IDs
// String = ID, IChromosome = Chromosome for ID, List = Index of Generation
// the chromosome appears in
Map<String, Map<IChromosome, List<Integer>>> chromIDs = new Hashtable();
// For each generator/evolution round...
// -------------------------------------
for (int i = 0; i <= size; i++) {
int evNo = evolutionIndexes.get(i);
contextMap = a_data.get(evNo);
Iterator<PopulationContext> values = contextMap.values().iterator();
// For each recorded Population state within a generation.
// -------------------------------------------------------
while (values.hasNext()) {
PopulationContext ctx = values.next();
Population pop = ctx.getPopulation();
// For each chromosome...
// ----------------------
for (int j = 0; j < pop.size(); j++) {
IChromosome chrom = pop.getChromosome(j);
Map<IChromosome, List<Integer>> entry = chromIDs.get(chrom.getUniqueID());
List valueList;
if(entry == null) {
// Add a new list with the first found evolution number.
// -----------------------------------------------------
valueList = new Vector();
valueList.add(evNo);
Map valueMap = new Hashtable();
valueMap.put(chrom, valueList);
chromIDs.put(chrom.getUniqueID(), valueMap);
}
else {
// Already found in another evolution, just add the new number.
// ------------------------------------------------------------
valueList = entry.values().iterator().next();
if(!valueList.contains(evNo)) {
valueList.add(evNo);
}
}
}
}
}
return chromIDs;
}
/**
* Sample usage of monitoring, together with an existing JGAP example.
*
* @param args String[]
* @throws Exception
*
* @author Klaus Meffert
* @since 3.5
*/
// public static void main(String[] args)
// throws Exception {
// args = new String[2];
// args[0] = "93";
// args[1] = "MONITOR";
// MinimizingMakeChange.main(args);
// IEvolutionMonitor monitor = MinimizingMakeChange.m_monitor;
// EvolutionEvaluator evaluator = new EvolutionEvaluator(
// monitor.getPopulations());
// evaluator.evaluate();
// }
}