Universidad Autónoma Metropolitana Unidad Iztapalapa ' División de Ciencias Básicas e Ingeniería i ' Licenciatura en Computación Applet para Algoritmo Genético Se implementa un algoritmo genético en un applet que sea capaz de ejecutarse en un explorador y medir su tiempo de respuesta, así como graficar los resu1tados. P e g i n a Inés González Flores 92320586 Para la obtención del grado de Licenciatura en Computación Asesor : John Goddard Close Indice Introducción........................................................................... 2 Algoritmos Genéticos................................................................ 3 Operación del applet.................................................................. 8 Un ejemplo: xSen(x) .................................................................. 11 . . de resultados................................................................ Análisis 13 Conclusiones........................................................................... 16 Trabajos Futuros....................................................................... 17 Apéndice A.. ............................................................................ 18 Apéndice B............................................................................. 22 Referencias. ........................................................................... 34 Introducción El avance en la tecnología obliga a que los sistemas computarizados de datos se desarrollen en plataformas que permitan su ejecución a través de internet mediante “buscadores”, así surgió la idea de desarrollar un applet de Java que ejecute un algoritmo genético, para observar el tiempo de ejecución y los resultados gráficos. En el presente trabajo se ha conjuntado la idea de los Algoritmos Genéticos con la programación orientada a objetos, y las aplicaciones que se ejecutan en los exploradores de la internet, que día a día tienen mayor influencia en los métodos de programación. En este documento se presenta una introducción a lo que son los Algoritmos Genéticos, y la explicación de como fue programado el applet que contiene un ejemplo de Algoritmo Genético. Este applet esta conformado por 8 clases: Genotype GeneticAigorihm FuncXSinX GenerationGraph FunctionGraph DrawControls OptionsGA Prueba Las 6 primeras clases contienen la operación y gráfica del algoritmo y la función xSen(x), las dos Últimas clases (OptionsGA y Prueba) controlan la operación en lo que corresponde a valores parametrizables dinámicamente y arranque del AG. Para la ejecución de este applet es necesario tener un archivo de texto gadata.ixt que contiene el domino en el cual se toman los posible valores para x. Para los gráficos se han utilizado las librerías awt de java versión 1.2.1. Al final de este documento en los apéndices A y B se incluye el código del applet. Aigoritmos Genéticos Imitación del comportamiento de la naturaleza Los algoritmos genéticos son métodos adaptables que permiten resolver problemas de búsqueda y optimización. L o s AG están basados en una imitación de los procesos naturales, teoría de la evolución de Charles Darwin. En la teoría de la evolución, los seres vivos están formados por estructuras de genes que contienen características de generaciones anteriores a ellos. De acuerdo con la teoría de la evolución, existe un número limitado de condiciones que permiten que la evolución ocurra : 0 Las estructuras deben ser capaces de reproducirse 0 Las estructuras de la población deben ser purificadas 0 Deben tener algunos errores en la reproducción para permitir que ocurran cambios (mutación) En la teoría de la evolución, para que un ser biológico adquiera las características que lo representan, debieron pasar muchos años, y muchas generaciones antes de él, es decir que cada ser biológico es producto de todo un proceso un tanto aleatorio de generaciones que le preceden. Imitando estos procesos, los AG son capaces de encontrar soluciones a problemas del mundo real, si tienen un código óptimo. Por ejemplo pueden ser usados para diseiíar puentes, para marcar procesos de control tales como hacer balances sobre un sistema de cómputo de múltiple proceso. Surgen los Algoritmos Genéticos 3 La primera publicación acerca de los AG es de Hollad en 1962', la estructura matemática se desarrolla en los 60's y es publicada en uno de sus libros en 1975. L o s algoritmos genéticos son probados en dos áreas : optimización y aprendizaje maquinal. En aplicaciones de optimización han sido usados en diversos campos, tales como funciones de optimización, procesamiento de imágenes, el problema del agente viajero, sistemas de identificación y control. En aprendizaje maquinal han sido usados en aprendizaje de sintácticas simples como IF-THEN en ambientes arbitrarios. Bases de Algontmos Genéticos. El AG es representado de la siguiente manera : EMPIEZA genera población inicial calculafitness de cada individuo MIENTRAS NO termina HAZ EMPIEZA /* Produce una nueva generación */ PARA tamaiíojoblación HAZ EMPIEZA /* Ciclo reproductivo */ selecciona dos individuos de la generación vieja por porcentaje /* basado en favor de los de mejorfitness */ combina los dos individuos para dar dos hijos calcula elfitness de los dos hijos inserta a los hijos en la nueva generación TERMINA SI la población ha convergido ENTONCES termina-erdadero TERMINA TERMINA 'pp 382 Capitulo 14 Genetic Algorithms 4 La selección natural es la liga entre los cromosomas y el desarrollo de sus códigos estructurales. Procesos de selección natural originan que cromosomas con mejores características se reproduzcan más frecuentemente que otros con peores características. La reproducción y mutación provocan que los hijos tengan estructuras diferentes a los padres, y el cruzamiento obliga a su vez a que los hijos contengan códigos estructurales de ambos padres. Es precisamente con éstas características de la evolución natural que se desarrollan los AG. L o s AG manipulan con cadenas de ceros y unos (dígitos binarios) llamados cromosomas, cada bit del cromosoma es llamado allele, mediante codificación, estos cromosomas son expuestos a los mecanismos del proceso de evolución natural que son: selección, cruzamiento y mutación. La única información que otorgan es mediante la evaluación de una función que representa al problema. Es mediante esta evaluación que se determina que cromosomas se reproducen más fkecuentemente que otros. Los algoritmos genéticos manejan poblaciones de cromosomas, que forman una generación. Si el AG está bien diseñado, la población converge a una solución óptima del problema. L o s AG’s no garantizan encontrar la solución global óptima del problema, pero si encuentran una solución aceptablemente buena, en un tiempo aceptablemente corto. Los problemas están representados por un conjunto de parámetros, los AG representan estos parámetros mediante genes, que son partes del cromosoma. Es decir que si tenemos una función que depende de 2 parámetros, y representamos cada parámetro por medio de 10 números binarios cada uno, tendremos cromosomas de tamaiío 20, con dos genes. Mediante esta representación tenemos oportunidad de representar un conjunto amplio de problemas que dependen de un numero variable de parámetros, que irán evolucionando de manera conjunta, y dependiendo unos de otros. El fitness, es el valor que toma el cromosoma al ser evaluado en la función que caracteriza al problema. Por ejemplo, en un problema de máximos la función característica será la suma de cada uno de los parámetros, por lo tanto el fitness será el resultado de esta suma, y para este caso nos interesará el cromosoma que nos proporcione el mayor fitness. L o s AG se basan para realizar sus procesos de selección en el fitness de cada cromosoma, otorgando mayor posibilidad de ser seleccionados a aquellos que otorguen los mejores fitness. Para reproducirse los AG emplean métodos de reproducción, cruzamiento y mutación. La reproducción es un método en el que un cromosoma es seleccionado por su fitness para formar parte de la nueva población. Uno de los métodos de reproducción conocidos es el método de la ruleta, que consiste en realizar algo así como una ruleta, en la cual cada rebanada corresponderá al valor obtenido en el fitness de cada uno de los cromosomas, de forma tal que los mejores cromosomas tengan mayor posibilidad de ser seleccionados para reproducirse, sin dejar de tener un valor puramente probabilístico. El cruzamiento consiste en seleccionar un par de cromosomas, y en los genes de cada uno de ellos elegir un punto de cruzamiento aleatorio, separando de esta forma al gene en dos partes que podemos llamar cabeza y tallo2, intercambiando los tallos de cada uno de ellos, de esta forma los genes sufien una pequeña deformación, que será reducida conforme la solución sea mejor. No es conveniente realizar mutación cada vez en todos los cromosomas de la población, por este motivo la determinación de efectuar o no la mutación se asocia a una probabilidad que la mayor de las veces oscila entre 0.6 y 1. Observemos el siguiente ejemplo Sean los cromosomas : (1101011001)y (0111010011) y el punto de cruzamiento 6 quedan los cromosomas (1 10101001 1) y ( O 1 1101 1001) La mutación es aplicada a cada hijo, después del cruzamiento. La mutación es una perturbación en el cromosoma que cambia las características de éste. Debido a que no es recomendable hacer mutación con los genes, pues esto provocaría la perdida de la información acumulada a lo largo de la evolución, ésta tiene asociada una pequeña probabilidad, comúnmente 0.001. En este caso se eligen uno o varios puntos de mutación, o se elige que genes del cromosoma mutarán. Observemos el siguiente ejemplo : Sea el cromosoma ( 1 1 O O O 1 O 1 1 O ) con puntos de mutación 5 y 7 , obtenemos así el cromosoma (1100111110). Para el caso de genes sea el cromosoma de dos genes de tamaño 5-bits cada uno (0110100110) si mutamos el segundo gene obtenemos : (0110111001) Tanto de cruzamiento como de mutación existen diversos métodos, dependiendo del tipo de datos tratados en los cromosomas. 'Tal como lo hacen Beasley, Bull y Martinen su articulo An overview of Genetic Algorithms Operación del applet El applet esta formado por las clases GenerationGraph,FunctionGraph,DrawControls y OptionsGA, que forman la parte gráfica de la ejecución del algoritmo; y la parte de la operación lógica del algoritmo está en la clase GeneticAlgorithm y el caso particular de la operación en la clase FuncXSinX. BestFitness: 32.891774t BestMember: 32.935303: MAX GENERATIONS Applet started. I r POP SIZE PXOVER PMUTATION 1.005 - La estructura genotipo (clase: genotype) En el programa realizado se define la clase genotype para instanciar objetos que han de almacenar los resultados de la población actual. Esta estructura fue tomada del libro de Michalewicz. La clase tiene los siguientes atributos: Double Double Double double double double gene [I fitness upper [ I lower [ I rfitness cfitness gene[] Esta estructura contiene los valores para cada uno de las variables de la función objetivo, así el arreglo gene tendrá 3 valores si la función objetivo es de 3 variables, XI, x2, x3. fitness En esta variable se guardará el resultado de la evaluación de la función objetivo para los valores almacenados en gene[]. upper[] En este arreglo se guardan los valores máximos que podrán tener cada una de las variables almacenadas en gene[]. lower[] En este arreglo se guardan los valores mínimos que podrán tener cada una de las variables almacenadas en gene[]. rfiíness Esta variable contendrá el porcentaje del valor del fitness de este genotipo con respecto a los demás fitness del total de la población, este valor será utilizado al aplicar el método de la ruleta para la selección. cfitness Esta variable almacena el valor porcentual acumulado para la selección. Ejecución La operación del algoritmo inicia en un objeto tipo Prueba, que hereda de la clase applet, genera y contiene los objetos: 0 ga que es de la clase FuncXSinX que es el objeto que tiene definido los valores (genotype) y el comportamiento del Algoritmo Genético (AG); gg que es de la clase GenerationGraph, hereda de Canvas y es el objeto que dibuja la gráfica de generaciones; fg que es de la clase FunctionGraph, hereda de Canvas y es el objeto que dibuja la gráfica de la función y el punto en el que se localiza el mejor miembro (fitness), oga que es de la clase OptionsGA que hereda de Panel, panel que muestra los resultados de “Best Member” y “Best Member”, dc que es de la clase Drawcontrols hereda de Panel y recibe como parhetros los objetos gg, fg, ga y oga, este objeto es el que controla la operación del AG, limpia las gráficas y los genotipos para comenzar una nueva ejecución cada vez que el botón “start GA” es presionado. Valores de los parámetros MAX GENEMTIONS Este parhetro se utiliza para definir dinámicamente el número de generaciones que serán ejecutadas. POP SIZE Este parámetro sirve para definir el tamaño de la población. PXOVER Este parámetro define el factor de cruzamiento. PMUTATION Este parámetro define el factor de mutación. Un ejemplo xSen(x) Se ha escogido maximizar la función xSen(x) para hacer el applet que ejecute el AG porque tiene máximos y mínimos locales, lo que hace la convergencia más lenta que cuando la función tiene un máximo y/o mínimo Único global. La clase en la que se codifica la función es FuncXSinX que hereda de la clase GmeticAlgorithm todo el comportamiento del algoritmo e implementa las funciones evaluate(), getAverage() y keepTheBest(). public void evaluate0 I double x[] = new double [NVARC+ll; for (int mem=O; mem<POPSIZE; mem++) { 1 1 for (int i=O; ieNVARS; i++) x [i+i]=population[meml .gene[il ; population [mem] .fitness=x111 *Math.sin (x111 1; En este método se guarda en la variable fitness de cada miembro de la población el resultado de la evaluación de xSin(x). public void keepTheBest0 { int cur-best=O; for (int mem=O; mem<POPSIZE; mem++){ if (population[mem].fitness>population[POPSIZE] . fitness) { cur-best=mem; population[POPSIZE] .fitness=population[mem] .fitness; 1 I for (int i=O; icNVARS; i++) population [POPSIZE].gene [i]=population[cur-best1 .gene[il ; 1 En este método se identifica cual es el mejor miembro de la población y se guarda en el Último genotipo (population [POPSIZE] de la población. public Double getAverage0 { double sum=0.0; Double average ; for (int mem=O;mem<POPSIZE ;mem++ { sum = sum + population[meml.fitness; 1 average = new Double(sum/POPSIZE); return (average); 1 Este método regresa el valor promedio de esta generación de la población. +. Análisis de resultados Los parámetros que tienen mayor impacto para la convergencia del máximo valor de esta función son el número de generaciones y el tamaño de la población. 1O0 generaciones, 1O miembros de población Digamos por ejemplo que tenemos 100 generaciones con una población de tamaño 10, un factor de cruzamiento de 0.8 y un factor de mutación de 0.15, en la primera ejecución esto es lo obtenido: Best Fitness: 1 MAX GENERATIONS Ikppiet started. 1100 POP S E 32.9984941 Best fflember: 110 PXOVER -33.031283 PMUTATION 10.15 1O0 generaciones, 1O0 miembros de la población Movamos ahora el tamaño de la población, digamos a 100, esto es lo que tenemos: Best Fitness: POP SIZE MAXQENERATIONS Max. Pop Size 33.001234t Best Member: -33.023192 (100 PXOMR (o8PMüTATlON Best Best Member Fitness Generations 1O0 10 32.9984 -33.03 1O0 100 33.O0123 -33.023 Con el incremento en el tamaño de la población el “Best Fitness” es más cercano al valor máximo de la función. 10 generaciones, 100 miembros de la población Cuando disminuimos el número de generaciones, digamos a 10 y dejamos un número grande en el tamaño de la población 100, este es el resultado que obtenemos: Max. Best Pop Size Best Member Fitness Generations 10 1O0 32.983155 -33.O5 0635 10 1O0 32.915926 32.94483O 10 1O0 33.O013471 -33.022612 10 1O0 33.O00857 -33.024819 10 1O0 33.O00452 -33.O07747 10 100 32.993539 32.9945503 Lo que observamos de estos resultados es que se acerca al máximo, pero no siempre converge. 1O0 generaciones, 1O miembros de la población Hagamos el caso contrario generaciones 1O0 y tamaño de la población 1O. Max. Pop Size Best Best Member Fitness Generations 1O0 10 32.9990560 -33.003957 1O0 10 32.998926 -33.O30338 100 10 32.996682 33.034708 1O0 10 32.982286 -33.051406 1O0 10 32.926173 33.0846351 1O0 10 32.9960021 33.035834 Aquí los brincos en los datos son menores, esto se debe a que en este algoritmo se aplica la función "keep the best" que implica que las generaciones siempre conservan al mejor miembro de la generación anterior, de esta manera conforme se van dando nuevas poblaciones, siempre existe al menos el mejor miembro de la generación anterior. 15 Conclusiones El algoritmo genético implementado en un applet se ejecuta correctamente, el problema observado es la manera en como se dibuja, no se hace segmento por segmento, se dibuja toda al final de la ejecución del algoritmo, este problema puede ser por haber hecho la gráfica con las librerías awt, se debería hacer otra función con swing para ver si el problema se resuelve. Utilizando el método “keep the best” la función converge pronto. La utilización de clases resuelve de manera sencilla la relación entre el algoritmo genético y sus gráficas de resultados, tanto la de fitness y average a lo largo de las generaciones como la de la función y su mejor resultado. Trabajos fbturos Hay mucho trabajo por hacer partiendo de la idea de implementar Algoritmos Genéticos con applets, algunos que identifico son: 0 hacer otras funciones para evaluar el desempeño del AG con otras funciones, cambiar las funciones que grafican para hacerlas con swing en vez de awt como están desarrolladas actualmente, con esto se intenta mejorar la manera de graficar y que sea punto a punto, actualmente se grafican todos los resultados de una sola vez, implementar otros tipos de datos para los valores del AG, implementar más tipos de métodos del AG (cruzamiento, mutación, selección, etc). Apéndice A. Estructura de las clases La aplicación se encuentra distribuida en 7 archivos java: GeneticA1gorithm.java FuncXSinX.java Generati0nGraph.java Functi0nGraph.java DrawContro1s.java 0ptionsGA.java Prueba.java GeneticAigorithnjava Clase: Genotype Atributos: double double double double double double Clase: GeneticAlgorithm Atributos: Static int POPSIZE Static int MAXGENS Static int W A R S Static float PXOVER Static float PMUTATION Static Genotype population [ I Static Genotype newPopulation[l Static Printstream ps Static FileOutputStream f o s Int generation Métodos: Abstract public void evaluate0 public void initilize0 public void select O public void crossover0 public void mutate O public void elitist O double randval(doub1e low,double high) void xover (int one,int two) void report O void openReportFile0 void bestResultsReport0 void closeReportFile0 public void runGA0 gene [ I fitness upper [ I lower [ 1 rfitness cfitness Genotype Esta clase contiene la estructura de datos que forman los genotipos. GeneticAigorithm Esta clase contiene el comportamiento genérico de los algoritmos genéticos, definidos en los métodos evaluate, initialize, select, crossover, mutate, elitist y runGA. FuncXSinX.java Clase: FuncXSinX Métodos FuncXSinX ( public void evaluate0 public Double getAverage0 public void keepTheBest0 FuncXSinX Esta clase hereda de GeneticAlgorith, presenta el caso particular de la función xSen(x), en esta clase se define la función evaluate que es abstract en GeneticAlgorithm. Sus métodos son propios de la función. Generati0nGraph.java Clase: GenerationGraph Atributos: Métodos: Int xMax Int yMax int segMaxSize Vector 1ineGraph Vector averageLine Public GenerationGraph(int xMax, int yMax) public void paint(Graphicc g) private void drawAxes (Graphics g) private void drawGraphic (Graphics g) GenerationGraph Esta clase es la que dibuja la gráfica de la evolución de generaciones, para dibujar utiliza funciones de awt. FunctionGraph.java Clase: GenerationGraph Atributos: Métodos: double value public FunctionGraphO public void paint(Graphics g) double f (double x) FunctionGraph Esta clase dibuja la gráfica de la función y el comportamiento del mejor resultado. DrawContro1s.java Clase: DrawControls Atributos: Métodos: FuncXSinX ga GenerationGraph gg FunctionGraph fg OptionsGA oga TextField maxGen TextField pxOver TextField pMutation TextField populationSize public DrawControls (GenerationGraph gg, FunctionGraph fg, FuncXSinX ga, OptionsGA oga) public void actionPerformed(ActionEvent ev ) public void runGA() DrawControls Esta clase es la clase controladora, comienza el AG y guarda los resultados en las clases GenerationGraph y FunctionGraph para después dibujarlos. 0ptionsGA.java Clase: OptionsGA Atributos: Label bestFitness Label bestMember Métodos: public OptionsGAO public void actionPerformed(ActionEvent ev ) public void paintResults (String labelBestFitness, String 1abelBestMember) OptionsGA Esta clase dibuja los valores para "Best Fitness" y "Best Member" Prueba.java Clase: Prueba Atributos: GenerationGraph gg FunctionGraph fg DrawControls dc FuncXSinX ga OptionsGA oga Métodos: Public void init0 Public void destroy (1 Prueba Esta clase es la que distribuye las gráficas en el applet. Apéndice B. Código import import import import java.io.*; java.util.Date; java.lang.Math; java.util.Random; class Genotype { double gene [I ; double fitness; double upper [ I ; double lower [I ; double rfitness; double cfitness; 1 abstract class GeneticAlgorithm { static int POPSIZE = 50; static int MAXGENS = 1000; static int WARS = 1; static float PXOVER = (float) 0.8; static float PMUTATION = (float) 0.15; static Genotype population[]; static Genotype newPopulation[l; static Printstream ps; static Fileoutputstream fos; int generation = O; abstract public void evaluate(); public void initilize (1 { File infile = new File ("GAData.txt"); Double lbound,ubound; String lineaLeida = int posseparator = O; population = new Genotype[POPSIZE+lI; newPopulation = new Genotype[POPSIZE+lI; i i i i ; try { BufferedReader br = new BufferedReader(new FileReader(infile1); for (int i=o;icNvARS; i++){ if ((lineaLeida=br.readLineO)!=null) posseparator = lineaLeida.indexOf(l%'); -lbound Double.valueOf(lineaLeida.substring(0,posSeparator) 1; -ubound Double.valueOf(lineaLeida.substring(posSeparator+l) 1; for (int j=O;j<=POPSIZE;j++) { if (i==O){ population[j] = new Genotype() ; population [ j1 . lower = new double [31; population [ jI .upper = new double [31 ; population [ jI .gene = new double 13 I ; popuiation[jl .fitness=O; population[jl .rfitness=O; population[jl .cfitness=O; newPopulation [j1 = new Genotype 0 ; newpopulation [ j1 . lower = new double [31 ; newPopulation[jl .upper = new double 131 ; newpopulation [ jI .gene = new double [31 ; newPopulation[jl.fitness=0; new~opulation[jl.rfitness=O; new~opulation[jl.cfitness=O; 1 if (j! =POPSIZE) { 22 population [ j]. lower [i] = lbound .doublevalue (I ; population [ j].upper[ i] = ubound.doublevalue ( ; population [ j1 .gene[il this.randval(population[j] .lower[il ,population[jl .upper[il); 1 1 new~opuiation[j].lower[il = O. O; newPopulation[jl .upper[il = 0.0; new~opuiation[j].gene[il = 0.0; public void select 0 { double sum=O; for (int mem=O; memePOPSIZE; mem++) sum+=population[mem].fitness; for(int mem=O; memePOPSIZE; mem++) popu~ation[mem].rfitness=popu~ation[mem].fitness/sum; population[^] .cfitness=population[0].rfitness; for(int mem=l;memePOPSIZE;mem++) population[mem] .cfitness=population[mem11 .cfitness+population[mem] .rfitness; for (int i=O; iePOPSIZE; i++){ double p; p = Math.random~)%1000/1000.0; if (pepopulation[O1 .cfitness) newpopulation [i]=population[O1 ; else { for(int j=O; j<POPSIZE; j++) if (p>=popuiation[ j] .cfitness&&pepopulation [ j+i] .cfitness) newpopulation [il=population[ j+11 ; public void crossover0 { int one=0; int first=O; double x; for (int mem=O; memePOPSIZE; mem++) { x=Math.random()%1000/1000.0; if (xePXOVER) { ++first; if (first%2==0) xover (one,mem) ; else one=mem; public void mutate 0 { double lbound,hbound,x; for(int i=O;i<POPSIZE;i++) for(int j=o;jeNvARs; j++) { x=Math.random()%1000/1000.0; if (x<PMUTATION){ lbound=population[il .lower[ j1 ; hbound=population[il .upper[ jI ; population [ i] .gene [ j] =randVal(lbound,hbound) ; 1 1 1 23 public void elitist 0 { double best,worst; int bestmem = O; int worstmem = O; worst=best=population[Ol .fitness; for(int i=O; icPOPSIZE; i++) { if (population[i] .fitness>population[i+i].fitness) { if (population[i].fitness>=best) { best=population[i] .fitness; bestmem=i; 1 if (population[i+i].fitnessc=worst) { worst=population[i+il .fitness; worstmem=i+l; 1 } else { if (population[i].fitness<=worst) { worst=popuiation[i].fitness; worstmem=i; 1 if (population[i+i].fitness>=best) { best=population[i+i].fitness; bestmem=i+l; if (best>=population[POPSIZE].fitness) { for(int i=O; icNVARS; i++) population [POPSIZE].gene[il=population[bestmeml .gene[il ; populat~on[POPSIZE].fitness=population[best~mem].f~tness; 1 else { for(int i=O; icNVARS; i++) population [worstmem].gene[il=population[POPSIZE].gene [il; populat~on[worst~mem].f~tness=populat~on[POPSIZE].fitness; 1 1 double randval(doub1e low,double high) { double val = O; val = (double)( (Math.random0* (high-low))+low) ; return (val); 1 void xover (int one,int two) { int point ; double temp; if WARS>^) { if ( N V A R S = = 2 point=i; else point= (int)(Math.random0% ( W A R S - 1 ) +l; for(int i=O; icpoint; i++) { / / *********** SWAP temp = population [one].gene[il ; populationlone] .gene[il = population[twol .gene[il ; population [two].gene[il = temp; 1 \J 1 void report 0 { double best-val = O; double avg = O; double stddev = O ; double double double String sum-square = O; square-sum = O; sum = O; reportline; sum = sum-square=O.O; for(int i=O; iePOPSIZE; i++){ sum+=popuiation[i] .fitness; sum~square+=population[i].fitness*population[i].fitness; I avg=sum/(double)POPSIZE; square-sum=avg*avg* (doub1e)POPSIZE; stddev=Math.sqrt((sums9uare-square-square-sum)/(POPSIZE-l)); best-val=population[POPSIZE] .fitness; reportLine = generation + 11 + best-val + 11 + avg s tddev ; ps.println(reportLine); ps.flush0; + + 1 void openReportFile (1 { try { fos = new FileOutputStream(new File ("Resultados.txt")) ps = new PrintStream(fos1; ; 1 catch (Exception e) { System.out .println("Exceptiongeneral I 1 + e) ; void bestResultsReport 0 { ps .println( llSimulation completed"); ps.println("Best member:"); for (int i=O; icNvARS; i++) ps .println(i + 11=11 + population [POPSIZE].gene[ill ; ps.println(llBest fitness=I1 + population[POPSIZE] .fitness); ps.println0; ; ps .println(llSuccessll) 1 void CloseReportFile (1 { try { fos.close0 ; 1 catch (Exception e) { System.out.println("Exceptiongeneral 1 I + e) ; public void runGA0 { openReportFile (1 ; while (generationeMAXGENS) { generation++; select 0 ; crossover(1 ; mutate 0 ; report 0 ; evaluate ( ) ; elitist ( ) ; 1 1 1 bestResultsReport 0 closeReportFile 0 ; ; class FuncXSinX extends GeneticAlgorithm { 25 FuncXSinXO { initilize 0 ; evaluate 0 ; keepTheBest( 1 ; public void evaluate 0 { double x[l = new double [NvARS+lI; for (int mem=O; memcPOPSIZE; mem++) { for (int i=o; icNvARs; i++) x [i+i]=population[meml .gene[il ; population [mem].fitness=x[ll*Math.sin(x [ll ) ; public Double getAverage0 { double sum=0.0; Double average ; for (int mem=O;memcPOPSIZE ;mem++ { sum = sum + population[mem].fitness; 1 average = new Double(sum/POPSIZE); return (average); 1 public void keepTheBest0 { int curbest=O; for (int mem=O; memcPOPSIZE; mem++) { if (population[meml , fitness>population[POPSIZEI.fitness) { cur-best=mem; population[POPSIZEl.fitness=population[meml.f~tness; 1 1 1 1 for (int i=o; icNvARS; i++) population [POPSIZE] .gene[il =population[cur~bestl.gene[i]; import java.awt.*; import java.awt.Graphics; import java.uti1.Vector; public class GenerationGtaph extends Canvas { int xMax; int yMax; int segMaxSize; Vector 1ineGraph = new Vector(); Vector averageLine = new Vector(); public GenerationGraph(int xMax, int yMax) { setsize (400, 400) ; setBackground(Color.gray) ; this.xMax = xMax; this.yMax = yMax; SegMaxSize = 15; 1 public void paint (Graphics g) { drawAxes (9); drawGraphic (9) ; private void drawAxes(Graphics g) { int valLabel = O; Font sizedFont; int xl, x2, yl, y2; double yFactor = 0.0, yDelta = 0.0; int len = O, skip = 1, current = 1; len = (int)(getsize().width-40); -new sizedFont g.getFont 0 .getstyle0 , 8 ) ; g.setFont(sizedFont); Font (g.getFont ( ) .getName ( 1 , / / Horizontal g.drawLine(20, getSize().height - 20, getSizeO.width 20, getsize0 .height - 20); if (xMax e = len) { if ( (len/xMax) c segMaxSize) { skip = (int)(segMaxSize/(len/xMax) ; 1 for (int i=l;ic=xMax;i++,current++) { if (current == skip) { .drawLine(((int)(i*(len/xMax) )+20,getSizeO.height i*(len/xMax)))+20, getsize0 .height - 19); g .drawstring ( I’ I’ +i , i* (len/xMax)) ) +la, getsize (1 .height - 10) ; current = O; 1 else { 1 19 I 1 for(int i=20; ie=getSize( ) .width-20; i= i+20) { getsize (1.height - 21) ; g.drawLine(i, getsize0 .height valLabel 20)/20)* (flax/( (getsize0 .width-lO)/20)1 ; g.drawString ( lllv+valLabel, getsize() .height - 10) ; 1 - - 19, i, (int)( (ii-4, 1 / / Vertical g.drawLine(20, 20, 20, getsize0 .height - 20); yFactor = (getsize0 .height - 40) / 20; yDelta = yMax / 20; for (int i=l;ic=2O;i++) { xl = 19; x2 = 21; y1 = y2 = (int)( (getsize().height-20)- (i*yFactor) g .~drawLine (xi, yl, x2, ~ 2 ;) g.drawString(It1l+( (int)(i*yDeita)1, 5, y1+3); ; 1 / / Line description 27 10) ; g.setFont(sizedFont); g .setcolor (Color.green) ; XI = getsize() .width-70; x2 = getsize (1 .width-60; y1 = y2 = 12; g .drawLine (xi, y1 , x2 , y2); g.setcolor (Color.black) ; g.drawString(I1Fitnessl1,getsize 0 .width-55, 15); g.setcolor(Color.yellow); XI = getsize ( ) .width-70; x2 = getsize0 .width-60; y1 = y2 = 22; g.drawLine (xi, yl, x2 , y21 ; g.setcolor (Color.black) ; g.drawString(llAverage”,getsize0 .width-55,25) ; private void drawGraphic(Graphics g) { int len = (int)(getsize0 .width-40); int current = 1; double yDelta = 0.0; yDeita = (getsize0 .height-40)/yMax ; int skip = 1; int xl, x2, yl, y2; x1=2o ; yl=getSize(1 .height-20; x2=y2=0; g .setcolor (Color.green) ; for (int i=O;iclineGraph.size();i++, current++) { if (xMax c= len) x2 = ((int)( (i+l)* (len/xMax)1 ) +20; else { skip = (int)(xMax/len); x2 = (int)(20+(i/skip)1 ; 1 ((( (int)( (getsize( ) .height-20)Y2 (Double)1ineGraph.elementAt (i)) .intValue (1 ) *yDelta)) ; if (current == skip) { g.drawLine (xi, yl, x2, y2); current = O; I I xl=x2; yl=y2; / / average graphic Xl = 20; y 1 = getsize ( ) .height-20; x2 = y2 = o; current = skip = 1; g.setColor(Color.yellow); for (int i=O;i<averageLine size O ;i++, current++ 1 { if (xMax c= len) x2 = ( (int)( (i+l)* (len/xMax)1) +20; else { 1 ( ( skip = (int)(xMax/len); x2 = (int)(20+(i/skip)1 ; (int)( (getsize0 .height-20)Y2 ( (Double)averageLine.elementAt (i) .intvalue (1 1 delta) i if (current == skip) { g.drawLine (xi, yl, x2 , Y21 ; current = O; 1 1 1 xl = x2; y1 = y2; I import java.awt.*; import java.util.Vector; public class FunctionGraph extends Canvas { double value = 0.0; public FunctionGraphO { setsize (400, 400) ; setBackground(Color.gray); 1 public void paint(Graphics g) { int xlfx2,yl,y2; int xFactor = 5; int yFactor = 5; Font sizedFont; double yTemp = 0.0; sizedFont g.getFont 0 .getstyle0 , 8 ) g.setFont(sizedFont); ( new ; / / dibuja lineas coordenadas xl = 10; x2 = getsize() .width - 10; y1 = y2 = getSize().height/2; g.drawLine(x1, yl, x2, ~ 2 ) ; x l = x2 = getsize 0 .width/2; y1 = 20; y2 = getsize0 .height-20; g.drawLine(x1, yl, x2, y2); / / escribe escala for (int y= (int)-1*( (getsize(1 .height-40)/ (2*yFactor)) ; yc (getsize( ) .height-40)/ (2*yFactor);y++) { if ( (y!=O) && (y%5==0) { XI = getsize() .width/2 - 1; x2 = getsize() .width/2 + 1; y1 = y2 = (-l*(y*yFactor)) + ( (getsize(1 .height)/2) ; g .drawLine (xi, y1, x2, y21; g.drawString(l'l'+y,getsize ( ) .width/2 +lo, (-l* (y*yFactor) (getsize0 .height)/2)+3) ; 1 1 + int i=i; x=-l*( (getsize0 .width(int for 20)/ (2*xFactor)) ;xc (getsize( ) .width-20) / (2*xFactor);x++, i++) { if ( (x ! = O) && (x%5==0)) { / / Escribe escala XI = x2 = (x*xFactor) + getsize0 .width/2; y1 = getsize() .height/2 - 1; y2 = getsize().height/2 + 1; g.drawLine (xi, yl, x2 , y21 ; if (xc0) + x, xl - 4 , getsize0 .height/2 + 10 1; g.drawString(llll else + x, xl - 2, getsize0 .height/2 + 10 1; g.drawString(llll 1 / / Dibuja Gráfica 1 xl = (x*xFactor) + getsize() .width/2; x2 = ( (x+l)*xFactor) + getsize 0 .width/2; yTemp = f (XI; if (yTemp >= O) y1 = (int)(getsize().height/2-(yTemp* yFactor) 1 ; else y1 = (int)( ( (yTemp*-1) *yFactor)+getsize ( ) .height/2); yTemp = f (x+i); if (yTemp >= O) y2 = (int)(getsize0 .height/2-(yTemp* yFactor)1 ; else y2 = (int)( ((yTemp*-1)*yFactor)+getSize() .height/2); g.drawLine (xi, yl, x2 , y21 ; / / Dibuja Valor 1 xl = x2 = (int)( (value*xFactor) y1 = o; y2 = getsize 0 .height ; g.setcolor (Color.pink1; g .drawLine (xi, y1 , x2 , y21 ; double f (double x) { return (x*Math.sin (x)) + getsize ( ) .width/2); ; import java.awt.*; import java.awt.event.*; class DrawControls extends Panel implements ActionLietener { FuncXSinX ga; GenerationGraph gg; FunctionGraph fg; OptionsGA oga; TextField maxGen, pxOver, pMutation, populationsize; public DrawControls(GenerationGraph gg, FunctionGraph fg, FuncXSinX ga, OptionsGA oga) I setsize (400, 200) ; this.gg = gg; this.ga = ga; this.fg = fg; this.oga = oga; 1 add (new Label ( !#MAXGENERATIONS" ; add (maxGen = new TextField ( t t l O O O r l , 6) ; add(new Label (IIPOP SIZE")) ; add (populationSize = new TextField ('15011f 4 ) 1; add (new Label ( llPXOVER"); add(px0ver = new T e ~ t F i e l d ( ~ ~ 06)) . 8 ~; ~ ~ add (new Label ( rfPMUTATION") ) ; add(pMutation = new TextField(t10.1511, 6)) ; Button b = null; b = new Button("Start GA"); b.addActionListener(this1; add(b) ; public void actionPerformed(ActionEvent ev) { String label = ev.getActionCommand0; gg.lineGraph.removeAllElements(); gg.averageLine.removeAllElements(); fg.value = 0.0; ga .MAXGENS -gg .xMax Integer.parseInt(maxGen.getText().trim()); ga.POPSIZE = Integer.parseInt(populationSize.getText() .trim()); -12/09/01 ga .PXOVER // Float .parseFloat(pxOver.getText ( ) .trim ( ) ) ; -12/09/ O 1 ga.PMüTATION // Float.parseFloat (pMutation.getText( ) .trim (1 1 ; ga.generation = O; ga.initilize (1 ; ga.evaluate (1 ; ga .keepTheBest ( ) ; runGA0 ; 1 public void runGA0 { while (ga.generation<ga.MGENS) { / / DEBUG RGF /* try I Thread.currentThread ( ) . sleep (50); 1 catch (InterruptedException e) { 1* / ga.generation++; ga.select (1 ; ga .crossover(1 ; ga .mutate( ) ; gg.lineGraph.addElement(new Double (ga.population[ga.POPSIZE] .fitness)) ; gg.averageLine.addElement(ga.getAverage0 1; gg.repaint 0 ; fg.value = ga.population[ga.POPSIZEl .gene[ O 1 ; fg .repaint ( 1; ga.evaluate ( 1 ; ga.elitist 0 ; 1 oga.paintResults (rlll+ga.population [ga.POPSIZE].fitness, f~~~+ga.population[ga.POPSIZEl .gene[ O 1 1; import java.awt.*; import java.awt.event.*; \ '. class OptionsGA extends Panel implements ActionListener { Label bestFitness, bestMember; public OptionsGA ( ) { setsize (400, 200) ; add (new Label ("Best Fitness : ' I ) ) ; add(bestFitness = new Label ( n O O O O O O O n ) add(new Label ("Best Member: ' I ) 1 ; add(bestMember = new Label ( " O O O O O O O n ) ) 1 ; ; public void actionPerformed(ActionE3ent ev) { 1 public void paintResults(String labelBestFitness, 1abelBestMember) { bestFitness.setText(labe1BestFitness); bestMember.setText(labe1BestMember) ; repaint 0 ; String 1 1 import java.applet.*; import java.awt.*; import java.awt.event.*; public class Prueba extends Applet { GeneratianGraph gg; FunctionGraph fg; DrawControls dc; FuncXSinX ga; OptionsGA oga; public void init 0 l 1 setLayout (new BorderLayout (1 ) ; ga = new FuncXSinXo; gg = new G e n e r a t i o n G r a p h ( g a . M G E N S , 100); fg = new FunctionGraphO; oga = new OptionsGAO ; dc = new DrawControls (gg, fg, ga, oga) ; add (oga, BorderLayout .NORTH) ; add(gg, BorderLayout.WEST); add(fg, BorderLayout.EAST); add(dc, BorderLayout.SOUTH); public void destroy0 { remove (gg); remove (fg); remove (dc ; 32 Referencias Holland Genetic Algorithm, 1962 Beasley, Bull y Martin An overview of Genetic Aigorithms Bruce Eckel Thinking in Java, 2ndEdition Prentince Hall mid-Jun2000 33