Algoritmo Genético para Resolver El TSP

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 18

05 de noviembre de 2015

Algoritmo gentico
TSP en c++

para

Inteligencia Artificial
Julcarima Calle, Josu.

Informe Algoritmo Gentico

Tabla de contenido
PRESENTACIN ............................................................................................................ 2
Resumen...................................................................................................................... 2
Introduccin ................................................................................................................ 2
EL PROBLEMA .............................................................................................................. 3
Especificacin del problema ....................................................................................... 3
SOLUCIN AL PROBLEMA .......................................................................................... 4
Especificacin del conocimiento declarativo ............................................................. 4
Estrategia de la solucin ............................................................................................. 4
Plantear el conocimiento procedural.......................................................................... 5
Descripcin del conocimiento procedural .................................................................. 5
RESULTADOS ................................................................................................................ 6
Resultados obtenidos .................................................................................................. 6
Conclusiones ............................................................................................................... 6
REFERENCIAS ............................................................................................................... 7
CDIGO FUENTE .......................................................................................................... 8

Inteligencia Artificial

PRESENTACIN
Resumen
El presente informe tiene como objetivo especificar el proceso de solucin llevado a cabo para resolver
el problema del agente viajero por medio de un algoritmo gentico e implementarlo en C++.

Introduccin
El problema del agente viajero es un problema NP-Hard de optimizacin combinatoria, el tiempo
requerido para resolverlo es super-polinomial. Resolver el peor caso para un algoritmo determinstico
tarda en proporcin exponencial a la cantidad ciudades (un parmetro de la entrada que se explica ms
adelante).
El problema fue formulado matemticamente en el 1800 por el matemtico irlands WR Hamilton y por
el matemtico britnico Thomas Kirkman.

Informe Algoritmo Gentico

EL PROBLEMA
Especificacin del problema
El problema del agente viajero en ciencias de la computacin puede ser planteado de la siguiente
manera:1
Dada una lista de las ciudades y las distancias entre cada par de ciudades, cul es el camino
ms corto que visita cada ciudad exactamente una vez y vuelve a la ciudad de origen?
En trminos de teora de grafos se puede plantear como sigue:
Dado una grafo ponderado completo (donde los vrtices representan las ciudades, las aristas
representan los caminos y los pesos son el costo o las distancias de estos caminos), encontrar
un ciclo de Hamilton con menor peso.
Sin embargo pueden existir variaciones al problema como por ejemplo que el grafo sea dirigido que el
grafo no sea necesariamente completo, este ltimo caso se puede incluir en el planteamiento original
considerando que las aristas que faltan tienen peso infinito.
En el caso del presente informe se resolver el problema de forma no determinstica tomando en cuenta
que los puntos o ciudades pertenecen a un espacio bidimensional y el peso de las aristas es la distancia
pitagrica (norma 2) entre los puntos.

(Wikipedia)
3

Inteligencia Artificial

SOLUCIN AL PROBLEMA
Especificacin del conocimiento declarativo
Respecto a la declaracin de variables de entrada se tiene:

Un conjunto de puntos todos en un espacio bidimensional.

Respecto a las variables de salida del algoritmo se tienen:

Una permutacin del conjunto de puntos de la entrada denotando el camino hamiltoniano


ptimo.

Estrategia de la solucin
Las soluciones existentes en la literatura son muy amplias y se pueden dividir en 2:
1.

Determinsticas. Es decir para una entrada dada siempre obtienen la misma salida.
o Heursticas
o Exactas.- Este tipo de algoritmos son los nicos que aseguran obtener la solucin
ptima
2. No determinsticas (aleatorizados).- Ntese que estos algoritmos pueden utilizar
aproximaciones heursticas en su procedimiento.
Para el desarrollo del presente trabajo se escogi la estrategia no determinstica del algoritmo gentico.

Informe Algoritmo Gentico

Plantear el conocimiento procedural


El algoritmo planteado es a grandes rasgos:

Generacin de la
poblacin inicial

Evolucin de la
poblacin hasta una
condicin de
parada predefinida

Obtencin del
mejor individuo de
la poblacin final
Descripcin del conocimiento procedural
Cada uno de los pasos anteriores se especifica como sigue:
1.

Generacin de la poblacin inicial


a. De manera aleatoria se generan los individuos iniciales barajando la permutacin
(identificador de un camino/ciclo Hamiltoniano).
2. Evolucin de la poblacin hasta una condicin de parada predefinida. Cada evolucin a la
siguiente generacin consta de los siguientes pasos.
a. Pase de una lite a la siguiente generacin (los ELITE mejores siempre pasan a la
siguiente generacin).
b. Cruce. Se cruzan los individuos donde la probabilidad de cada participante de un
apareamiento es proporcional a su fitness (funcin de aptitud, la cual en el problema
actual es el recproco de la distancia).
c. Mutacin. Despus de cada cruce se realiza una mutacin en los hijos dependiendo de
la probabilidad de mutacin.
3. Obtencin del mejor individuo de la poblacin final. La condicin de parada establecida en este
caso es el nmero de generaciones o poblaciones (NUMBER_OF_GENERATIONS)

Inteligencia Artificial

RESULTADOS
Resultados obtenidos
Se prob el algoritmo para el caso de xqf1312 (la entrada posee 131 nodos y se encuentra en
http://www.math.uwaterloo.ca/tsp/vlsi/xqf131.tsp) con los siguientes parmetros:

int TOTAL_POPULATION = 5000;


double MUTATION_PROBABILITY = 0.07;
int NUMBER_OF_GENERATIONS = 10000;
int ELITE = 3;

Obteniendo los siguientes resultados:

Mejores distancias encontradas por generacin (poblacin)

Generation
0
1000
2000
3000
4000
5000
6000
7000
8000
9000
9999

Best distance
found
3891.81
2827.73
2623.44
2466.63
2332.91
2185.81
2141.97
2059.38
1991.88
1922.1
1890.8

Conclusiones
Se concluye que en la mayora de los casos a mayor tiempo gastado en buscar una solucin se obtiene
una solucin ms ptima al final.
Para el caso propuesto la solucin ptima tiene una distancia de 564 segn 3, mientras el programa
diseado con los parmetros dados solo logr encontrar una solucin con distancia de 1890. Esto
comprueba que la probabilidad de necesitar un tiempo muy alto para hallar la solucin ptima es muy
alta.

(Math U. Waterloo)
(xqf131 TSP Problem Optimal Tour)
6
2
3

Informe Algoritmo Gentico

REFERENCIAS
Math U. Waterloo. (s.f.). Obtenido de http://www.math.uwaterloo.ca/tsp/vlsi/index.html
Math U. Waterloo. (s.f.). Obtenido de http://www.math.uwaterloo.ca/tsp/vlsi/xqf131.tour
Wikipedia. (s.f.). Obtenido de https://en.wikipedia.org/wiki/Travelling_salesman_problem

Inteligencia Artificial

CDIGO FUENTE
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstring>
#include <cmath>
#include <climits>
using namespace std;

/** Parameters **/


int TOTAL_POPULATION = 500;
double MUTATION_PROBABILITY = 0.07;
int NUMBER_OF_GENERATIONS = 1000;
int ELITE = 1; // the best ones which always pass to the next generation

struct Point{
double x, y;
Point(){}
Point(double _x, double _y): x(_x), y(_y) {}
double dist(Point p){
return hypot(p.x - x, p.y - y );
}
};

struct Population{
private:

Informe Algoritmo Gentico

vector<Point> &points;
vector<vector<int> > routes;
vector<double> prob;
int n; // size of the route

public:
/** Freeing memory **/
~Population(){
routes.clear();
prob.clear();
}

/** Constructors **/


Population(vector<Point> &_points): points(_points){}
Population(int
points(_points){}

routeSize,

Population(int
points(_points) {

popuSize,

vector<Point>

int

routeSize,

&_points):

n(routeSize),

vector<Point>

&_points):

n = routeSize;
routes.clear();
vector<int> ind; // indexes to shuffle
for(int i = 0; i < n; i++) ind.push_back(i);

// random init
for(int i = 0; i < popuSize; i++){
random_shuffle ( ind.begin(), ind.end() );
vector<int> newRoute = ind;
routes.push_back( newRoute );
}
}
9

Inteligencia Artificial

vector<vector<int> > getRoutes() const{


return routes;
}

int getRouteSize() const{


return n;
}

vector<double> getProb() const{


return prob;
}

void operator=(const Population& pob){


routes = pob.getRoutes();
n = pob.getRouteSize();
prob = pob.getProb();
}

// OX1 type crossover


void crossover(vector<int> &p1, vector<int> &p2,
vector<int> &h1, vector<int> &h2
){
h1.clear();
h2.clear();
int a = rand()%(n-1), b = rand()%(n-1) ;
if( a > b ) swap(a,b);

bool oc1[n];
bool oc2[n];
10

Informe Algoritmo Gentico

memset(oc1, 0, sizeof(oc1));
memset(oc2, 0, sizeof(oc2));

for(int i = 0; i < n; i++){


h1.push_back( -1 );
h2.push_back( -1 );
}

for(int i = a+1; i <= b; i++){


h1[i] = p1[i];
oc1[ p1[i] ] = 1;
h2[i] = p2[i];
oc2[ p2[i] ] = 1;
}
int i1 = (b+1)%n, i2 = (b+1)%n;
for(int i = 0; i < n; i++){
if( !oc1[ p2[ (b+1+i)%n ] ] ){
h1[i1] = p2[ (b+1+i)%n ];
i1 = (i1+1)%n;
}
if( !oc2[ p1[ (b+1+i)%n ] ] ){
h2[i2] = p1[ (b+1+i)%n ];
i2 = (i2+1)%n;
}
}
/*
cout << "indices: " << a << " " << b<<endl;
for(int i = 0; i < n; i++){
cout << h1[i] << "\t" << h2[i] << "\tp:\t"<< p1[i] <<"\t"<<
p2[i]<<endl;
11

Inteligencia Artificial

}*/

/** mutation **/


double r;
r = (double)rand()/(double)RAND_MAX;
if( r <= MUTATION_PROBABILITY ){
a = rand()%(n);
b = rand()%(n);
swap(h1[a], h1[b]);
}

r = (double)rand()/(double)RAND_MAX;
if( r <= MUTATION_PROBABILITY ){
a = rand()%(n);
b = rand()%(n);
swap(h2[a], h2[b]);
}
}

Population evolve(){
Population pSiguiente = Population(n, points);
order();
int cant;
for(cant = 0; cant < ELITE && cant < (int)routes.size(); cant++){
vector<int> nRuta = routes[cant];
pSiguiente.addRoute( nRuta );
}

/** Fitness proportionate selection or roulette-wheel selection **/


for(; ELITE < (int)routes.size() ;){
12

Informe Algoritmo Gentico

vector<int> h1,h2;
double r;

r = (double)rand()/(double)RAND_MAX;
int
prob.begin();

ind1

lower_bound(

prob.begin(),

prob.end(),

r)

prob.end(),

r)

int ind2 = ind1;


while( ind2 == ind1){
r = (double)rand()/(double)RAND_MAX;
ind2

lower_bound(

prob.begin(),

prob.begin();
}

//cout <<"a cruzar: " << ind1<<" " << ind2 << endl;

crossover( routes[ind1], routes[ind2], h1, h2 );


pSiguiente.addRoute( h1 );
if( pSiguiente.getSize() == (int)routes.size() ) break;
pSiguiente.addRoute( h2 );
if( pSiguiente.getSize() == (int)routes.size() ) break;
}
return pSiguiente;
}

/**

This is the total distance of the i-th chromosome **/

double getNoFitness(int i){


if( i >= 0 && i < routes.size() ){
double noFitness = 0;
for(int j = 0; j < n; j++){

13

Inteligencia Artificial

noFitness
points[routes[i][(j+1)%n] ] )

+=

points[routes[i][j]].dist(

}
return noFitness;
}else return -1.0;
}

void order(){
vector<pair<double,int> > ind;
double totalFitness = 0;
for(int i = 0; i < (int)routes.size(); i++){
double noFitness = getNoFitness(i);
double fitness = 1.0/(double)noFitness;
totalFitness += fitness;
ind.push_back( make_pair(-fitness, i) );
}
sort( ind.begin(), ind.end() );
vector<vector<int> > rutas2;
double ac = 0;
prob.clear();
for(int i = 0; i < (int)routes.size(); i++){
rutas2.push_back(routes[ ind[i].second ]);
ac+= -ind[i].first;
prob.push_back( ac/totalFitness );
}
routes = rutas2;

void addRoute(vector<int> &nRuta){


14

Informe Algoritmo Gentico

routes.push_back(nRuta);
}

int getSize(){
return (int)routes.size();
}

/** You have to order before calling to this method **/


vector<Point> getFirst(){
vector<Point> res;
for(int i = 0; i < n; i++) res.push_back( points[ routes[0][i] ]);
return res;
}

vector<int> getFirstIndexes(){
return routes[0];
}

Point getPoint(int i){


return points[i];
}

};

/** Genetic algorithm **/


vector<Point> ga_tsp(vector<Point> &points){
int n = (int)points.size();

Population pActual (TOTAL_POPULATION, n, points);

15

Inteligencia Artificial

pActual.order();
vector<Point> result = pActual.getFirst();
vector<int> rIndexes = pActual.getFirstIndexes();

cout << "Route/cycle more with more fitness on initial population with
distance:"<< pActual.getNoFitness(0)<< endl;
for(int i = 0; i < result.size(); i++) {
cout<< rIndexes[i] << " : "<< result[i].x << " " << result[i].y <<
endl;
}

cout << "\nGeneration" << "\t"<<"distance found" << endl;

for(int iter = 0; iter < NUMBER_OF_GENERATIONS; iter++){


Population pNext = pActual.evolve();

pActual = pNext;

pActual.order();
if(iter%100 == 0 || iter == NUMBER_OF_GENERATIONS - 1) cout <<iter
<<"\t"<< pActual.getNoFitness(0) << endl;
}
pActual.order();
return pActual.getFirst();
}

int main(){

ios_base::sync_with_stdio(true);

srand ( unsigned ( time(0) ) );


16

Informe Algoritmo Gentico

vector<Point> points;

/** Reading input **/


double x, y;
while( cin >>x >> y ){
points.push_back( Point(x,y) );
}
vector<Point> result = ga_tsp( points );

cout << "\nRoute/cycle more with more fitness found:"<< endl;


for(int i = 0; i < result.size(); i++) {
cout<< result[i].x << " " << result[i].y << endl;
}
}

17

También podría gustarte