Population.java
package progen.kernel.population;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import progen.context.ProGenContext;
import progen.kernel.grammar.Grammar;
/**
* Clase que representa a una población completa en programación genética.
*
* @author jirsis
* @since 1.0
*/
public class Population {
private static final String PROGEN_TOTAL_RPB_PROPERTY = "progen.total.RPB";
private static final String PROGEN_POPULATION_SIZE_PROPERTY = "progen.population.size";
/**
* Gramáticas que definirán los distintos árboles que representa a un
* individuo.
*
* @see Individual
*/
private Map<String, Grammar> grammars;
/** Indica el número de árboles RPB que tiene cada individuo de la poblción. */
private int totalRPB;
/** Indica el número de árboles ADF que tiene cada individuo de la poblción. */
private int totalADF;
/** Representación del conjunto de individuos que conforman la población. */
private List<Individual> individuals;
/**
* Constructor genérico de la clase. Carga la población en función del tamaño
* definido en el fichero de configuración, a través de la propiedad
* <code>progen.population.size</code>
*
*/
public Population() {
final int populationSize = ProGenContext.getOptionalProperty(PROGEN_POPULATION_SIZE_PROPERTY, 100);
ProGenContext.setProperty(PROGEN_POPULATION_SIZE_PROPERTY, String.valueOf(populationSize));
final Population pop = new Population(populationSize);
this.grammars = pop.grammars;
this.individuals = pop.individuals;
this.totalADF = pop.totalADF;
this.totalRPB = pop.totalRPB;
}
/**
* Constructor de la clase que crea una población del tamaño especificado en
* el parámetro.
*
* @param populationSize
* Tamaño de la población a crear.
*/
public Population(int populationSize) {
grammars = new HashMap<String, Grammar>();
totalRPB = 0;
totalADF = 0;
this.loadGrammars();
individuals = new ArrayList<Individual>();
initIndividuals(populationSize);
}
/**
* Crea las estructuras de las gramáticas que se utilizarán para crear todos
* los árboles de los individuos.
*/
private void loadGrammars() {
totalRPB = ProGenContext.getOptionalProperty(PROGEN_TOTAL_RPB_PROPERTY, 1);
ProGenContext.setProperty(PROGEN_TOTAL_RPB_PROPERTY, String.valueOf(totalRPB));
totalADF = ProGenContext.getOptionalProperty("progen.total.ADF", 0);
loadGrammar("RPB", totalRPB);
loadGrammar("ADF", totalADF);
}
/**
* Crea todas las gramáticas de un tipo determinado, RPB o ADF. Cargará en
* memoria una única instancia de la gramática generada por cada function-set,
* de tal forma, que si varios árboles comparten el mismo function-set,
* tendrán la misma referencia a la gramática que lo genera.
*
* @param type
* El tipo de gramática a cargar, [RPB | ADF].
* @param total
* Número total de gramáticas que hay que cargar.
*
*/
private void loadGrammar(String type, int total) {
Grammar grammarLoaded;
String functionSet;
for (int i = 0; i < total; i++) {
grammarLoaded = null;
functionSet = ProGenContext.getMandatoryProperty("progen." + type + i + ".functionSet");
for (Grammar grammar : grammars.values()) {
if (grammar.getFunctionSetId().equals(functionSet)) {
grammarLoaded = grammar;
}
}
if (grammarLoaded == null) {
grammarLoaded = Grammar.makeInstance(type + i);
}
grammars.put(type + i, grammarLoaded);
}
}
/**
* Inicialización del conjunto de individuos, indicando el tamaño de la
* población.
*
* @param populationSize
* El tamaño de la población.
*/
private void initIndividuals(int populationSize) {
for (int i = 0; i < populationSize; i++) {
individuals.add(new Individual(grammars));
}
}
/**
* Representación de la población en forma de String. Se consigue una
* representación de todos los individuos que conforman cada población.
*/
public String toString() {
final StringBuilder population = new StringBuilder();
for (int i = 0; i < individuals.size(); i++) {
population.append(individuals.get(i)).append("\n");
}
return population.toString();
}
/**
* Devuelve el conjunto de individuos que componene la población.
*
* @return los individuos.
*/
public List<Individual> getIndividuals() {
return individuals;
}
/**
* Devuelve el idindividuo que ocupa la posición indicada como parámetro.
*
* @param individualId
* El identificador del individuo.
* @return El individuo deseado.
*/
public Individual getIndividual(int individualId) {
return individuals.get(individualId);
}
/**
* Método para establecer un nuevo conjunto de individuos que formará la
* población.
*
* @param individuals
* El nuevo conjunto de individuos que define la población.
*/
public void setPopulation(List<Individual> individuals) {
this.individuals = individuals;
}
/**
* Devuelve el individuo que tiene el valor más bajo de <i>rawFitness</i>
*
* @return El mejor individuo de toda la población.
*/
public Individual getBestIndividual() {
Individual best;
Individual candidate;
best = this.getIndividual(0);
for (int i = 1; i < individuals.size(); i++) {
candidate = getIndividual(i);
if (candidate.getRawFitness() < best.getRawFitness()) {
best = candidate;
}
}
return best;
}
/**
* Returns the size of the population
*
* @return the size of the population
*/
public int size() {
return individuals.size();
}
}