Informe Algoritmo Genético para el TSP

21
05 de noviembre de 2015 Algoritmo genético para TSP en c++ Inteligencia Artificial Julcarima Calle, Josué.

description

Algoritmo genético en c++ para el problema del agente viajero usando un cruce de tipo OX1, elitismo y selección proporcional a la aptitud.

Transcript of Informe Algoritmo Genético para el TSP

Page 1: Informe Algoritmo Genético para el TSP

05 de noviembre de 2015

Algoritmo genético para TSP en c++ Inteligencia Artificial

Julcarima Calle, Josué.

Page 2: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

Tabla de contenido

PRESENTACIÓN.........................................................................................2

Resumen...................................................................................................2

Introducción.............................................................................................2

EL PROBLEMA............................................................................................3

Especificación del problema....................................................................3

SOLUCIÓN AL PROBLEMA........................................................................4

Especificación del conocimiento declarativo...........................................4

Estrategia de la solución..........................................................................4

Plantear el conocimiento procedural.......................................................5

Descripción del conocimiento procedural................................................5

RESULTADOS.............................................................................................6

Resultados obtenidos...............................................................................6

Conclusiones............................................................................................6

REFERENCIAS............................................................................................7

CÓDIGO FUENTE.......................................................................................8

1

Page 3: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

PRESENTACIÓN

Resumen

El presente informe tiene como objetivo especificar el proceso de solución llevado a cabo para resolver el problema del agente viajero por medio de un algoritmo genético e implementarlo en C++.

Introducción

El problema del agente viajero es un problema NP-Hard de optimización combinatoria, el tiempo requerido para resolverlo es super-polinomial. Resolver el peor caso para un algoritmo determinístico tarda en proporción exponencial a la cantidad ciudades (un parámetro de la entrada que se explica más adelante).

El problema fue formulado matemáticamente en el 1800 por el matemático irlandés WR Hamilton y por el matemático británico Thomas Kirkman.

2

Page 4: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

EL PROBLEMA

Especificación del problema

El problema del agente viajero en ciencias de la computación puede ser planteado de la siguiente manera:1

Dada una lista de las ciudades y las distancias entre cada par de ciudades, ¿cuál es el camino más corto que visita cada ciudad exactamente una vez y vuelve a la ciudad de origen?

En términos de teoría de grafos se puede plantear como sigue:

Dado una grafo ponderado completo (donde los vértices 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 determinística tomando en cuenta que los puntos o ciudades pertenecen a un espacio bidimensional y el peso de las aristas es la distancia pitagórica (norma 2) entre los puntos.

1 (Wikipedia)3

Page 5: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

SOLUCIÓN AL PROBLEMA

Especificación del conocimiento declarativo

Respecto a la declaración 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 permutación del conjunto de puntos de la entrada denotando el camino hamiltoniano óptimo.

Estrategia de la solución

Las soluciones existentes en la literatura son muy amplias y se pueden dividir en 2:

1. Determinísticas. – Es decir para una entrada dada siempre obtienen la misma salida.

o Heurísticaso Exactas.- Este tipo de algoritmos son los únicos que aseguran obtener la

solución óptima2. No determinísticas (aleatorizados).- Nótese que estos algoritmos pueden utilizar

aproximaciones heurísticas en su procedimiento.

Para el desarrollo del presente trabajo se escogió la estrategia no determinística del algoritmo genético.

4

Page 6: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

Plantear el conocimiento procedural

El algoritmo planteado es a grandes rasgos:

Descripción del conocimiento procedural

Cada uno de los pasos anteriores se especifica como sigue:

1. Generación de la población iniciala. De manera aleatoria se generan los individuos iniciales barajando la

permutación (identificador de un camino/ciclo Hamiltoniano).2. Evolución de la población hasta una condición de parada predefinida. Cada

evolución a la siguiente generación consta de los siguientes pasos.a. Pase de una élite a la siguiente generación (los ELITE mejores siempre

pasan a la siguiente generación).b. Cruce. Se cruzan los individuos donde la probabilidad de cada

participante de un apareamiento es proporcional a su fitness (función de aptitud, la cual en el problema actual es el recíproco de la distancia).

c. Mutación. Después de cada cruce se realiza una mutación en los hijos dependiendo de la probabilidad de mutación.

3. Obtención del mejor individuo de la población final. La condición de parada establecida en este caso es el número de generaciones o poblaciones (NUMBER_OF_GENERATIONS)

5

Generación de la población inicial

Evolución de la población hasta

una condición de parada

predefinida

Obtención del mejor individuo de la población

final

Page 7: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

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 parámetros:

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 generación (población)

Generation Best distance found

0 3891.811000 2827.732000 2623.443000 2466.634000 2332.915000 2185.816000 2141.977000 2059.388000 1991.889000 1922.19999 1890.8

Conclusiones

Se concluye que en la mayoría de los casos a mayor tiempo gastado en buscar una solución se obtiene una solución más óptima al final.

Para el caso propuesto la solución óptima tiene una distancia de 564 según 3, mientras el programa diseñado con los parámetros dados solo logró encontrar una solución con distancia de 1890. Esto comprueba que la probabilidad de necesitar un tiempo muy alto para hallar la solución óptima es muy alta.

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

6

Page 8: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

REFERENCIASMath 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

7

Page 9: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

CÓDIGO 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:

8

Page 10: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

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 routeSize, vector<Point> &_points): n(routeSize), points(_points){}

Population(int popuSize, int routeSize, vector<Point> &_points): points(_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

Page 11: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

}

}

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);

10

Page 12: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

bool oc1[n];

bool oc2[n];

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++){11

Page 13: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

cout << h1[i] << "\t" << h2[i] << "\tp:\t"<< p1[i] <<"\t"<< p2[i]<<endl;

}*/

/** 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 );

}

12

Page 14: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

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

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

vector<int> h1,h2;

double r;

r = (double)rand()/(double)RAND_MAX;

int ind1 = lower_bound( prob.begin(), prob.end(), r) - prob.begin();

int ind2 = ind1;

while( ind2 == ind1){

r = (double)rand()/(double)RAND_MAX;

ind2 = lower_bound( prob.begin(), prob.end(), r) - 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() ){

13

Page 15: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

double noFitness = 0;

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

noFitness += points[routes[i][j]].dist( points[routes[i][(j+1)%n] ] ) ;

}

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;

}

14

Page 16: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

void addRoute(vector<int> &nRuta){

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();

15

Page 17: Informe Algoritmo Genético para el TSP

Informe Algoritmo Genético

Population pActual (TOTAL_POPULATION, n, points);

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);

16

Page 18: Informe Algoritmo Genético para el TSP

Inteligencia Artificial

srand ( unsigned ( time(0) ) );

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