/*
* Copyright 2007-2013
* Licensed under GNU Lesser General Public License
*
* This file is part of EpochX
*
* EpochX is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EpochX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with EpochX. If not, see <http://www.gnu.org/licenses/>.
*
* The latest version is available from: http://www.epochx.org
*/
package org.epochx;
import java.util.List;
import org.epochx.Config.Template;
import org.epochx.event.ConfigEvent;
import org.epochx.event.EventManager;
import org.epochx.event.GenerationEvent.EndGeneration;
import org.epochx.event.GenerationEvent.StartGeneration;
import org.epochx.event.Listener;
/**
* A <code>GenerationalStrategy</code> is an evolutionary strategy with clearly
* defined generations. It consists of a main loop that is executed until a
* termination criteria is met. At each iteration of the loop, a new population
* is created using the pipeline's components.
*
* The main loop can be illustrated as:
*
* <pre>
* while (!terminate) {
* generate (and optionally evaluate) new population
* }
* </pre>
*
* The {@link TerminationCriteria} is obtained from the {@link Config}, using
* the appropriate <code>ConfigKey</code>. A new population is generated using
* the pipeline's components, which typically will include a {@link Breeder} and
* {@link FitnessEvaluator} instances.
*
* @see Breeder
* @see FitnessEvaluator
* @see TerminationCriteria
*/
public class GenerationalStrategy extends Pipeline implements EvolutionaryStrategy, Listener<ConfigEvent> {
/**
* The list of termination criteria.
*/
private List<TerminationCriteria> criteria;
/**
* Constructs a <code>GenerationalStrategy</code> with the provided
* components. One of those components would typically be a {@link Breeder}.
*
* @param components
*/
public GenerationalStrategy(Component ... components) {
for (Component component: components) {
add(component);
}
setup();
EventManager.getInstance().add(ConfigEvent.class, this);
}
/**
* Evolves the population until the termination criteria is met. A
* {@link StartGeneration} event is fired at the start of the generation
* and an {@link EndGeneration} event at the end of the generation.
*
* @param population the population to be evolved
*
* @return the evolved population.
*/
@Override
public Population process(Population population) {
int generation = 1;
while (!terminate()) {
EventManager.getInstance().fire(new StartGeneration(generation, population));
population = super.process(population);
EventManager.getInstance().fire(new EndGeneration(generation, population));
generation++;
}
return population;
}
/**
* Returns <code>true</code> if any of the termination criteria is met.
*
* @return <code>true</code> if any of the termination criteria is met;
* <code>false</code> otherwise.
*/
protected boolean terminate() {
for (TerminationCriteria tc: criteria) {
if (tc.terminate()) {
return true;
}
}
return false;
}
/**
* Looks up the {@link TerminationCriteria} and the {@link FitnessEvaluator}
* in the {@link Config}.
*/
protected void setup() {
criteria = Config.getInstance().get(EvolutionaryStrategy.TERMINATION_CRITERIA);
}
/**
* Receives {@link ConfigEvent} event notifications.
*
* @param event the fired event.
*/
@Override
public void onEvent(ConfigEvent event) {
if (event.isKindOf(Template.TEMPLATE, EvolutionaryStrategy.TERMINATION_CRITERIA)) {
setup();
}
}
}