/*
* 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.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import org.epochx.Config.ConfigKey;
/**
* A <code>Population</code> is an ordered collection of {@link Individual}s.
*/
public class Population implements Iterable<Individual>, Cloneable {
// TODO: make it serializable
/**
* The key for setting and retrieving the population size configuration
* parameter.
*/
public static final ConfigKey<Integer> SIZE = new ConfigKey<Integer>();
/**
* The list of individuals of this propulation.
*/
private ArrayList<Individual> individuals;
/**
* Constructs an empty <code>Population</code>.
*/
public Population() {
individuals = new ArrayList<Individual>(Config.getInstance().get(SIZE));
}
/**
* Returns the number of individuals within this population.
*
* @return the number of individuals in this population
*/
public int size() {
return individuals.size();
}
/**
* Appends the specified individual to the end of this population.
*
* @param individual the individual to add to this population
*/
public void add(Individual individual) {
individuals.add(individual);
}
/**
* Returns the individual at the specified index in this population.
*
* @param index the index of the individual to be returned
* @return the individual at the specified index position
* @throws IndexOutOfBoundsException if the index is out of range
* <code>(index < 0 || index > size())</code>
*/
public Individual get(int index) {
return individuals.get(index);
}
/**
* Returns the individual in this population with the best fitness. If
* multiple individuals have equal fitnesses then the individual with the
* lowest index will be returned.
*
* @return an <code>Individual</code> with the best fitness in this
* population.
*/
public Individual fittest() {
Individual fittest = null;
for (Individual individual: individuals) {
if ((fittest == null) || (individual.compareTo(fittest) > 0)) {
fittest = individual;
}
}
return fittest;
}
/**
* Returns the group of best individuals of the population.
*
* @param size the number of individuals of the group (elite).
*
* @return the group of best individuals of the population.
*/
public Individual[] elites(int size) {
Population copy = this.clone();
copy.sort();
Individual[] fittest = new Individual[size];
for (int i = 0; i < size; i++) {
fittest[i] = copy.get(i);
}
return fittest;
}
/**
* Sorts this population according to the natural ordering provided by its
* individuals' fitness from best to worst.
*/
public void sort() {
Collections.sort(individuals, new Comparator<Individual>() {
@Override
public int compare(Individual o1, Individual o2) {
return o2.compareTo(o1);
}
});
}
/**
* Returns an iterator over the individuals in this population.
*
* @return an iterator over the individuals in this population.
*/
@Override
public Iterator<Individual> iterator() {
return individuals.iterator();
}
/**
* Returns true if this population contains the specified individual.
*
* @return true if this population contains the individual and false
* otherwise
*/
public boolean contains(Individual individual) {
return individuals.contains(individual);
}
@Override
public Population clone() {
try {
Population clone = (Population) super.clone();
clone.individuals = new ArrayList<Individual>(individuals);
return clone;
} catch (CloneNotSupportedException e) {
// This shouldn't happen, since we are Cloneable.
throw new InternalError();
}
}
}