You are on page 1of 9

Algoritmo de colonia de hormigas

La observacin de la naturaleza ha sido una de las principales fuentes de inspiracin para la


propuesta de nuevos paradigmas computacionales. As nacieron diversas tcnicas de
Inteligencia Artificial como: los Algoritmos Genticos (Genetic Algorithms), Templado
Simulado (Simulated Annealing), Redes Neuronales (Neural Networks), y entre estas
tcnicas, el sistema basado en Colonias de Hormigas (Ant Colony System)
Resulta realmente interesante analizar como las hormigas buscan su alimento y logran
establecer el camino ms corto para luego regresar a su nido. Para esto, al moverse una
hormiga, deposita una sustancia qumica denominada feromona como una seal odorfera
para que las dems puedan seguirla.
Las feromonas son un sistema indirecto de comunicacin qumica entre animales de una
misma especie, las cuales son recibidas en el sistema olfativo del animal receptor, quien
interpreta esas seales, jugando un papel importante en la organizacin y la supervivencia
de muchas especies
Al iniciar la bsqueda de alimento, una hormiga aislada se mueve a ciegas, es decir, sin
ninguna seal que pueda guiarla, pero las que le siguen deciden con buena probabilidad
seguir el camino con mayor cantidad de feromonas. Considere la siguiente figura en donde
se observa como las hormigas establecen el camino ms corto. En la figura (a) las hormigas
llegan a un punto donde tienen que decidir por uno de los caminos que se les presenta, lo
que resuelven de manera aleatoria. En consecuencia, la mitad de las hormigas de dirigirn
hacia un extremo y la otra mitad hacia el otro extremo, como ilustra la figura (b).
Como las hormigas se mueven aproximadamente a una velocidad constante, las que
eligieron el camino ms corto alcanzarn el otro extremo ms rpido que las que tomaron el
camino ms largo, quedando depositado mayor cantidad de feromona por unidad de
longitud, como ilustra la figura (c). La mayor densidad de feromonas depositadas en el
trayecto ms corto hace que ste sea ms deseable para las siguientes hormigas y por lo
tanto la mayora elige transitar por l. Considerando que la evaporacin de la sustancia
qumica hace que los caminos menos transitados sean cada vez menos deseables y la
realimentacin positiva en el camino con ms feromonas, resulta claro que al cabo de un
tiempo casi todas las hormigas transiten por el camino ms corto.

Ant System
Inspirados en el comportamiento de las hormigas, arriba descripto, Dorigo proponen tres
variantes del algoritmo Ant System (AS), que bsicamente difieren en el momento y la
modalidad en que actualizan la matriz de feromonas que sirve para guiar el movimiento de
los agentes computacionales llamados hormigas; estos algoritmos son:
Ant-density: con actualizacin constante de las feromonas por donde pasa una hormiga.
Ant-quantity: con actualizacin de feromonas inversamente proporcional a la distancia
entre 2 ciudades recorridas.
Ant-cycle: con actualizacin de feromonas inversamente proporcional al trayecto
completo, al terminar un recorrido.
Para el presente trabajo, se considera un conjunto de MAXC ciudades y se define b (t) i
como el nmero de hormigas en la ciudad i en el tiempo t, por consiguiente, el nmero total
de hormigas MAXH estar dado por:
MAXC

MAXH =

(t)

i=1

Para satisfacer la restriccin de que una hormiga visite todas las ciudades una sola vez, se
asocia a cada hormiga k una estructura de datos llamada lista tab, tabuk, que guarda las
ciudades ya visitadas por dicha hormiga. Una vez que todas las ciudades hayan sido
recorridas, el trayecto o tour (ciclo) es completado, la lista tab se vaca y nuevamente la
hormiga est libre para iniciar un nuevo tour. Se define como tabuk(s) al elemento s-esimo
de la lista tab de la hormiga k.
El punto de partida para la solucin del problema en cuestin, es la matriz de distancias D =
{di j -distancia entre la ciudad i y la ciudad j}, a partir de la cual se calcula la visibilidad Vij=
1/ dij. Por su parte, se denota como T = {Tij} a la matriz de feromonas a ser utilizada para
consolidar la informacin que va siendo recogida por las hormigas; en otras palabras, la
cantidad de feromona que se va almacenando entre cada par de ciudades i, j.
Durante la ejecucin del algoritmo Ant System, cada hormiga elige en forma probabilstica
la prxima ciudad a visitar, realizando un clculo de probabilidad que es funcin de la

distancia y la cantidad de feromonas depositada en el arco que une a las ciudades origendestino, esto es:

donde y son constantes que expresan la importancia relativa del sendero de feromonas y
la distancia entre las ciudades respectivamente. As, un alto valor de significa que el
sendero de feromonas es muy importante y que las hormigas tienden a elegir caminos por
los cuales otras hormigas ya pasaron. Si por el contrario, el valor de es muy alto, una
hormiga tiende a elegir la ciudad ms cercana. Se resalta aqu que cada hormiga debe
realizar un tour legal o sea, no puede viajar a una ciudad ya visitada con anterioridad hasta
que complete su tour.
En el instante t, las hormigas se mueven de una ciudad a la siguiente (movimiento llamado:
iteracin), en donde se encontrarn en el instante t+1. Lgicamente, al cabo de (MAXC
1) iteraciones, las hormigas han visitado la ltima ciudad y estn en condiciones de regresar
a su ciudad origen, posiblemente para actualizar la matriz de feromonas con la informacin
recogida en el tour completo.
La matriz Tij(t) que especifica la intensidad de las feromonas del arco (i, j) en t, se actualiza
segn la frmula:

Tij (t + 1) = Tij (t) + ATij t, t + 1

donde es el coeficiente de persistencia de las feromonas, de forma tal que (1-) representa
la evaporacin de la substancia entre t y t+1, mientras que la cantidad de feromona
depositada en un arco (i, j), est dada por:
MAXH

ATij(t,t+1)=

ATkij(t,t+1)

k=1

con ATkij (t, t+1) representando la cantidad de feromonas por unidad de longitud,
depositada en el arco (i,j) por la hormiga k-esima entre t y t+1. Cabe destacar aqu que la
principal diferencia entre las diversas variantes del algoritmo Ant System, est dada
justamente en la forma de calcular ATkij (t, t+1), conforme ser explicado en las prximas
subsecciones.
El proceso se repite iterativamente hasta que se cumpla algn criterio de parada. En este
trabajo, el proceso termina si el contador de tour alcanza un nmero mximo de ciclos
NCMAX (definido por el usuario) o todas las hormigas realizan el mismo tour. En este
ltimo caso, es evidente que las hormigas han dejado de buscar nuevas soluciones, lo que
constituye un criterio de convergencia del algoritmo (similar a la uniformizacin de la
poblacin de un algoritmo gentico).
Ant Quantity
En esta variante del algoritmo (ver Pseudocdigo 1), la hormiga k que viaja desde la ciudad
i a la ciudad j, deposita en el
trayecto una cantidad de feromonas inversamente proporcional a la distancia dij, esto es:

si la hormiga k esima camina por el arco ( , ) entre y + 1


de otra manera
donde Q1 es una constante.
Pseudocdigo 1: Ant-quantity secuencial.
t=0; /*t es contador de tiempo*/
nc=0; /*nc es el contador de ciclos*/
s=1; /*ndice de la lista tab*/
Para cada arco (i,j) inicializar T (t) c ij = ; /*c es una constante positiva pequea*/
Para cada arco (i,j) AT (t) ij = 0 ;
Colocar las MAXH hormigas en las MAXC ciudades;
Colocar la ciudad origen de la hormiga k-esima en tabuk(s)
DO WHILE (nc<=NCMAX y que todas las hormigas no realicen el mismo tour)
FOR t=1 hasta MAXC-1 /*se repite hasta que la lista tab este llena*/
s=s+1
FOR i=1 hasta i<=MAXC
FOR k=1 hasta k<=b(t)
Elegir la ciudad j a mover, con probabilidad pij(t) dado por la ecuacin (1);
Mover la hormiga k-esima a la ciudad;
Insertar la ciudad j en tabuk(s);
Calcular ATij (t, t +1) = AT ij (t, t+ 1) + Q 1 / d ij;
END FOR
END FOR
Para cada arco (i,j) calcular T (t t ) ij , + 1 segn la ecuacin (2);
END FOR
Guardar el camino ms corto;
nc=nc+1;
IF (nc<=NCMAX)
Vaciar todas las listas tab;
Para cada arco (i,j) AT ij(t + 1) = 0 ;
s=1;
Colocar la ciudad origen de la hormiga k-esima en tabuk(s);
END IF
END WHILE
Imprimir el mejor camino;

in-silico
Proyectos para el Aprendizaje de Tcnicas de
Inteligencia Artificial

Project Home Downloads Wiki Issues Source


Checkout Browse Changes
Source path: svn/
trunk/ Proyectos/ src/ genericos/ hormigas/ Hormigas.java
1
2
3
4
5
6
7
8
9

package genericos.hormigas;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Scanner;

r141

r16
5

r672

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

public class Hormigas


{
Method metodoCambio;
/**
* Funcin que soluciona un problema utilizando el algoritmo de colonia de
hormigas
* @param matrizCostos: Matriz de adyacencia con los costos entre los nodos
* @param modelo: Modelo establecido para seleccionar los vecinos y los
parametros
* @return solucionOptima: Mejor solucion encontrada
*/
public ArrayList <Integer> solucionar(double [][] matrizCostos,
ModeloHormigas modelo)
{
double[][] feromonas = new double[matrizCostos.length]
[matrizCostos.length];
double inicializacion = ((double)modelo.darM()) / ((double)(modelo.darQ()
* modelo.darInicial()));
for(int i = 0; i < matrizCostos.length; i++)
for(int j = 0; j < matrizCostos.length; j++)
feromonas[i][j] = inicializacion;
int iteracion = 0;
double pesoOptimo = modelo.darInicial();
ArrayList <Integer> solucionOptima = null;
while(iteracion++ < modelo.darNumeroIteraciones())
{
System.gc();
int hormiga = 0;
@SuppressWarnings("unchecked")
ArrayList <Integer> [] hormigas = new ArrayList [modelo.darM()];
while(hormiga++ < modelo.darM())
{
ArrayList <Integer> candidatas = new ArrayList <Integer> ();
for(int i = 1; i < matrizCostos.length; i++)
candidatas.add(i);
int actual = 0;
ArrayList <Integer> rutaActual = new ArrayList <Integer> ();
rutaActual.add(actual);
while(!candidatas.isEmpty())
{
double [] probabilidades = new double[candidatas.size()];

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

double sumatoria = 0;
for(int j = 0; j < candidatas.size(); j++)
{
probabilidades[j] = Math.pow(feromonas[actual]
[candidatas.get(j)], modelo.darA()) * Math.pow(1 / matrizCostos[actual]
[candidatas.get(j)], modelo.darB());
sumatoria += probabilidades[j];
}
for(int j = 0; j < candidatas.size(); j++)
{
probabilidades[j] /= sumatoria;
}
int escogido = modelo.escoger(probabilidades);
rutaActual.add(candidatas.get(escogido));
for(int j = 0; j < rutaActual.size() - 1; j++)
{
feromonas[rutaActual.get(j)][rutaActual.get(j + 1)] =
feromonas[rutaActual.get(j)][rutaActual.get(j + 1)] * (1 - modelo.darP());
}
actual = candidatas.get(escogido);
candidatas.remove(escogido);
}
rutaActual.add(0);
hormigas[hormiga - 1] = rutaActual;
}
for(int i = 0; i < matrizCostos.length; i++)
for(int j = 0; j < matrizCostos.length; j++)
feromonas[i][j] = feromonas[i][j] * (1 - modelo.darE());
double mejorPeso = Double.POSITIVE_INFINITY;
ArrayList <Integer> mejorSolucion = null;
for(int i = 0; i < hormigas.length; i++)
{
double peso = 0;
for(int j = 0; j < hormigas[i].size() - 1; j++)
{
peso += matrizCostos[hormigas[i].get(j)][hormigas[i].get(j +
1)];
}
for(int j = 0; j < hormigas[i].size() - 1; j++)
{
feromonas[hormigas[i].get(j)][hormigas[i].get(j + 1)] += 1 /
peso;

94
95
96
97
98
99
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

}
if(peso < mejorPeso)
{
mejorPeso = peso;
mejorSolucion = hormigas[i];
}
}
if(mejorPeso < pesoOptimo)
{
pesoOptimo = mejorPeso;
modelo.establecerMejorActual(mejorSolucion, mejorPeso);
solucionOptima = mejorSolucion;
double init = modelo.darM() / (modelo.darQ() * mejorPeso);
for(int i = 0; i < matrizCostos.length; i++)
for(int j = 0; j < matrizCostos.length; j++)
feromonas[i][j] = init;
}
}
return solucionOptima;
}
public static double [][] leer(String nombreArchivo)
{
Scanner scanner;
double dato;
try {
scanner = new Scanner(new File(nombreArchivo));
} catch (FileNotFoundException e) {
scanner = new Scanner("");
e.printStackTrace();
}
int tam = scanner.nextInt();
double [][] datosPrueba = new double[tam][tam];
for(int i = 0; i < datosPrueba.length; i++)
for(int j = 0; j < datosPrueba.length; j++){
dato = scanner.nextDouble();
if (dato < 0)
datosPrueba[i][j] = Double.POSITIVE_INFINITY;
else
datosPrueba[i][j] = dato;
}

return datosPrueba;
}
}

You might also like