/*
* 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.PopulationHistoryIndexed;
/**
* A meta monitor that chains together given monitors and executes them
* subsequently.
*
* @author Klaus Meffert
* @since 3.4.4
*/
public class ChainedMonitors
implements IEvolutionMonitor {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.4 $";
private List<IEvolutionMonitor> m_monitors;
private int m_positiveMonitorsRequired;
/**
*
* @param a_monitors sequence of monitors to use
* @param a_positiveMonitorsRequired number of monitors that must return true
* in nextCycle in order to let the evolution continue. If this parameter
* equals one, it means we have an or-operation, if it equals the number of
* monitors, we have an and-operation.
*
* @author Klaus Meffert
* @since 3.4.4
*/
public ChainedMonitors(List<IEvolutionMonitor> a_monitors,
int a_positiveMonitorsRequired) {
if (a_monitors == null || a_monitors.size() < 1) {
throw new IllegalArgumentException(
"Number of monitors must be one or greater!");
}
if (a_positiveMonitorsRequired < 1) {
throw new IllegalArgumentException(
"Number of positive monitors must be one or greater!");
}
if (a_positiveMonitorsRequired > a_monitors.size()) {
throw new IllegalArgumentException("Number of positive monitors must not"
+ " be bigger than number of available monitors!");
}
m_monitors = a_monitors;
m_positiveMonitorsRequired = a_positiveMonitorsRequired;
}
/**
* Called after another evolution cycle has been executed.
*
* @param a_pop the currently evolved population
* @param a_messages the monitor can append messages here 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) {
int size = m_monitors.size();
int positive = 0;
for (IEvolutionMonitor monitor : m_monitors) {
if (monitor.nextCycle(a_pop, a_messages)) {
positive++;
if (positive >= m_positiveMonitorsRequired) {
return true;
}
}
else {
// Check for early fail.
// ---------------------
size--;
if (size + positive < m_positiveMonitorsRequired) {
return false;
}
}
}
return false;
}
/**
* Called just before the evolution starts.
*
* @param a_config the configuration used
*/
public void start(Configuration a_config) {
for (IEvolutionMonitor monitor : m_monitors) {
monitor.start(a_config);
}
}
/**
* 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) {
for (IEvolutionMonitor monitor : m_monitors) {
monitor.event(a_monitorEvent, a_evolutionNo, a_information);
}
}
/**
* @return null, use getMonitors() and then call each monitor's method
*
* @author Klaus Meffert
* @since 3.5
*/
public PopulationHistoryIndexed getPopulations() {
return null;
}
/**
* @return List of monitors registered
*
* @author Klaus Meffert
* @since 3.5
*/
public List<IEvolutionMonitor> getMonitors() {
return m_monitors;
}
}