/*
* 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.distr;
import org.jgap.*;
/**
* Breeds populations using a GA that will be executed either on a single
* server or on multiple servers, whose results will be merged/synchronized
* later on.
* <p>
* A breeder is part of a fractal structure (fractal because each Breeder can
* be parent and/or child of other Breeder's).
*
* @author Klaus Meffert
* @since 2.0
*/
public abstract class Breeder
implements Runnable {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.13 $";
/**
* The parent Breeder to report to
*/
private Breeder m_master; /**@todo use*/
/**
* The child Breeder's doing work for us and reporting to this Breeder.
*/
private Breeder[] m_workers; /**@todo use*/
/**
* The Genotype this Breeder is responsible for
*/
private Genotype m_genotype; /**@todo construct somewhere*/
/**
* Helper class for merging together two Populations into one.
*/
private IPopulationMerger m_populationMerger; /**@todo use*/
private transient boolean m_running;
private transient boolean m_stopped = true;
private transient MeanBuffer m_meanBuffer = new MeanBuffer(40);
public Breeder(final IPopulationMerger a_populationMerger) {
super();
m_populationMerger = a_populationMerger;
}
/**
* Runs the evolution.
*
* @author Klaus Meffert
* @since 2.0
*/
public void run() {
try {
m_stopped = false;
while (m_running) {
evalOneGeneration();
int sleepTime = m_meanBuffer.mean() / 100;
if (sleepTime <= 0) {
pause(1);
}
else {
pause(sleepTime);
}
}
m_stopped = true;
}
catch (Throwable t) {
m_stopped = true;
m_running = false;
// if (exHandler != null) {
// exHandler.handleThrowable(t);
// }
}
}
/**
* Evaluate one generation and memorize the time needed. This is important
* for load balancing and calculating the performance of a system
* @throws Exception
*
* @author Klaus Meffert
* @since 2.0
*/
private void evalOneGeneration()
throws Exception {
long begin = System.currentTimeMillis();
m_genotype.evolve(1);
informParent();
m_meanBuffer.add( (int) (System.currentTimeMillis() - begin));
}
protected void informParent() {
/**@todo implement*/
}
/**
* Pauses the Breeder. This is important if a user providing a system for
* running the GA does not want to make available 100% of his CPU resources.
* @param a_milliSec number of milliseconds to wait
*
* @author Klaus Meffert
* @since 2.0
*/
private synchronized void pause(final int a_milliSec) {
try {
wait(a_milliSec);
}
catch (InterruptedException e) {
;
}
}
public void start() {
if (!m_running) {
m_running = true;
Thread thread = new Thread(this);
thread.start();
}
}
public void stop() {
if (m_running) {
m_running = false;
if (m_genotype != null) {
/**@todo implement*/
//: genAlgo.stop();
/*
if (genAlgo.getRacer() != null) {
genAlgo.getRacer().reset();
}
*/
}
}
}
public boolean isRunning() {
return m_running;
}
public boolean canBeStarted() {
return !m_running;
}
public boolean canBeStopped() {
return m_running;
}
}
/**
* A buffer that calculate the mean of a certain amount
* of values. Uses a fifo inside.
*/
class MeanBuffer {
private int[] m_buf = null;
private int m_size;
private int m_index;
public MeanBuffer(final int a_size) {
m_size = a_size;
m_buf = new int[m_size];
for (int i = 0; i < m_size; i++) {
m_buf[i] = 0;
}
}
public void add(final int a_val) {
m_buf[m_index] = a_val;
m_index = (m_index + 1) % m_size;
}
public int mean() {
int sum = 0;
for (int i = 0; i < m_size; i++) {
sum += m_buf[i];
}
return sum / m_size;
}
public void reset() {
for (int i = 0; i < m_size; i++) {
m_buf[i] = 0;
}
}
}