SlideShare uma empresa Scribd logo
1 de 66
Anatomía de un algoritmo genético en Jenes
Programación en Jenes es fácil, intuitiva y divertida. En esta sección, vamos a proporcionar
algunos conceptos que hay que tener en cuenta al esbozar una solución en Jenes. Estos
conceptos le ayudarán a moverse de manera efectiva entre las clases previstas en el API
Jenes. Usted se sorprenderá de lo rápido que se puede definir un algoritmo genético,
implementado y probado.
Los cromosomas, individuos y poblaciones.
La primera cosa a tener en cuenta es la diferencia entre los cromosomas, los individuos y
las poblaciones.

Soluciones en un espacio de búsqueda se representan por los individuos. Están hechas de
un cromosoma y de la aptitud de valor: INDIVIDUAL = CROMOSOMA + FITNESS.

Los cromosomas son las codificaciones de solución. En Jenes, se les considera como un
conjunto de genes. Aquí está una lista de las clases de cromosomas proporcionadas por
Jenes.
BitwiseChromosome: modelos de un cromosoma de bits. Su genoma contiene valores
codificados otorgado a la codificación de bits especificado.
BooleanChromosome: modelos de un cromosoma de valores booleanos. Cada gen alelo
puede ser verdadera o falsa.
DoubleChromosome: modelos de un cromosoma de valores dobles. Cada valor está en el
rango [lowerBound, upperBound]. Estos límites se especifican en el momento de
instancias.
IntegerChromosome: modelos de un cromosoma de valores enteros. Cada valor está en el
rango [lowerBound, upperBound]. Estos límites se especifican en el momento de
instancias.
ObjectChromosome: representa un cromosoma con genes que contiene un valor de alelo
objeto.
PermutationChromosome: proporciona un cromosoma capaz de modelar permutaciones.
Una matriz de valores enteros es su genoma. La propiedad más importante es que el
genoma no contiene valores duplicados.
Todas las clases de cromosomas son la implementación de la interfaz del cromosoma. En
general, los cromosomas se fija número de genes, pero su longitud puede variar durante la
ejecución del algoritmo con el fin de implementar una codificación de longitud variable de
solución. Una población es simplemente una colección de individuos (por ejemplo,
soluciones).

Los individuos son todas las instancias de la clase paramétrica individual <T extiende
Chromosome>, con el fin de tener un mayor control sobre los tipos. Un individuo puede ser
legal o no legal. Es posible ajustar el lagality de un individuo mediante la invocación del
método setLegal (boolen) en su instancia. Por defecto, cada individuo se fija te bo
inicialmente legal.

Durante la evolución de algoritmos, las poblaciones del pasado se almacenan en la historia
del algoritmo. En cada iteración de la evolución, la población más antigua y sus individuos
se vuelven a utilizar. Las poblaciones del pasado, en lugar de ser cancelado la asignación,
se mantenido en la memoria y volver a utilizar. Esta técnica evita la asignación en memoria
de las nuevas poblaciones y limita el uso del recolector de basura.

Como se ha dicho, un algoritmo genético procesa una población de individuos. En cada
generación hay poblaciones de entrada y salida. Es importante tener en cuenta que la
población de salida se pre-inizialized con individuos "reciclados" tomados de la historia
(por razones de rendimiento). Así Jenes generalmente no asigna nuevos individuos.
Estructura Algoritmo

Jenes proporciona una estructura flexible para la evolución de una población de individuos.
En general, un algoritmo genético está estructurado como se muestra en la figura.
Básicamente, un algoritmo genético realiza el siguiente bucle:
Aleatoriamente crear una población inicial
repetición
Valorar la aptitud de cada individuo
Seleccione uno o más individuos de la población con una probabilidad basada en la
aptitud para partecipate en las operaciones genéticas
Crear nuevos individuos mediante la aplicación de las operaciones genéticas con
probabilidades especificadas
hasta que una solución aceptable se encuentra o se cumpla alguna otra condición parar
devolverle al individuo mejor tan lejos
En Jenes un algoritmo genético se puede implementar mediante el uso o la subclasificación
GeneticAlgorithm y definir una implementación de funcion gimnasio subclasificando
Fitness y la implementación del método abstracto evaluar (Individual). Este método se
utiliza para evaluar la capacidad de un solo individuo. La implementación de este método
está relacionada específicamente con el problema a resolver.
En Jenes cuerpo algoritmo genético es un "tubo" de etapas. Las etapas se ejecutan
secuencialmente en el orden en que se agregan a la secuencia. Cada etapa recibe una
población de entrada (producido como salida por la etapa anterior) y produce una población
de salida. ¿Qué etapas y en qué orden para considerar que queda a las necesidades del
algoritmo.

La referencia a la actual y en el proceso de llenado se puede respectivamente obtiene por la
getCurrentPopulation métodos () y getNextPopulation ().

Jenes también permite definir etapas paralelas. Una etapa paralelo está formado por
diferentes ramas, cada rama es una etapa que recibe una subpoblación de acuerdo con el
dispensador de población utilizada. Un dispensador distribuye una población entre las
ramas de una etapa en paralelo y se funde la salida de cada rama en la población de salida
del paralelo.
El punto de quiebre y los operadores genéticos representan las etapas de tuberías generales
más simples.

Una etapa BreakPoint notifica a sus oyentes cuando se invocated su método de proceso. No
alterate la población de entrada.

Operadores genéticos utilizados en los algoritmos genéticos son análogos a éstos que se
producen en el mundo natural:
Selección: la que da preferencia a los mejores individuos, que les permite pasar a la
siguiente generación.
Crossover: lo que representa el apareamiento entre individuos.
Mutación: que introduce modificaciones aleatorias.
Jenes proporciona la implementación de los operadores genéticos más comunes:
TournamentSelector: choses a un número aleatorio de individuos de la población. Estos se
comparan entre sí y el mejor de ellos es elegido para ser un padre. Selector torneo hace
asegurar que incluso los individuos de calidad media tienen alguna posibilidad de tener
hijos. En Jenes es necesario especificar el número de intentos de torneo.
RouletteWheelSelector: coge un miembro particular de la población para ser un padre con
una probabilidad igual a su condición física, dividido por el total de la aptitud de la
población.
OnePointCrossover: elige al azar un punto de cruce de los cromosomas de los padres y crea
una nueva descendencia. Uno de los puntos de cruce puede tener este aspecto (donde "|" es
el punto de cruce):
Chromosome 1 11101 | 001000
Chromosome 2 00001 | 010101
Offspring 1

11101 | 010101

Offspring 2

00001 | 001000

TwoPointsCrossover: escoge al azar dos puntos de cruce de los cromosomas de los padres y
crea una nueva descendencia. Dos puntos de cruce puede tener este aspecto:
Chromosome 1 11 | 10100 | 1000
Chromosome 2 00 | 00101 | 0101
Offspring 1

11 | 00101 | 1000

Offspring 2

00 | 10100 | 0101

En Jenes necesita especificar la probabilidad por la cual se utilizará el operador de cruce.
En general, para un operador de cruce la probabilidad se establece en 80%

Mutador simple: choses al azar un punto de mutación y aleatoriza su gen. Operador de
mutación también necesita un número probabilidad que especifica su uso.
En general, para un operador de mutación la probabilidad se establece en 20%.

Jenes proporciona también una interfaz sencilla para GeneticAlgorithm. Es SimpleGA clase
que implementa un algoritmo genético tres etapas hecha de una herramienta de selección,
uno de cruce y uno Mutador en secuencia.
Ofrece una forma sencilla de implementar su propio algoritmo genético que le permite
descuidar los problemas relacionados con la construcción de los estadios.
La clase proporciona un conjunto de constructores por lo que crear una instancia de un
algoritmo SimpleGA. Constructores permite decidir qué método de selección (es decir,
Torneo o ruleta) o el método cruzado (es decir, un punto o dos puntos) a adoptar. También
cruce y probabilidad de mutación puede ser especificado en el momento de la construcción.
SimpleGA es una subclase GeneticAlgorithm.

Jenes incluye un soporte para el elitismo, es decir los mejores individuos de cada
generación tienen la garantía de estar en la próxima generación. El número de individuos de
la élite es fijado por el setElitism método (int).
Estos individuos se sustituyen a algunos individuos a la población procesada de acuerdo
con las siguientes estrategias:
Random Estrategia Elitismo: próximos individuos de población son seleccionados al azar y
se sustituye por la élite.
Peor Estrategia Elitismo: próximo de población peores individuos son sustituidos por la
élite.
Usted puede configurar su estrategia de elitismo preferida de la siguiente manera:
sga.setElitismStrategy(ElitismStrategy.RANDOM);
or
sga.setElitismStrategy(ElitismStrategy.WORST);

La primera estrategia es más eficiente, ya que no requiere para ordenar la población. El
inconveniente es que los individuos con una buena aptitud podrían ser sustituidos por la
élite. La segunda estrategia es más lento, pero asegura que sólo los peores individuos están
sustituidos.

Jenes utiliza el MersenneTwisterRandom clase para la generación de números y valores de
pseudo-aleatorios. Este una clase optimizado que proporciona para la generación rápida de
números aleatorios de muy alta calidad. Por esta razón, se utiliza en lugar de
java.util.Random. La generación de números pseudoaleatorios es muy útil durante todas las
fases de la evolución algoritmo (tales como la inicialización de la población, el uso de
operadores de selección, la determinación de puntos de cruce y mutación, y así
sucesivamente).

Eventos, oyentes y Estadísticas
La ejecución del algoritmo genético es invocado por el método de evolucionar (). La
ejecución del algoritmo pasa a través de los siguientes eventos:
Inicio: la evolución algoritmo comienza.
Init: estructuras internas, como la población dada como entrada a la generación 0 y la
historia, se inicializan.
Generación: una generación se ha acaba de realizar.
Stop: el algoritmo termina sus ejecuciones.
Cada uno de estos eventos pueden ser capturados por AlgorithmEventListeners y
GenerationEventListeners. También pueden ser caputured por la subclase
GeneticAlgorithm, reemplazando los métodos onStart (largos), onInit (largo), onGeneration
(tiempo) y onStop (largo). La captura de eventos es útil para recopilar estadísticas y realizar
análisis.

AlgorithmEventListeners proporciona la interfaz para la captura de eventos a nivel de
algoritmo. Esta interfaz debe ser implementado por todas las clases interesadas en beign
notificado
por
acontecimientos
algoritmo
(Start,
inicio,
parada).
Un
AlgorithmEventListener se puede registrar en el algoritmo por el método
GeneticAlgorithm.addAlgorithmEventListener (AlgorithmEventListener). El oyente puede
ser
eliminado
por
la
invocación
del
método
GeneticAlgorithm.removeAlgorithmEventListener (AlgorithmEventListener).

GenerationEventListener es un oyente del evento de generación de algoritmo genético. Esta
escucha se notifica una vez que se ejecuta una etapa de generación. A
GenerationEventListener se puede registrar en el algoritmo por el método
GeneticAlgorithm.addGenerationEventListener (GenerationEventListener). El oyente
puede
ser
eliminado
por
la
invocación
del
método
GeneticAlgorithm.removeGenerationEventListener (GenerationEventListener).
Durante la evolución del algoritmo genético , Jenes recopila estadísticas sobre:
Ejecución de algoritmo: La clase GeneticAlgorithm.Statistics se encarga de almacenar
información sobre el tiempo dedicado por todo el proceso evolutivo y el número de
generaciones creadas . Puede invocar el método () GeneticAlgorithm.getStatistics para
obtener las estadísticas de algoritmos .
Población: La clase Population.Statistics se encarga de almacenar información sobre una
población. A medida que cada lata población contiene individuos legales e ilegales ,
mantiene los individuos con la aptitud mayor y menor , los valores medios y la desviación
ambos consideran a las personas jurídicas y las ilegales . Puede invocar el método las
Population.getStatistics () para obtener sus estadísticas .
Operadores: Las Selection.Statistics , Crossover.Statistics y Mutator.Statistics clases son
responsables de almacenar información sobre los operadores utilizados y el tiempo
empleado para su ejecución . Ellos sostienen respectivamente el número de cruce ,
selección y mutación realizado . Puede invocar el método () Operator.getStatistics en una
instancia de la clase operador para obtener sus estadísticas.
Un problema boolean sencilla
Vamos a empezar con un problema sencillo. Dado un espacio de búsqueda hecha de
variables booleanas, nuestro objetivo es encontrar una solución hecha de verdaderos valores
(o valores falsos). Este problema es enfrentado por el diseño de un algoritmo genético de
trabajo en los cromosomas booleanos. La función de aptitud se calcula contando el número
de verdaderos valores dentro del cromosoma. Así que con el fin de encontrar la solución
con todos los verdaderos valores podemos maximizar la función de aptitud, mientras que se
minimiza la función de aptitud con el fin de encontrar una solución a base de todos los
falsos valores.

Este tutorial te dará la oportunidad de entender cómo se estructura un algoritmo genético y
taylored a un problema de optimización. Por otra parte, vamos a ver cómo los oyentes se
pueden utilizar para capturar los eventos algoritmos.
1. Elegir un problema cromosómico adecuado y crear la población inicial.
La elección de una representación cromosómica adecuada es la tarea más importante que
hacer antes de ejecutar un algoritmo genético. ¿Qué representación a utilizar depende de la
estructura de las soluciones a los problemas. En nuestro caso, las soluciones están hechas
de matrices booleanas. Por lo tanto, BooleanChromosome parece ser la opción
approppriate. Los cromosomas representan el componente clave de las soluciones (es decir,
individuos). Para la construcción de la población inicial que necesitamos un prototipo de
soluciones (muestra), como se muestra en el siguiente código.
060
Individual<BooleanChromosome> sample = new Individual<BooleanChromosome>(new BooleanC
hromosome(CHROMOSOME_LENGTH));
061
Population<BooleanChromosome> pop = new Population<BooleanChromosome>(sample, POPUL
ATION_SIZE);
cuando
045
046
047

private static int POPULATION_SIZE=50;
private static int CHROMOSOME_LENGTH=100;
private static int GENERATION_LIMIT=1000;

2. Puesta en marcha del algoritmo genético.
Cualquier algoritmo en Jenes 2.0 se basa en GeneticAlgorithm, para wich debe definir una
función de aptitud que se utiliza para evaluar a los individuos. Para definir una función de
aptitud en Jenes 2.0 sólo tenemos que crear una subclase de fitness, una clase abstracta, la
aplicación del método de evaluar (individual).
Cualquier algoritmo en Jenes se basa en GeneticAlgorithm, una clase abstracta cuyo único
método es abstracto evaluateIndividual que es un problema dependiente. A continuación se
muestra el código para crear una subclase de GeneticAlgorithm y evaluar a un individuo en
nuestro problema.

Por ejemplo, podría ser fácil de definir una función de aptitud mediante el uso de una clase
interna anónima como seguimiento:
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077

Fitness<BooleanChromosome> fit = new Fitness<BooleanChromosome>(false) {
@Override
public void evaluate(Individual<BooleanChromosome> individual) {
BooleanChromosome chrom = individual.getChromosome();
int count = 0;
int length=chrom.length();
for(int i=0;i<length;i++)
if(chrom.getValue(i))
count++;
individual.setScore(count);
}
};

Y luego pasar este objeto como primer parámetro de algoritmo genético (o cualquier
subclase predefinido)
079
080

GeneticAlgorithm<BooleanChromosome> ga = new GeneticAlgorithm<BooleanChromosome>
(fit, pop, GENERATION_LIMIT);

La clase de fitness ofrece dos constructores diferentes para definir el número de objetivos a
considerar en la evaluación de las personas, y para cada objetivo de la bandera que indica si
se trata de una función de maximizar o no. En el código que aparece más arriba, creamos
un gimnasio para un solo problema objetivo (sólo una bandera como parámetros).

3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en
el ga.

Una vez definido el algoritmo genético, es necesario especificar la secuencia de la
población operadores atravesará. El esquema más simple contiene sólo tres operadores en
secuencia: un selector, una de cruce y uno de mutador. Sin embargo, es posible crear un
tubo más complejo que tiene paralléles y secuencias. A los efectos de este tutorial vamos a
adoptar la siguiente estructura simple (ver APIs forman más detalles sobre los operadores
adoptados):
082
083
);
084
085
086
087

AbstractStage<BooleanChromosome> selection = new TournamentSelector<BooleanChromosome>(3);
AbstractStage<BooleanChromosome> crossover = new OnePointCrossover<BooleanChromosome>(0.8
AbstractStage<BooleanChromosome> mutation = new SimpleMutator<BooleanChromosome>(0.02);
ga.addStage(selection);
ga.addStage(crossover);
ga.addStage(mutation);

4. Establezca los parámetros del algoritmo y ejecutar la evolución.

Es posible personalizar el ajuste del valor de elitismo algoritmo genético y el objetivo de
optimización antes de ejecutar la evolución. El elitismo es el número de las mejores
personas para celebrar en la próxima generación (1 en nuestro caso).
089

ga.setElitism(1);

Por último, podemos hacer que el algoritmo de funcionamiento.
091

ga.evolve();

5. Obtención del resultado de la evolución.
Jenes proporciona estadísticas tanto para el algoritmo y la población. La primera referencia
a las estadísticas relativas a la ejecución de algoritmo, es decir, los tiempos de
inicialización, comenzando, la evolución y las generaciones. El segundo a la distribución de
soluciones y servicios conexos valores de fitness, como las personas ordenadas por la
disminución de la función física, la media máxima, y mínima de los valores de fitness.
Ellos se pueden recuperar en cualquier momento. Le llamaremos cuando el algoritmo ha
terminado.
093
094
095
096
"));
097
098
099
100
101
102
103

Population.Statistics stats = ga.getCurrentPopulation().getStatistics();
GeneticAlgorithm.Statistics algostats = ga.getStatistics();
System.out.println("Objective: " + (fit.getBiggerIsBetter()[0] ? "Max! (All true)" : "Min! (None true)
System.out.println();
Group legals = stats.getGroup(Population.LEGALS);
Individual solution = legals.get(0);
System.out.println("Solution: ");
104
105
106
107
108

System.out.println( solution );
System.out.format("found in %d ms.n", algostats.getExecutionTime() );
System.out.println();
Utils.printStatistics(stats);

Ejemplo completo:
package jenes.tutorials.problem1;
import jenes.Fitness;
import jenes.GeneticAlgorithm;
import jenes.chromosome.BooleanChromosome;
import jenes.population.Individual;
import jenes.population.Population;
import jenes.population.Population.Statistics.Group;
import jenes.stage.AbstractStage;
import jenes.stage.operator.common.OnePointCrossover;
import jenes.stage.operator.common.SimpleMutator;
import jenes.stage.operator.common.TournamentSelector;
import jenes.tutorials.utils.Utils;

public class BooleanProblem {
private static int POPULATION_SIZE=50;
private static int CHROMOSOME_LENGTH=100;
private static int GENERATION_LIMIT=1000;
public static void main(String[] args) throws Exception {
Utils.printHeader();
System.out.println();
System.out.println("TUTORIAL 1:");
System.out.println("This algorithm aims to find a vector of booleans that is entirely true or false.");
System.out.println();
// Random.getInstance().setStandardSeed();
Individual<BooleanChromosome> sample = new Individual<BooleanChromosome>(new BooleanChro
mosome(CHROMOSOME_LENGTH));
Population<BooleanChromosome> pop = new Population<BooleanChromosome>(sample, POPULATI
ON_SIZE);
Fitness<BooleanChromosome> fit = new Fitness<BooleanChromosome>(false) {
@Override
public void evaluate(Individual<BooleanChromosome> individual) {
BooleanChromosome chrom = individual.getChromosome();
int count = 0;
int length=chrom.length();
for(int i=0;i<length;i++)
if(chrom.getValue(i))
count++;
individual.setScore(count);
}
};
GeneticAlgorithm<BooleanChromosome> ga = new GeneticAlgorithm<BooleanChromosome>
(fit, pop, GENERATION_LIMIT);
AbstractStage<BooleanChromosome> selection = new TournamentSelector<BooleanChromosome>(3);
AbstractStage<BooleanChromosome> crossover = new OnePointCrossover<BooleanChromosome>(0.8)
;
AbstractStage<BooleanChromosome> mutation = new SimpleMutator<BooleanChromosome>(0.02);
ga.addStage(selection);
ga.addStage(crossover);
ga.addStage(mutation);
ga.setElitism(1);
ga.evolve();
Population.Statistics stats = ga.getCurrentPopulation().getStatistics();
GeneticAlgorithm.Statistics algostats = ga.getStatistics();
System.out.println("Objective: " + (fit.getBiggerIsBetter()[0] ? "Max! (All true)" : "Min! (None true)"));
System.out.println();
Group legals = stats.getGroup(Population.LEGALS);
Individual solution = legals.get(0);
System.out.println("Solution: ");
System.out.println( solution );
System.out.format("found in %d ms.n", algostats.getExecutionTime() );
System.out.println();
Utils.printStatistics(stats);
}
}
Estructuración de un algoritmo genético avanzado
En nuestro segundo tutorial mostramos cómo crear un escenario paralelo y lo puso en la
secuencia algoritmo, cómo distribuir y combinar estrategias paralelas, cómo establecer una
condición de terminación definida por el usuario y cómo utilizar los oyentes de atrapar
eventos algoritmo. El objetivo en este problema tutorial es para encontrar la matriz más
cercano número entero (representable con un número especificado de cifras decimales) a
una de destino con cada número dentro de la gama [0,49].
1. Elegir un problema cromosómico adecuado y crear la población inicial
Un IntegerChromosome es una representación natural de la matriz de enteros, cada valor
gen se verá limitado en el rango [0,49] para respetar el problema de alcance restricción.
065
066

IntegerChromosome chrom = new IntegerChromosome(CHROMOSOME_LENGTH,0,MAX_INT);
Individual<IntegerChromosome> ind = new Individual<IntegerChromosome>(chrom);

Donde MAX_INT esta definido como:
059

private static int MAX_INT = 49;

2. Puesta en marcha del algoritmo genético.
En este tutorial vamos a crear una subclase de GeneticAlogithm llamado PatternGA en
wich personalizamos la condición de terminación del algoritmo ovverriding final () método
que mejor se expone en el apartado 4.

La aptitud de cada individuo es el error absoluto entre su cromosoma y el cromosoma de
destino. Por lo tanto, la mejor individuo es el uno con el error absoluto más pequeño. La
función de aptitud se codifica en clase PatternFitness definida como clase interna en
PatternGA. En este caso le ofrecemos una definición de un problema de un solo objetivo
que ofrece al programador la posibilidad de configurar el esquema de solución esperada y
la precisión mínima a alcanzar para detener la búsqueda.

El método de evaluar se mostró a continuación:
67
68
69
70
71
72
73
74
75
76

@Override
public void evaluate(Individual<IntegerChromosome> individual) {
IntegerChromosome chrom = individual.getChromosome();
int diff = 0;
int length = chrom.length();
for (int i = 0; i < length; i++) {
diff += Math.abs(chrom.getValue(i) - target[i]);
}
individual.setScore(diff);
}

3 . Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas
en la ga.
Supongamos que tenemos dos operadores de cruce diferentes (un punto con probabilidad
0,8 y dos puntos con una probabilidad de 0,5) para aplicarlos en dos subconjuntos de
población separados. En Jenes podemos hacer esto a través del uso de la clase paralela. Por
lo tanto organizamos los dos operadores de cruce como dos ramas paralelas de la tubería
principal.
El dispensador distribuye la población entre las ramas de la etapa en paralelo y se funde la
salida de cada rama en la población salida de la etapa paralela. En Jenes hay dos tipos de
dispenses : el dispencer general y la dispencer exclusiva . El dispencer en general permite
que , durante la operación de distribución, para agregar un individuo en más sucursales ( se
requieren copias de la misma persona para evitar la superposición de referencias entre
subpopolations sucursales ) . El dispencer exclusiva no lo permite: cada individuo se puede
agregar en una sola rama (no es necesario añadir una copia de la misma). Elegimos utilizar
un dispencer exclusiva. La aplicación se mostró a continuación.
43 public class SimpleDispenser<T extends Chromosome> extends ExclusiveDispenser<T> {
44
45 private int count;
46
47 public SimpleDispenser(int span) {
48
super(span);
49 }
50
51 public void preDistribute(Population<T> population){
52
this.count = 0;
53 }
54
55 @Override
56 public int distribute(Individual<T> ind) {
57
return count++ % span;
58 }
59
60 }

Esta implementación básica de un dispencer exclusiva utiliza una política de distribución
simple. Esto pone a las personas en posiciones pares en la primera rama y los individuos en
las posiciones impares en la rama otros. El método preDistribute es útil para restablecer el
estado dispencer. El método de distribuir devuelve el índice de la sección donde poner el
individuo especificado. No hay que preocuparse por la fusión de la salida de los manojos,
ya que se lleva a cabo por la clase ExclusiveDispencer.

El código siguiente muestra cómo crear un escenario paralelo y la inserta en la tubería.
072
AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(2
);
073
074
Parallel<IntegerChromosome> parallel = new Parallel<IntegerChromosome>(new SimpleDispense
r<IntegerChromosome>(2));
075
076
AbstractStage<IntegerChromosome> crossover1p = new OnePointCrossover<IntegerChromosome>
(0.8);
077
parallel.add(crossover1p);
078
079
AbstractStage<IntegerChromosome> crossover2p = new TwoPointsCrossover<IntegerChromosome
>(0.5);
080
parallel.add(crossover2p);
081
082
AbstractStage<IntegerChromosome> mutation = new SimpleMutator<IntegerChromosome>(0.02);
083
084
algorithm.addStage(selection);
085
algorithm.addStage(parallel);
086
algorithm.addStage(mutation);

3. Personalizar el algoritmo genético.
Como se dijo antes la meta de nuestro algoritmo genético es minimizar el error absoluto de
los individuos generados, con el fin de obtener una matriz de enteros, tan pronto como sea
posible cerca del destino.
En Jenes la evolución del algoritmo genético se ejecuta hasta que alcance el límite de
generación especificada o hasta que se cumpla un criterio de terminación. Para especificar
el criterio de terminación nuestro algoritmo genético tiene que reemplazar el método
"extremo". Por defecto, este método tiene un cuerpo vacío por lo que no tiene ningún efecto
sobre la evolución del algoritmo. En nuestro ejemplo, la evolución se detiene cuando el
valor de aptitud más bajo es inferior a un valor (denominado precisión) especificado por el
usuario.
52
53
54
55
56

@Override
protected boolean end() {
jenes.population.Population.Statistics stat = this.getCurrentPopulation(). getStatistics();
return stat.getGroup(Population.LEGALS).getMin()[0] <= this.fitness.precision;
}

La clase GeneticAlgorithm implementa el patrón Observer para notificar a sus oyentes la
ocurrencia de un evento en particular. En Jenes hay dos tipos de detectores de eventos: el
detector de eventos de generación (invocado cuando finaliza una generación) y el detector
de eventos algoritmo (Se invoca cuando un evento occours algoritmo, por ejemplo, el
inicio, el final y el inicio del algoritmo).
En este tutorial vamos optar por utilizar un detector de eventos de generación con el fin de
imprimir algunas informaciones al final de cada generación. El código de oyente se mostró
a continuación.
113
114

public void onGeneration(GeneticAlgorithm ga, long time) {
Statistics stat = ga.getCurrentPopulation().getStatistics();
115
116
117
118
119

Group legals = stat.getGroup(Population.LEGALS);
System.out.println("Current generation: " + ga.getGeneration());
System.out.println("tBest score: " + legals.getMin()[0]);
System.out.println("tAvg score : " + legals.getMean()[0]);
}

El código para añadir un detector de eventos generación en la clase Algoritmo Genético es:
087

algorithm.addGenerationEventListener(this);

En el código siguiente se resumen los principales pasos para la configuración del algoritmo
genético.
65
IntegerChromosome chrom = new IntegerChromosome(CHROMOSOME_LENGTH,0,MAX_INT);
066
Individual<IntegerChromosome> ind = new Individual<IntegerChromosome>(chrom);
067
Population<IntegerChromosome> pop = new Population<IntegerChromosome>(ind,
POPULATION_SIZE);
068
069
algorithm = new PatternGA(pop, GENERATION_LIMIT);
070
algorithm.setElitism(5);
071
072
AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(2
);
073
074
Parallel<IntegerChromosome> parallel = new Parallel<IntegerChromosome>(new SimpleDispense
r<IntegerChromosome>(2));
075
076
AbstractStage<IntegerChromosome> crossover1p = new OnePointCrossover<IntegerChromosome>
(0.8);
077
parallel.add(crossover1p);
078
079
AbstractStage<IntegerChromosome> crossover2p = new TwoPointsCrossover<IntegerChromosome
>(0.5);
080
parallel.add(crossover2p);
081
082
AbstractStage<IntegerChromosome> mutation = new SimpleMutator<IntegerChromosome>(0.02);
083
084
085
086
087

algorithm.addStage(selection);
algorithm.addStage(parallel);
algorithm.addStage(mutation);
algorithm.addGenerationEventListener(this);

Ejemplo1:
package jenes.tutorials.problem2;
020
021 import jenes.GenerationEventListener;
022 import jenes.GeneticAlgorithm;
023 import jenes.utils.Random;
024 import jenes.chromosome.IntegerChromosome;
025 import jenes.population.Individual;
026 import jenes.population.Population;
027 import jenes.population.Population.Statistics;
028 import jenes.population.Population.Statistics.Group;
029 import jenes.stage.AbstractStage;
030 import jenes.stage.Parallel;
031 import jenes.stage.operator.common.OnePointCrossover;
032 import jenes.stage.operator.common.SimpleMutator;
033 import jenes.stage.operator.common.TournamentSelector;
034 import jenes.stage.operator.common.TwoPointsCrossover;
035 import jenes.tutorials.utils.Utils;
054 public class PatternProblem implements GenerationEventListener<IntegerChromosome> {
055
056 private static int POPULATION_SIZE = 100;
057 private static int CHROMOSOME_LENGTH = 10;
058 private static int GENERATION_LIMIT = 1000;
059 private static int MAX_INT = 49;
060
061 private PatternGA algorithm = null;
062
063 public PatternProblem() {
064
065
IntegerChromosome chrom = new IntegerChromosome(CHROMOSOME_LENGTH,0,MAX_INT);
066
Individual<IntegerChromosome> ind = new Individual<IntegerChromosome>(chrom);
067
Population<IntegerChromosome> pop = new Population<IntegerChromosome>(ind, POPULATIO
N_SIZE);
068
069
algorithm = new PatternGA(pop, GENERATION_LIMIT);
070
algorithm.setElitism(5);
071
072
AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(2
);
073
074
Parallel<IntegerChromosome> parallel = new Parallel<IntegerChromosome>(new SimpleDispenser
<IntegerChromosome>(2));
075
076
AbstractStage<IntegerChromosome> crossover1p = new OnePointCrossover<IntegerChromosome>
(0.8);
077
parallel.add(crossover1p);
078
079
AbstractStage<IntegerChromosome> crossover2p = new TwoPointsCrossover<IntegerChromosome
>(0.5);
080
parallel.add(crossover2p);
081
082
AbstractStage<IntegerChromosome> mutation = new SimpleMutator<IntegerChromosome>(0.02);
083
084
algorithm.addStage(selection);
085
algorithm.addStage(parallel);
086
algorithm.addStage(mutation);
087
algorithm.addGenerationEventListener(this);
088 }
089
090 public void run(int[] target, int precision) {
091
((PatternGA.PatternFitness) algorithm.getFitness()).setTarget(target);
092
((PatternGA.PatternFitness) algorithm.getFitness()).setPrecision(precision);
093
algorithm.evolve();
094
095
Population.Statistics stats = algorithm.getCurrentPopulation().getStatistics();
096
GeneticAlgorithm.Statistics algostats = algorithm.getStatistics();
097
098
System.out.println();
099
System.out.print("Target:[");
100
for( int i = 0; i < target.length; ++i ) {
101
System.out.print(target[i]+ ( i < target.length - 1 ? " " : ""));
102
}
103
System.out.println("]");
104
System.out.println();
105
106
System.out.println("Solution: ");
107
System.out.println(stats.getGroup(Population.LEGALS).get(0));
108
System.out.format("found in %d ms and %d generations.n", algostats.getExecutionTime(), algostats
.getGenerations() );
109
System.out.println();
110 }
111
112
113 public void onGeneration(GeneticAlgorithm ga, long time) {
114
Statistics stat = ga.getCurrentPopulation().getStatistics();
115
Group legals = stat.getGroup(Population.LEGALS);
116
System.out.println("Current generation: " + ga.getGeneration());
117
System.out.println("tBest score: " + legals.getMin()[0]);
118
System.out.println("tAvg score : " + legals.getMean()[0]);
119 }
120
121 private static void randomize(int[] sample) {
122
for(int i=0;i<sample.length;i++)
123
sample[i] = Random.getInstance().nextInt(0, MAX_INT+1);
124 }
125
126 public static void main(String[] args) {
127
128
Utils.printHeader();
129
System.out.println();
130
131
System.out.println("TUTORIAL 2:");
132
System.out.println("This algorithm aims to autonomously find a vector of integers that best matches
with a target vector.");
133
134
135
136
137
138
139
140
141
142
143
144
145
146 }
147
148 }

System.out.println();
Random.getInstance().setStandardSeed();
PatternProblem problem = new PatternProblem();
int[] target = new int[CHROMOSOME_LENGTH];
randomize(target);
problem.run(target, 2);
randomize(target);
problem.run(target, 0);

Ejemplo2:
19 package jenes.tutorials.problem2;
20
21 import jenes.chromosome.Chromosome;
22 import jenes.population.Individual;
23 import jenes.population.Population;
24 import jenes.stage.ExclusiveDispenser;
43 public class SimpleDispenser<T extends Chromosome> extends ExclusiveDispenser<T> {
44
45 private int count;
46
47 public SimpleDispenser(int span) {
48
super(span);
49 }
50
51 public void preDistribute(Population<T> population){
52
this.count = 0;
53 }
54
55 @Override
56 public int distribute(Individual<T> ind) {
57
return count++ % span;
58 }
59
60 }
Ejemplo3:
19 package jenes.tutorials.problem2;
20
21 import jenes.Fitness;
22 import jenes.GeneticAlgorithm;
23 import jenes.chromosome.IntegerChromosome;
24 import jenes.population.Individual;
25 import jenes.population.Population;
43 public class PatternGA extends GeneticAlgorithm<IntegerChromosome> {
44
45 private PatternFitness fitness = new PatternFitness();
46
47 public PatternGA(Population<IntegerChromosome> pop, int numGen) {
48
super(pop, numGen);
49
this.setFitness(fitness);
50 }
51
52 @Override
53 protected boolean end() {
54
jenes.population.Population.Statistics stat = this.getCurrentPopulation().getStatistics();
55
return stat.getGroup(Population.LEGALS).getMin()[0] <= this.fitness.precision;
56 }
57
58 public class PatternFitness extends Fitness<IntegerChromosome> {
59
60
private int[] target = null;
61
private int precision = 0;
62
63
private PatternFitness() {
64
super(false);
65
}
66
67
@Override
68
public void evaluate(Individual<IntegerChromosome> individual) {
69
IntegerChromosome chrom = individual.getChromosome();
70
int diff = 0;
71
int length = chrom.length();
72
for (int i = 0; i < length; i++) {
73
diff += Math.abs(chrom.getValue(i) - target[i]);
74
}
75
individual.setScore(diff);
76
}
77
78
public void setTarget(int[] target) {
79
this.target = target;
80
}
81
82
public void setPrecision(int precision) {
83
this.precision = precision;
84
}
85 }
86 }
Redefinición de las operaciones genéticas
En algunas circunstancias el espacio de búsqueda es escasa dentro de un espacio más
grande. Este es el caso del problema del agente de viajes, con el objetivo de encontrar una
mínima de enrutamiento entre un conjunto de puntos, teniendo en cuenta las distancias
entre ellos.
Una forma natural para la representación de una solución es por una permutación de
elementos, proporcionando el orden por el que la mínima de enrutamiento visita los puntos.
Por lo tanto, un cromosoma es generalmente de Indices de enteros, cada referencia a un
punto en particular (ciudad). Los operadores tradicionales de cruce y mutación no aseguran
para producir soluciones válidas, es decir, permutaciones, ya que algunas ciudades podrían
reproducirse o falta. Hay una necesidad para la redefinición de estas operaciones. En este
tutorial se muestran dos formas de realizar esta tarea.
1. El uso o la creación de una clase cromosoma específico
2. Redefinir el cruce y mutador
1. El uso o la creación de una clase cromosoma específico.
En Jenes, los operadores genéticos se basan en los primitivos puestos a disposición por la
interfaz de cromosomas, tales como cruz, de forma aleatoria, de intercambio y
desplazamiento. Por lo tanto, es posible también definir una subclase cromosoma específico
con un conjunto de primitivas evitando transformaciones que conducen a soluciones no
factibles.
En Jenes la PermutationChromosome es capaz de procesar permutaciones de acuerdo a la
siguiente Stategy:
Crossover: alelos en un cromosoma se ordenarán de acuerdo con el orden en que son
considerados por el otro cromosoma
Mutación: un alelo se intercambia con otro elegido al azar
El código de código utilizado para configurar el algoritmo y la función de aptitud se mostró
a continuación:

127
Individual<PermutationChromosome> sample = new Individual<PermutationChromosome>(new P
ermutationChromosome(cities));
128
Population<PermutationChromosome> pop = new Population<PermutationChromosome>(sample,
POPULATION_SIZE);
129
130
Fitness<PermutationChromosome> fitness = new Fitness<PermutationChromosome>(false) {
131
132
@Override
133
public void evaluate(Individual<PermutationChromosome> individual) {
134
PermutationChromosome chrom = individual.getChromosome();
135
double count = 0;
136
int size = chrom.length();
137
for(int i=0;i<size-1;i++){
138
int val1 = chrom.getElementAt(i);
139
int val2 = chrom.getElementAt(i+1);
140
count += TravelSalesmanProblem.this.map[val1][val2];
141
}
142
count += TravelSalesmanProblem.this.map[size-1][0];
143
individual.setScore(count);
144
}
145
146
};
147
148
SimpleGA<PermutationChromosome> sga = new SimpleGA<PermutationChromosome>(fitness, po
p, GENERATION_LIMIT);

2. Redefinir el cruce y mutador
Crossover
Redefinición de un crossover es bastante simple. Lo primero que debe hacer es extender la
clase del cromosoma.
057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{

El Crossover Ciudad Centrado, elige una ciudad y volver a ordenar las siguientes ciudades
en un cromosoma de acuerdo a la orden dada por el otro. Esta operación se realiza mediante
la aplicación del método de cruz.
078 protected void cross(Individual<IntegerChromosome> offsprings[]) {
079
080
IntegerChromosome chrom_child1 = offsprings[0].getChromosome();
081
IntegerChromosome chrom_child2 = offsprings[1].getChromosome();
082
083
if( chrom_parent1 == null ) {
084
chrom_parent1 = chrom_child1.clone();
085
chrom_parent2 = chrom_child2.clone();
086
} else {
087
chrom_parent1.setAs(chrom_child1);
088
chrom_parent2.setAs(chrom_child2);
089
}
090
091
final int size = chrom_child1.length();
092
if( chrom_child2.length() != size )
093
throw new AlgorithmException("Error: the two chromosomes are required to have the same lengt
h.");
094
095
096
//we choose a random city
097
int city = Random.getInstance().nextInt(0, size);
098
099
//i1, i2 are the positions of the city respectively in child1 and child2
100
int i1 = findPositionOf(city, chrom_child1);
101
int i2 = findPositionOf(city, chrom_child2);
102
103
int j1 = 0;
104
int j2 = 0;
105
for( int i = 0; i < size; ++i ) {
106
// get the city c1 in position i for parent1
107
int c1 = chrom_parent1.getValue(i);
108
// find the position of c1 in parent 2
109
int p2 = findPositionOf(c1, chrom_parent2);
110
// if the position is over the cross-point, it copies c1 in child2
111
if( p2 > i2 ) {
112
chrom_child2.setValue(i2 + (++j2), c1);
113
}
114
115
// similarly we process the other pair
116
int c2 = chrom_parent2.getValue(i);
117
int p1 = findPositionOf(c2, chrom_parent1);
118
if( p1 > i1 ) {
119
chrom_child1.setValue(i1 + (++j1), c2);
120
}
121
}
122 }
Mutador
Redefinir el mutador es sencillo también. En primer lugar, tenemos que crear una subclase
de la operadora Mutador.
047 public class TSPScrambleMutator extends Mutator<IntegerChromosome> {

El mutador Scramble se basa en la siguiente estrategia: dos Indices de i1 e i2 se eligen al
azar y el orden de los elementos dentro de la gama [i1, i2] cambia aleatoriamente.
Este algoritmo es ejecutado por el método randomize:
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101

public void randomize(IntegerChromosome chrom, int min, int max) {
//we create a temporany array
int len = max-min+1;
int[] base = new int[len];
//we fill it with the elements within [min,max]
for(int i=0;i<len;i++)
base[i]= chrom.getValue(min+i);
//the loop ends when the temporany array is empty
for( int i = 0; len > 0; --len, ++i) {
//we choose a random position pos in the array and copy the element at pos in the chromosome
int pos = Random.getInstance().nextInt(0,len);
chrom.setValue(min+i,base[pos]);
//we removes the chosen element from the temporany array
for(int j=pos;j<(len-1);j++){
base[j]=base[j+1];
}
}
}

Ejemplo del tema:
019 package jenes.tutorials.problem3;
020
021 import jenes.Fitness;
022 import jenes.GeneticAlgorithm;
023 import jenes.utils.Random;
024 import jenes.algorithms.SimpleGA;
025 import jenes.chromosome.IntegerChromosome;
026 import jenes.chromosome.PermutationChromosome;
027 import jenes.population.Individual;
028 import jenes.population.Population;
029 import jenes.population.Population.Statistics.Group;
030 import jenes.stage.AbstractStage;
031 import jenes.stage.operator.common.TournamentSelector;
032 import jenes.tutorials.utils.Utils;
046 public class TravelSalesmanProblem {
047
048 public static final int POPULATION_SIZE = 1000;
049 private static int GENERATION_LIMIT = 2000;
050 public static final int MAX_DISTANCE = 10;
051
052 private TSPGA algorithm;
053 private int cities;
054 private double[][] map;
055
056 public static void main(String[] args) {
057
058
Utils.printHeader();
059
System.out.println();
060
061
System.out.println("TUTORIAL 3:");
062
System.out.println("The Travel Salesman Problem, a classics.");
063
System.out.println();
064
065
Random.getInstance().setStandardSeed();
066
067
System.out.println("Case 1: 10 cities in circle");
068
double[][] m1 = simpleMap(10);
069
TravelSalesmanProblem tsp1 = new TravelSalesmanProblem(m1);
070
tsp1.solve();
071
072
System.out.println("Case 2: 30 cities in circle");
073
double[][] m2 = simpleMap(30);
074
TravelSalesmanProblem tsp2 = new TravelSalesmanProblem(m2);
075
tsp2.solve();
076
077
System.out.println("Case 3: 30 cities at random");
078
double[][] m3 = randomMap(30);
079
TravelSalesmanProblem tsp3 = new TravelSalesmanProblem(m3);
080
tsp3.solve();
081
082
System.out.println("Case 4: An application of PermutationChromosome");
083
tsp2.solvePC();
084 }
085
086 public TravelSalesmanProblem(double[][] matrix) {
087
088
cities = matrix[0].length;
089
map = matrix;
090
091
IntegerChromosome chrom = new IntegerChromosome(cities,0,cities-1);
092
for( int i = 0; i < cities; ++i ) {
093
chrom.setValue(i, i < cities - 1 ? i+1 : 0);
094
}
095
Individual<IntegerChromosome> sample = new Individual<IntegerChromosome>(chrom);
096
Population<IntegerChromosome> pop = new Population<IntegerChromosome>(sample, POPULAT
ION_SIZE);
097
098
algorithm = new TSPGA(matrix, pop, GENERATION_LIMIT);
099
algorithm.setRandomization(true);
100
101
AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(1
);
102
AbstractStage<IntegerChromosome> crossover = new TSPCityCenteredCrossover(0.8);
103
AbstractStage<IntegerChromosome> mutation = new TSPScrambleMutator(0.02);
104
105
algorithm.addStage(selection);
106
algorithm.addStage(crossover);
107
algorithm.addStage(mutation);
108
109
algorithm.setElitism(10);
110 }
111
112 public void solve() {
113
algorithm.evolve();
114
115
Population.Statistics stats = algorithm.getCurrentPopulation().getStatistics();
116
GeneticAlgorithm.Statistics algostats = algorithm.getStatistics();
117
118
Group legals = stats.getGroup(Population.LEGALS);
119
120
System.out.println(legals.get(0));
121
System.out.format("found in %d ms and %d generations.n", algostats.getExecutionTime(), algostats
.getGenerations() );
122
System.out.println();
123 }
124
125 public void solvePC() {
126
127
Individual<PermutationChromosome> sample = new Individual<PermutationChromosome>(new P
ermutationChromosome(cities));
128
Population<PermutationChromosome> pop = new Population<PermutationChromosome>(sample,
POPULATION_SIZE);
129
130
Fitness<PermutationChromosome> fitness = new Fitness<PermutationChromosome>(false) {
131
132
@Override
133
public void evaluate(Individual<PermutationChromosome> individual) {
134
PermutationChromosome chrom = individual.getChromosome();
135
double count = 0;
136
int size = chrom.length();
137
for(int i=0;i<size-1;i++){
138
int val1 = chrom.getElementAt(i);
139
int val2 = chrom.getElementAt(i+1);
140
count += TravelSalesmanProblem.this.map[val1][val2];
141
}
142
count += TravelSalesmanProblem.this.map[size-1][0];
143
individual.setScore(count);
144
}
145
146
};
147
148
SimpleGA<PermutationChromosome> sga = new SimpleGA<PermutationChromosome>(fitness, po
p, GENERATION_LIMIT);
149
150
sga.setElitism(10);
151
sga.setMutationProbability(0.02);
152
sga.evolve();
153
154
Population.Statistics stats = sga.getCurrentPopulation().getStatistics();
155
GeneticAlgorithm.Statistics algostats = sga.getStatistics();
156
157
Group legals = stats.getGroup(Population.LEGALS);
158
159
System.out.println(legals.get(0));
160
System.out.format("found in %d ms and %d generations.n", algostats.getExecutionTime(), algostats
.getGenerations() );
161
System.out.println();
162 }
163
164 public static double[][] simpleMap( int cities ) {
165
double[][] matrix = new double[cities][cities];
166
167
matrix[0][0] = 0;
168
for( int i = 1; i <= cities/2; ++i) {
169
matrix[0][i] = i;
170
matrix[0][cities-i] = i;
171
}
172
173
for( int i = 1; i < cities; ++i ) {
174
for( int j = 0; j < cities; ++j ) {
175
matrix[i][(i+j)%cities] = matrix[0][j];
176
}
177
}
178
return matrix;
179 }
180
181 public static double[][] randomMap( int cities ) {
182
double[][] matrix = new double[cities][cities];
183
for( int i = 0; i < cities; ++i ) {
184
for( int j = 0; j < cities; ++j ) {
185
matrix[i][j] = i!=j ? Random.getInstance().nextDouble(MAX_DISTANCE) : 0;
186
}
187
}
188
return matrix;
189 }
190
191 }
Ejemplo del tema:
019 package jenes.tutorials.problem3;
020
021 import jenes.utils.Random;
022 import jenes.chromosome.IntegerChromosome;
023 import jenes.population.Individual;
024 import jenes.stage.operator.Mutator;
047 public class TSPScrambleMutator extends Mutator<IntegerChromosome> {
048
049 public TSPScrambleMutator(double pMut) {
050
super(pMut);
051 }
052
053 @Override
054 protected void mutate(Individual<IntegerChromosome> t) {
055
int size = t.getChromosomeLength();
056
int index1,index2;
057
do{
058
index1 = Random.getInstance().nextInt(0,size);
059
index2 = Random.getInstance().nextInt(0,size);
060
}while(index2==index1);
061
062
int min,max;
063
if(index1<index2){
064
min=index1;
065
max=index2;
066
}else{
067
min=index2;
068
max=index1;
069
}
070
071
randomize(t.getChromosome(),min, max);
072 }
073
074 /**
075
* Randomizes the elements chromosome within the range [min,max]
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102 }

* <p>
* @param chrom the individual to mutate
* @param min the lower bound
* @param max the upper bound
*/
public void randomize(IntegerChromosome chrom, int min, int max) {
//we create a temporany array
int len = max-min+1;
int[] base = new int[len];
//we fill it with the elements within [min,max]
for(int i=0;i<len;i++)
base[i]= chrom.getValue(min+i);
//the loop ends when the temporany array is empty
for( int i = 0; len > 0; --len, ++i) {
//we choose a random position pos in the array and copy the element at pos in the chromosome
int pos = Random.getInstance().nextInt(0,len);
chrom.setValue(min+i,base[pos]);
//we removes the chosen element from the temporany array
for(int j=pos;j<(len-1);j++){
base[j]=base[j+1];
}
}
}

Ejemplo del tema:
package jenes.tutorials.problem3;
import jenes.Fitness;
import jenes.GeneticAlgorithm;
import jenes.utils.Random;
import jenes.chromosome.IntegerChromosome;
import jenes.population.Individual;
import jenes.population.Population;
public class TSPGA extends GeneticAlgorithm<IntegerChromosome> {
private double[][] matrix;
private TSPFitness fitness;
public TSPGA(double[][] matrix, Population<IntegerChromosome> pop, int genlimit) {
super(null, pop, genlimit);
this.matrix = matrix;
fitness = new TSPFitness();
this.setFitness(fitness);
}
@Override
protected void randomizeIndividual(Individual<IntegerChromosome> individual) {
Random rand = Random.getInstance();
int len = individual.getChromosomeLength();
for( int i = 0; i < 100; ++i ) {
int j = rand.nextInt(len);
int k = rand.nextInt(len);
individual.getChromosome().swap(j, k);
}
}
public class TSPFitness extends Fitness<IntegerChromosome> {
public TSPFitness() {
super(false);
}
@Override
public void evaluate(Individual<IntegerChromosome> individual) {
IntegerChromosome chrom = individual.getChromosome();
double count = 0;
int size = chrom.length();
for (int i = 0; i < size - 1; i++) {
int val1 = chrom.getValue(i);
int val2 = chrom.getValue(i + 1);
count += matrix[val1][val2];
}
count += matrix[size - 1][0];
individual.setScore(count);
}
}

}
Ejemplo del tema:
019 package jenes.tutorials.problem3;
020
021 import jenes.AlgorithmException;
022 import jenes.utils.Random;
023 import jenes.chromosome.IntegerChromosome;
024 import jenes.population.Individual;
025 import jenes.stage.operator.Crossover;
057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{
058
059 public TSPCityCenteredCrossover(double pCross) {
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
h.");
094
095
096
097
098
099
100
101
102
103
104
105
106
107

super(pCross);
}
/**
* Returns the number of chromosomes (i.e. 2) this operator entails.
*/
@Override
public int spread() {
return 2;
}
private IntegerChromosome chrom_parent1 = null;
private IntegerChromosome chrom_parent2 = null;
/**
* This method implements the crossover operation.
*
* @param offsprings the chromosomes to be crossed.
*/
protected void cross(Individual<IntegerChromosome> offsprings[]) {
IntegerChromosome chrom_child1 = offsprings[0].getChromosome();
IntegerChromosome chrom_child2 = offsprings[1].getChromosome();
if( chrom_parent1 == null ) {
chrom_parent1 = chrom_child1.clone();
chrom_parent2 = chrom_child2.clone();
} else {
chrom_parent1.setAs(chrom_child1);
chrom_parent2.setAs(chrom_child2);
}
final int size = chrom_child1.length();
if( chrom_child2.length() != size )
throw new AlgorithmException("Error: the two chromosomes are required to have the same lengt

//we choose a random city
int city = Random.getInstance().nextInt(0, size);
//i1, i2 are the positions of the city respectively in child1 and child2
int i1 = findPositionOf(city, chrom_child1);
int i2 = findPositionOf(city, chrom_child2);
int j1 = 0;
int j2 = 0;
for( int i = 0; i < size; ++i ) {
// get the city c1 in position i for parent1
int c1 = chrom_parent1.getValue(i);
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 }

// find the position of c1 in parent 2
int p2 = findPositionOf(c1, chrom_parent2);
// if the position is over the cross-point, it copies c1 in child2
if( p2 > i2 ) {
chrom_child2.setValue(i2 + (++j2), c1);
}
// similarly we process the other pair
int c2 = chrom_parent2.getValue(i);
int p1 = findPositionOf(c2, chrom_parent1);
if( p1 > i1 ) {
chrom_child1.setValue(i1 + (++j1), c2);
}
}
}
/**
* Finds the position of one specific city in the chromosome.
* <p>
* @param city the city to find
* @param chrom the chromosome to search
* @return the city position
*/
private int findPositionOf(int city, IntegerChromosome chrom){
final int size = chrom.length();
for( int i = 0; i < size; ++i ) {
if( chrom.getValue(i) == city )
return i;
}
return -1;
}

Redefinición de las operaciones genéticas
En algunas circunstancias el espacio de búsqueda es escasa dentro de un espacio más
grande. Este es el caso del problema del agente de viajes, con el objetivo de encontrar una
mínima de enrutamiento entre un conjunto de puntos, teniendo en cuenta las distancias
entre ellos.
Una forma natural para la representación de una solución es por una permutación de
elementos, proporcionando el orden por el que la mínima de enrutamiento visita los puntos.
Por lo tanto, un cromosoma es generalmente de Indices de enteros, cada referencia a un
punto en particular (ciudad). Los operadores tradicionales de cruce y mutación no aseguran
para producir soluciones válidas, es decir, permutaciones, ya que algunas ciudades podrían
reproducirse o falta. Hay una necesidad para la redefinición de estas operaciones. En este
tutorial se muestran dos formas de realizar esta tarea.
1. El uso o la creación de una clase cromosoma específico
2. Redefinir el cruce y matador
1. El uso o la creación de una clase cromosoma específico

En Jenes, los operadores genéticos se basan en los primitivos puestos a disposición por la
interfaz de cromosomas, tales como cruz, de forma aleatoria, de intercambio y
desplazamiento. Por lo tanto, es posible también definir una subclase cromosoma específico
con un conjunto de primitivas evitando transformaciones que conducen a soluciones no
factibles.
En Jenes la PermutationChromosome es capaz de procesar permutaciones de acuerdo a la
siguiente Stategy:
Crossover: alelos en un cromosoma se ordenarán de acuerdo con el orden en que son
considerados por el otro cromosoma
Mutación: un alelo se intercambia con otro elegido al azar
El código de código utilizado para configurar el algoritmo y la función de aptitud se mostró
a continuación:
127
Individual<PermutationChromosome> sample = new Individual<PermutationChromosome>(new P
ermutationChromosome(cities));
128
Population<PermutationChromosome> pop = new Population<PermutationChromosome>(sample,
POPULATION_SIZE);
129
130
Fitness<PermutationChromosome> fitness = new Fitness<PermutationChromosome>(false) {
131
132
@Override
133
public void evaluate(Individual<PermutationChromosome> individual) {
134
PermutationChromosome chrom = individual.getChromosome();
135
double count = 0;
136
int size = chrom.length();
137
for(int i=0;i<size-1;i++){
138
int val1 = chrom.getElementAt(i);
139
int val2 = chrom.getElementAt(i+1);
140
count += TravelSalesmanProblem.this.map[val1][val2];
141
}
142
count += TravelSalesmanProblem.this.map[size-1][0];
143
individual.setScore(count);
144
}
145
146
};
147
148
SimpleGA<PermutationChromosome> sga = new SimpleGA<PermutationChromosome>(fitness, po
p, GENERATION_LIMIT);

2. Redefinir el cruce y mutador

crossover

Redefinición de un crossover es bastante simple. Lo primero que debe hacer es extender la
clase del cromosoma.
057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{

El Crossover Ciudad Centrado, elige una ciudad y volver a ordenar las siguientes ciudades
en un cromosoma de acuerdo a la orden dada por el otro. Esta operación se realiza mediante
la aplicación del método de cruz.
078 protected void cross(Individual<IntegerChromosome> offsprings[]) {
079
080
IntegerChromosome chrom_child1 = offsprings[0].getChromosome();
081
IntegerChromosome chrom_child2 = offsprings[1].getChromosome();
082
083
if( chrom_parent1 == null ) {
084
chrom_parent1 = chrom_child1.clone();
085
chrom_parent2 = chrom_child2.clone();
086
} else {
087
chrom_parent1.setAs(chrom_child1);
088
chrom_parent2.setAs(chrom_child2);
089
}
090
091
final int size = chrom_child1.length();
092
if( chrom_child2.length() != size )
093
throw new AlgorithmException("Error: the two chromosomes are required to have the same lengt
h.");
094
095
096
//we choose a random city
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

int city = Random.getInstance().nextInt(0, size);
//i1, i2 are the positions of the city respectively in child1 and child2
int i1 = findPositionOf(city, chrom_child1);
int i2 = findPositionOf(city, chrom_child2);
int j1 = 0;
int j2 = 0;
for( int i = 0; i < size; ++i ) {
// get the city c1 in position i for parent1
int c1 = chrom_parent1.getValue(i);
// find the position of c1 in parent 2
int p2 = findPositionOf(c1, chrom_parent2);
// if the position is over the cross-point, it copies c1 in child2
if( p2 > i2 ) {
chrom_child2.setValue(i2 + (++j2), c1);
}
// similarly we process the other pair
int c2 = chrom_parent2.getValue(i);
int p1 = findPositionOf(c2, chrom_parent1);
if( p1 > i1 ) {
chrom_child1.setValue(i1 + (++j1), c2);
}
}
}

mutador

Redefinir el mutador es sencillo también. En primer lugar, tenemos que crear una subclase
de la operadora Mutador.
047 public class TSPScrambleMutator extends Mutator<IntegerChromosome> {

El mutador Scramble se basa en la siguiente estrategia: dos Indices de i1 e i2 se eligen al
azar y el orden de los elementos dentro de la gama [i1, i2] cambia aleatoriamente.
Este algoritmo es ejecutado por el método randomize.
081
082
083
084
085
086
087
088

public void randomize(IntegerChromosome chrom, int min, int max) {
//we create a temporany array
int len = max-min+1;
int[] base = new int[len];
//we fill it with the elements within [min,max]
for(int i=0;i<len;i++)
089
090
091
092
093
094
095
096
097
098
099
100
101

base[i]= chrom.getValue(min+i);
//the loop ends when the temporany array is empty
for( int i = 0; len > 0; --len, ++i) {
//we choose a random position pos in the array and copy the element at pos in the chromosome
int pos = Random.getInstance().nextInt(0,len);
chrom.setValue(min+i,base[pos]);
//we removes the chosen element from the temporany array
for(int j=pos;j<(len-1);j++){
base[j]=base[j+1];
}
}
}

Cómo utilizar SimpleGa
En este tutorial se muestra cómo utilizar SimpleGA, una subclase estándar
GeneticAlgorithm. Representa la configuración clásica de un algoritmo genético, utilizando
sólo los principales operadores (selectores, cruce y mutantes) en un tubo muy simple. Es
útil cuando no se necesitan operadores de complejos y se requiere una ga rápida puesta en
marcha. El objetivo de este tutorial es para minimizar la entropía de Shannon de un
conjunto de valores en el rango [0,1].
1. Elegir un problema cromosómico adecuada y crear la población inicial;
Un DoubleChromosome es adecuado para este problema con cada alelo dentro del rango
[0,1].
55
Individual<DoubleChromosome> sample = new Individual<DoubleChromosome>(new DoubleChro
mosome(CHROMOSOME_LENGTH,0,1));
56
Population<DoubleChromosome> pop = new Population<DoubleChromosome>(sample, POPULATI
ON_SIZE);

2. Puesta en marcha del algoritmo genético

Para utilizar SimpleGA tenemos que definir sólo la codificación función de aptitud. En este
caso, la aptitud de cada individuo es igual al valor de entropía de acuerdo a la definición
clásica de entropía: la entropía es la medida de la cantidad de información que falta antes de
la recepción y se refiere a veces como la entropía de Shannon.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

@Override
public void evaluate(Individual<DoubleChromosome> individual) {
DoubleChromosome chrom = individual.getChromosome();
int length = chrom.length();
double sum = 0.0;
for (int i = 0; i < length; ++i) {
sum += chrom.getValue(i);
}
double entropy = 0.0;
for (int i = 0; i < length; ++i) {
double pxi = chrom.getValue(i) / sum;
chrom.setValue(i, pxi);
entropy -= (pxi * Math.log(pxi) / Math.log(2));
}
individual.setScore(entropy);
}

3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en
la ga.
Con SimpleGA nuestro algoritmo genético ya está configurado con respecto a los
operadores a utilizar. Por defecto se utiliza la selección del torneo (intentos = 2), cruce de
un punto (probabilidad = 0,8) y simple mutador (probabilidad = 0,2). Además SimpleGA
usa por defecto una estrategia de sustitución de azar para el elitismo. De todos modos, es
possibile para modificar esta configuración predeterminada que proporciona diferentes
parámetros para los operadores y / o una estrategia de elitismo diferente. En nuestro caso
utilizamos la configuración SimpleGA defecto.
4. Personalizar el algoritmo genético
El código de configuración entera se enumeran a continuación:
55
Individual<DoubleChromosome> sample = new Individual<DoubleChromosome>(new DoubleChro
mosome(CHROMOSOME_LENGTH,0,1));
56
Population<DoubleChromosome> pop = new Population<DoubleChromosome>(sample, POPULATI
ON_SIZE);
57
58
ga = new SimpleGA<DoubleChromosome>(null, pop, GENERATION_LIMIT);
59
60
System.out.println("Solving Max!:");
61
solve( EntropyFitness.MAX );
62
63
64

System.out.println("Solving Min!:");
solve( EntropyFitness.MIN );

Como puede ver, el algoritmo genético se ha inicializado sin la definición de la función de
idoneidad para su uso. Este es possibile en que los casos en wich el gimnasio podría ser
determinada sólo en un momento posterior con respecto a la creación del algoritmo
genético. De todos modos la definición de una función de aptitud se requiere antes de que
el método de evolucionar de GeneticAlgorithm se invoca, y esto es posible sólo hacer la
siguiente llamada al método:
68
69

ga.setFitness(fitness);
ga.evolve();

Ejemplos del tema:
19 package jenes.tutorials.problem4;
20
21 import jenes.GeneticAlgorithm;
22 import jenes.algorithms.SimpleGA;
23 import jenes.chromosome.DoubleChromosome;
24 import jenes.population.Individual;
25 import jenes.population.Population;
26 import jenes.population.Population.Statistics;
27 import jenes.population.Population.Statistics.Group;
28 import jenes.tutorials.utils.Utils;
29
30 /**
31 * Tutorial showing how to set-up a minimization problem.
32 * The problem is to find a vector whose entroy, after normalization, is minimal.
33 *
34 * @author Luigi Troiano
35 *
36 * @version 2.0
37 * @since 1.0
38 */
39 public class EntropyProblem {
40
41 private static int POPULATION_SIZE = 100;
42 private static int CHROMOSOME_LENGTH = 5;
43 private static int GENERATION_LIMIT = 100;
44
45 private static GeneticAlgorithm<DoubleChromosome> ga;
46
47 public static void main(String[] args) {
48
Utils.printHeader();
49
System.out.println();
50
51
System.out.println("TUTORIAL 4:");
52
System.out.println("Find the probability distribution that maximizes (or minimize) the Shannon's entr
opy.");
53
System.out.println();
54
55
Individual<DoubleChromosome> sample = new Individual<DoubleChromosome>(new DoubleChro
mosome(CHROMOSOME_LENGTH,0,1));
56
Population<DoubleChromosome> pop = new Population<DoubleChromosome>(sample, POPULATI
ON_SIZE);
57
58
ga = new SimpleGA<DoubleChromosome>(null, pop, GENERATION_LIMIT);
59
60
System.out.println("Solving Max!:");
61
solve( EntropyFitness.MAX );
62
63
System.out.println("Solving Min!:");
64
solve( EntropyFitness.MIN );
65 }
66
67 private static void solve(EntropyFitness fitness) {
68
ga.setFitness(fitness);
69
ga.evolve();
70
71
Statistics stats = ga.getCurrentPopulation().getStatistics();
72
GeneticAlgorithm.Statistics algostats = ga.getStatistics();
73
74
Group legals = stats.getGroup(Population.LEGALS);
75
76
System.out.println(legals.get(0));
77
System.out.format("found in %d ms.n", algostats.getExecutionTime() );
78
System.out.println();
79
80
Utils.printStatistics(stats);
81 }
82 }
Ejemplos del tema:
19 package jenes.tutorials.problem4;
20
21 import jenes.Fitness;
22 import jenes.chromosome.DoubleChromosome;
23 import jenes.population.Individual;
24
25 /**
26 *
27 * @author Luigi Troiano
28 */
29 public class EntropyFitness extends Fitness<DoubleChromosome> {
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 }

public static EntropyFitness MAX = new EntropyFitness(true);
public static EntropyFitness MIN = new EntropyFitness(false);
private EntropyFitness(boolean maximize) {
super(maximize);
}
@Override
public void evaluate(Individual<DoubleChromosome> individual) {
DoubleChromosome chrom = individual.getChromosome();
int length = chrom.length();
double sum = 0.0;
for (int i = 0; i < length; ++i) {
sum += chrom.getValue(i);
}
double entropy = 0.0;
for (int i = 0; i < length; ++i) {
double pxi = chrom.getValue(i) / sum;
chrom.setValue(i, pxi);
entropy -= (pxi * Math.log(pxi) / Math.log(2));
}
individual.setScore(entropy);
}
ObjectChromosome

En este tutorial se muestra cómo utilizar el ObjectChromosome en Jenes. El
ObjectChromosome representa un cromosoma complejo con genes que contienen un valor
de alelo objeto. Dado un espacio de búsqueda hecho de variables objeto de cromosomas,
nuestro objetivo es encontrar la secuencia más cercana de los valores (representable con
objetos específicos) a una de destino. En nuestro problema de ejemplo cada cromosoma
tiene cinco genes pertenecientes a diferentes valores de los alelos objeto. El primer gen es
un número entero en el intervalo [0,9], el segundo es también un número entero, pero en el
intervalo [10,30], la tercera es un número real en el intervalo [0,1], la cuarta es una boolean
y el último es un gen que es el alfabeto {NEGRO, ROJO, BLANCO}
1 . Elegir un problema cromosómico adecuada y crear la población inicial ;

Un ObjectChromosome es adecuado para este problema . Contará con cinco genes cada uno
de ellos con un conjunto de alelos diferentes : dos conjuntos de alelos entero para los dos
primeros genes , la primera con el rango [ 0,9 ] y el segundo con rango [ 10,30 ], un doble
alelo fijado para el tercer gen con rango [ 0,1] , un alelo boolean fijado para el gen de la
vuelta y un grupo de alelos de la enumeración basada contiene { NEGRO , ROJO,
BLANCO } para el último gen .
Para crear instancias de un grupo de alelos que podemos implementar la interfaz AlleleSet
o utilizar la clase GenericAlleleSet . El grupo de alelos de número entero se obtiene
subclases la clase GenericAlleleSet e implementación de dos métodos de fábrica , que se
utiliza para crear instancias de los valores enteros en sus rangos especificados ( los valores
son elegidos al azar o con una distribución de probabilidad uniforme en los intervalos
especificados ) . El conjunto alelo real se obtiene de la misma manera . El grupo de alelos
boolean se obtiene creando un objeto GenericAlleleSet containg los valores booleanos true
y false. Por último , se define una enumeración, llamada Color , que contiene los valores
NEGRO , rojo y blanco, entonces se crea un objeto GenericAlleleSet con los valores de la
enumeración de color. El código se mostró a continuación.
36 public enum Color {
37
38 RED, BLACK, WHITE;
39
40 }

Ahora podemos construir nuestra representación cromosoma.
053
054
055
056
057
058

private static ObjectChromosome template =
new ObjectChromosome( IntegerAlleleSet.createUniform(10, 0, 9),
IntegerAlleleSet.createUniform(21, 10, 30),
DoubleAlleleSet.createRandom(10, 0, 1),
new GenericAlleleSet<Boolean>(true, false),
new GenericAlleleSet<Color>(Color.values()) );

2. Puesta en marcha del algoritmo genético
A continuación se muestra el código para evaluar a un individuo en nuestro problema.
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081

@Override
public void evaluate(Individual<ObjectChromosome> individual) {
ObjectChromosome template = individual.getChromosome();
int i1 = (Integer)template.getValue(0);
int i2 = (Integer)template.getValue(1);
double d = (Double)template.getValue(2);
boolean b = (Boolean)template.getValue(3);
Color c = (Color)template.getValue(4);
double acc = b ? (3*i1 + 4*i2 + d) : i1;
switch( c ) {
case BLACK : acc += 10; break;
case RED : acc += 10; break;
case WHITE : acc += 10; break;
}
individual.setScore(acc);
}
En nuestro ejemplo los mejores individuos son los que tienen los valores más altos para el
entero y genes dobles, con un verdadero valor para el gen boolean y con cualquier valor
para el gen "Color".
Por lo tanto, la mejor persona que esperamos ejecutar este ejemplo podría ser: [9, 30, 0,99,
es cierto, NEGRO].
3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en
la ga
En este tutorial se utiliza la configuración simple algoritmo clásico.
098
099
100

ga.addStage(new TournamentSelector<ObjectChromosome>(3));
ga.addStage(new OnePointCrossover<ObjectChromosome>(0.8));
ga.addStage(new SimpleMutator<ObjectChromosome>(0.02));

4.Personalizar el algoritmo genético
El objetivo global del algoritmo genético es maximizar los valores de fitness. Todo el
código es visible en los archivos adjuntos a este tutorial.
Ejemplo de tema:
019 package jenes.tutorials.problem5;
020
021 import jenes.Fitness;
022 import jenes.GeneticAlgorithm;
023 import jenes.chromosome.GenericAlleleSet;
024 import jenes.chromosome.ObjectChromosome;
025 import jenes.population.Individual;
026 import jenes.population.Population;
027 import jenes.population.Population.Statistics;
028 import jenes.population.Population.Statistics.Group;
029 import jenes.stage.operator.common.OnePointCrossover;
030 import jenes.stage.operator.common.SimpleMutator;
031 import jenes.stage.operator.common.TournamentSelector;
032 import jenes.tutorials.utils.Utils;
033
034 /**
035 * Tutorial illustrating the use of object-oriented chromosomes, whose
036 * allele set can be defined by the user for each gene.
037 *
038 * In this example the chromosomes are combinations of colors. We aim at finding
039 * the vector of colors closest to a given sequence.
040 *
041 * This class defines the problem.
042 *
043 * @author Luigi Troiano
044 *
045 * @version 2.0
046 * @since 1.0
047 */
048 public class OCProblem {
049
050 private static int POPULATION_SIZE = 10;
051 private static int GENERATION_LIMIT = 100;
052
053 private static ObjectChromosome template =
054
new ObjectChromosome( IntegerAlleleSet.createUniform(10, 0, 9),
055
IntegerAlleleSet.createUniform(21, 10, 30),
056
DoubleAlleleSet.createRandom(10, 0, 1),
057
new GenericAlleleSet<Boolean>(true, false),
058
new GenericAlleleSet<Color>(Color.values()) );
059
060 private static Fitness<ObjectChromosome> fitness = new Fitness<ObjectChromosome>(true) {
061
062
@Override
063
public void evaluate(Individual<ObjectChromosome> individual) {
064
ObjectChromosome template = individual.getChromosome();
065
066
int i1 = (Integer)template.getValue(0);
067
int i2 = (Integer)template.getValue(1);
068
double d = (Double)template.getValue(2);
069
boolean b = (Boolean)template.getValue(3);
070
Color c = (Color)template.getValue(4);
071
072
double acc = b ? (3*i1 + 4*i2 + d) : i1;
073
074
switch( c ) {
075
case BLACK : acc += 10; break;
076
case RED : acc += 10; break;
077
case WHITE : acc += 10; break;
078
}
079
080
individual.setScore(acc);
081
}
082 };
083
084 private static GeneticAlgorithm<ObjectChromosome> ga =
085
new GeneticAlgorithm<ObjectChromosome>( fitness, new Population<ObjectChromosome>(ne
w Individual<ObjectChromosome>(template), POPULATION_SIZE), GENERATION_LIMIT);
086
087
088 public static void main(String[] args)throws Exception {
089
Utils.printHeader();
090
System.out.println();
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 }
116 }

System.out.println("TUTORIAL 5:");
System.out.println("Find the sequence of colors nearest to the target.");
System.out.println();
//Random.getInstance().setStandardSeed();
ga.addStage(new TournamentSelector<ObjectChromosome>(3));
ga.addStage(new OnePointCrossover<ObjectChromosome>(0.8));
ga.addStage(new SimpleMutator<ObjectChromosome>(0.02));
ga.evolve();
Statistics stats = ga.getCurrentPopulation().getStatistics();
GeneticAlgorithm.Statistics algostats = ga.getStatistics();
Group legals = stats.getGroup(Population.LEGALS);
System.out.println("Solution: ");
System.out.println(legals.get(0));
System.out.format("found in %d ms.n", algostats.getExecutionTime() );
System.out.println();
Utils.printStatistics(stats);

Ejemplos de tema:
19 package jenes.tutorials.problem5;
20
21
22 /**
23 * Tutorial illustrating the use of object-oriented chromosomes, whose
24 * allele set can be defined by the user for each gene.
25 *
26 * In this example the chromosomes are combinations of colors. We aim at finding
27 * the vector of colors closest to a given sequence.
28 *
29 * This class defines the enumeration of possible colors.
30 *
31 * @author Luigi Troiano
32 *
33 * @version 1.0
34 * @since 1.0
35 */
36 public enum Color {
37
38 RED, BLACK, WHITE;
39
40 }
Ejemplos del tema:
19 package jenes.tutorials.problem5;
20
21 import java.util.HashSet;
22 import java.util.Set;
23
24 import jenes.utils.Random;
25 import jenes.chromosome.GenericAlleleSet;
26
27 /**
28 * Tutorial illustrating the use of object-oriented chromosomes, whose
29 * allele set can be defined by the user for each gene.
30 *
31 * In this example the chromosomes are combinations of colors. We aim at finding
32 * the vector of colors closest to a given sequence.
33 *
34 * This class defines an allele set made of doubles.
35 *
36 * @author Luigi Troiano
37 *
38 * @version 1.0
39 * @since 1.0
40 */
41
42 public class DoubleAlleleSet extends GenericAlleleSet<Double> {
43
44 public DoubleAlleleSet(Set<Double> set) {
45
super(set);
46 }
47
48 /**
49
* Builds a DoubleAlleleSet with random values within the range [lowerBound,upperBound]
50
* <p>
51
* @param size the allala set cardinality
52
* @param lowerBound the min value to choose
53
* @param upperBound the max value to choose
54
* @return a new DoubleAlleleSet
55
*/
56 public static DoubleAlleleSet createRandom(int size, double lowerBound, double upperBound ) {
57
HashSet<Double> values = new HashSet<Double>();
58
Random rand = Random.getInstance();
59
60
for( int i = 0; i < size; ++i ) {
61
values.add(rand.nextDouble(lowerBound, upperBound+Double.MIN_VALUE));
62
}
63
64
return new DoubleAlleleSet(values);
65 }
66
67 /**
68
* Builds a new DoubleAlleleSet with uniformly distributed values within the range [lowerBound,upper
Bound]
69
* <p>
70
* @param size the allala set cardinality
71
* @param lowerBound the min value to choose
72
* @param upperBound the max value to choose
73
* @return a new DoubleAlleleSet
74
*/
75 public static DoubleAlleleSet createUniform(int size, int lowerBound, int upperBound ) {
76
HashSet<Double> values = new HashSet<Double>();
77
78
double step = 1.0/upperBound - lowerBound;
79
for( double x = lowerBound; x <= upperBound; x += step ) {
80
values.add(x);
81
}
82
83
return new DoubleAlleleSet(values);
84 }
85
86
87 }
Ejemplos del tema:
19 package jenes.tutorials.problem5;
20
21 import java.util.HashSet;
22 import java.util.Set;
23
24 import jenes.utils.Random;
25 import jenes.chromosome.GenericAlleleSet;
26
27 /**
28 * Tutorial illustrating the use of object-oriented chromosomes, whose
29 * allele set can be defined by the user for each gene.
30 *
31 * In this example the chromosomes are combinations of colors. We aim at finding
32 * the vector of colors closest to a given sequence.
33 *
34 * This class defines a set of integers.
35 *
36 * @author Luigi Troiano
37 *
38 * @version 1.0
39 * @since 1.0
40 */
41 public class IntegerAlleleSet extends GenericAlleleSet<Integer> {
42
43 public IntegerAlleleSet(Set<Integer> set) {
44
super(set);
45 }
46
47 /**
48
* Builds an IntegerAlleleSet with random values within the range [lowerBound,upperBound]
49
* <p>
50
* @param size the allala set cardinality
51
* @param lowerBound the min value to choose
52
* @param upperBound the max value to choose
53
* @return a new IntegerAlleleSet
54
*/
55 public static IntegerAlleleSet createRandom(int size, int lowerBound, int upperBound ) {
56
HashSet<Integer> values = new HashSet<Integer>();
57
int s0 = upperBound - lowerBound + 1;
58
if( size > s0 ) size = s0;
59
60
Random rand = Random.getInstance();
61
62
for( int i = 0; i < s0; ++i ) {
63
64
int chosen = values.size();
65
double coin = ((double)size-chosen)/(s0-i);
66
boolean justEnough = s0-i == size-chosen;
67
68
if( justEnough || rand.nextBoolean(coin) ) {
69
values.add(lowerBound + i);
70
}
71
}
72
73
return new IntegerAlleleSet(values);
74 }
75
76 /**
77
* Builds a new IntegerAlleleSet with uniformly distributed values within the range [lowerBound,upper
Bound]
78
* <p>
79
* @param size the allala set cardinality
80
* @param lowerBound the min value to choose
81
* @param upperBound the max value to choose
82
* @return a new IntegerAlleleSet
83
*/
84 public static IntegerAlleleSet createUniform(int size, int lowerBound, int upperBound ) {
85
HashSet<Integer> values = new HashSet<Integer>();
86
int s0 = upperBound - lowerBound + 1;
87
88
89
90
91
92
93
94
95
96 }
97
98 }

if( size > s0 ) size = s0;
double step = 1.0/(upperBound - lowerBound);
for( double x = lowerBound; x <= upperBound; x += step ) {
int i = (int) Math.round(x);
values.add(i);
}
return new IntegerAlleleSet(values);

El uso de metas de algoritmo genético locales
Jenes ofrece la posibilidad de utilizar objetivos de algoritmos genéticos locales. El objetivo global es el
utilizado por GeneticAlgorithm durante la evolución de la población en su principal secuencia de etapas. En
su lugar, el objetivo local es el utilizado por la sola etapa (por ejemplo, una secuencia contenida en una rama
paralela, etc.). Esta tutoriales muestra cómo resolver el problema de la mochila que define dos secuencias
paralelas diferentes, con diferentes objetivos internos. El objetivo del problema de la mochila es maximizar la
utilidad total de los elementos dentro de la bolsa, sin exceder la capacidad máxima de la bolsa. Tenemos n
elementos cada uno con tiene una huella y un valor de utilidad.
1. Elegir un problema cromosómico adecuada y crear la población inicial

Una solución candidata es un conjunto de elementos con un peso y una utilidad. Las soluciones se codifican
usando un cromosoma booleano. Los valores boolean Indica si un elemento está presente o no dentro de la
bolsa. Por ejemplo, si el gen i-ésimo es verdad, entonces el elemento de orden i está en la bolsa. Un
cromosoma con todos los genes que tiene un valor falso representa una bolsa vacía, mientras que un
cromosoma con todos los genes que tengan un verdadero valor representa una bolsa con todos los elementos
posibles.
070 public KnapsackGA( int popsize, int generations, double[] utilities, double[] weights) {
071
super( new Population<BooleanChromosome>(new Individual<BooleanChromosome>(new Boole
anChromosome(utilities.length)), popsize), generations);
072
2. Puesta en marcha del algoritmo genético

Ponemos en práctica la clase KnapsackGA subclasificando GeneticAlgorithm e implementación de la función
de aptitud como se informa a continuación.
053
054
055

@Override
public void evaluate(Individual<BooleanChromosome> individual) {
double utility = KnapsackGA.this.getUtilityOf(individual);
056
057
058
059

double weight = KnapsackGA.this.getWeightOf(individual);
individual.setScore(utility);
individual.setLegal(weight <= KnapsackGA.this.capacity);
}

La aptitud de cada solución es igual a la suma de las utilidades de los elementos que contiene. Si el peso total
supera la capacidad de la bolsa, entonces el individuo se establece como ilegal. La función de código anterior,
utilice los siguientes métodos de utilidad para evaluar la utilidad y el peso de una solución particular.
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

public double getUtilityOf(Individual<BooleanChromosome> individual) {
BooleanChromosome chrom = individual.getChromosome();
double utility = 0.0;
int size = chrom.length();
for(int i = 0; i < size; ++i){
utility += chrom.getValue(i) ? this.utilities[i] : 0.0;
}
return utility;
}
public double getWeightOf(Individual<BooleanChromosome> individual) {
BooleanChromosome chrom = individual.getChromosome();
double weight=0.0;
int size = chrom.length();
for(int i = 0; i < size; ++i){
weight += chrom.getValue(i) ? this.weights[i] : 0.0;
}
return weight;
}

3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en la ga

Decidimos procesar individuos de manera diferente legales e ilegales. Por lo tanto, creamos una secuencia,
llamada seq_legal, para procesar persona jurídica y una secuencia, llamada seq_illegal, para procesar los
individuos ilegales. Estas secuencias tienen el mismo cuerpo (selector de torneo, un punto de cruce y simple
mutador), pero diferentes objetivos. De hecho, el objetivo de seq_legal es maximizar la aptitud de las
personas jurídicas, mientras que la de seq_illegal es minimizar la aptitud de las personas ilegales con el fin de
eliminar el exceso de elementos y hacer legal la persona.
Evolucionamos en personas legales e ilegales paralelas y en cada generación pasamos las soluciones legales
para seq_legal y las soluciones ilegales para seq_illegal a través del uso de un dispensador exclusivo
076
077
078
079
080
081
082
083

Parallel<BooleanChromosome> parallel =
new Parallel<BooleanChromosome>(new ExclusiveDispenser<BooleanChromosome>(2){
@Override
public int distribute(Individual<BooleanChromosome> ind) {
return ind.isLegal() ? 0 :1;
}
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104

});
this.setFitness(this.maximize);
Sequence<BooleanChromosome> seq_legal = new Sequence<BooleanChromosome>();
seq_legal.appendStage(new TournamentSelector<BooleanChromosome>(2));
seq_legal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8));
seq_legal.appendStage(new SimpleMutator<BooleanChromosome>(0.02));
Sequence<BooleanChromosome> seq_illegal = new Sequence<BooleanChromosome>();
seq_illegal.appendStage(new TournamentSelector<BooleanChromosome>(2));
seq_illegal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8));
seq_illegal.appendStage(new SimpleMutator<BooleanChromosome>(0.2));
parallel.add(seq_legal);
parallel.add(seq_illegal);
this.addStage(parallel);
seq_legal.setFitness(this.maximize);
seq_illegal.setFitness(this.minimize);

Ejemplo del tema:
019 package jenes.tutorials.problem6;
020
021 import jenes.utils.Random;
022 import jenes.population.Individual;
023 import jenes.population.Population;
024 import jenes.population.Population.Statistics;
025 import jenes.population.Population.Statistics.Group;
026 import jenes.tutorials.utils.Utils;
027
028 /**
029 * Tutorial showing how to minimization and maximization sub-prolems can cohesists in
030 * the breeding structure of Jenes.
031 *
032 * This class defines the problem to solve.
033 *
034 * @author Luigi Troiano
035 *
036 * @version 1.0
037 * @since 1.0
038 */
039 public class KnapsackProblem {
040
041 private static int POPSIZE=100;
042 private static int GENERATION_LIMIT=100;
043
044 private static final double[] WEIGHTS = {1, 5, 3, 2, 8, 6, 4, 7, 9, 6};
045 private static final double[] UTILITIES = {7, 2, 7, 1, 6, 4, 2, 8, 9, 2};
046
047 private KnapsackGA algorithm;
048 private double[] utilities;
049 private double[] weights;
050
051 public KnapsackProblem(double[] utilities, double[] weights) {
052
algorithm = new KnapsackGA(POPSIZE, GENERATION_LIMIT, utilities, weights);
053
this.weights = weights;
054
this.utilities = utilities;
055 }
056
057 @SuppressWarnings("unchecked")
058 public void run() {
059
this.algorithm.evolve();
060
061
Statistics stat=algorithm.getCurrentPopulation().getStatistics();
062
Group legals = stat.getGroup(Population.LEGALS);
063
Individual solution= legals.get(0);
064
System.out.println(solution.getChromosome());
065
System.out.format("W: %f U: %fn", algorithm.getWeightOf(solution), algorithm.getUtilityOf(solut
ion) );
066 }
067
068 public double getCapacity() {
069
return this.algorithm.getCapacity();
070 }
071
072 public void setCapacity(double c) {
073
this.algorithm.setCapacity(c);
074 }
075
076 public double[] getUtilities() {
077
return utilities;
078 }
079
080 public double[] getWeights() {
081
return weights;
082 }
083
084 public static KnapsackProblem build(int n) {
085
086
Random r = Random.getInstance();
087
088
double[] utilities = new double[n];
089
for( int i = 0; i < n; ++i ) {
090
utilities[i] = r.nextInt(10);
091
}
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

double[] weights = new double[n];
for( int i = 0; i < n; ++i ) {
weights[i] = r.nextInt(10);
}
return new KnapsackProblem(utilities, weights);
}
public static void main(String[] args) {
Utils.printHeader();
System.out.println();
System.out.println("TUTORIAL 6:");
System.out.println("The Knapsack Problem.");
System.out.println();
KnapsackProblem p1 = new KnapsackProblem(UTILITIES, WEIGHTS);
System.out.println("Case 1: 10 elements, capacity 15");
System.out.println("Utilities: " + toString(p1.getUtilities()) );
System.out.println(" Weights: " + toString(p1.getWeights()) );
p1.setCapacity(15);
p1.run();
System.out.println();
System.out.println("Case 2: 10 elements, capacity 30");
System.out.println("Utilities: " + toString(p1.getUtilities()) );
System.out.println(" Weights: " + toString(p1.getWeights()) );
p1.setCapacity(30);
p1.run();
System.out.println();
KnapsackProblem p2 = KnapsackProblem.build(20);
System.out.println("Case 3: 20 random elements, capacity 50");
System.out.println("Utilities: " + toString(p2.getUtilities()) );
System.out.println(" Weights: " + toString(p2.getWeights()) );
p2.setCapacity(50);
p2.run();
System.out.println();
}
private static String toString(double[] values) {
String s = "[";
for(int i = 0; i < values.length; ++i ){
s += values[i]+ (i < values.length-1 ? " " : "]");
}
141
return s;
142 }
143
144 }
Ejemplo del tema:
019 package jenes.tutorials.problem6;
020
021 import jenes.Fitness;
022 import jenes.GeneticAlgorithm;
023 import jenes.chromosome.BooleanChromosome;
024 import jenes.population.Individual;
025 import jenes.population.Population;
026 import jenes.stage.ExclusiveDispenser;
027 import jenes.stage.Parallel;
028 import jenes.stage.Sequence;
029 import jenes.stage.operator.common.OnePointCrossover;
030 import jenes.stage.operator.common.SimpleMutator;
031 import jenes.stage.operator.common.TournamentSelector;
032
033 /**
034 * Tutorial showing how to minimization and maximization sub-prolems can cohesists in
035 * the breeding structure of Jenes.
036 *
037 * This class implements a genetic algorithm for solving the Knapsack problem.
038 *
039 * @author Luigi Troiano
040 *
041 * @version 2.0
042 *
043 * @since 1.0
044 */
045 public class KnapsackGA extends GeneticAlgorithm<BooleanChromosome>{
046
047 private class KnapsackFitness extends Fitness<BooleanChromosome> {
048
049
private KnapsackFitness(boolean maximize) {
050
super( maximize );
051
}
052
053
@Override
054
public void evaluate(Individual<BooleanChromosome> individual) {
055
double utility = getUtilityOf(individual);
056
double weight = getWeightOf(individual);
057
individual.setScore(utility);
058
individual.setLegal(weight <= KnapsackGA.this.capacity);
059
}
060
061 }
062
063 private double capacity;
064 private double[] weights;
065 private double[] utilities;
066
067 private KnapsackFitness maximize = new KnapsackFitness(true);
068 private KnapsackFitness minimize = new KnapsackFitness(false);
069
070 public KnapsackGA( int popsize, int generations, double[] utilities, double[] weights) {
071
super( new Population<BooleanChromosome>(new Individual<BooleanChromosome>(new Boole
anChromosome(utilities.length)), popsize), generations);
072
073
this.utilities = utilities;
074
this.weights = weights;
075
076
Parallel<BooleanChromosome> parallel =
077
new Parallel<BooleanChromosome>(new ExclusiveDispenser<BooleanChromosome>(2){
078
079
@Override
080
public int distribute(Individual<BooleanChromosome> ind) {
081
return ind.isLegal() ? 0 :1;
082
}
083
084
});
085
086
this.setFitness(this.maximize);
087
088
Sequence<BooleanChromosome> seq_legal = new Sequence<BooleanChromosome>();
089
seq_legal.appendStage(new TournamentSelector<BooleanChromosome>(2));
090
seq_legal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8));
091
seq_legal.appendStage(new SimpleMutator<BooleanChromosome>(0.02));
092
093
Sequence<BooleanChromosome> seq_illegal = new Sequence<BooleanChromosome>();
094
seq_illegal.appendStage(new TournamentSelector<BooleanChromosome>(2));
095
seq_illegal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8));
096
seq_illegal.appendStage(new SimpleMutator<BooleanChromosome>(0.2));
097
098
parallel.add(seq_legal);
099
parallel.add(seq_illegal);
100
101
this.addStage(parallel);
102
103
seq_legal.setFitness(this.maximize);
104
seq_illegal.setFitness(this.minimize);
105 }
106
107 public double getCapacity() {
108
return this.capacity;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 }

}

public void setCapacity(double capacity) {
this.capacity = capacity;
}
public double getUtilityOf(Individual<BooleanChromosome> individual) {
BooleanChromosome chrom = individual.getChromosome();
double utility = 0.0;
int size = chrom.length();
for(int i = 0; i < size; ++i){
utility += chrom.getValue(i) ? this.utilities[i] : 0.0;
}
return utility;
}
public double getWeightOf(Individual<BooleanChromosome> individual) {
BooleanChromosome chrom = individual.getChromosome();
double weight=0.0;
int size = chrom.length();
for(int i = 0; i < size; ++i){
weight += chrom.getValue(i) ? this.weights[i] : 0.0;
}
return weight;
}
Registro de las estadísticas

Experimentar con algoritmo genético requiere a menudo para recopilar datos sobre la evolución a lo largo de
los diferentes experimentos. En este tutorial vamos a aprender a capturar estadísticas evolución en. Csv y los
archivos de MS Excel.
Los madereros

Hay dos tres métodos para registrar las estadísticas en Jenes. La primera es hacerlo usted mismo por guardar
los datos en un archivo o base de datos. Los otros dos se basan en los registradores disponibles desde Jenes
1.3.0. La forma más fácil es usar un StatisticsLogger. Esta clase es capaz de grabar automáticamente los
objetos que pertenecen desde LoggableStatistics, por ejemplo, Population.Statistics y objetos
GeneticAlgorithm.Statistics. StatisticsLogger basa en un registrador real para grabar realmente los datos en
algún medio. Por ejemplo, se puede hacer uso de un CSVLogger para grabar en. Csv (es decir, valores
separados por comas) archive
072
csvlogger = new StatisticsLogger(
073
new CSVLogger(new String[]{"LegalHighestScore", "LegalScoreAvg","LegalScoreDev"},
FOLDER + "knapsackproblem.csv" ) );
o XLSLogger para grabar directamente en un archivo xls MS Excel.
075
xlslogge1 = new StatisticsLogger(
076
new XLSLogger(new String[]{"LegalHighestScore", "LegalScoreAvg","LegalScoreDev"},
FOLDER + "knapsack1.log.xls" ) );
En algún momento es útil volver a utilizar un spreedsheet. En este caso, podemos especificar que plantilla se
usan en el método constructor de XLSLogger.
078
xlslogge2 = new StatisticsLogger(
079
new XLSLogger(new String[]{"LegalHighestScore", "LegalScoreAvg" , "IllegalScoreAvg"}
, FOLDER + "knapsack2.log.xls", FOLDER +"knapsack.tpl.xls" ) );
El tercer método hace uso directo de registrador real, por ejemplo
081
xlslogge3 = new XLSLogger(new String[]{"LegalHighestScore", "LegalScoreAvg" , "Run"}, FOL
DER + "knapsack3.log.xls");
Esquema

Los madereros son capaces de procesar datos tabulares con un esquema determinado, es decir, un conjunto de
campos etiquetados. El esquema de datos se tiene que dar en el momento de la construcción. Por ejemplo, en
el primer y segundo caso estamos interesados en grabar LegalHighestScore, LegalScoreAvg y LegalScoreDev
largo de las generaciones. En el tercer caso grabamos LegalHighestScore, LegalScoreAvg y IllegalScoreAvg.
Finalmente, en el tercer caso grabamos LegalHighestScore, LegalScoreAvg and Run, representando este
último el número de ejecución de la experimentación.

Si utilizamos StatisticsLogger, los campos tienen que ser etiquetados de la misma manera las estadísticas son
anotados por registrable (etiqueta). Si utilizamos directamente los madereros reales, podemos hacer uso de
distintivos que deseamos para el esquema, como el mapeo estará en nuestro poder, como se describe a
continuación.

Tenga en cuenta que el esquema entre mayúsculas y minúsculas, por lo que "someStatistic" es diferente de
"SomeStatistic", y ambos son diferentes de "SOMESTATISTIC".
Medios de comunicación

Grabación en. Csv es sencillo. Si el archivo existe, se puede decidir si desea sobrescribir los datos (por
defecto) o para añadir datos.

Cuando usamos. Xls debemos cuidar algunos detalles. Cuando no existe el archivo de registro, el registrador
crea un libro vacío con una hoja, donde las columnas se asignan de acuerdo con el esquema con primera fila
asignada a las etiquetas de campo.

Podemos optar por utilizar un pre-hechos xls.. En este caso tenemos que reservar una columna para cada
campo en el esquema. La columna puede colocarse en cualquier parte de la hoja, que la hoja no importa. La
única restricción es que la celda en la fila 1 debe contener la etiqueta del campo. También podemos optar por
utilizar un archivo xls. Como plantilla. Una plantilla es simplemente un archivo de pre-hechos. En este caso,
el archivo no se sobrescribe como el destino es diferente (ver xlslogge2 para un ejemplo).

Por ejemplo, podemos decidir utilizar la plantilla se muestra en la Figura 1.
Recolección de Datos

Una vez que los madereros están establecidos y esquema definido, podemos recoger datos.
La mejor manera de recoger los datos es por medio de oyentes. Por ejemplo
143
GenerationEventListener<BooleanChromosome> logger1 = new GenerationEventListener<Boolean
Chromosome>() {
144
145
public void onGeneration(GeneticAlgorithm ga, long time) {
146
Population.Statistics stats = ga.getCurrentPopulation().getStatistics();
147
148
prb.csvlogger.record(stats);
149
prb.xlslogge1.record(stats);
150
prb.xlslogge2.record(stats);
151
152
}
153
154
};

En este caso StatisticsLogger se encarga de registrar datos. Tan sólo hay que proporcionar
una LoggableStatistics y StatisticsLogger haremos el trabajo por nosotros. El inconveniente
de esta solución es que no somos capaces de añadir datos no considerados por el objeto de
estadísticas. Para obtener un control más preciso del proceso, podemos hacer uso directo de
un registrador real. Por ejemplo
172
GenerationEventListener<BooleanChromosome> logger2 = new GenerationEventListener<Boolean
Chromosome>() {
173
public void onGeneration(GeneticAlgorithm ga, long time) {
174
Population.Statistics stats = ga.getCurrentPopulation().getStatistics();
175
176
Group legals = stats.getGroup(Population.LEGALS);
177
178
prb.xlslogge3.put("LegalHighestScore", legals.getMax());
179
prb.xlslogge3.put("LegalScoreAvg", legals.getMin());
180
prb.xlslogge3.put("Run", prb.exec);
181
182
prb.xlslogge3.log();
183
}
184
185
};

Entrar cierre
Por último, podemos hacer que los datos persistentes cerrando los madereros.
165
166

prb.csvlogger.close();
prb.xlslogge1.close();
Anatomía de un algoritmo genético en jenes
Anatomía de un algoritmo genético en jenes
Anatomía de un algoritmo genético en jenes
Anatomía de un algoritmo genético en jenes
Anatomía de un algoritmo genético en jenes

Mais conteúdo relacionado

Mais procurados

Algoritmos genéticos y sus aplicaciones - S.O.
Algoritmos genéticos y sus aplicaciones - S.O.Algoritmos genéticos y sus aplicaciones - S.O.
Algoritmos genéticos y sus aplicaciones - S.O.Pol C. Arapa Sánchez
 
Algoritmos genéticos con matlab
Algoritmos genéticos con matlabAlgoritmos genéticos con matlab
Algoritmos genéticos con matlabUNIV OF PERU
 
Algoritmo 13 11-12
Algoritmo 13 11-12Algoritmo 13 11-12
Algoritmo 13 11-12felo1019
 
Tema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicos
Tema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicosTema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicos
Tema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicosESCOM
 
Utp i_ay_se_s10_algoritmo genéticos_
 Utp i_ay_se_s10_algoritmo genéticos_ Utp i_ay_se_s10_algoritmo genéticos_
Utp i_ay_se_s10_algoritmo genéticos_jcbenitezp
 
Algoritmos Genéticos_Inteligencia Artificial
Algoritmos Genéticos_Inteligencia ArtificialAlgoritmos Genéticos_Inteligencia Artificial
Algoritmos Genéticos_Inteligencia ArtificialGabriela_Rodriguez
 
Algoritmos geneticos
Algoritmos geneticosAlgoritmos geneticos
Algoritmos geneticosYAn_dy
 
Trabajo algoritmo genetico uba
Trabajo algoritmo genetico uba Trabajo algoritmo genetico uba
Trabajo algoritmo genetico uba yucci2323
 

Mais procurados (9)

Algoritmos genéticos y sus aplicaciones - S.O.
Algoritmos genéticos y sus aplicaciones - S.O.Algoritmos genéticos y sus aplicaciones - S.O.
Algoritmos genéticos y sus aplicaciones - S.O.
 
Algoritmos genéticos con matlab
Algoritmos genéticos con matlabAlgoritmos genéticos con matlab
Algoritmos genéticos con matlab
 
Algoritmo 13 11-12
Algoritmo 13 11-12Algoritmo 13 11-12
Algoritmo 13 11-12
 
A Geneticos
A GeneticosA Geneticos
A Geneticos
 
Tema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicos
Tema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicosTema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicos
Tema 7 Aprendizaje De Sistemas Difusos Con Algoritmos GenéTicos
 
Utp i_ay_se_s10_algoritmo genéticos_
 Utp i_ay_se_s10_algoritmo genéticos_ Utp i_ay_se_s10_algoritmo genéticos_
Utp i_ay_se_s10_algoritmo genéticos_
 
Algoritmos Genéticos_Inteligencia Artificial
Algoritmos Genéticos_Inteligencia ArtificialAlgoritmos Genéticos_Inteligencia Artificial
Algoritmos Genéticos_Inteligencia Artificial
 
Algoritmos geneticos
Algoritmos geneticosAlgoritmos geneticos
Algoritmos geneticos
 
Trabajo algoritmo genetico uba
Trabajo algoritmo genetico uba Trabajo algoritmo genetico uba
Trabajo algoritmo genetico uba
 

Semelhante a Anatomía de un algoritmo genético en jenes

Algoritmo genetico
Algoritmo geneticoAlgoritmo genetico
Algoritmo geneticoVane Erraez
 
computacion Evolutiva
computacion Evolutivacomputacion Evolutiva
computacion Evolutivaguest590a846
 
Artículo predicción mundial 2014 algoritmos geneticos
Artículo predicción mundial 2014   algoritmos geneticosArtículo predicción mundial 2014   algoritmos geneticos
Artículo predicción mundial 2014 algoritmos geneticosRichar León
 
Inteligencia Artificial Clase 5
Inteligencia Artificial Clase 5Inteligencia Artificial Clase 5
Inteligencia Artificial Clase 5UNEFA
 
Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.
Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.
Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.SantiagoGarridoBulln
 
Algoritmo genetico
Algoritmo geneticoAlgoritmo genetico
Algoritmo geneticoRufino meri?
 
Algoritmo genetico
Algoritmo geneticoAlgoritmo genetico
Algoritmo geneticoyenpochih
 
Algoritmos evolutivos ii
Algoritmos evolutivos iiAlgoritmos evolutivos ii
Algoritmos evolutivos iinando85
 

Semelhante a Anatomía de un algoritmo genético en jenes (20)

ALGORITMO GENETICO - II.pptx
ALGORITMO GENETICO - II.pptxALGORITMO GENETICO - II.pptx
ALGORITMO GENETICO - II.pptx
 
Algoritmo genetico
Algoritmo geneticoAlgoritmo genetico
Algoritmo genetico
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
Resumen 2 Unidad
Resumen 2 UnidadResumen 2 Unidad
Resumen 2 Unidad
 
computacion Evolutiva
computacion Evolutivacomputacion Evolutiva
computacion Evolutiva
 
Artículo predicción mundial 2014 algoritmos geneticos
Artículo predicción mundial 2014   algoritmos geneticosArtículo predicción mundial 2014   algoritmos geneticos
Artículo predicción mundial 2014 algoritmos geneticos
 
Ag (2005 verano)
Ag (2005 verano)Ag (2005 verano)
Ag (2005 verano)
 
Inteligencia Artificial Clase 5
Inteligencia Artificial Clase 5Inteligencia Artificial Clase 5
Inteligencia Artificial Clase 5
 
Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.
Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.
Genetic Algorithms. Algoritmos Genéticos y cómo funcionan.
 
Algoritmos Genéticos (1).pptx
Algoritmos Genéticos (1).pptxAlgoritmos Genéticos (1).pptx
Algoritmos Genéticos (1).pptx
 
Algoritmo genetico
Algoritmo geneticoAlgoritmo genetico
Algoritmo genetico
 
Algoritmo genetico
Algoritmo geneticoAlgoritmo genetico
Algoritmo genetico
 
Algoritmos evolutivos ii
Algoritmos evolutivos iiAlgoritmos evolutivos ii
Algoritmos evolutivos ii
 
Algoritmos genéticos 2 s lun 30 sep-13
Algoritmos genéticos 2 s lun 30 sep-13Algoritmos genéticos 2 s lun 30 sep-13
Algoritmos genéticos 2 s lun 30 sep-13
 

Último

VOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMAL
VOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMALVOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMAL
VOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMALEDUCCUniversidadCatl
 
SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024
SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024
SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024gharce
 
La Función tecnológica del tutor.pptx
La  Función  tecnológica  del tutor.pptxLa  Función  tecnológica  del tutor.pptx
La Función tecnológica del tutor.pptxJunkotantik
 
Tema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdf
Tema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdfTema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdf
Tema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdfDaniel Ángel Corral de la Mata, Ph.D.
 
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdfTarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdfManuel Molina
 
DETALLES EN EL DISEÑO DE INTERIOR
DETALLES EN EL DISEÑO DE INTERIORDETALLES EN EL DISEÑO DE INTERIOR
DETALLES EN EL DISEÑO DE INTERIORGonella
 
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docxPLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docxJUANSIMONPACHIN
 
Uses of simple past and time expressions
Uses of simple past and time expressionsUses of simple past and time expressions
Uses of simple past and time expressionsConsueloSantana3
 
Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024IES Vicent Andres Estelles
 
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...fcastellanos3
 
IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO YESSENIA 933623393 NUEV...
IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO  YESSENIA 933623393 NUEV...IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO  YESSENIA 933623393 NUEV...
IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO YESSENIA 933623393 NUEV...YobanaZevallosSantil1
 
Monitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptx
Monitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptxMonitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptx
Monitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptxJUANCARLOSAPARCANARE
 
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdfFisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdfcoloncopias5
 
c3.hu3.p1.p3.El ser humano como ser histórico.pptx
c3.hu3.p1.p3.El ser humano como ser histórico.pptxc3.hu3.p1.p3.El ser humano como ser histórico.pptx
c3.hu3.p1.p3.El ser humano como ser histórico.pptxMartín Ramírez
 
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdfLA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdfNataliaMalky1
 

Último (20)

VOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMAL
VOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMALVOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMAL
VOLUMEN 1 COLECCION PRODUCCION BOVINA . SERIE SANIDAD ANIMAL
 
SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024
SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024
SISTEMA INMUNE FISIOLOGIA MEDICA UNSL 2024
 
La Función tecnológica del tutor.pptx
La  Función  tecnológica  del tutor.pptxLa  Función  tecnológica  del tutor.pptx
La Función tecnológica del tutor.pptx
 
Tema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdf
Tema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdfTema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdf
Tema 8.- Gestion de la imagen a traves de la comunicacion de crisis.pdf
 
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdfTarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
Tarea 5_ Foro _Selección de herramientas digitales_Manuel.pdf
 
DETALLES EN EL DISEÑO DE INTERIOR
DETALLES EN EL DISEÑO DE INTERIORDETALLES EN EL DISEÑO DE INTERIOR
DETALLES EN EL DISEÑO DE INTERIOR
 
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docxPLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
PLANIFICACION ANUAL 2024 - INICIAL UNIDOCENTE.docx
 
Uses of simple past and time expressions
Uses of simple past and time expressionsUses of simple past and time expressions
Uses of simple past and time expressions
 
Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024Metabolismo 3: Anabolismo y Fotosíntesis 2024
Metabolismo 3: Anabolismo y Fotosíntesis 2024
 
Earth Day Everyday 2024 54th anniversary
Earth Day Everyday 2024 54th anniversaryEarth Day Everyday 2024 54th anniversary
Earth Day Everyday 2024 54th anniversary
 
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
Estas son las escuelas y colegios que tendrán modalidad no presencial este lu...
 
Sesión La luz brilla en la oscuridad.pdf
Sesión  La luz brilla en la oscuridad.pdfSesión  La luz brilla en la oscuridad.pdf
Sesión La luz brilla en la oscuridad.pdf
 
VISITA À PROTEÇÃO CIVIL _
VISITA À PROTEÇÃO CIVIL                  _VISITA À PROTEÇÃO CIVIL                  _
VISITA À PROTEÇÃO CIVIL _
 
IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO YESSENIA 933623393 NUEV...
IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO  YESSENIA 933623393 NUEV...IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO  YESSENIA 933623393 NUEV...
IV SES LUN 15 TUTO CUIDO MI MENTE CUIDANDO MI CUERPO YESSENIA 933623393 NUEV...
 
Monitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptx
Monitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptxMonitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptx
Monitoreo a los coordinadores de las IIEE JEC_28.02.2024.vf.pptx
 
DIA INTERNACIONAL DAS FLORESTAS .
DIA INTERNACIONAL DAS FLORESTAS         .DIA INTERNACIONAL DAS FLORESTAS         .
DIA INTERNACIONAL DAS FLORESTAS .
 
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdfFisiologia.Articular. 3 Kapandji.6a.Ed.pdf
Fisiologia.Articular. 3 Kapandji.6a.Ed.pdf
 
TL/CNL – 2.ª FASE .
TL/CNL – 2.ª FASE                       .TL/CNL – 2.ª FASE                       .
TL/CNL – 2.ª FASE .
 
c3.hu3.p1.p3.El ser humano como ser histórico.pptx
c3.hu3.p1.p3.El ser humano como ser histórico.pptxc3.hu3.p1.p3.El ser humano como ser histórico.pptx
c3.hu3.p1.p3.El ser humano como ser histórico.pptx
 
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdfLA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
LA OVEJITA QUE VINO A CENAR CUENTO INFANTIL.pdf
 

Anatomía de un algoritmo genético en jenes

  • 1. Anatomía de un algoritmo genético en Jenes Programación en Jenes es fácil, intuitiva y divertida. En esta sección, vamos a proporcionar algunos conceptos que hay que tener en cuenta al esbozar una solución en Jenes. Estos conceptos le ayudarán a moverse de manera efectiva entre las clases previstas en el API Jenes. Usted se sorprenderá de lo rápido que se puede definir un algoritmo genético, implementado y probado. Los cromosomas, individuos y poblaciones. La primera cosa a tener en cuenta es la diferencia entre los cromosomas, los individuos y las poblaciones. Soluciones en un espacio de búsqueda se representan por los individuos. Están hechas de un cromosoma y de la aptitud de valor: INDIVIDUAL = CROMOSOMA + FITNESS. Los cromosomas son las codificaciones de solución. En Jenes, se les considera como un conjunto de genes. Aquí está una lista de las clases de cromosomas proporcionadas por Jenes. BitwiseChromosome: modelos de un cromosoma de bits. Su genoma contiene valores codificados otorgado a la codificación de bits especificado. BooleanChromosome: modelos de un cromosoma de valores booleanos. Cada gen alelo puede ser verdadera o falsa. DoubleChromosome: modelos de un cromosoma de valores dobles. Cada valor está en el rango [lowerBound, upperBound]. Estos límites se especifican en el momento de instancias. IntegerChromosome: modelos de un cromosoma de valores enteros. Cada valor está en el rango [lowerBound, upperBound]. Estos límites se especifican en el momento de instancias. ObjectChromosome: representa un cromosoma con genes que contiene un valor de alelo objeto. PermutationChromosome: proporciona un cromosoma capaz de modelar permutaciones. Una matriz de valores enteros es su genoma. La propiedad más importante es que el genoma no contiene valores duplicados.
  • 2. Todas las clases de cromosomas son la implementación de la interfaz del cromosoma. En general, los cromosomas se fija número de genes, pero su longitud puede variar durante la ejecución del algoritmo con el fin de implementar una codificación de longitud variable de solución. Una población es simplemente una colección de individuos (por ejemplo, soluciones). Los individuos son todas las instancias de la clase paramétrica individual <T extiende Chromosome>, con el fin de tener un mayor control sobre los tipos. Un individuo puede ser legal o no legal. Es posible ajustar el lagality de un individuo mediante la invocación del método setLegal (boolen) en su instancia. Por defecto, cada individuo se fija te bo inicialmente legal. Durante la evolución de algoritmos, las poblaciones del pasado se almacenan en la historia del algoritmo. En cada iteración de la evolución, la población más antigua y sus individuos se vuelven a utilizar. Las poblaciones del pasado, en lugar de ser cancelado la asignación, se mantenido en la memoria y volver a utilizar. Esta técnica evita la asignación en memoria de las nuevas poblaciones y limita el uso del recolector de basura. Como se ha dicho, un algoritmo genético procesa una población de individuos. En cada generación hay poblaciones de entrada y salida. Es importante tener en cuenta que la población de salida se pre-inizialized con individuos "reciclados" tomados de la historia (por razones de rendimiento). Así Jenes generalmente no asigna nuevos individuos. Estructura Algoritmo Jenes proporciona una estructura flexible para la evolución de una población de individuos. En general, un algoritmo genético está estructurado como se muestra en la figura.
  • 3. Básicamente, un algoritmo genético realiza el siguiente bucle: Aleatoriamente crear una población inicial repetición Valorar la aptitud de cada individuo Seleccione uno o más individuos de la población con una probabilidad basada en la aptitud para partecipate en las operaciones genéticas Crear nuevos individuos mediante la aplicación de las operaciones genéticas con probabilidades especificadas hasta que una solución aceptable se encuentra o se cumpla alguna otra condición parar devolverle al individuo mejor tan lejos En Jenes un algoritmo genético se puede implementar mediante el uso o la subclasificación GeneticAlgorithm y definir una implementación de funcion gimnasio subclasificando Fitness y la implementación del método abstracto evaluar (Individual). Este método se utiliza para evaluar la capacidad de un solo individuo. La implementación de este método está relacionada específicamente con el problema a resolver.
  • 4. En Jenes cuerpo algoritmo genético es un "tubo" de etapas. Las etapas se ejecutan secuencialmente en el orden en que se agregan a la secuencia. Cada etapa recibe una población de entrada (producido como salida por la etapa anterior) y produce una población de salida. ¿Qué etapas y en qué orden para considerar que queda a las necesidades del algoritmo. La referencia a la actual y en el proceso de llenado se puede respectivamente obtiene por la getCurrentPopulation métodos () y getNextPopulation (). Jenes también permite definir etapas paralelas. Una etapa paralelo está formado por diferentes ramas, cada rama es una etapa que recibe una subpoblación de acuerdo con el dispensador de población utilizada. Un dispensador distribuye una población entre las ramas de una etapa en paralelo y se funde la salida de cada rama en la población de salida del paralelo. El punto de quiebre y los operadores genéticos representan las etapas de tuberías generales más simples. Una etapa BreakPoint notifica a sus oyentes cuando se invocated su método de proceso. No alterate la población de entrada. Operadores genéticos utilizados en los algoritmos genéticos son análogos a éstos que se producen en el mundo natural: Selección: la que da preferencia a los mejores individuos, que les permite pasar a la siguiente generación. Crossover: lo que representa el apareamiento entre individuos. Mutación: que introduce modificaciones aleatorias. Jenes proporciona la implementación de los operadores genéticos más comunes: TournamentSelector: choses a un número aleatorio de individuos de la población. Estos se comparan entre sí y el mejor de ellos es elegido para ser un padre. Selector torneo hace
  • 5. asegurar que incluso los individuos de calidad media tienen alguna posibilidad de tener hijos. En Jenes es necesario especificar el número de intentos de torneo. RouletteWheelSelector: coge un miembro particular de la población para ser un padre con una probabilidad igual a su condición física, dividido por el total de la aptitud de la población. OnePointCrossover: elige al azar un punto de cruce de los cromosomas de los padres y crea una nueva descendencia. Uno de los puntos de cruce puede tener este aspecto (donde "|" es el punto de cruce): Chromosome 1 11101 | 001000 Chromosome 2 00001 | 010101 Offspring 1 11101 | 010101 Offspring 2 00001 | 001000 TwoPointsCrossover: escoge al azar dos puntos de cruce de los cromosomas de los padres y crea una nueva descendencia. Dos puntos de cruce puede tener este aspecto: Chromosome 1 11 | 10100 | 1000 Chromosome 2 00 | 00101 | 0101 Offspring 1 11 | 00101 | 1000 Offspring 2 00 | 10100 | 0101 En Jenes necesita especificar la probabilidad por la cual se utilizará el operador de cruce. En general, para un operador de cruce la probabilidad se establece en 80% Mutador simple: choses al azar un punto de mutación y aleatoriza su gen. Operador de mutación también necesita un número probabilidad que especifica su uso. En general, para un operador de mutación la probabilidad se establece en 20%. Jenes proporciona también una interfaz sencilla para GeneticAlgorithm. Es SimpleGA clase que implementa un algoritmo genético tres etapas hecha de una herramienta de selección, uno de cruce y uno Mutador en secuencia. Ofrece una forma sencilla de implementar su propio algoritmo genético que le permite descuidar los problemas relacionados con la construcción de los estadios.
  • 6. La clase proporciona un conjunto de constructores por lo que crear una instancia de un algoritmo SimpleGA. Constructores permite decidir qué método de selección (es decir, Torneo o ruleta) o el método cruzado (es decir, un punto o dos puntos) a adoptar. También cruce y probabilidad de mutación puede ser especificado en el momento de la construcción. SimpleGA es una subclase GeneticAlgorithm. Jenes incluye un soporte para el elitismo, es decir los mejores individuos de cada generación tienen la garantía de estar en la próxima generación. El número de individuos de la élite es fijado por el setElitism método (int). Estos individuos se sustituyen a algunos individuos a la población procesada de acuerdo con las siguientes estrategias: Random Estrategia Elitismo: próximos individuos de población son seleccionados al azar y se sustituye por la élite. Peor Estrategia Elitismo: próximo de población peores individuos son sustituidos por la élite. Usted puede configurar su estrategia de elitismo preferida de la siguiente manera: sga.setElitismStrategy(ElitismStrategy.RANDOM); or sga.setElitismStrategy(ElitismStrategy.WORST); La primera estrategia es más eficiente, ya que no requiere para ordenar la población. El inconveniente es que los individuos con una buena aptitud podrían ser sustituidos por la élite. La segunda estrategia es más lento, pero asegura que sólo los peores individuos están sustituidos. Jenes utiliza el MersenneTwisterRandom clase para la generación de números y valores de pseudo-aleatorios. Este una clase optimizado que proporciona para la generación rápida de números aleatorios de muy alta calidad. Por esta razón, se utiliza en lugar de java.util.Random. La generación de números pseudoaleatorios es muy útil durante todas las fases de la evolución algoritmo (tales como la inicialización de la población, el uso de operadores de selección, la determinación de puntos de cruce y mutación, y así sucesivamente). Eventos, oyentes y Estadísticas
  • 7. La ejecución del algoritmo genético es invocado por el método de evolucionar (). La ejecución del algoritmo pasa a través de los siguientes eventos: Inicio: la evolución algoritmo comienza. Init: estructuras internas, como la población dada como entrada a la generación 0 y la historia, se inicializan. Generación: una generación se ha acaba de realizar. Stop: el algoritmo termina sus ejecuciones. Cada uno de estos eventos pueden ser capturados por AlgorithmEventListeners y GenerationEventListeners. También pueden ser caputured por la subclase GeneticAlgorithm, reemplazando los métodos onStart (largos), onInit (largo), onGeneration (tiempo) y onStop (largo). La captura de eventos es útil para recopilar estadísticas y realizar análisis. AlgorithmEventListeners proporciona la interfaz para la captura de eventos a nivel de algoritmo. Esta interfaz debe ser implementado por todas las clases interesadas en beign notificado por acontecimientos algoritmo (Start, inicio, parada). Un AlgorithmEventListener se puede registrar en el algoritmo por el método GeneticAlgorithm.addAlgorithmEventListener (AlgorithmEventListener). El oyente puede ser eliminado por la invocación del método GeneticAlgorithm.removeAlgorithmEventListener (AlgorithmEventListener). GenerationEventListener es un oyente del evento de generación de algoritmo genético. Esta escucha se notifica una vez que se ejecuta una etapa de generación. A GenerationEventListener se puede registrar en el algoritmo por el método GeneticAlgorithm.addGenerationEventListener (GenerationEventListener). El oyente puede ser eliminado por la invocación del método GeneticAlgorithm.removeGenerationEventListener (GenerationEventListener). Durante la evolución del algoritmo genético , Jenes recopila estadísticas sobre: Ejecución de algoritmo: La clase GeneticAlgorithm.Statistics se encarga de almacenar información sobre el tiempo dedicado por todo el proceso evolutivo y el número de generaciones creadas . Puede invocar el método () GeneticAlgorithm.getStatistics para obtener las estadísticas de algoritmos .
  • 8. Población: La clase Population.Statistics se encarga de almacenar información sobre una población. A medida que cada lata población contiene individuos legales e ilegales , mantiene los individuos con la aptitud mayor y menor , los valores medios y la desviación ambos consideran a las personas jurídicas y las ilegales . Puede invocar el método las Population.getStatistics () para obtener sus estadísticas . Operadores: Las Selection.Statistics , Crossover.Statistics y Mutator.Statistics clases son responsables de almacenar información sobre los operadores utilizados y el tiempo empleado para su ejecución . Ellos sostienen respectivamente el número de cruce , selección y mutación realizado . Puede invocar el método () Operator.getStatistics en una instancia de la clase operador para obtener sus estadísticas.
  • 9. Un problema boolean sencilla Vamos a empezar con un problema sencillo. Dado un espacio de búsqueda hecha de variables booleanas, nuestro objetivo es encontrar una solución hecha de verdaderos valores (o valores falsos). Este problema es enfrentado por el diseño de un algoritmo genético de trabajo en los cromosomas booleanos. La función de aptitud se calcula contando el número de verdaderos valores dentro del cromosoma. Así que con el fin de encontrar la solución con todos los verdaderos valores podemos maximizar la función de aptitud, mientras que se minimiza la función de aptitud con el fin de encontrar una solución a base de todos los falsos valores. Este tutorial te dará la oportunidad de entender cómo se estructura un algoritmo genético y taylored a un problema de optimización. Por otra parte, vamos a ver cómo los oyentes se pueden utilizar para capturar los eventos algoritmos. 1. Elegir un problema cromosómico adecuado y crear la población inicial. La elección de una representación cromosómica adecuada es la tarea más importante que hacer antes de ejecutar un algoritmo genético. ¿Qué representación a utilizar depende de la estructura de las soluciones a los problemas. En nuestro caso, las soluciones están hechas de matrices booleanas. Por lo tanto, BooleanChromosome parece ser la opción approppriate. Los cromosomas representan el componente clave de las soluciones (es decir, individuos). Para la construcción de la población inicial que necesitamos un prototipo de soluciones (muestra), como se muestra en el siguiente código. 060 Individual<BooleanChromosome> sample = new Individual<BooleanChromosome>(new BooleanC hromosome(CHROMOSOME_LENGTH)); 061 Population<BooleanChromosome> pop = new Population<BooleanChromosome>(sample, POPUL ATION_SIZE); cuando 045 046 047 private static int POPULATION_SIZE=50; private static int CHROMOSOME_LENGTH=100; private static int GENERATION_LIMIT=1000; 2. Puesta en marcha del algoritmo genético. Cualquier algoritmo en Jenes 2.0 se basa en GeneticAlgorithm, para wich debe definir una función de aptitud que se utiliza para evaluar a los individuos. Para definir una función de aptitud en Jenes 2.0 sólo tenemos que crear una subclase de fitness, una clase abstracta, la aplicación del método de evaluar (individual).
  • 10. Cualquier algoritmo en Jenes se basa en GeneticAlgorithm, una clase abstracta cuyo único método es abstracto evaluateIndividual que es un problema dependiente. A continuación se muestra el código para crear una subclase de GeneticAlgorithm y evaluar a un individuo en nuestro problema. Por ejemplo, podría ser fácil de definir una función de aptitud mediante el uso de una clase interna anónima como seguimiento: 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 Fitness<BooleanChromosome> fit = new Fitness<BooleanChromosome>(false) { @Override public void evaluate(Individual<BooleanChromosome> individual) { BooleanChromosome chrom = individual.getChromosome(); int count = 0; int length=chrom.length(); for(int i=0;i<length;i++) if(chrom.getValue(i)) count++; individual.setScore(count); } }; Y luego pasar este objeto como primer parámetro de algoritmo genético (o cualquier subclase predefinido) 079 080 GeneticAlgorithm<BooleanChromosome> ga = new GeneticAlgorithm<BooleanChromosome> (fit, pop, GENERATION_LIMIT); La clase de fitness ofrece dos constructores diferentes para definir el número de objetivos a considerar en la evaluación de las personas, y para cada objetivo de la bandera que indica si se trata de una función de maximizar o no. En el código que aparece más arriba, creamos un gimnasio para un solo problema objetivo (sólo una bandera como parámetros). 3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en el ga. Una vez definido el algoritmo genético, es necesario especificar la secuencia de la población operadores atravesará. El esquema más simple contiene sólo tres operadores en secuencia: un selector, una de cruce y uno de mutador. Sin embargo, es posible crear un
  • 11. tubo más complejo que tiene paralléles y secuencias. A los efectos de este tutorial vamos a adoptar la siguiente estructura simple (ver APIs forman más detalles sobre los operadores adoptados): 082 083 ); 084 085 086 087 AbstractStage<BooleanChromosome> selection = new TournamentSelector<BooleanChromosome>(3); AbstractStage<BooleanChromosome> crossover = new OnePointCrossover<BooleanChromosome>(0.8 AbstractStage<BooleanChromosome> mutation = new SimpleMutator<BooleanChromosome>(0.02); ga.addStage(selection); ga.addStage(crossover); ga.addStage(mutation); 4. Establezca los parámetros del algoritmo y ejecutar la evolución. Es posible personalizar el ajuste del valor de elitismo algoritmo genético y el objetivo de optimización antes de ejecutar la evolución. El elitismo es el número de las mejores personas para celebrar en la próxima generación (1 en nuestro caso). 089 ga.setElitism(1); Por último, podemos hacer que el algoritmo de funcionamiento. 091 ga.evolve(); 5. Obtención del resultado de la evolución. Jenes proporciona estadísticas tanto para el algoritmo y la población. La primera referencia a las estadísticas relativas a la ejecución de algoritmo, es decir, los tiempos de inicialización, comenzando, la evolución y las generaciones. El segundo a la distribución de soluciones y servicios conexos valores de fitness, como las personas ordenadas por la disminución de la función física, la media máxima, y mínima de los valores de fitness. Ellos se pueden recuperar en cualquier momento. Le llamaremos cuando el algoritmo ha terminado. 093 094 095 096 ")); 097 098 099 100 101 102 103 Population.Statistics stats = ga.getCurrentPopulation().getStatistics(); GeneticAlgorithm.Statistics algostats = ga.getStatistics(); System.out.println("Objective: " + (fit.getBiggerIsBetter()[0] ? "Max! (All true)" : "Min! (None true) System.out.println(); Group legals = stats.getGroup(Population.LEGALS); Individual solution = legals.get(0); System.out.println("Solution: ");
  • 12. 104 105 106 107 108 System.out.println( solution ); System.out.format("found in %d ms.n", algostats.getExecutionTime() ); System.out.println(); Utils.printStatistics(stats); Ejemplo completo: package jenes.tutorials.problem1; import jenes.Fitness; import jenes.GeneticAlgorithm; import jenes.chromosome.BooleanChromosome; import jenes.population.Individual; import jenes.population.Population; import jenes.population.Population.Statistics.Group; import jenes.stage.AbstractStage; import jenes.stage.operator.common.OnePointCrossover; import jenes.stage.operator.common.SimpleMutator; import jenes.stage.operator.common.TournamentSelector; import jenes.tutorials.utils.Utils; public class BooleanProblem { private static int POPULATION_SIZE=50; private static int CHROMOSOME_LENGTH=100; private static int GENERATION_LIMIT=1000; public static void main(String[] args) throws Exception { Utils.printHeader(); System.out.println(); System.out.println("TUTORIAL 1:"); System.out.println("This algorithm aims to find a vector of booleans that is entirely true or false."); System.out.println(); // Random.getInstance().setStandardSeed(); Individual<BooleanChromosome> sample = new Individual<BooleanChromosome>(new BooleanChro mosome(CHROMOSOME_LENGTH)); Population<BooleanChromosome> pop = new Population<BooleanChromosome>(sample, POPULATI ON_SIZE); Fitness<BooleanChromosome> fit = new Fitness<BooleanChromosome>(false) {
  • 13. @Override public void evaluate(Individual<BooleanChromosome> individual) { BooleanChromosome chrom = individual.getChromosome(); int count = 0; int length=chrom.length(); for(int i=0;i<length;i++) if(chrom.getValue(i)) count++; individual.setScore(count); } }; GeneticAlgorithm<BooleanChromosome> ga = new GeneticAlgorithm<BooleanChromosome> (fit, pop, GENERATION_LIMIT); AbstractStage<BooleanChromosome> selection = new TournamentSelector<BooleanChromosome>(3); AbstractStage<BooleanChromosome> crossover = new OnePointCrossover<BooleanChromosome>(0.8) ; AbstractStage<BooleanChromosome> mutation = new SimpleMutator<BooleanChromosome>(0.02); ga.addStage(selection); ga.addStage(crossover); ga.addStage(mutation); ga.setElitism(1); ga.evolve(); Population.Statistics stats = ga.getCurrentPopulation().getStatistics(); GeneticAlgorithm.Statistics algostats = ga.getStatistics(); System.out.println("Objective: " + (fit.getBiggerIsBetter()[0] ? "Max! (All true)" : "Min! (None true)")); System.out.println(); Group legals = stats.getGroup(Population.LEGALS); Individual solution = legals.get(0); System.out.println("Solution: "); System.out.println( solution ); System.out.format("found in %d ms.n", algostats.getExecutionTime() ); System.out.println(); Utils.printStatistics(stats); } }
  • 14. Estructuración de un algoritmo genético avanzado En nuestro segundo tutorial mostramos cómo crear un escenario paralelo y lo puso en la secuencia algoritmo, cómo distribuir y combinar estrategias paralelas, cómo establecer una condición de terminación definida por el usuario y cómo utilizar los oyentes de atrapar eventos algoritmo. El objetivo en este problema tutorial es para encontrar la matriz más cercano número entero (representable con un número especificado de cifras decimales) a una de destino con cada número dentro de la gama [0,49]. 1. Elegir un problema cromosómico adecuado y crear la población inicial Un IntegerChromosome es una representación natural de la matriz de enteros, cada valor gen se verá limitado en el rango [0,49] para respetar el problema de alcance restricción.
  • 15. 065 066 IntegerChromosome chrom = new IntegerChromosome(CHROMOSOME_LENGTH,0,MAX_INT); Individual<IntegerChromosome> ind = new Individual<IntegerChromosome>(chrom); Donde MAX_INT esta definido como: 059 private static int MAX_INT = 49; 2. Puesta en marcha del algoritmo genético. En este tutorial vamos a crear una subclase de GeneticAlogithm llamado PatternGA en wich personalizamos la condición de terminación del algoritmo ovverriding final () método que mejor se expone en el apartado 4. La aptitud de cada individuo es el error absoluto entre su cromosoma y el cromosoma de destino. Por lo tanto, la mejor individuo es el uno con el error absoluto más pequeño. La función de aptitud se codifica en clase PatternFitness definida como clase interna en PatternGA. En este caso le ofrecemos una definición de un problema de un solo objetivo que ofrece al programador la posibilidad de configurar el esquema de solución esperada y la precisión mínima a alcanzar para detener la búsqueda. El método de evaluar se mostró a continuación: 67 68 69 70 71 72 73 74 75 76 @Override public void evaluate(Individual<IntegerChromosome> individual) { IntegerChromosome chrom = individual.getChromosome(); int diff = 0; int length = chrom.length(); for (int i = 0; i < length; i++) { diff += Math.abs(chrom.getValue(i) - target[i]); } individual.setScore(diff); } 3 . Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en la ga. Supongamos que tenemos dos operadores de cruce diferentes (un punto con probabilidad 0,8 y dos puntos con una probabilidad de 0,5) para aplicarlos en dos subconjuntos de población separados. En Jenes podemos hacer esto a través del uso de la clase paralela. Por lo tanto organizamos los dos operadores de cruce como dos ramas paralelas de la tubería principal.
  • 16. El dispensador distribuye la población entre las ramas de la etapa en paralelo y se funde la salida de cada rama en la población salida de la etapa paralela. En Jenes hay dos tipos de dispenses : el dispencer general y la dispencer exclusiva . El dispencer en general permite que , durante la operación de distribución, para agregar un individuo en más sucursales ( se requieren copias de la misma persona para evitar la superposición de referencias entre subpopolations sucursales ) . El dispencer exclusiva no lo permite: cada individuo se puede agregar en una sola rama (no es necesario añadir una copia de la misma). Elegimos utilizar un dispencer exclusiva. La aplicación se mostró a continuación. 43 public class SimpleDispenser<T extends Chromosome> extends ExclusiveDispenser<T> { 44 45 private int count; 46 47 public SimpleDispenser(int span) { 48 super(span); 49 } 50 51 public void preDistribute(Population<T> population){ 52 this.count = 0; 53 } 54 55 @Override 56 public int distribute(Individual<T> ind) { 57 return count++ % span; 58 } 59 60 } Esta implementación básica de un dispencer exclusiva utiliza una política de distribución simple. Esto pone a las personas en posiciones pares en la primera rama y los individuos en las posiciones impares en la rama otros. El método preDistribute es útil para restablecer el estado dispencer. El método de distribuir devuelve el índice de la sección donde poner el individuo especificado. No hay que preocuparse por la fusión de la salida de los manojos, ya que se lleva a cabo por la clase ExclusiveDispencer. El código siguiente muestra cómo crear un escenario paralelo y la inserta en la tubería. 072 AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(2 ); 073 074 Parallel<IntegerChromosome> parallel = new Parallel<IntegerChromosome>(new SimpleDispense r<IntegerChromosome>(2)); 075 076 AbstractStage<IntegerChromosome> crossover1p = new OnePointCrossover<IntegerChromosome> (0.8);
  • 17. 077 parallel.add(crossover1p); 078 079 AbstractStage<IntegerChromosome> crossover2p = new TwoPointsCrossover<IntegerChromosome >(0.5); 080 parallel.add(crossover2p); 081 082 AbstractStage<IntegerChromosome> mutation = new SimpleMutator<IntegerChromosome>(0.02); 083 084 algorithm.addStage(selection); 085 algorithm.addStage(parallel); 086 algorithm.addStage(mutation); 3. Personalizar el algoritmo genético. Como se dijo antes la meta de nuestro algoritmo genético es minimizar el error absoluto de los individuos generados, con el fin de obtener una matriz de enteros, tan pronto como sea posible cerca del destino. En Jenes la evolución del algoritmo genético se ejecuta hasta que alcance el límite de generación especificada o hasta que se cumpla un criterio de terminación. Para especificar el criterio de terminación nuestro algoritmo genético tiene que reemplazar el método "extremo". Por defecto, este método tiene un cuerpo vacío por lo que no tiene ningún efecto sobre la evolución del algoritmo. En nuestro ejemplo, la evolución se detiene cuando el valor de aptitud más bajo es inferior a un valor (denominado precisión) especificado por el usuario. 52 53 54 55 56 @Override protected boolean end() { jenes.population.Population.Statistics stat = this.getCurrentPopulation(). getStatistics(); return stat.getGroup(Population.LEGALS).getMin()[0] <= this.fitness.precision; } La clase GeneticAlgorithm implementa el patrón Observer para notificar a sus oyentes la ocurrencia de un evento en particular. En Jenes hay dos tipos de detectores de eventos: el detector de eventos de generación (invocado cuando finaliza una generación) y el detector de eventos algoritmo (Se invoca cuando un evento occours algoritmo, por ejemplo, el inicio, el final y el inicio del algoritmo). En este tutorial vamos optar por utilizar un detector de eventos de generación con el fin de imprimir algunas informaciones al final de cada generación. El código de oyente se mostró a continuación. 113 114 public void onGeneration(GeneticAlgorithm ga, long time) { Statistics stat = ga.getCurrentPopulation().getStatistics();
  • 18. 115 116 117 118 119 Group legals = stat.getGroup(Population.LEGALS); System.out.println("Current generation: " + ga.getGeneration()); System.out.println("tBest score: " + legals.getMin()[0]); System.out.println("tAvg score : " + legals.getMean()[0]); } El código para añadir un detector de eventos generación en la clase Algoritmo Genético es: 087 algorithm.addGenerationEventListener(this); En el código siguiente se resumen los principales pasos para la configuración del algoritmo genético. 65 IntegerChromosome chrom = new IntegerChromosome(CHROMOSOME_LENGTH,0,MAX_INT); 066 Individual<IntegerChromosome> ind = new Individual<IntegerChromosome>(chrom); 067 Population<IntegerChromosome> pop = new Population<IntegerChromosome>(ind, POPULATION_SIZE); 068 069 algorithm = new PatternGA(pop, GENERATION_LIMIT); 070 algorithm.setElitism(5); 071 072 AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(2 ); 073 074 Parallel<IntegerChromosome> parallel = new Parallel<IntegerChromosome>(new SimpleDispense r<IntegerChromosome>(2)); 075 076 AbstractStage<IntegerChromosome> crossover1p = new OnePointCrossover<IntegerChromosome> (0.8); 077 parallel.add(crossover1p); 078 079 AbstractStage<IntegerChromosome> crossover2p = new TwoPointsCrossover<IntegerChromosome >(0.5); 080 parallel.add(crossover2p); 081 082 AbstractStage<IntegerChromosome> mutation = new SimpleMutator<IntegerChromosome>(0.02); 083 084 085 086 087 algorithm.addStage(selection); algorithm.addStage(parallel); algorithm.addStage(mutation); algorithm.addGenerationEventListener(this); Ejemplo1: package jenes.tutorials.problem2; 020 021 import jenes.GenerationEventListener; 022 import jenes.GeneticAlgorithm; 023 import jenes.utils.Random; 024 import jenes.chromosome.IntegerChromosome;
  • 19. 025 import jenes.population.Individual; 026 import jenes.population.Population; 027 import jenes.population.Population.Statistics; 028 import jenes.population.Population.Statistics.Group; 029 import jenes.stage.AbstractStage; 030 import jenes.stage.Parallel; 031 import jenes.stage.operator.common.OnePointCrossover; 032 import jenes.stage.operator.common.SimpleMutator; 033 import jenes.stage.operator.common.TournamentSelector; 034 import jenes.stage.operator.common.TwoPointsCrossover; 035 import jenes.tutorials.utils.Utils; 054 public class PatternProblem implements GenerationEventListener<IntegerChromosome> { 055 056 private static int POPULATION_SIZE = 100; 057 private static int CHROMOSOME_LENGTH = 10; 058 private static int GENERATION_LIMIT = 1000; 059 private static int MAX_INT = 49; 060 061 private PatternGA algorithm = null; 062 063 public PatternProblem() { 064 065 IntegerChromosome chrom = new IntegerChromosome(CHROMOSOME_LENGTH,0,MAX_INT); 066 Individual<IntegerChromosome> ind = new Individual<IntegerChromosome>(chrom); 067 Population<IntegerChromosome> pop = new Population<IntegerChromosome>(ind, POPULATIO N_SIZE); 068 069 algorithm = new PatternGA(pop, GENERATION_LIMIT); 070 algorithm.setElitism(5); 071 072 AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(2 ); 073 074 Parallel<IntegerChromosome> parallel = new Parallel<IntegerChromosome>(new SimpleDispenser <IntegerChromosome>(2)); 075 076 AbstractStage<IntegerChromosome> crossover1p = new OnePointCrossover<IntegerChromosome> (0.8); 077 parallel.add(crossover1p); 078 079 AbstractStage<IntegerChromosome> crossover2p = new TwoPointsCrossover<IntegerChromosome >(0.5); 080 parallel.add(crossover2p); 081 082 AbstractStage<IntegerChromosome> mutation = new SimpleMutator<IntegerChromosome>(0.02); 083 084 algorithm.addStage(selection); 085 algorithm.addStage(parallel);
  • 20. 086 algorithm.addStage(mutation); 087 algorithm.addGenerationEventListener(this); 088 } 089 090 public void run(int[] target, int precision) { 091 ((PatternGA.PatternFitness) algorithm.getFitness()).setTarget(target); 092 ((PatternGA.PatternFitness) algorithm.getFitness()).setPrecision(precision); 093 algorithm.evolve(); 094 095 Population.Statistics stats = algorithm.getCurrentPopulation().getStatistics(); 096 GeneticAlgorithm.Statistics algostats = algorithm.getStatistics(); 097 098 System.out.println(); 099 System.out.print("Target:["); 100 for( int i = 0; i < target.length; ++i ) { 101 System.out.print(target[i]+ ( i < target.length - 1 ? " " : "")); 102 } 103 System.out.println("]"); 104 System.out.println(); 105 106 System.out.println("Solution: "); 107 System.out.println(stats.getGroup(Population.LEGALS).get(0)); 108 System.out.format("found in %d ms and %d generations.n", algostats.getExecutionTime(), algostats .getGenerations() ); 109 System.out.println(); 110 } 111 112 113 public void onGeneration(GeneticAlgorithm ga, long time) { 114 Statistics stat = ga.getCurrentPopulation().getStatistics(); 115 Group legals = stat.getGroup(Population.LEGALS); 116 System.out.println("Current generation: " + ga.getGeneration()); 117 System.out.println("tBest score: " + legals.getMin()[0]); 118 System.out.println("tAvg score : " + legals.getMean()[0]); 119 } 120 121 private static void randomize(int[] sample) { 122 for(int i=0;i<sample.length;i++) 123 sample[i] = Random.getInstance().nextInt(0, MAX_INT+1); 124 } 125 126 public static void main(String[] args) { 127 128 Utils.printHeader(); 129 System.out.println(); 130 131 System.out.println("TUTORIAL 2:"); 132 System.out.println("This algorithm aims to autonomously find a vector of integers that best matches with a target vector.");
  • 21. 133 134 135 136 137 138 139 140 141 142 143 144 145 146 } 147 148 } System.out.println(); Random.getInstance().setStandardSeed(); PatternProblem problem = new PatternProblem(); int[] target = new int[CHROMOSOME_LENGTH]; randomize(target); problem.run(target, 2); randomize(target); problem.run(target, 0); Ejemplo2: 19 package jenes.tutorials.problem2; 20 21 import jenes.chromosome.Chromosome; 22 import jenes.population.Individual; 23 import jenes.population.Population; 24 import jenes.stage.ExclusiveDispenser; 43 public class SimpleDispenser<T extends Chromosome> extends ExclusiveDispenser<T> { 44 45 private int count; 46 47 public SimpleDispenser(int span) { 48 super(span); 49 } 50 51 public void preDistribute(Population<T> population){ 52 this.count = 0; 53 } 54 55 @Override 56 public int distribute(Individual<T> ind) { 57 return count++ % span; 58 } 59 60 } Ejemplo3: 19 package jenes.tutorials.problem2; 20 21 import jenes.Fitness;
  • 22. 22 import jenes.GeneticAlgorithm; 23 import jenes.chromosome.IntegerChromosome; 24 import jenes.population.Individual; 25 import jenes.population.Population; 43 public class PatternGA extends GeneticAlgorithm<IntegerChromosome> { 44 45 private PatternFitness fitness = new PatternFitness(); 46 47 public PatternGA(Population<IntegerChromosome> pop, int numGen) { 48 super(pop, numGen); 49 this.setFitness(fitness); 50 } 51 52 @Override 53 protected boolean end() { 54 jenes.population.Population.Statistics stat = this.getCurrentPopulation().getStatistics(); 55 return stat.getGroup(Population.LEGALS).getMin()[0] <= this.fitness.precision; 56 } 57 58 public class PatternFitness extends Fitness<IntegerChromosome> { 59 60 private int[] target = null; 61 private int precision = 0; 62 63 private PatternFitness() { 64 super(false); 65 } 66 67 @Override 68 public void evaluate(Individual<IntegerChromosome> individual) { 69 IntegerChromosome chrom = individual.getChromosome(); 70 int diff = 0; 71 int length = chrom.length(); 72 for (int i = 0; i < length; i++) { 73 diff += Math.abs(chrom.getValue(i) - target[i]); 74 } 75 individual.setScore(diff); 76 } 77 78 public void setTarget(int[] target) { 79 this.target = target; 80 } 81 82 public void setPrecision(int precision) { 83 this.precision = precision; 84 } 85 } 86 }
  • 23. Redefinición de las operaciones genéticas En algunas circunstancias el espacio de búsqueda es escasa dentro de un espacio más grande. Este es el caso del problema del agente de viajes, con el objetivo de encontrar una mínima de enrutamiento entre un conjunto de puntos, teniendo en cuenta las distancias entre ellos. Una forma natural para la representación de una solución es por una permutación de elementos, proporcionando el orden por el que la mínima de enrutamiento visita los puntos. Por lo tanto, un cromosoma es generalmente de Indices de enteros, cada referencia a un punto en particular (ciudad). Los operadores tradicionales de cruce y mutación no aseguran para producir soluciones válidas, es decir, permutaciones, ya que algunas ciudades podrían reproducirse o falta. Hay una necesidad para la redefinición de estas operaciones. En este tutorial se muestran dos formas de realizar esta tarea. 1. El uso o la creación de una clase cromosoma específico 2. Redefinir el cruce y mutador 1. El uso o la creación de una clase cromosoma específico. En Jenes, los operadores genéticos se basan en los primitivos puestos a disposición por la interfaz de cromosomas, tales como cruz, de forma aleatoria, de intercambio y desplazamiento. Por lo tanto, es posible también definir una subclase cromosoma específico con un conjunto de primitivas evitando transformaciones que conducen a soluciones no factibles. En Jenes la PermutationChromosome es capaz de procesar permutaciones de acuerdo a la siguiente Stategy:
  • 24. Crossover: alelos en un cromosoma se ordenarán de acuerdo con el orden en que son considerados por el otro cromosoma Mutación: un alelo se intercambia con otro elegido al azar El código de código utilizado para configurar el algoritmo y la función de aptitud se mostró a continuación: 127 Individual<PermutationChromosome> sample = new Individual<PermutationChromosome>(new P ermutationChromosome(cities)); 128 Population<PermutationChromosome> pop = new Population<PermutationChromosome>(sample, POPULATION_SIZE); 129 130 Fitness<PermutationChromosome> fitness = new Fitness<PermutationChromosome>(false) { 131 132 @Override 133 public void evaluate(Individual<PermutationChromosome> individual) { 134 PermutationChromosome chrom = individual.getChromosome(); 135 double count = 0; 136 int size = chrom.length(); 137 for(int i=0;i<size-1;i++){ 138 int val1 = chrom.getElementAt(i); 139 int val2 = chrom.getElementAt(i+1); 140 count += TravelSalesmanProblem.this.map[val1][val2]; 141 } 142 count += TravelSalesmanProblem.this.map[size-1][0]; 143 individual.setScore(count); 144 } 145 146 }; 147 148 SimpleGA<PermutationChromosome> sga = new SimpleGA<PermutationChromosome>(fitness, po p, GENERATION_LIMIT); 2. Redefinir el cruce y mutador Crossover Redefinición de un crossover es bastante simple. Lo primero que debe hacer es extender la clase del cromosoma. 057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{ El Crossover Ciudad Centrado, elige una ciudad y volver a ordenar las siguientes ciudades en un cromosoma de acuerdo a la orden dada por el otro. Esta operación se realiza mediante la aplicación del método de cruz.
  • 25. 078 protected void cross(Individual<IntegerChromosome> offsprings[]) { 079 080 IntegerChromosome chrom_child1 = offsprings[0].getChromosome(); 081 IntegerChromosome chrom_child2 = offsprings[1].getChromosome(); 082 083 if( chrom_parent1 == null ) { 084 chrom_parent1 = chrom_child1.clone(); 085 chrom_parent2 = chrom_child2.clone(); 086 } else { 087 chrom_parent1.setAs(chrom_child1); 088 chrom_parent2.setAs(chrom_child2); 089 } 090 091 final int size = chrom_child1.length(); 092 if( chrom_child2.length() != size ) 093 throw new AlgorithmException("Error: the two chromosomes are required to have the same lengt h."); 094 095 096 //we choose a random city 097 int city = Random.getInstance().nextInt(0, size); 098 099 //i1, i2 are the positions of the city respectively in child1 and child2 100 int i1 = findPositionOf(city, chrom_child1); 101 int i2 = findPositionOf(city, chrom_child2); 102 103 int j1 = 0; 104 int j2 = 0; 105 for( int i = 0; i < size; ++i ) { 106 // get the city c1 in position i for parent1 107 int c1 = chrom_parent1.getValue(i); 108 // find the position of c1 in parent 2 109 int p2 = findPositionOf(c1, chrom_parent2); 110 // if the position is over the cross-point, it copies c1 in child2 111 if( p2 > i2 ) { 112 chrom_child2.setValue(i2 + (++j2), c1); 113 } 114 115 // similarly we process the other pair 116 int c2 = chrom_parent2.getValue(i); 117 int p1 = findPositionOf(c2, chrom_parent1); 118 if( p1 > i1 ) { 119 chrom_child1.setValue(i1 + (++j1), c2); 120 } 121 } 122 }
  • 26. Mutador Redefinir el mutador es sencillo también. En primer lugar, tenemos que crear una subclase de la operadora Mutador. 047 public class TSPScrambleMutator extends Mutator<IntegerChromosome> { El mutador Scramble se basa en la siguiente estrategia: dos Indices de i1 e i2 se eligen al azar y el orden de los elementos dentro de la gama [i1, i2] cambia aleatoriamente. Este algoritmo es ejecutado por el método randomize: 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 public void randomize(IntegerChromosome chrom, int min, int max) { //we create a temporany array int len = max-min+1; int[] base = new int[len]; //we fill it with the elements within [min,max] for(int i=0;i<len;i++) base[i]= chrom.getValue(min+i); //the loop ends when the temporany array is empty for( int i = 0; len > 0; --len, ++i) { //we choose a random position pos in the array and copy the element at pos in the chromosome int pos = Random.getInstance().nextInt(0,len); chrom.setValue(min+i,base[pos]); //we removes the chosen element from the temporany array for(int j=pos;j<(len-1);j++){ base[j]=base[j+1]; } } } Ejemplo del tema: 019 package jenes.tutorials.problem3; 020 021 import jenes.Fitness; 022 import jenes.GeneticAlgorithm; 023 import jenes.utils.Random; 024 import jenes.algorithms.SimpleGA; 025 import jenes.chromosome.IntegerChromosome; 026 import jenes.chromosome.PermutationChromosome; 027 import jenes.population.Individual; 028 import jenes.population.Population;
  • 27. 029 import jenes.population.Population.Statistics.Group; 030 import jenes.stage.AbstractStage; 031 import jenes.stage.operator.common.TournamentSelector; 032 import jenes.tutorials.utils.Utils; 046 public class TravelSalesmanProblem { 047 048 public static final int POPULATION_SIZE = 1000; 049 private static int GENERATION_LIMIT = 2000; 050 public static final int MAX_DISTANCE = 10; 051 052 private TSPGA algorithm; 053 private int cities; 054 private double[][] map; 055 056 public static void main(String[] args) { 057 058 Utils.printHeader(); 059 System.out.println(); 060 061 System.out.println("TUTORIAL 3:"); 062 System.out.println("The Travel Salesman Problem, a classics."); 063 System.out.println(); 064 065 Random.getInstance().setStandardSeed(); 066 067 System.out.println("Case 1: 10 cities in circle"); 068 double[][] m1 = simpleMap(10); 069 TravelSalesmanProblem tsp1 = new TravelSalesmanProblem(m1); 070 tsp1.solve(); 071 072 System.out.println("Case 2: 30 cities in circle"); 073 double[][] m2 = simpleMap(30); 074 TravelSalesmanProblem tsp2 = new TravelSalesmanProblem(m2); 075 tsp2.solve(); 076 077 System.out.println("Case 3: 30 cities at random"); 078 double[][] m3 = randomMap(30); 079 TravelSalesmanProblem tsp3 = new TravelSalesmanProblem(m3); 080 tsp3.solve(); 081 082 System.out.println("Case 4: An application of PermutationChromosome"); 083 tsp2.solvePC(); 084 } 085 086 public TravelSalesmanProblem(double[][] matrix) { 087 088 cities = matrix[0].length; 089 map = matrix;
  • 28. 090 091 IntegerChromosome chrom = new IntegerChromosome(cities,0,cities-1); 092 for( int i = 0; i < cities; ++i ) { 093 chrom.setValue(i, i < cities - 1 ? i+1 : 0); 094 } 095 Individual<IntegerChromosome> sample = new Individual<IntegerChromosome>(chrom); 096 Population<IntegerChromosome> pop = new Population<IntegerChromosome>(sample, POPULAT ION_SIZE); 097 098 algorithm = new TSPGA(matrix, pop, GENERATION_LIMIT); 099 algorithm.setRandomization(true); 100 101 AbstractStage<IntegerChromosome> selection = new TournamentSelector<IntegerChromosome>(1 ); 102 AbstractStage<IntegerChromosome> crossover = new TSPCityCenteredCrossover(0.8); 103 AbstractStage<IntegerChromosome> mutation = new TSPScrambleMutator(0.02); 104 105 algorithm.addStage(selection); 106 algorithm.addStage(crossover); 107 algorithm.addStage(mutation); 108 109 algorithm.setElitism(10); 110 } 111 112 public void solve() { 113 algorithm.evolve(); 114 115 Population.Statistics stats = algorithm.getCurrentPopulation().getStatistics(); 116 GeneticAlgorithm.Statistics algostats = algorithm.getStatistics(); 117 118 Group legals = stats.getGroup(Population.LEGALS); 119 120 System.out.println(legals.get(0)); 121 System.out.format("found in %d ms and %d generations.n", algostats.getExecutionTime(), algostats .getGenerations() ); 122 System.out.println(); 123 } 124 125 public void solvePC() { 126 127 Individual<PermutationChromosome> sample = new Individual<PermutationChromosome>(new P ermutationChromosome(cities)); 128 Population<PermutationChromosome> pop = new Population<PermutationChromosome>(sample, POPULATION_SIZE); 129 130 Fitness<PermutationChromosome> fitness = new Fitness<PermutationChromosome>(false) { 131 132 @Override 133 public void evaluate(Individual<PermutationChromosome> individual) {
  • 29. 134 PermutationChromosome chrom = individual.getChromosome(); 135 double count = 0; 136 int size = chrom.length(); 137 for(int i=0;i<size-1;i++){ 138 int val1 = chrom.getElementAt(i); 139 int val2 = chrom.getElementAt(i+1); 140 count += TravelSalesmanProblem.this.map[val1][val2]; 141 } 142 count += TravelSalesmanProblem.this.map[size-1][0]; 143 individual.setScore(count); 144 } 145 146 }; 147 148 SimpleGA<PermutationChromosome> sga = new SimpleGA<PermutationChromosome>(fitness, po p, GENERATION_LIMIT); 149 150 sga.setElitism(10); 151 sga.setMutationProbability(0.02); 152 sga.evolve(); 153 154 Population.Statistics stats = sga.getCurrentPopulation().getStatistics(); 155 GeneticAlgorithm.Statistics algostats = sga.getStatistics(); 156 157 Group legals = stats.getGroup(Population.LEGALS); 158 159 System.out.println(legals.get(0)); 160 System.out.format("found in %d ms and %d generations.n", algostats.getExecutionTime(), algostats .getGenerations() ); 161 System.out.println(); 162 } 163 164 public static double[][] simpleMap( int cities ) { 165 double[][] matrix = new double[cities][cities]; 166 167 matrix[0][0] = 0; 168 for( int i = 1; i <= cities/2; ++i) { 169 matrix[0][i] = i; 170 matrix[0][cities-i] = i; 171 } 172 173 for( int i = 1; i < cities; ++i ) { 174 for( int j = 0; j < cities; ++j ) { 175 matrix[i][(i+j)%cities] = matrix[0][j]; 176 } 177 } 178 return matrix; 179 } 180
  • 30. 181 public static double[][] randomMap( int cities ) { 182 double[][] matrix = new double[cities][cities]; 183 for( int i = 0; i < cities; ++i ) { 184 for( int j = 0; j < cities; ++j ) { 185 matrix[i][j] = i!=j ? Random.getInstance().nextDouble(MAX_DISTANCE) : 0; 186 } 187 } 188 return matrix; 189 } 190 191 } Ejemplo del tema: 019 package jenes.tutorials.problem3; 020 021 import jenes.utils.Random; 022 import jenes.chromosome.IntegerChromosome; 023 import jenes.population.Individual; 024 import jenes.stage.operator.Mutator; 047 public class TSPScrambleMutator extends Mutator<IntegerChromosome> { 048 049 public TSPScrambleMutator(double pMut) { 050 super(pMut); 051 } 052 053 @Override 054 protected void mutate(Individual<IntegerChromosome> t) { 055 int size = t.getChromosomeLength(); 056 int index1,index2; 057 do{ 058 index1 = Random.getInstance().nextInt(0,size); 059 index2 = Random.getInstance().nextInt(0,size); 060 }while(index2==index1); 061 062 int min,max; 063 if(index1<index2){ 064 min=index1; 065 max=index2; 066 }else{ 067 min=index2; 068 max=index1; 069 } 070 071 randomize(t.getChromosome(),min, max); 072 } 073 074 /** 075 * Randomizes the elements chromosome within the range [min,max]
  • 31. 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 } * <p> * @param chrom the individual to mutate * @param min the lower bound * @param max the upper bound */ public void randomize(IntegerChromosome chrom, int min, int max) { //we create a temporany array int len = max-min+1; int[] base = new int[len]; //we fill it with the elements within [min,max] for(int i=0;i<len;i++) base[i]= chrom.getValue(min+i); //the loop ends when the temporany array is empty for( int i = 0; len > 0; --len, ++i) { //we choose a random position pos in the array and copy the element at pos in the chromosome int pos = Random.getInstance().nextInt(0,len); chrom.setValue(min+i,base[pos]); //we removes the chosen element from the temporany array for(int j=pos;j<(len-1);j++){ base[j]=base[j+1]; } } } Ejemplo del tema: package jenes.tutorials.problem3; import jenes.Fitness; import jenes.GeneticAlgorithm; import jenes.utils.Random; import jenes.chromosome.IntegerChromosome; import jenes.population.Individual; import jenes.population.Population; public class TSPGA extends GeneticAlgorithm<IntegerChromosome> { private double[][] matrix; private TSPFitness fitness; public TSPGA(double[][] matrix, Population<IntegerChromosome> pop, int genlimit) { super(null, pop, genlimit); this.matrix = matrix; fitness = new TSPFitness(); this.setFitness(fitness); }
  • 32. @Override protected void randomizeIndividual(Individual<IntegerChromosome> individual) { Random rand = Random.getInstance(); int len = individual.getChromosomeLength(); for( int i = 0; i < 100; ++i ) { int j = rand.nextInt(len); int k = rand.nextInt(len); individual.getChromosome().swap(j, k); } } public class TSPFitness extends Fitness<IntegerChromosome> { public TSPFitness() { super(false); } @Override public void evaluate(Individual<IntegerChromosome> individual) { IntegerChromosome chrom = individual.getChromosome(); double count = 0; int size = chrom.length(); for (int i = 0; i < size - 1; i++) { int val1 = chrom.getValue(i); int val2 = chrom.getValue(i + 1); count += matrix[val1][val2]; } count += matrix[size - 1][0]; individual.setScore(count); } } } Ejemplo del tema: 019 package jenes.tutorials.problem3; 020 021 import jenes.AlgorithmException; 022 import jenes.utils.Random; 023 import jenes.chromosome.IntegerChromosome; 024 import jenes.population.Individual; 025 import jenes.stage.operator.Crossover; 057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{ 058 059 public TSPCityCenteredCrossover(double pCross) {
  • 33. 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 h."); 094 095 096 097 098 099 100 101 102 103 104 105 106 107 super(pCross); } /** * Returns the number of chromosomes (i.e. 2) this operator entails. */ @Override public int spread() { return 2; } private IntegerChromosome chrom_parent1 = null; private IntegerChromosome chrom_parent2 = null; /** * This method implements the crossover operation. * * @param offsprings the chromosomes to be crossed. */ protected void cross(Individual<IntegerChromosome> offsprings[]) { IntegerChromosome chrom_child1 = offsprings[0].getChromosome(); IntegerChromosome chrom_child2 = offsprings[1].getChromosome(); if( chrom_parent1 == null ) { chrom_parent1 = chrom_child1.clone(); chrom_parent2 = chrom_child2.clone(); } else { chrom_parent1.setAs(chrom_child1); chrom_parent2.setAs(chrom_child2); } final int size = chrom_child1.length(); if( chrom_child2.length() != size ) throw new AlgorithmException("Error: the two chromosomes are required to have the same lengt //we choose a random city int city = Random.getInstance().nextInt(0, size); //i1, i2 are the positions of the city respectively in child1 and child2 int i1 = findPositionOf(city, chrom_child1); int i2 = findPositionOf(city, chrom_child2); int j1 = 0; int j2 = 0; for( int i = 0; i < size; ++i ) { // get the city c1 in position i for parent1 int c1 = chrom_parent1.getValue(i);
  • 34. 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 } // find the position of c1 in parent 2 int p2 = findPositionOf(c1, chrom_parent2); // if the position is over the cross-point, it copies c1 in child2 if( p2 > i2 ) { chrom_child2.setValue(i2 + (++j2), c1); } // similarly we process the other pair int c2 = chrom_parent2.getValue(i); int p1 = findPositionOf(c2, chrom_parent1); if( p1 > i1 ) { chrom_child1.setValue(i1 + (++j1), c2); } } } /** * Finds the position of one specific city in the chromosome. * <p> * @param city the city to find * @param chrom the chromosome to search * @return the city position */ private int findPositionOf(int city, IntegerChromosome chrom){ final int size = chrom.length(); for( int i = 0; i < size; ++i ) { if( chrom.getValue(i) == city ) return i; } return -1; } Redefinición de las operaciones genéticas En algunas circunstancias el espacio de búsqueda es escasa dentro de un espacio más grande. Este es el caso del problema del agente de viajes, con el objetivo de encontrar una mínima de enrutamiento entre un conjunto de puntos, teniendo en cuenta las distancias entre ellos.
  • 35. Una forma natural para la representación de una solución es por una permutación de elementos, proporcionando el orden por el que la mínima de enrutamiento visita los puntos. Por lo tanto, un cromosoma es generalmente de Indices de enteros, cada referencia a un punto en particular (ciudad). Los operadores tradicionales de cruce y mutación no aseguran para producir soluciones válidas, es decir, permutaciones, ya que algunas ciudades podrían reproducirse o falta. Hay una necesidad para la redefinición de estas operaciones. En este tutorial se muestran dos formas de realizar esta tarea. 1. El uso o la creación de una clase cromosoma específico 2. Redefinir el cruce y matador 1. El uso o la creación de una clase cromosoma específico En Jenes, los operadores genéticos se basan en los primitivos puestos a disposición por la interfaz de cromosomas, tales como cruz, de forma aleatoria, de intercambio y desplazamiento. Por lo tanto, es posible también definir una subclase cromosoma específico con un conjunto de primitivas evitando transformaciones que conducen a soluciones no factibles. En Jenes la PermutationChromosome es capaz de procesar permutaciones de acuerdo a la siguiente Stategy: Crossover: alelos en un cromosoma se ordenarán de acuerdo con el orden en que son considerados por el otro cromosoma Mutación: un alelo se intercambia con otro elegido al azar El código de código utilizado para configurar el algoritmo y la función de aptitud se mostró a continuación: 127 Individual<PermutationChromosome> sample = new Individual<PermutationChromosome>(new P ermutationChromosome(cities)); 128 Population<PermutationChromosome> pop = new Population<PermutationChromosome>(sample, POPULATION_SIZE); 129 130 Fitness<PermutationChromosome> fitness = new Fitness<PermutationChromosome>(false) { 131 132 @Override 133 public void evaluate(Individual<PermutationChromosome> individual) { 134 PermutationChromosome chrom = individual.getChromosome(); 135 double count = 0; 136 int size = chrom.length(); 137 for(int i=0;i<size-1;i++){ 138 int val1 = chrom.getElementAt(i);
  • 36. 139 int val2 = chrom.getElementAt(i+1); 140 count += TravelSalesmanProblem.this.map[val1][val2]; 141 } 142 count += TravelSalesmanProblem.this.map[size-1][0]; 143 individual.setScore(count); 144 } 145 146 }; 147 148 SimpleGA<PermutationChromosome> sga = new SimpleGA<PermutationChromosome>(fitness, po p, GENERATION_LIMIT); 2. Redefinir el cruce y mutador crossover Redefinición de un crossover es bastante simple. Lo primero que debe hacer es extender la clase del cromosoma. 057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{ El Crossover Ciudad Centrado, elige una ciudad y volver a ordenar las siguientes ciudades en un cromosoma de acuerdo a la orden dada por el otro. Esta operación se realiza mediante la aplicación del método de cruz. 078 protected void cross(Individual<IntegerChromosome> offsprings[]) { 079 080 IntegerChromosome chrom_child1 = offsprings[0].getChromosome(); 081 IntegerChromosome chrom_child2 = offsprings[1].getChromosome(); 082 083 if( chrom_parent1 == null ) { 084 chrom_parent1 = chrom_child1.clone(); 085 chrom_parent2 = chrom_child2.clone(); 086 } else { 087 chrom_parent1.setAs(chrom_child1); 088 chrom_parent2.setAs(chrom_child2); 089 } 090 091 final int size = chrom_child1.length(); 092 if( chrom_child2.length() != size ) 093 throw new AlgorithmException("Error: the two chromosomes are required to have the same lengt h."); 094 095 096 //we choose a random city
  • 37. 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 int city = Random.getInstance().nextInt(0, size); //i1, i2 are the positions of the city respectively in child1 and child2 int i1 = findPositionOf(city, chrom_child1); int i2 = findPositionOf(city, chrom_child2); int j1 = 0; int j2 = 0; for( int i = 0; i < size; ++i ) { // get the city c1 in position i for parent1 int c1 = chrom_parent1.getValue(i); // find the position of c1 in parent 2 int p2 = findPositionOf(c1, chrom_parent2); // if the position is over the cross-point, it copies c1 in child2 if( p2 > i2 ) { chrom_child2.setValue(i2 + (++j2), c1); } // similarly we process the other pair int c2 = chrom_parent2.getValue(i); int p1 = findPositionOf(c2, chrom_parent1); if( p1 > i1 ) { chrom_child1.setValue(i1 + (++j1), c2); } } } mutador Redefinir el mutador es sencillo también. En primer lugar, tenemos que crear una subclase de la operadora Mutador. 047 public class TSPScrambleMutator extends Mutator<IntegerChromosome> { El mutador Scramble se basa en la siguiente estrategia: dos Indices de i1 e i2 se eligen al azar y el orden de los elementos dentro de la gama [i1, i2] cambia aleatoriamente. Este algoritmo es ejecutado por el método randomize. 081 082 083 084 085 086 087 088 public void randomize(IntegerChromosome chrom, int min, int max) { //we create a temporany array int len = max-min+1; int[] base = new int[len]; //we fill it with the elements within [min,max] for(int i=0;i<len;i++)
  • 38. 089 090 091 092 093 094 095 096 097 098 099 100 101 base[i]= chrom.getValue(min+i); //the loop ends when the temporany array is empty for( int i = 0; len > 0; --len, ++i) { //we choose a random position pos in the array and copy the element at pos in the chromosome int pos = Random.getInstance().nextInt(0,len); chrom.setValue(min+i,base[pos]); //we removes the chosen element from the temporany array for(int j=pos;j<(len-1);j++){ base[j]=base[j+1]; } } } Cómo utilizar SimpleGa En este tutorial se muestra cómo utilizar SimpleGA, una subclase estándar GeneticAlgorithm. Representa la configuración clásica de un algoritmo genético, utilizando sólo los principales operadores (selectores, cruce y mutantes) en un tubo muy simple. Es útil cuando no se necesitan operadores de complejos y se requiere una ga rápida puesta en marcha. El objetivo de este tutorial es para minimizar la entropía de Shannon de un conjunto de valores en el rango [0,1]. 1. Elegir un problema cromosómico adecuada y crear la población inicial; Un DoubleChromosome es adecuado para este problema con cada alelo dentro del rango [0,1]. 55 Individual<DoubleChromosome> sample = new Individual<DoubleChromosome>(new DoubleChro mosome(CHROMOSOME_LENGTH,0,1)); 56 Population<DoubleChromosome> pop = new Population<DoubleChromosome>(sample, POPULATI ON_SIZE); 2. Puesta en marcha del algoritmo genético Para utilizar SimpleGA tenemos que definir sólo la codificación función de aptitud. En este caso, la aptitud de cada individuo es igual al valor de entropía de acuerdo a la definición clásica de entropía: la entropía es la medida de la cantidad de información que falta antes de la recepción y se refiere a veces como la entropía de Shannon.
  • 39. 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 @Override public void evaluate(Individual<DoubleChromosome> individual) { DoubleChromosome chrom = individual.getChromosome(); int length = chrom.length(); double sum = 0.0; for (int i = 0; i < length; ++i) { sum += chrom.getValue(i); } double entropy = 0.0; for (int i = 0; i < length; ++i) { double pxi = chrom.getValue(i) / sum; chrom.setValue(i, pxi); entropy -= (pxi * Math.log(pxi) / Math.log(2)); } individual.setScore(entropy); } 3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en la ga. Con SimpleGA nuestro algoritmo genético ya está configurado con respecto a los operadores a utilizar. Por defecto se utiliza la selección del torneo (intentos = 2), cruce de un punto (probabilidad = 0,8) y simple mutador (probabilidad = 0,2). Además SimpleGA usa por defecto una estrategia de sustitución de azar para el elitismo. De todos modos, es possibile para modificar esta configuración predeterminada que proporciona diferentes parámetros para los operadores y / o una estrategia de elitismo diferente. En nuestro caso utilizamos la configuración SimpleGA defecto. 4. Personalizar el algoritmo genético El código de configuración entera se enumeran a continuación: 55 Individual<DoubleChromosome> sample = new Individual<DoubleChromosome>(new DoubleChro mosome(CHROMOSOME_LENGTH,0,1)); 56 Population<DoubleChromosome> pop = new Population<DoubleChromosome>(sample, POPULATI ON_SIZE); 57 58 ga = new SimpleGA<DoubleChromosome>(null, pop, GENERATION_LIMIT); 59 60 System.out.println("Solving Max!:"); 61 solve( EntropyFitness.MAX ); 62
  • 40. 63 64 System.out.println("Solving Min!:"); solve( EntropyFitness.MIN ); Como puede ver, el algoritmo genético se ha inicializado sin la definición de la función de idoneidad para su uso. Este es possibile en que los casos en wich el gimnasio podría ser determinada sólo en un momento posterior con respecto a la creación del algoritmo genético. De todos modos la definición de una función de aptitud se requiere antes de que el método de evolucionar de GeneticAlgorithm se invoca, y esto es posible sólo hacer la siguiente llamada al método: 68 69 ga.setFitness(fitness); ga.evolve(); Ejemplos del tema: 19 package jenes.tutorials.problem4; 20 21 import jenes.GeneticAlgorithm; 22 import jenes.algorithms.SimpleGA; 23 import jenes.chromosome.DoubleChromosome; 24 import jenes.population.Individual; 25 import jenes.population.Population; 26 import jenes.population.Population.Statistics; 27 import jenes.population.Population.Statistics.Group; 28 import jenes.tutorials.utils.Utils; 29 30 /** 31 * Tutorial showing how to set-up a minimization problem. 32 * The problem is to find a vector whose entroy, after normalization, is minimal. 33 * 34 * @author Luigi Troiano 35 * 36 * @version 2.0 37 * @since 1.0 38 */ 39 public class EntropyProblem { 40 41 private static int POPULATION_SIZE = 100; 42 private static int CHROMOSOME_LENGTH = 5; 43 private static int GENERATION_LIMIT = 100; 44 45 private static GeneticAlgorithm<DoubleChromosome> ga; 46 47 public static void main(String[] args) { 48 Utils.printHeader(); 49 System.out.println(); 50 51 System.out.println("TUTORIAL 4:");
  • 41. 52 System.out.println("Find the probability distribution that maximizes (or minimize) the Shannon's entr opy."); 53 System.out.println(); 54 55 Individual<DoubleChromosome> sample = new Individual<DoubleChromosome>(new DoubleChro mosome(CHROMOSOME_LENGTH,0,1)); 56 Population<DoubleChromosome> pop = new Population<DoubleChromosome>(sample, POPULATI ON_SIZE); 57 58 ga = new SimpleGA<DoubleChromosome>(null, pop, GENERATION_LIMIT); 59 60 System.out.println("Solving Max!:"); 61 solve( EntropyFitness.MAX ); 62 63 System.out.println("Solving Min!:"); 64 solve( EntropyFitness.MIN ); 65 } 66 67 private static void solve(EntropyFitness fitness) { 68 ga.setFitness(fitness); 69 ga.evolve(); 70 71 Statistics stats = ga.getCurrentPopulation().getStatistics(); 72 GeneticAlgorithm.Statistics algostats = ga.getStatistics(); 73 74 Group legals = stats.getGroup(Population.LEGALS); 75 76 System.out.println(legals.get(0)); 77 System.out.format("found in %d ms.n", algostats.getExecutionTime() ); 78 System.out.println(); 79 80 Utils.printStatistics(stats); 81 } 82 } Ejemplos del tema: 19 package jenes.tutorials.problem4; 20 21 import jenes.Fitness; 22 import jenes.chromosome.DoubleChromosome; 23 import jenes.population.Individual; 24 25 /** 26 * 27 * @author Luigi Troiano 28 */ 29 public class EntropyFitness extends Fitness<DoubleChromosome> { 30
  • 42. 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 } public static EntropyFitness MAX = new EntropyFitness(true); public static EntropyFitness MIN = new EntropyFitness(false); private EntropyFitness(boolean maximize) { super(maximize); } @Override public void evaluate(Individual<DoubleChromosome> individual) { DoubleChromosome chrom = individual.getChromosome(); int length = chrom.length(); double sum = 0.0; for (int i = 0; i < length; ++i) { sum += chrom.getValue(i); } double entropy = 0.0; for (int i = 0; i < length; ++i) { double pxi = chrom.getValue(i) / sum; chrom.setValue(i, pxi); entropy -= (pxi * Math.log(pxi) / Math.log(2)); } individual.setScore(entropy); }
  • 43. ObjectChromosome En este tutorial se muestra cómo utilizar el ObjectChromosome en Jenes. El ObjectChromosome representa un cromosoma complejo con genes que contienen un valor de alelo objeto. Dado un espacio de búsqueda hecho de variables objeto de cromosomas, nuestro objetivo es encontrar la secuencia más cercana de los valores (representable con objetos específicos) a una de destino. En nuestro problema de ejemplo cada cromosoma tiene cinco genes pertenecientes a diferentes valores de los alelos objeto. El primer gen es un número entero en el intervalo [0,9], el segundo es también un número entero, pero en el intervalo [10,30], la tercera es un número real en el intervalo [0,1], la cuarta es una boolean y el último es un gen que es el alfabeto {NEGRO, ROJO, BLANCO} 1 . Elegir un problema cromosómico adecuada y crear la población inicial ; Un ObjectChromosome es adecuado para este problema . Contará con cinco genes cada uno de ellos con un conjunto de alelos diferentes : dos conjuntos de alelos entero para los dos primeros genes , la primera con el rango [ 0,9 ] y el segundo con rango [ 10,30 ], un doble alelo fijado para el tercer gen con rango [ 0,1] , un alelo boolean fijado para el gen de la vuelta y un grupo de alelos de la enumeración basada contiene { NEGRO , ROJO, BLANCO } para el último gen . Para crear instancias de un grupo de alelos que podemos implementar la interfaz AlleleSet o utilizar la clase GenericAlleleSet . El grupo de alelos de número entero se obtiene subclases la clase GenericAlleleSet e implementación de dos métodos de fábrica , que se utiliza para crear instancias de los valores enteros en sus rangos especificados ( los valores son elegidos al azar o con una distribución de probabilidad uniforme en los intervalos
  • 44. especificados ) . El conjunto alelo real se obtiene de la misma manera . El grupo de alelos boolean se obtiene creando un objeto GenericAlleleSet containg los valores booleanos true y false. Por último , se define una enumeración, llamada Color , que contiene los valores NEGRO , rojo y blanco, entonces se crea un objeto GenericAlleleSet con los valores de la enumeración de color. El código se mostró a continuación. 36 public enum Color { 37 38 RED, BLACK, WHITE; 39 40 } Ahora podemos construir nuestra representación cromosoma. 053 054 055 056 057 058 private static ObjectChromosome template = new ObjectChromosome( IntegerAlleleSet.createUniform(10, 0, 9), IntegerAlleleSet.createUniform(21, 10, 30), DoubleAlleleSet.createRandom(10, 0, 1), new GenericAlleleSet<Boolean>(true, false), new GenericAlleleSet<Color>(Color.values()) ); 2. Puesta en marcha del algoritmo genético A continuación se muestra el código para evaluar a un individuo en nuestro problema. 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 @Override public void evaluate(Individual<ObjectChromosome> individual) { ObjectChromosome template = individual.getChromosome(); int i1 = (Integer)template.getValue(0); int i2 = (Integer)template.getValue(1); double d = (Double)template.getValue(2); boolean b = (Boolean)template.getValue(3); Color c = (Color)template.getValue(4); double acc = b ? (3*i1 + 4*i2 + d) : i1; switch( c ) { case BLACK : acc += 10; break; case RED : acc += 10; break; case WHITE : acc += 10; break; } individual.setScore(acc); }
  • 45. En nuestro ejemplo los mejores individuos son los que tienen los valores más altos para el entero y genes dobles, con un verdadero valor para el gen boolean y con cualquier valor para el gen "Color". Por lo tanto, la mejor persona que esperamos ejecutar este ejemplo podría ser: [9, 30, 0,99, es cierto, NEGRO]. 3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en la ga En este tutorial se utiliza la configuración simple algoritmo clásico. 098 099 100 ga.addStage(new TournamentSelector<ObjectChromosome>(3)); ga.addStage(new OnePointCrossover<ObjectChromosome>(0.8)); ga.addStage(new SimpleMutator<ObjectChromosome>(0.02)); 4.Personalizar el algoritmo genético El objetivo global del algoritmo genético es maximizar los valores de fitness. Todo el código es visible en los archivos adjuntos a este tutorial. Ejemplo de tema: 019 package jenes.tutorials.problem5; 020 021 import jenes.Fitness; 022 import jenes.GeneticAlgorithm; 023 import jenes.chromosome.GenericAlleleSet; 024 import jenes.chromosome.ObjectChromosome; 025 import jenes.population.Individual; 026 import jenes.population.Population; 027 import jenes.population.Population.Statistics; 028 import jenes.population.Population.Statistics.Group; 029 import jenes.stage.operator.common.OnePointCrossover; 030 import jenes.stage.operator.common.SimpleMutator; 031 import jenes.stage.operator.common.TournamentSelector; 032 import jenes.tutorials.utils.Utils; 033 034 /** 035 * Tutorial illustrating the use of object-oriented chromosomes, whose 036 * allele set can be defined by the user for each gene. 037 * 038 * In this example the chromosomes are combinations of colors. We aim at finding 039 * the vector of colors closest to a given sequence. 040 * 041 * This class defines the problem. 042 * 043 * @author Luigi Troiano
  • 46. 044 * 045 * @version 2.0 046 * @since 1.0 047 */ 048 public class OCProblem { 049 050 private static int POPULATION_SIZE = 10; 051 private static int GENERATION_LIMIT = 100; 052 053 private static ObjectChromosome template = 054 new ObjectChromosome( IntegerAlleleSet.createUniform(10, 0, 9), 055 IntegerAlleleSet.createUniform(21, 10, 30), 056 DoubleAlleleSet.createRandom(10, 0, 1), 057 new GenericAlleleSet<Boolean>(true, false), 058 new GenericAlleleSet<Color>(Color.values()) ); 059 060 private static Fitness<ObjectChromosome> fitness = new Fitness<ObjectChromosome>(true) { 061 062 @Override 063 public void evaluate(Individual<ObjectChromosome> individual) { 064 ObjectChromosome template = individual.getChromosome(); 065 066 int i1 = (Integer)template.getValue(0); 067 int i2 = (Integer)template.getValue(1); 068 double d = (Double)template.getValue(2); 069 boolean b = (Boolean)template.getValue(3); 070 Color c = (Color)template.getValue(4); 071 072 double acc = b ? (3*i1 + 4*i2 + d) : i1; 073 074 switch( c ) { 075 case BLACK : acc += 10; break; 076 case RED : acc += 10; break; 077 case WHITE : acc += 10; break; 078 } 079 080 individual.setScore(acc); 081 } 082 }; 083 084 private static GeneticAlgorithm<ObjectChromosome> ga = 085 new GeneticAlgorithm<ObjectChromosome>( fitness, new Population<ObjectChromosome>(ne w Individual<ObjectChromosome>(template), POPULATION_SIZE), GENERATION_LIMIT); 086 087 088 public static void main(String[] args)throws Exception { 089 Utils.printHeader(); 090 System.out.println(); 091
  • 47. 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 } 116 } System.out.println("TUTORIAL 5:"); System.out.println("Find the sequence of colors nearest to the target."); System.out.println(); //Random.getInstance().setStandardSeed(); ga.addStage(new TournamentSelector<ObjectChromosome>(3)); ga.addStage(new OnePointCrossover<ObjectChromosome>(0.8)); ga.addStage(new SimpleMutator<ObjectChromosome>(0.02)); ga.evolve(); Statistics stats = ga.getCurrentPopulation().getStatistics(); GeneticAlgorithm.Statistics algostats = ga.getStatistics(); Group legals = stats.getGroup(Population.LEGALS); System.out.println("Solution: "); System.out.println(legals.get(0)); System.out.format("found in %d ms.n", algostats.getExecutionTime() ); System.out.println(); Utils.printStatistics(stats); Ejemplos de tema: 19 package jenes.tutorials.problem5; 20 21 22 /** 23 * Tutorial illustrating the use of object-oriented chromosomes, whose 24 * allele set can be defined by the user for each gene. 25 * 26 * In this example the chromosomes are combinations of colors. We aim at finding 27 * the vector of colors closest to a given sequence. 28 * 29 * This class defines the enumeration of possible colors. 30 * 31 * @author Luigi Troiano 32 * 33 * @version 1.0 34 * @since 1.0 35 */ 36 public enum Color { 37 38 RED, BLACK, WHITE;
  • 48. 39 40 } Ejemplos del tema: 19 package jenes.tutorials.problem5; 20 21 import java.util.HashSet; 22 import java.util.Set; 23 24 import jenes.utils.Random; 25 import jenes.chromosome.GenericAlleleSet; 26 27 /** 28 * Tutorial illustrating the use of object-oriented chromosomes, whose 29 * allele set can be defined by the user for each gene. 30 * 31 * In this example the chromosomes are combinations of colors. We aim at finding 32 * the vector of colors closest to a given sequence. 33 * 34 * This class defines an allele set made of doubles. 35 * 36 * @author Luigi Troiano 37 * 38 * @version 1.0 39 * @since 1.0 40 */ 41 42 public class DoubleAlleleSet extends GenericAlleleSet<Double> { 43 44 public DoubleAlleleSet(Set<Double> set) { 45 super(set); 46 } 47 48 /** 49 * Builds a DoubleAlleleSet with random values within the range [lowerBound,upperBound] 50 * <p> 51 * @param size the allala set cardinality 52 * @param lowerBound the min value to choose 53 * @param upperBound the max value to choose 54 * @return a new DoubleAlleleSet 55 */ 56 public static DoubleAlleleSet createRandom(int size, double lowerBound, double upperBound ) { 57 HashSet<Double> values = new HashSet<Double>(); 58 Random rand = Random.getInstance(); 59 60 for( int i = 0; i < size; ++i ) { 61 values.add(rand.nextDouble(lowerBound, upperBound+Double.MIN_VALUE)); 62 }
  • 49. 63 64 return new DoubleAlleleSet(values); 65 } 66 67 /** 68 * Builds a new DoubleAlleleSet with uniformly distributed values within the range [lowerBound,upper Bound] 69 * <p> 70 * @param size the allala set cardinality 71 * @param lowerBound the min value to choose 72 * @param upperBound the max value to choose 73 * @return a new DoubleAlleleSet 74 */ 75 public static DoubleAlleleSet createUniform(int size, int lowerBound, int upperBound ) { 76 HashSet<Double> values = new HashSet<Double>(); 77 78 double step = 1.0/upperBound - lowerBound; 79 for( double x = lowerBound; x <= upperBound; x += step ) { 80 values.add(x); 81 } 82 83 return new DoubleAlleleSet(values); 84 } 85 86 87 } Ejemplos del tema: 19 package jenes.tutorials.problem5; 20 21 import java.util.HashSet; 22 import java.util.Set; 23 24 import jenes.utils.Random; 25 import jenes.chromosome.GenericAlleleSet; 26 27 /** 28 * Tutorial illustrating the use of object-oriented chromosomes, whose 29 * allele set can be defined by the user for each gene. 30 * 31 * In this example the chromosomes are combinations of colors. We aim at finding 32 * the vector of colors closest to a given sequence. 33 * 34 * This class defines a set of integers. 35 * 36 * @author Luigi Troiano 37 * 38 * @version 1.0
  • 50. 39 * @since 1.0 40 */ 41 public class IntegerAlleleSet extends GenericAlleleSet<Integer> { 42 43 public IntegerAlleleSet(Set<Integer> set) { 44 super(set); 45 } 46 47 /** 48 * Builds an IntegerAlleleSet with random values within the range [lowerBound,upperBound] 49 * <p> 50 * @param size the allala set cardinality 51 * @param lowerBound the min value to choose 52 * @param upperBound the max value to choose 53 * @return a new IntegerAlleleSet 54 */ 55 public static IntegerAlleleSet createRandom(int size, int lowerBound, int upperBound ) { 56 HashSet<Integer> values = new HashSet<Integer>(); 57 int s0 = upperBound - lowerBound + 1; 58 if( size > s0 ) size = s0; 59 60 Random rand = Random.getInstance(); 61 62 for( int i = 0; i < s0; ++i ) { 63 64 int chosen = values.size(); 65 double coin = ((double)size-chosen)/(s0-i); 66 boolean justEnough = s0-i == size-chosen; 67 68 if( justEnough || rand.nextBoolean(coin) ) { 69 values.add(lowerBound + i); 70 } 71 } 72 73 return new IntegerAlleleSet(values); 74 } 75 76 /** 77 * Builds a new IntegerAlleleSet with uniformly distributed values within the range [lowerBound,upper Bound] 78 * <p> 79 * @param size the allala set cardinality 80 * @param lowerBound the min value to choose 81 * @param upperBound the max value to choose 82 * @return a new IntegerAlleleSet 83 */ 84 public static IntegerAlleleSet createUniform(int size, int lowerBound, int upperBound ) { 85 HashSet<Integer> values = new HashSet<Integer>(); 86 int s0 = upperBound - lowerBound + 1;
  • 51. 87 88 89 90 91 92 93 94 95 96 } 97 98 } if( size > s0 ) size = s0; double step = 1.0/(upperBound - lowerBound); for( double x = lowerBound; x <= upperBound; x += step ) { int i = (int) Math.round(x); values.add(i); } return new IntegerAlleleSet(values); El uso de metas de algoritmo genético locales Jenes ofrece la posibilidad de utilizar objetivos de algoritmos genéticos locales. El objetivo global es el utilizado por GeneticAlgorithm durante la evolución de la población en su principal secuencia de etapas. En su lugar, el objetivo local es el utilizado por la sola etapa (por ejemplo, una secuencia contenida en una rama paralela, etc.). Esta tutoriales muestra cómo resolver el problema de la mochila que define dos secuencias paralelas diferentes, con diferentes objetivos internos. El objetivo del problema de la mochila es maximizar la utilidad total de los elementos dentro de la bolsa, sin exceder la capacidad máxima de la bolsa. Tenemos n elementos cada uno con tiene una huella y un valor de utilidad. 1. Elegir un problema cromosómico adecuada y crear la población inicial Una solución candidata es un conjunto de elementos con un peso y una utilidad. Las soluciones se codifican usando un cromosoma booleano. Los valores boolean Indica si un elemento está presente o no dentro de la bolsa. Por ejemplo, si el gen i-ésimo es verdad, entonces el elemento de orden i está en la bolsa. Un cromosoma con todos los genes que tiene un valor falso representa una bolsa vacía, mientras que un cromosoma con todos los genes que tengan un verdadero valor representa una bolsa con todos los elementos posibles. 070 public KnapsackGA( int popsize, int generations, double[] utilities, double[] weights) { 071 super( new Population<BooleanChromosome>(new Individual<BooleanChromosome>(new Boole anChromosome(utilities.length)), popsize), generations); 072 2. Puesta en marcha del algoritmo genético Ponemos en práctica la clase KnapsackGA subclasificando GeneticAlgorithm e implementación de la función de aptitud como se informa a continuación. 053 054 055 @Override public void evaluate(Individual<BooleanChromosome> individual) { double utility = KnapsackGA.this.getUtilityOf(individual);
  • 52. 056 057 058 059 double weight = KnapsackGA.this.getWeightOf(individual); individual.setScore(utility); individual.setLegal(weight <= KnapsackGA.this.capacity); } La aptitud de cada solución es igual a la suma de las utilidades de los elementos que contiene. Si el peso total supera la capacidad de la bolsa, entonces el individuo se establece como ilegal. La función de código anterior, utilice los siguientes métodos de utilidad para evaluar la utilidad y el peso de una solución particular. 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 public double getUtilityOf(Individual<BooleanChromosome> individual) { BooleanChromosome chrom = individual.getChromosome(); double utility = 0.0; int size = chrom.length(); for(int i = 0; i < size; ++i){ utility += chrom.getValue(i) ? this.utilities[i] : 0.0; } return utility; } public double getWeightOf(Individual<BooleanChromosome> individual) { BooleanChromosome chrom = individual.getChromosome(); double weight=0.0; int size = chrom.length(); for(int i = 0; i < size; ++i){ weight += chrom.getValue(i) ? this.weights[i] : 0.0; } return weight; } 3. Elija los operadores a utilizar por el algoritmo genético y agregarlos como etapas en la ga Decidimos procesar individuos de manera diferente legales e ilegales. Por lo tanto, creamos una secuencia, llamada seq_legal, para procesar persona jurídica y una secuencia, llamada seq_illegal, para procesar los individuos ilegales. Estas secuencias tienen el mismo cuerpo (selector de torneo, un punto de cruce y simple mutador), pero diferentes objetivos. De hecho, el objetivo de seq_legal es maximizar la aptitud de las personas jurídicas, mientras que la de seq_illegal es minimizar la aptitud de las personas ilegales con el fin de eliminar el exceso de elementos y hacer legal la persona. Evolucionamos en personas legales e ilegales paralelas y en cada generación pasamos las soluciones legales para seq_legal y las soluciones ilegales para seq_illegal a través del uso de un dispensador exclusivo 076 077 078 079 080 081 082 083 Parallel<BooleanChromosome> parallel = new Parallel<BooleanChromosome>(new ExclusiveDispenser<BooleanChromosome>(2){ @Override public int distribute(Individual<BooleanChromosome> ind) { return ind.isLegal() ? 0 :1; }
  • 53. 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 }); this.setFitness(this.maximize); Sequence<BooleanChromosome> seq_legal = new Sequence<BooleanChromosome>(); seq_legal.appendStage(new TournamentSelector<BooleanChromosome>(2)); seq_legal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8)); seq_legal.appendStage(new SimpleMutator<BooleanChromosome>(0.02)); Sequence<BooleanChromosome> seq_illegal = new Sequence<BooleanChromosome>(); seq_illegal.appendStage(new TournamentSelector<BooleanChromosome>(2)); seq_illegal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8)); seq_illegal.appendStage(new SimpleMutator<BooleanChromosome>(0.2)); parallel.add(seq_legal); parallel.add(seq_illegal); this.addStage(parallel); seq_legal.setFitness(this.maximize); seq_illegal.setFitness(this.minimize); Ejemplo del tema: 019 package jenes.tutorials.problem6; 020 021 import jenes.utils.Random; 022 import jenes.population.Individual; 023 import jenes.population.Population; 024 import jenes.population.Population.Statistics; 025 import jenes.population.Population.Statistics.Group; 026 import jenes.tutorials.utils.Utils; 027 028 /** 029 * Tutorial showing how to minimization and maximization sub-prolems can cohesists in 030 * the breeding structure of Jenes. 031 * 032 * This class defines the problem to solve. 033 * 034 * @author Luigi Troiano 035 * 036 * @version 1.0 037 * @since 1.0 038 */ 039 public class KnapsackProblem { 040 041 private static int POPSIZE=100; 042 private static int GENERATION_LIMIT=100; 043
  • 54. 044 private static final double[] WEIGHTS = {1, 5, 3, 2, 8, 6, 4, 7, 9, 6}; 045 private static final double[] UTILITIES = {7, 2, 7, 1, 6, 4, 2, 8, 9, 2}; 046 047 private KnapsackGA algorithm; 048 private double[] utilities; 049 private double[] weights; 050 051 public KnapsackProblem(double[] utilities, double[] weights) { 052 algorithm = new KnapsackGA(POPSIZE, GENERATION_LIMIT, utilities, weights); 053 this.weights = weights; 054 this.utilities = utilities; 055 } 056 057 @SuppressWarnings("unchecked") 058 public void run() { 059 this.algorithm.evolve(); 060 061 Statistics stat=algorithm.getCurrentPopulation().getStatistics(); 062 Group legals = stat.getGroup(Population.LEGALS); 063 Individual solution= legals.get(0); 064 System.out.println(solution.getChromosome()); 065 System.out.format("W: %f U: %fn", algorithm.getWeightOf(solution), algorithm.getUtilityOf(solut ion) ); 066 } 067 068 public double getCapacity() { 069 return this.algorithm.getCapacity(); 070 } 071 072 public void setCapacity(double c) { 073 this.algorithm.setCapacity(c); 074 } 075 076 public double[] getUtilities() { 077 return utilities; 078 } 079 080 public double[] getWeights() { 081 return weights; 082 } 083 084 public static KnapsackProblem build(int n) { 085 086 Random r = Random.getInstance(); 087 088 double[] utilities = new double[n]; 089 for( int i = 0; i < n; ++i ) { 090 utilities[i] = r.nextInt(10); 091 }
  • 55. 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 double[] weights = new double[n]; for( int i = 0; i < n; ++i ) { weights[i] = r.nextInt(10); } return new KnapsackProblem(utilities, weights); } public static void main(String[] args) { Utils.printHeader(); System.out.println(); System.out.println("TUTORIAL 6:"); System.out.println("The Knapsack Problem."); System.out.println(); KnapsackProblem p1 = new KnapsackProblem(UTILITIES, WEIGHTS); System.out.println("Case 1: 10 elements, capacity 15"); System.out.println("Utilities: " + toString(p1.getUtilities()) ); System.out.println(" Weights: " + toString(p1.getWeights()) ); p1.setCapacity(15); p1.run(); System.out.println(); System.out.println("Case 2: 10 elements, capacity 30"); System.out.println("Utilities: " + toString(p1.getUtilities()) ); System.out.println(" Weights: " + toString(p1.getWeights()) ); p1.setCapacity(30); p1.run(); System.out.println(); KnapsackProblem p2 = KnapsackProblem.build(20); System.out.println("Case 3: 20 random elements, capacity 50"); System.out.println("Utilities: " + toString(p2.getUtilities()) ); System.out.println(" Weights: " + toString(p2.getWeights()) ); p2.setCapacity(50); p2.run(); System.out.println(); } private static String toString(double[] values) { String s = "["; for(int i = 0; i < values.length; ++i ){ s += values[i]+ (i < values.length-1 ? " " : "]"); }
  • 56. 141 return s; 142 } 143 144 } Ejemplo del tema: 019 package jenes.tutorials.problem6; 020 021 import jenes.Fitness; 022 import jenes.GeneticAlgorithm; 023 import jenes.chromosome.BooleanChromosome; 024 import jenes.population.Individual; 025 import jenes.population.Population; 026 import jenes.stage.ExclusiveDispenser; 027 import jenes.stage.Parallel; 028 import jenes.stage.Sequence; 029 import jenes.stage.operator.common.OnePointCrossover; 030 import jenes.stage.operator.common.SimpleMutator; 031 import jenes.stage.operator.common.TournamentSelector; 032 033 /** 034 * Tutorial showing how to minimization and maximization sub-prolems can cohesists in 035 * the breeding structure of Jenes. 036 * 037 * This class implements a genetic algorithm for solving the Knapsack problem. 038 * 039 * @author Luigi Troiano 040 * 041 * @version 2.0 042 * 043 * @since 1.0 044 */ 045 public class KnapsackGA extends GeneticAlgorithm<BooleanChromosome>{ 046 047 private class KnapsackFitness extends Fitness<BooleanChromosome> { 048 049 private KnapsackFitness(boolean maximize) { 050 super( maximize ); 051 } 052 053 @Override 054 public void evaluate(Individual<BooleanChromosome> individual) { 055 double utility = getUtilityOf(individual); 056 double weight = getWeightOf(individual); 057 individual.setScore(utility); 058 individual.setLegal(weight <= KnapsackGA.this.capacity); 059 } 060
  • 57. 061 } 062 063 private double capacity; 064 private double[] weights; 065 private double[] utilities; 066 067 private KnapsackFitness maximize = new KnapsackFitness(true); 068 private KnapsackFitness minimize = new KnapsackFitness(false); 069 070 public KnapsackGA( int popsize, int generations, double[] utilities, double[] weights) { 071 super( new Population<BooleanChromosome>(new Individual<BooleanChromosome>(new Boole anChromosome(utilities.length)), popsize), generations); 072 073 this.utilities = utilities; 074 this.weights = weights; 075 076 Parallel<BooleanChromosome> parallel = 077 new Parallel<BooleanChromosome>(new ExclusiveDispenser<BooleanChromosome>(2){ 078 079 @Override 080 public int distribute(Individual<BooleanChromosome> ind) { 081 return ind.isLegal() ? 0 :1; 082 } 083 084 }); 085 086 this.setFitness(this.maximize); 087 088 Sequence<BooleanChromosome> seq_legal = new Sequence<BooleanChromosome>(); 089 seq_legal.appendStage(new TournamentSelector<BooleanChromosome>(2)); 090 seq_legal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8)); 091 seq_legal.appendStage(new SimpleMutator<BooleanChromosome>(0.02)); 092 093 Sequence<BooleanChromosome> seq_illegal = new Sequence<BooleanChromosome>(); 094 seq_illegal.appendStage(new TournamentSelector<BooleanChromosome>(2)); 095 seq_illegal.appendStage(new OnePointCrossover<BooleanChromosome>(0.8)); 096 seq_illegal.appendStage(new SimpleMutator<BooleanChromosome>(0.2)); 097 098 parallel.add(seq_legal); 099 parallel.add(seq_illegal); 100 101 this.addStage(parallel); 102 103 seq_legal.setFitness(this.maximize); 104 seq_illegal.setFitness(this.minimize); 105 } 106 107 public double getCapacity() { 108 return this.capacity;
  • 58. 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 } } public void setCapacity(double capacity) { this.capacity = capacity; } public double getUtilityOf(Individual<BooleanChromosome> individual) { BooleanChromosome chrom = individual.getChromosome(); double utility = 0.0; int size = chrom.length(); for(int i = 0; i < size; ++i){ utility += chrom.getValue(i) ? this.utilities[i] : 0.0; } return utility; } public double getWeightOf(Individual<BooleanChromosome> individual) { BooleanChromosome chrom = individual.getChromosome(); double weight=0.0; int size = chrom.length(); for(int i = 0; i < size; ++i){ weight += chrom.getValue(i) ? this.weights[i] : 0.0; } return weight; }
  • 59. Registro de las estadísticas Experimentar con algoritmo genético requiere a menudo para recopilar datos sobre la evolución a lo largo de los diferentes experimentos. En este tutorial vamos a aprender a capturar estadísticas evolución en. Csv y los archivos de MS Excel. Los madereros Hay dos tres métodos para registrar las estadísticas en Jenes. La primera es hacerlo usted mismo por guardar los datos en un archivo o base de datos. Los otros dos se basan en los registradores disponibles desde Jenes 1.3.0. La forma más fácil es usar un StatisticsLogger. Esta clase es capaz de grabar automáticamente los objetos que pertenecen desde LoggableStatistics, por ejemplo, Population.Statistics y objetos GeneticAlgorithm.Statistics. StatisticsLogger basa en un registrador real para grabar realmente los datos en algún medio. Por ejemplo, se puede hacer uso de un CSVLogger para grabar en. Csv (es decir, valores separados por comas) archive 072 csvlogger = new StatisticsLogger( 073 new CSVLogger(new String[]{"LegalHighestScore", "LegalScoreAvg","LegalScoreDev"}, FOLDER + "knapsackproblem.csv" ) ); o XLSLogger para grabar directamente en un archivo xls MS Excel. 075 xlslogge1 = new StatisticsLogger( 076 new XLSLogger(new String[]{"LegalHighestScore", "LegalScoreAvg","LegalScoreDev"}, FOLDER + "knapsack1.log.xls" ) ); En algún momento es útil volver a utilizar un spreedsheet. En este caso, podemos especificar que plantilla se usan en el método constructor de XLSLogger. 078 xlslogge2 = new StatisticsLogger( 079 new XLSLogger(new String[]{"LegalHighestScore", "LegalScoreAvg" , "IllegalScoreAvg"} , FOLDER + "knapsack2.log.xls", FOLDER +"knapsack.tpl.xls" ) ); El tercer método hace uso directo de registrador real, por ejemplo 081 xlslogge3 = new XLSLogger(new String[]{"LegalHighestScore", "LegalScoreAvg" , "Run"}, FOL DER + "knapsack3.log.xls"); Esquema Los madereros son capaces de procesar datos tabulares con un esquema determinado, es decir, un conjunto de campos etiquetados. El esquema de datos se tiene que dar en el momento de la construcción. Por ejemplo, en el primer y segundo caso estamos interesados en grabar LegalHighestScore, LegalScoreAvg y LegalScoreDev largo de las generaciones. En el tercer caso grabamos LegalHighestScore, LegalScoreAvg y IllegalScoreAvg.
  • 60. Finalmente, en el tercer caso grabamos LegalHighestScore, LegalScoreAvg and Run, representando este último el número de ejecución de la experimentación. Si utilizamos StatisticsLogger, los campos tienen que ser etiquetados de la misma manera las estadísticas son anotados por registrable (etiqueta). Si utilizamos directamente los madereros reales, podemos hacer uso de distintivos que deseamos para el esquema, como el mapeo estará en nuestro poder, como se describe a continuación. Tenga en cuenta que el esquema entre mayúsculas y minúsculas, por lo que "someStatistic" es diferente de "SomeStatistic", y ambos son diferentes de "SOMESTATISTIC". Medios de comunicación Grabación en. Csv es sencillo. Si el archivo existe, se puede decidir si desea sobrescribir los datos (por defecto) o para añadir datos. Cuando usamos. Xls debemos cuidar algunos detalles. Cuando no existe el archivo de registro, el registrador crea un libro vacío con una hoja, donde las columnas se asignan de acuerdo con el esquema con primera fila asignada a las etiquetas de campo. Podemos optar por utilizar un pre-hechos xls.. En este caso tenemos que reservar una columna para cada campo en el esquema. La columna puede colocarse en cualquier parte de la hoja, que la hoja no importa. La única restricción es que la celda en la fila 1 debe contener la etiqueta del campo. También podemos optar por utilizar un archivo xls. Como plantilla. Una plantilla es simplemente un archivo de pre-hechos. En este caso, el archivo no se sobrescribe como el destino es diferente (ver xlslogge2 para un ejemplo). Por ejemplo, podemos decidir utilizar la plantilla se muestra en la Figura 1.
  • 61. Recolección de Datos Una vez que los madereros están establecidos y esquema definido, podemos recoger datos. La mejor manera de recoger los datos es por medio de oyentes. Por ejemplo 143 GenerationEventListener<BooleanChromosome> logger1 = new GenerationEventListener<Boolean Chromosome>() { 144 145 public void onGeneration(GeneticAlgorithm ga, long time) { 146 Population.Statistics stats = ga.getCurrentPopulation().getStatistics(); 147 148 prb.csvlogger.record(stats); 149 prb.xlslogge1.record(stats); 150 prb.xlslogge2.record(stats); 151 152 } 153 154 }; En este caso StatisticsLogger se encarga de registrar datos. Tan sólo hay que proporcionar una LoggableStatistics y StatisticsLogger haremos el trabajo por nosotros. El inconveniente de esta solución es que no somos capaces de añadir datos no considerados por el objeto de estadísticas. Para obtener un control más preciso del proceso, podemos hacer uso directo de un registrador real. Por ejemplo 172 GenerationEventListener<BooleanChromosome> logger2 = new GenerationEventListener<Boolean Chromosome>() { 173 public void onGeneration(GeneticAlgorithm ga, long time) { 174 Population.Statistics stats = ga.getCurrentPopulation().getStatistics(); 175 176 Group legals = stats.getGroup(Population.LEGALS); 177 178 prb.xlslogge3.put("LegalHighestScore", legals.getMax()); 179 prb.xlslogge3.put("LegalScoreAvg", legals.getMin()); 180 prb.xlslogge3.put("Run", prb.exec); 181 182 prb.xlslogge3.log(); 183 } 184 185 }; Entrar cierre Por último, podemos hacer que los datos persistentes cerrando los madereros. 165 166 prb.csvlogger.close(); prb.xlslogge1.close();