/*
 * 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 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 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 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 getMonitors() {
    return m_monitors;
  }
}

 

Ads help maintain this website.