You are on page 1of 9

Diseño e implementación de un algoritmo

genético sobre dispositivos de lógica


programable
Alumno: Iker Uzin Larrañaga, Tutores: Javier Echanobe, Inés del Campo

Resumen—El objetivo de este trabajo es el diseño y la implementación de un algoritmo genético sobre un dispositivo de lógica
programable, concretamente un dispositivo FPGA. Primero se resolverá un problema mediante un algoritmo genético utilizando el
software Matlab para estudiar dicho algoritmo, luego se diseñará un sistema electrónico digital que realice las funciones de este
algoritmo para finalmente implementarlo sobre una FPGA.

Palabras clave—algoritmos genéticos, computación evolutiva, diseño hardware, soft computing.

I. INTRODUCCIÓN

P ARA hablar de algoritmos genéticos tenemos que hablar antes de inteligencia computacional o soft computing, ya que la
computación evolutiva (dentro de la cual se comprenden los algoritmos genéticos) es uno de los campos constituyentes de
esta nueva disciplina. El soft computing es una técnica innovadora para construir sistemas inteligentes. A diferencia de la
computación convencional, tolera imprecisiones, incertidumbres y aproximaciones. El objetivo del soft computing es
precisamente conseguir soluciones aceptables, robustas y de bajo coste tolerando lo máximo posible las imprecisiones,
incertidumbres y aproximaciones sobre el problema a resolver.
Los principales campos constituyentes del soft computing son la lógica fuzzy, la computación neuronal (redes neuronales), la
computación evolutiva (algoritmos genéticos), el aprendizaje de las máquinas y el razonamiento probabilístico, con las más
recientes incorporaciones de la teoría del caos y partes de la teoría del aprendizaje. Es importante remarcar que el soft computing
no es una disputa de eficacia entre todos estos campos. Al contrario, se trata de combinar las distintas metodologías de estos
campos para conseguir el sistema más cercano posible que imite la inteligencia humana en una tarea específica.
Los algoritmos genéticos son algoritmos de búsqueda de propósito general que se basan en el modo en que la naturaleza
consigue hacer que sus especies estén cada vez más adaptadas a su entorno, es decir, en la evolución. El año 1975 se toma como
punto de referencia del origen de los estudios sobre algoritmos genéticos y, desde entonces hasta hoy en día, han ido mejorando
y han sido utilizados para resolver problemas de los ámbitos más diversos.
En este trabajo se presenta un diseño hardware de un algoritmo genético. Primero se explicará en qué consisten estos
algoritmos, luego se verá un ejemplo y por último se describirá el diseño realizado.[1]

II. ALGORITMOS GENÉTICOS

A. Algoritmos genéticos básicos


Los algoritmos genéticos básicos son los algoritmos genéticos más simples y son en los que se basan el resto de variantes. Su
funcionamiento se basa en intentar imitar la evolución natural para buscar la mejor solución para un problema.
Los algoritmos genéticos operan sobre un grupo de posibles soluciones al que se le llama población y que inicialmente es
creado aleatoriamente. A cada una de estas posibles soluciones se le llama individuo o cromosoma y se representa como una
cadena de números, habitualmente bits (0 y 1). Los individuos tienen una longitud concreta y a cada uno de los números que
conforman un individuo se le llama gen. Lógicamente, la población que es generada al principio aleatoriamente será una
población de malas soluciones, pero precisamente se trata de que la población vaya mejorando por medio de la evolución natural
hasta conseguir buenas soluciones.
B. Función de fitness
La evolución natural se basa en que las especies se vayan adaptando a su entorno. Del mismo modo, en los algoritmos
genéticos, las soluciones han de ir adaptándose al problema para que, al final, tengamos una población de buenas soluciones. La
función de fitness es la función que mide lo adaptado que está un individuo al problema. Esta función será la que diga lo cerca
que está una posible solución de la mejor solución del problema: cuanto mayor sea la función de fitness de un individuo, más
cerca estará de la mejor solución.
La función de fitness es la única función específica de cada problema de todas las funciones que realiza un algoritmo genético.
Es, en cierto modo, la que define el problema dentro del algoritmo genético.
C. Selección de individuos
En cada generación de individuos debe hacerse una selección de los individuos más cualificados para pasar sus genes a la
siguiente generación, al igual que ocurre con la selección natural. Para acercarse lo más posible a ésta última, la selección en un
algoritmo genético se hará de manera aleatoria, pero teniendo cada individuo una probabilidad de ser seleccionado proporcional
a su función de fitness, es decir, a la bondad de sus genes. De este modo conseguimos que en general se vayan eligiendo a los
mejores individuos, pero, al mismo tiempo, los que no son tan buenos también tienen posibilidades de pasar y aportar algún gen
que haga falta para formar mejores individuos en la siguiente generación.
D. Cruce
Una vez seleccionados los individuos cuyos genes pasarán a la siguiente generación, se procede a la formación de ésta. Para
ello primero se realizarán un número aleatorio de cruces (como máximo población/2).
Los individuos que se vayan a cruzar también se deberán elegir aleatoriamente, teniendo en cuenta que un mismo individuo no
puede cruzarse más de una vez. El cruce consiste en un intercambio de genes entre dos individuos a partir de un punto que, como
casi todo, se elige aleatoriamente. A continuación se muestra un ejemplo:

110|01 110|11
+ =>
010|11 010|01

Ejemplo 1: cruce

Después de realizarse todos los cruces tendremos un nuevo grupo de individuos que poseerán nuevas características con
respecto a los anteriores.
E. Mutación
En la naturaleza se dan cambios en las especies que no se deben a los genes heredados de sus antepasados, sino a las
mutaciones que se producen por azar en su cadena genética y pueden aportar valores positivos o negativos en la adaptación de la
especie a su entorno. Esto mismo se realiza en los algoritmos genéticos.
Se elige al azar cuántos y cuáles de los individuos van a mutar (un individuo no puede mutar más de una vez), se elige que gen
de su cadena mutará y se cambia ese gen por su complementado, como se ve a continuación:

1|0|101 => 1|1|101

Ejemplo 2: mutación

Una vez realizadas las mutaciones, ya tendremos la nueva generación, que, previsiblemente tendrá mejores características de
adaptación al problema que la anterior, es decir, mejores funciones de fitness.
F. Condición de parada
Se deben realizar numerosos ciclos de selección, cruce y mutación para mejorar suficientemente la población de individuos. El
algoritmo genético debe finalizar cuando considere que la mejor solución encontrada hasta ese momento es bastante buena o que
no va a poder encontrar una mejor. Para eso se define una condición de parada.
La condición de parada más sencilla es hacer que el algoritmo pare siempre después de haber hecho un número de ciclos
predeterminado. Otra posible condición de parada es que la función de fitness alcance un valor determinado que se considere que
es suficientemente bueno para ese problema.
La condición que se utilizará en este trabajo como condición de parada es una mezcla de ambas. Se guardará el individuo que
tenga el valor de fitness más alto de la generación inicial. A partir de ahí, si ese valor no es superado en veinte ciclos, el
algoritmo parará. Siempre que el valor de fitness del individuo sea superado, se guardará el nuevo mejor individuo y se volverá a
contar hasta veinte ciclos del algoritmo.
La solución al problema será el individuo que esté guardado en el momento que pare el algoritmo.
A continuación se muestra el diagrama de flujo del algoritmo:
Inicialización

Cálculo de
fitness

Evaluar sí
parada Fin
no

Selección

Cruce

Mutación

Fig. 1: Diagrama de flujo del algoritmo genético

III. PROBLEMA RESUELTO CON UN ALGORITMO G ENÉTICO

A. Problema del péndulo invertido


En esta parte del trabajo se resuelve un problema utilizando algoritmos genéticos. De este modo se verá un ejemplo de cómo
los algoritmos genéticos pueden buscar soluciones a los problemas. Este ejemplo se programará y se simulará utilizando el
software Matlab.
El problema que se trata de resolver es un problema de control. Se trata de hacer un controlador que mantenga en equilibrio un
péndulo invertido. El péndulo es una barra de masa m y longitud l que se coloca encima de un carro de masa M que se mueve sin
que le afecte ningún tipo de rozamiento. El péndulo partirá de la posición vertical pero, al ser esta posición un punto de equilibrio
inestable, caerá hacia un lado haciendo que el carro se desplace en dirección opuesta.

Fig. 2: Esquema del péndulo invertido

La función del controlador consiste en ejercer una fuerza sobre el carro para acercar la posición del péndulo otra vez a la
vertical. Esta fuerza será función de las variables de estado del sistema, es decir, de la posición x y la velocidad dx/dt del carro y
del ángulo θ y la velocidad angular dθ/dt del péndulo. El diagrama de bloques es el siguiente:
F

Controlador Péndulo

Fig. 3: Diagrama de bloques del péndulo invertido

La acción de control que se realiza es muy sencilla: solamente ejercerá una fuerza F (a la derecha) o –F (a la izquierda) sobre
el carro. Las variables de estado del sistema se discretizan por rangos y, de este modo, el controlador es una tabla de valores F y
–F para todas las combinaciones de variables de estado.
La posición x del carro se separa en tres rangos para discretizarlo, al igual que la velocidad dx/dt. El ángulo θ del péndulo se
separa en seis rangos y la velocidad angular dθ/dt en tres. A continuación se muestran los rangos que se han elegido para hacer la
discretización:
x: (-∞, -2), [-2, 2], (2, ∞)
dx/dt: (-∞, -0.3), [-0.3, 0.3], (0.3, ∞)
θ: (-π/2, -π/3), [-π/3, -π/6), [-π/6, 0), (0, π/6], (π/6, π/3], (π/3, π/2)
dθ/dt: (-∞, -0.3π), [-0.3π, 0.3π], (0.3π, ∞)
Las distintas combinaciones que pueden llegar al controlador son: 3·3·6·3=162. Por lo tanto el controlador es una tabla de 162
posiciones. Los posibles controladores son los individuos del algoritmo genético, por lo tanto los individuos tienen 162 genes.
Cada gen es un 1 (F) o un 0 (-F). Se utiliza una población de 50 individuos para resolver el problema mediante un algoritmo
genético.
B. Funciones del algoritmo genético
Como ya se ha dicho anteriormente, todas las funciones de los algoritmos genéticos excepto la función de fitness son
independientes al problema que se va a solucionar, salvo por el tamaño de la población y el número de genes de cada individuo.
Por lo tanto para escribir las funciones de generación inicial, selección, cruce y mutación no se tiene en cuenta el problema del
péndulo invertido.
- Generación inicial: La función que crea la generación inicial es la más sencilla de todas, ya que sólo se trata de generar una
matriz con números discretos aleatorios entre 0 y 1, donde el número de filas es el tamaño de la población y el número de
columnas la longitud de cada individuo. En nuestro ejemplo la matriz es de 50x162.
- Selección: Antes de hacer la selección se deben tener la generación de individuos actual y sus respectivas funciones de
fitness guardadas en dos matrices. La selección se realiza en varios pasos. Primero se suman todas las funciones de fitness
fi de los individuos actuales para formar un vector en el que se guarda fi/suma, que es la probabilidad de ser seleccionado
de cada individuo. A partir de este vector se forma otro en el que en cada posición del vector se suma la probabilidad de
esa posición con todas las anteriores. De este modo, en la primera posición queda la probabilidad del primer individuo, en
la segunda la suma de las probabilidades de los dos primeros, y así hasta que en la última posición aparece la suma de
todas las probabilidades que, lógicamente, es 1. Una vez se tenga este vector se crea un vector del tamaño de la población
con números reales aleatorios entre 0 y 1. Se comprueba en qué rango del anterior encaja cada número de este vector y se
selecciona el individuo al que pertenece ese rango. Es fácil ver que el tamaño del rango correspondiente a cada individuo
es proporcional a su función de fitness.
- Cruce: Para hacer el cruce de los individuos seleccionados se sigue al pie de la letra lo anteriormente explicado sobre el
cruce. Primero se elige el número de cruces que se van a hacer, que será el número de ciclos que hará el algoritmo. Una
vez dentro del ciclo se procede a elegir los individuos. Se utiliza un flag para cada individuo que indica si ya ha sido
elegido anteriormente o no, para evitar que el mismo individuo se cruce más de una vez. Si se intenta elegir un individuo
con el flag a 1, automáticamente se elegirá el siguiente individuo. La elección de los dos individuos que se van a cruzar
tampoco puede ser simultanea por la misma razón, para evitar que un individuo se cruce consigo mismo. Así que se elige
primero un individuo y luego el otro, y se ponen sus flags a 1. Se elige también en qué punto se van a cruzar mediante un
número aleatorio, y se hace el intercambio de genes.
- Mutación: La mutación es muy similar al cruce, con la diferencia de que en este caso sólo hay que elegir un individuo y
cambiarle un solo gen. Para evitar que se elija el mismo individuo más de una vez se utiliza el mismo sistema de flags.
C. Cálculo de la función de fitness
Como ya se ha dicho antes, la función de fitness es la función que mide cuánto se acerca una posible solución a la solución real
del problema. En este caso del péndulo invertido se debe medir la bondad de una solución examinando cuánto aguantaría el
péndulo sin caerse con ese controlador en el sistema.
Lo primero que se tiene que hacer es conseguir las ecuaciones del sistema del péndulo invertido y linealizarlos en torno al
punto de equilibrio para conseguir las ecuaciones de estado del sistema. Las matrices de estado son las siguientes:

&0 1 0 0# & 0 #
A = $$ 0 0 m 2 · g ·l 2 !
0! B = $$ I + m·l 2 !
!
2
$ I ·( M + m) + M ·m·l 2 ! $ I ·( M + m) + M ·m·l !
$0 0 0 1! $ 0 !
$ m· g ·l ·( M + m) ! $ m·l !
$0 0 0! $ 2 !
% I ·( M + m) + M ·m·l 2 " % I ·( M + m) + M ·m·l "
Donde M es la masa del carro, m la masa del péndulo, l la longitud del péndulo, I el momento de inercia del péndulo y g la
fuerza de la gravedad.
Por otro lado, se tiene que hacer una función que discretice las variables de estado para que en función de éstos el controlador
le aplique una fuerza F a la derecha o a la izquierda. El algoritmo para calcular la función de fitness deberá resolver dos sistemas
de ecuaciones diferenciales distintas dependiendo de si la fuerza que aplicamos al carro es a la derecha o a la izquierda.
Si el controlador devuelve 1 => x& = A· x + B·F
Si el controlador devuelve 0 => x& = A· x + B·(! F )
Después de tener la discretización y las ecuaciones definidas, se debe hacer una simulación de cómo responde el péndulo ante
un controlador dado. Para ello se define que el periodo del controlador será de 0.1 segundos, es decir, cada 0.1 segundos analiza
las variables de estado discretizadas y devuelve la fuerza que ejerce sobre el carro. La simulación parte siempre de la posición
vertical. Se discretizan las condiciones iniciales, se busca la respuesta del controlador y se resuelve el sistema de ecuaciones
pertinente durante 0.1 segundos. Después se coge el último resultado de la simulación y, si el ángulo θ no es menor que –π/2 ni
mayor que π/2, se coge este último resultado como condición inicial, se discretiza, se busca la respuesta del controlador y se
vuelve a resolver el sistema de ecuaciones diferenciales pertinente durante un periodo. Se procede de esta forma hasta que el
ángulo θ salga del rango establecido y en ese momento se mide el tiempo que ha tardado el péndulo en caer (la cantidad de
simulaciones que se han hecho por 0.1). Este tiempo será el valor de fitness para un controlador.
La función que tenemos que hacer debe calcular los valores de fitness para todos los individuos de la generación actual, así que
debe repetir ese procedimiento 50 veces, uno para cada individuo.
D. Solución del problema
La solución global del problema se obtiene aplicando al algoritmo genético la condición de parada que se ha explicado en el
segundo apartado.
Así pues, primero se obtiene una generación inicial y después se entrará en el ciclo donde se calcula primero la función de
fitness, luego se evalúa la condición de parada y, siempre que no se cumpla, se procede a la selección, el cruce y la mutación para
obtener una generación de controladores mejor.
En el siguiente gráfico se observa cómo el mejor individuo de la generación va mejorando hasta que llega un momento en el
que ya es difícil mejorar. El resultado del algoritmo será el individuo que haya dado la mejor función de fitness, que en este caso
ha sido 7.3 segundos.

Fig. 4: Gráfica de amejoramiento del valor de fitness del mejor individuo a lo largo de generaciones

IV. IMPLEMENTACIÓN HARDWARE DE UN A LGORITMO GENÉTICO


En este apartado se describirá el diseño que se ha hecho para la implementación de un algoritmo genético en hardware. Primero
se describirá el dispositivo de lógica programable sobre el que se va a implementar el diseño y después se explicará cómo se ha
realizado el propio diseño empezando desde el nivel superior para examinar luego los distintos bloques.
A. Dispositivo de lógica programable
El PLD que se va a utilizar es un dispositivo FPGA (field programmable gate array). Es de la familia APEX 20KE de Altera y
el modelo concreto es EP20K200EFC484-2X. Tiene un total de 200000 puertas lógicas. La arquitectura característica de los
FPGA consiste en una matriz de celdas lógicas que se comunican entre sí y con las celdas de entrada/salida a través de cables o
canales de comunicación.
En el caso de la familia APEX 20KE la característica fundamental es que combina tres modelos de estructuras de PLDs: los
LUT (look-up tables), bloques de términos producto y bloques de memoria embebida. Las celdas en las que se agrupan estos tres
elementos junto con una interconexión local formarán un LAB (logic array block). Los LABs están agrupados dentro de
MegaLABs formando una estructura jerárquica, además de estar interconectados por las interconexiones globales verticales y
horizontales. La estructura tiene también bloques de memoria, celdas de entrada/salida y circuitería para el manejo del reloj,
incluyendo PLLs.[2]
B. Esquema general
En esta parte del trabajo se diseña un circuito digital que haga las funciones propias generales de un algoritmo genético, es
decir, la función de inicialización, la de selección, la de cruce y la de mutación. Esto quiere decir que no se implementa de
momento ninguna función de fitness, sino que esto se deja para el siguiente apartado.
En el nivel superior del circuito se pueden distinguir tres clases de grandes bloques.
- Por un lado está el bloque generador de números aleatorios (RNG). Este bloque no se diseña en este trabajo dado que es un
bloque muy complejo que por sí solo podría llevar mucho tiempo diseñarlo. Se utiliza un RNG diseñado en otro trabajo
dirigido y aquí se considera como un bloque funcional al que se le pasa un valor límite y genera números aleatorios entre 0
y ese valor.
- En segundo lugar están las memorias RAM. Debe haber dos memorias RAM en el sistema: uno para guardar los
individuos y otro para guardar los valores de fitness correspondientes. Se considera que el problema que se va a resolver
tiene una población de n individuos y la longitud de los individuos es de m genes. Por lo tanto la memoria de individuos es
de n posiciones y cada palabra es de m+1 bits, puesto que el bit más significativo de la memoria se utilizará como flag en
las funciones de cruce y mutación. El tamaño de las palabras de la memoria de fitness es de l bits, siendo l el número de
bits que se necesitan para representar un valor de fitness, y el número de posiciones de memoria es el mismo que en la de
individuos. Las memorias tienen tanto la entrada como la salida pasadas por registro y el reloj será el mismo para los dos
casos. Además, tienen una señal de habilitación de escritura (we).
- Por último están los bloques más importantes: los controladores. Hay un módulo por cada función que ha de realizar el
algoritmo y, además, un controlador general que ejecuta la función global. Los módulos actúan cambiando el contenido de
las memorias y el controlador general actúa sobre los módulos enviándoles señales para que ejecuten sus respectivas
funciones. El controlador general tiene tres funciones importantes. La primera de ellas es la ya mencionada de enviar
señales al resto de módulos. La segunda es controlar el acceso a memoria de éstos, ya que varios de ellos necesitan acceder
a cada memoria. Para hacer esto se utilizan multiplexores en los accesos a memoria controlados por el controlador general.
La tercera función del controlador general es evaluar la condición de parada en cada ciclo del algoritmo y dar por
finalizado el algoritmo en caso de que se cumpla.
Aquí se muestra un esquema de bloques de la máquina:
Módulo
fitness

RNG Módulo RAM


generación individuos
inicial

Módulo
Controlador selección

general RAM
fitness
Módulo
cruce

Módulo
mutación

Fig. 5: Diagrama de bloques de la máquina de algoritmos genéticos

C. Módulo para la generación inicial


Al principio del algoritmo hay que crear una generación inicial a partir de la cual empezará a evolucionar el sistema. Esta
generación se crea a partir de números aleatorios generados en el RNG, por lo tanto el módulo debe indicar al RNG cuál es el
número máximo que admite para meterlo en memoria. En este caso, puesto que tenemos cinco bits, será 31.
El módulo debe llenar la memoria de individuos con números aleatorios, así que debe dar como salida la dirección de memoria
donde va a escribir, los datos que va meter en él y la señal de habilitación de escritura “we”.
sig
Número de RNG
Módulo Datos a RAM individuos
generación
inicial we
scg
Dirección a RAM individuos
clk
Max para RNG

Fig. 6: Entradas y salidas del módulo para la generación inicial


La señal del controlador general “scg” y la señal de reloj “clk” son señales de entrada que comparten todos los módulos, así
como la señal de salida “sig” que indica al controlador general que este controlador ha finalizado su ejecución.
El módulo tiene un contador de 0 a 5 para ir cambiando la dirección de memoria. Primero debe poner el contador a cero para
apuntar a la primera dirección, pasa directamente el número procedente del RNG a la salida de datos y da la señal de “we”.
Después de esto se incrementa el contador y hasta que llegue de nuevo a cero se repite la acción. En cuanto el contador haya
dado una vuelta completa se activa la señal “sig”.
D. Módulo para hacer la selección
El módulo de selección debe leer de la memoria de individuos y de la de fitness para hacer la selección de individuos en
función de su valor de fitness. Luego escribe en la memoria de individuos los individuos seleccionados. Además, como la
selección es semialeatoria, debe recibir también números aleatorios del RNG.
sig
Número de RNG
Número de RNG Reg. Acum Fitness
Individuo Datos a RAM individuos
Módulo
Fitness we
selección
<
scg Dirección a RAM individuos y fitness

clk Max para RNG


t

Fig. 7: Entradas y salidas del módulo de selección y el bloque de selección


Para hacer la probabilidad de selección proporcional a la función de fitness se utiliza un bloque formado por un registro, un
acumulador y un comparador. En el registro se mete un número aleatorio entre 0 y la suma de todos los fitness de la memoria. En
el acumulador se van metiendo los fitness uno por uno y el comparador devuelve 1 en el momento en que el valor del registro sea
menor que el del acumulador. En ese momento se selecciona el individuo al que corresponde el último valor de fitness
introducido en el acumulador.
El módulo de selección consta de tres partes. En la primera se hace la suma de todos los valores fitness de la memoria RAM de
fitness para pasar el resultado como valor límite al RNG. El método para recorrer la memoria es igual que en el controlador de
inicialización. En la segunda parte se hace la selección de individuos como se ha explicado anteriormente, pero repitiendo la
acción seis veces. Estos individuos seleccionados se guardan en una memoria interna del controlador, ya que no se puede ir
sobrescribiendo la memoria principal mientras se hace la selección. La tercera parte del controlador recorre las memorias interna
y principal para copiar lo que hay en la primera en la segunda.
E. Módulo de cruce
El módulo de cruce lee de la memoria de individuos, hace el cruce y luego vuelve a escribir en la misma memoria de la que ha
leído. El número de cruces, los individuos a cruzar y el punto donde se cruzan son aleatorios, así que el controlador también debe
coger los números que le proporciona el RNG en un rango que no será el mismo en todo el controlador, sino que variará.
sig
Número de RNG

Módulo
Datos a RAM individuos …An+1An An-1An-2An-3… Cruce …An+1AnBn-1Bn-2Bn-3…
Individuo
cruce we …Bn+1BnBn-1Bn-2Bn-3… …Bn+1BnAn-1An-2A n-3…

scg Dirección a RAM individuos


n
clk Max para RNG

Fig. 8: Entradas y salidas del módulo de cruce y el bloque de cruce

El módulo de cruce tiene un contador que cuenta hacia atrás y al que se le puede cargar un valor inicial. El valor que se le carga
proviene del RNG y es el número de cruces que se van a realizar. A partir de aquí se entra en un ciclo donde primero se
selecciona un individuo, luego el otro, después se hace el cruce, y, tras escribir los dos nuevos individuos en memoria, se
decrementa el contador. La elección de un individuo no es sencilla, ya que el módulo se ha de asegurar de que ese individuo no
haya sido cruzado anteriormente. Para ello se utilizan los flags de la memoria de individuos. En cada elección de un individuo,
después de coger una dirección aleatoria del RNG, el módulo entra en un ciclo donde incrementa en uno el valor de la dirección
de memoria en caso de que el flag de la dirección actual esté a 1. Después de elegir el primer individuo que se va a cruzar pone
su flag en memoria a 1 para que en la elección del segundo individuo no se pueda repetir el resultado. Una vez que se eligen los
dos individuos, se meten a un bloque junto con un número aleatorio. Lo único que hace este bloque es separar los buses en el
punto indicado por el número aleatorio y enlazar luego las partes correspondientes a individuos diferentes. Después de esto se
escriben los nuevos individuos en las direcciones de memoria correspondientes a los antiguos poniéndoles el flag a 1.
Cuando todos los cruces se hayan realizado el contador llega a 0. En ese momento el módulo pasa a otro ciclo donde recorre
toda la memoria de individuos poniendo los flags a 0.
F. Módulo de mutación
El módulo de mutación es muy parecido al de cruce, con las mismas entradas y salidas.
sig
Número de RNG

Módulo
Datos a RAM individuos …An+2An+1A nAn-1An-2… Mutación …An+2An+1Ā nAn-1An-2…
Individuo
mutación we

scg Dirección a RAM individuos n

clk Max para RNG

Fig. 9: Módulo de mutación y bloque de mutación

Este módulo también tiene un contador en el que se cargará el número de mutaciones que se van a realizar. La elección de
individuos se hace también de forma similar al controlador de cruce, utilizando los flags, con la única diferencia de que, como
sólo hay que elegir un individuo, el flag se pone 1 únicamente después de haberse realizado la mutación. Tras haberse hecho
todas las mutaciones, el módulo entra en un bloque para reponer los flags a 0 exactamente igual que el del cruce.
G. Controlador general
El controlador general es el que controla la ejecución global del algoritmo, por tanto el que envía todas las señales “scg” a los
otros controladores y el que recibe todas las señales “sig”. Además de eso debe controlar también los accesos a memoria de los
demás módulos, lo cual hace enviando señales de selección de entrada a los multiplexores que hay en los accesos a memoria. Por
otro lado este controlador debe controlar también la condición de parada, para lo cual él mismo debe acceder a las memorias a
comprobar las funciones de fitness y elegir el mejor individuo hasta el momento. A este controlador llega también la señal de
inicio del algoritmo y él mismo es el que debe dar la señal de finalización y la solución.
Sel mux dirección individuos
Señal de inicio
Sel mux individuo
Sig generación inicial
Sel mux dirección fitness
Sig fitness
Dirección a RAM individuos y fitness
Sig selección Controlador
Solución
Sig cruce
general Scg generación inicial
Sig mutación
Scg fitness

Individuo Scg selección

Fitness Scg cruce

Scg mutación
clk
Finalización

Fig. 10: Entradas y salidas del controlador general

Al recibir la señal de inicio el controlador general envía la señal de “scg” al controlador de generación inicial después de haber
actualizado convenientemente los selectores de los multiplexores. Cuando reciba la señal “sig” de este controlador se mete en un
bucle donde primero hace que se calculen todas las funciones de fitness. Después comprueba si se cumple la condición de
parada. Para ello tendrá dos registros, en uno de los cuales se guarda el mejor individuo hasta el momento y en el otro su función
de fitness, y un contador que cuenta de veinte hacia atrás. En cada ciclo se compara el valor de fitness almacenado con todos los
de la memoria y, si hay alguno mayor, se actualizan los registros y se pone el contador a veinte. Después de esto se continúa
enviando la señal de “scg” al controlador de selección, cuando éste acabe al de cruce y cuando éste acabe al de mutación.
Siempre entre un controlador y otro se actualizan los selectores de los multiplexores para hacer un direccionamiento apropiado a
memoria. Cuando se acabe con la mutación se vuelve al principio del ciclo, a calcular las funciones de fitness y la señal de
finalización y la solución se dan cuando el contador llega a cero.

V. EXPERIMENTOS Y SIMULACIONES
Para comprobar el buen funcionamiento del circuito diseñado se intentará resolver con él un problema concreto. Para eso se
implementa en hardware una función de fitness. Para simplificar lo máximo posible esta implementación, se elige un problema
muy sencillo: buscar un entero entre 0 y 31 tal que f(x) = x2 sea máxima.
Este módulo fitness recibe como entradas, además de las señales “scg” y “clk”, los individuos de la memoria. A partir de estos
individuos calcula el valor de fitness que les corresponde y lo escribe en la memoria de fitness, en la misma dirección de la que
ha cogido el individuo.
sig
Individuo Controlador
Datos a RAM fitness
scg fitness
we
clk
Dirección a RAM individuos y fitness

Fig. 11: Entradas y salidas del controlador de fitness


El módulo de fitness contiene una tabla con los cuadrados de todos los números de 0 a 31. De este modo, lo único que tiene
que hacer este controlador es recibir un individuo, consultar la tabla y escribir la función de fitness correspondiente en la
memoria de fitness. Debe hacer esto para todos los individuos en cada ciclo del algoritmo.
Tras diseñar esta función junto con todas las anteriores, se hace una simulación utilizando el software Quartus II para
comprobar su correcto funcionamiento. Lo que se muestra a continuación es el resultado de la simulación del circuito completo
diseñado para ejecutar un algoritmo genético:

Fig. 12: Simulación de un algoritmo genético implementado en hardware

De las formas de onda que aparecen en la figura, las más importantes son las tres inferiores. En ellas se ven la generación a la
que ha llegado el algoritmo, el individuo que tiene almacenado en cada momento en el registro destinado a la solución del
problema y la señal de finalización. Como se ve, el mejor individuo mejora a lo largo de las generaciones hasta llegar a 31, que
es la mejor solución posible al problema. Una vez que llega a esta solución, comprueba que no se puede conseguir una mejor
sacando hasta veinte generaciones más de individuos, y cuando lo haya comprobado da la señal de finalización.
Al implementarlo sobre la FPGA anteriormente descrita, el circuito diseñado tiene una frecuencia máxima de 32.55 MHz y
ocupa sobre el dispositivo el 13% de las puertas lógicas y menos del 1% de memoria.

VI. CONCLUSIONES
En este trabajo se ha hecho un estudio de los algoritmos genéticos básicos, comprobando su capacidad para buscar soluciones
a ciertos problemas. Se concluye que los algoritmos genéticos pueden facilitar mucho la solución de problemas complejos,
siendo especialmente eficaces en problemas de optimización. Otra de las conclusiones que se sacan de este trabajo es que para
aplicar algoritmos genéticos se requieren tres cosas: un espacio de búsqueda limitado, posibilidad de definir una función de
fitness y posibilidad de codificar las soluciones como cadenas de genes. También hay que resaltar que los algoritmos genéticos
no necesitan conocimientos específicos sobre el problema que intentan resolver.
En este trabajo también se ha desarrollado una implementación de un algoritmo genético en hardware digital sobre una FPGA.
Se ha comprobado que el lenguaje VHDL, utilizado para el diseño de algunos bloques, facilita mucho el diseño de circuitos
digitales. La herramienta de diseño Quartus II nos ha permitido realizar simulaciones temporales muy precisas. Por último, se ha
comprobado mediante simulación el correcto funcionamiento del circuito.

VII. BIBLIOGRAFÍA
[1]”Neuro-Fuzzy and Soft Computing”; J.-S. R. Jang, C.-T. Sun, E. Mizutani; Prentice-Hall; 1997
[2] www.altera.com
[3] www.soft-computing.de; “A definition of soft computing – adapted from L. A. Zadeh”
[4] www.geocities.com/rainforest; “Biografía de Charles Robert Darwin”
[5] fai.unne.edu.ar/biologia/evolucion; “Desarrollo de la teoría de la evolución
[6] www.optimatics.com; “A brief history of GA optimization”
[7] www.estec.esa.nl; “History of GA’s”
[8] “Análisis y diseño de circuitos lógicos digitales”; Victor P. Nelson, H. Troy Nagle, Bill D. Carroll, J. David Irwin; Primera Edición; Prentice-Hall
Hispanoamericana, S.A.; 1996
[9]“Modern control engineering. Third edition”; Katsuhiko Ogata; Prentice-Hall International; 1997

You might also like