From 976f5eead93ebdb4e529d424c0ed5527425c0809 Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Sun, 10 Apr 2022 22:40:23 -0500 Subject: Add test/GA.ipynb --- test/.ipynb_checkpoints/GA-checkpoint.ipynb | 112 ++++++++++++++++++++++++++++ test/GA.ipynb | 112 ++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 test/.ipynb_checkpoints/GA-checkpoint.ipynb create mode 100644 test/GA.ipynb (limited to 'test') diff --git a/test/.ipynb_checkpoints/GA-checkpoint.ipynb b/test/.ipynb_checkpoints/GA-checkpoint.ipynb new file mode 100644 index 0000000..bab966d --- /dev/null +++ b/test/.ipynb_checkpoints/GA-checkpoint.ipynb @@ -0,0 +1,112 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2fd45b3a-9a24-4782-812c-08223edb750e", + "metadata": {}, + "source": [ + "# Prueba del algoritmo genetico" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6b4829a-9001-410c-b20c-01c65c777d8a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "511ff788-0d1a-4ac7-9575-de182d236574", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "078280b5-70ef-4691-8798-a686d85d188c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3ad92de-b2ed-4f21-a696-1fa2981f89dc", + "metadata": {}, + "outputs": [], + "source": [ + "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", + " \"Algoritmo Genetico \"\n", + " \n", + " popsize = len(population)\n", + " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness = [population[ibest[0]].fitness]\n", + " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", + " \n", + " for g in range(ngen): # Por cada generacion\n", + " \n", + " ## Selecciona las parejas de padres para cruzamiento \n", + " mating_pool = []\n", + " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", + " \n", + " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", + " offspring_population = []\n", + " for i in range(len(mating_pool)): \n", + " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", + " offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", + "\n", + " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", + " for i in range(len(offspring_population)):\n", + " if random.uniform(0, 1) < pmut: \n", + " offspring_population[i] = offspring_population[i].mutate_position()\n", + " \n", + " ## Evalua la poblacion descendencia\n", + " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", + " \n", + " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", + " population = select_survivors(population, offspring_population, popsize)\n", + "\n", + " ## Almacena la historia del fitness del mejor individuo\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness.append(population[ibest[0]].fitness)\n", + " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", + " \n", + " return population[ibest[0]], bestfitness " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/test/GA.ipynb b/test/GA.ipynb new file mode 100644 index 0000000..bab966d --- /dev/null +++ b/test/GA.ipynb @@ -0,0 +1,112 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2fd45b3a-9a24-4782-812c-08223edb750e", + "metadata": {}, + "source": [ + "# Prueba del algoritmo genetico" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6b4829a-9001-410c-b20c-01c65c777d8a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "511ff788-0d1a-4ac7-9575-de182d236574", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "078280b5-70ef-4691-8798-a686d85d188c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3ad92de-b2ed-4f21-a696-1fa2981f89dc", + "metadata": {}, + "outputs": [], + "source": [ + "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", + " \"Algoritmo Genetico \"\n", + " \n", + " popsize = len(population)\n", + " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness = [population[ibest[0]].fitness]\n", + " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", + " \n", + " for g in range(ngen): # Por cada generacion\n", + " \n", + " ## Selecciona las parejas de padres para cruzamiento \n", + " mating_pool = []\n", + " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", + " \n", + " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", + " offspring_population = []\n", + " for i in range(len(mating_pool)): \n", + " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", + " offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", + "\n", + " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", + " for i in range(len(offspring_population)):\n", + " if random.uniform(0, 1) < pmut: \n", + " offspring_population[i] = offspring_population[i].mutate_position()\n", + " \n", + " ## Evalua la poblacion descendencia\n", + " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", + " \n", + " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", + " population = select_survivors(population, offspring_population, popsize)\n", + "\n", + " ## Almacena la historia del fitness del mejor individuo\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness.append(population[ibest[0]].fitness)\n", + " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", + " \n", + " return population[ibest[0]], bestfitness " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- cgit v1.2.3 From 624334fec2d4c7c9811f75d05892439e1b1af07a Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Sun, 10 Apr 2022 22:44:18 -0500 Subject: Add test/ and .gitignore --- test/GA.ipynb | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 test/GA.ipynb (limited to 'test') diff --git a/test/GA.ipynb b/test/GA.ipynb new file mode 100644 index 0000000..bab966d --- /dev/null +++ b/test/GA.ipynb @@ -0,0 +1,112 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "2fd45b3a-9a24-4782-812c-08223edb750e", + "metadata": {}, + "source": [ + "# Prueba del algoritmo genetico" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6b4829a-9001-410c-b20c-01c65c777d8a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "511ff788-0d1a-4ac7-9575-de182d236574", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "078280b5-70ef-4691-8798-a686d85d188c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3ad92de-b2ed-4f21-a696-1fa2981f89dc", + "metadata": {}, + "outputs": [], + "source": [ + "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", + " \"Algoritmo Genetico \"\n", + " \n", + " popsize = len(population)\n", + " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness = [population[ibest[0]].fitness]\n", + " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", + " \n", + " for g in range(ngen): # Por cada generacion\n", + " \n", + " ## Selecciona las parejas de padres para cruzamiento \n", + " mating_pool = []\n", + " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", + " \n", + " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", + " offspring_population = []\n", + " for i in range(len(mating_pool)): \n", + " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", + " offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", + "\n", + " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", + " for i in range(len(offspring_population)):\n", + " if random.uniform(0, 1) < pmut: \n", + " offspring_population[i] = offspring_population[i].mutate_position()\n", + " \n", + " ## Evalua la poblacion descendencia\n", + " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", + " \n", + " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", + " population = select_survivors(population, offspring_population, popsize)\n", + "\n", + " ## Almacena la historia del fitness del mejor individuo\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness.append(population[ibest[0]].fitness)\n", + " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", + " \n", + " return population[ibest[0]], bestfitness " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- cgit v1.2.3 From 212409071524b431d1e8f29d7d3f0e8ef291dd4c Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Tue, 19 Apr 2022 22:36:54 -0500 Subject: Add VRPTW_GA.ipynb + test/data dir --- test/GA.ipynb | 257 ++++++++++++++++++- test/VRPTW_GA.ipynb | 724 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/data/RC101.csv | 102 ++++++++ 3 files changed, 1079 insertions(+), 4 deletions(-) create mode 100644 test/VRPTW_GA.ipynb create mode 100644 test/data/RC101.csv (limited to 'test') diff --git a/test/GA.ipynb b/test/GA.ipynb index bab966d..9d73164 100644 --- a/test/GA.ipynb +++ b/test/GA.ipynb @@ -10,16 +10,217 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, + "id": "45972b70-b2a6-48f2-aafa-9f660548079a", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import random" + ] + }, + { + "cell_type": "markdown", + "id": "34eab22f-a400-4a14-9ac4-047d87dff69f", + "metadata": {}, + "source": [ + "Data" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "id": "a5736dba-4c38-4b7f-9a1a-963bdb006236", + "metadata": {}, + "outputs": [], + "source": [ + "class Ciudad:\n", + " regiones = {\n", + " 'costa': {\n", + " 'plazoentrega': 1\n", + " },\n", + " 'sierra': {\n", + " 'plazoentrega': 2\n", + " },\n", + " 'selva': {\n", + " 'plazoentrega': 3\n", + " }\n", + " }\n", + " def __init__(self, nombre, region, longitud, latitud):\n", + " self.nombre = nombre\n", + " self.region = region\n", + " self.x = longitud\n", + " self.y = latitud" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "id": "8ee9610f-d128-4d1b-9458-ca9048073f20", + "metadata": {}, + "outputs": [], + "source": [ + "class Road_network:\n", + " def __init__(self, cities, distances):\n", + " \"\"\"Grafo completo del pais\n", + " \n", + " Params\n", + " ------\n", + " \n", + " cities: list\n", + " Lista de objetos Ciudad\n", + " \n", + " routes: dict\n", + " (Aun no se como implementar esto)\n", + " \"\"\"\n", + " \n", + " self.cities = cities\n", + " self.routes = {}" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "id": "7dd72c93-acba-46f9-ac99-8c3d1a8cfa67", + "metadata": {}, + "outputs": [], + "source": [ + "class Vehiculo:\n", + " tipos = {\n", + " 1: {\n", + " 'cargamax': 50\n", + " },\n", + " 2: {\n", + " 'cargamax': 100\n", + " },\n", + " 3: {\n", + " 'cargamax': 200\n", + " }\n", + " }\n", + " \n", + " def __init__(self):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "id": "474a3596-f75d-411e-bf4c-20b8b8259434", + "metadata": {}, + "outputs": [], + "source": [ + "class Pedido:\n", + " def __init__(self, cliente, cantidad):\n", + " self.cliente = cliente\n", + " self.cantidad = cantidad" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "id": "7602722f-9026-44dc-b922-e17a7d3af45b", + "metadata": {}, + "outputs": [], + "source": [ + "class Cliente:\n", + " def __init__(self, nombre, ciudad):\n", + " self.nombre = nombre\n", + " self.ciudad = ciudad" + ] + }, + { + "cell_type": "code", + "execution_count": 100, "id": "f6b4829a-9001-410c-b20c-01c65c777d8a", "metadata": {}, "outputs": [], + "source": [ + "class VRP:\n", + " def __init__(self):\n", + " # Conjuntos\n", + " self.I = range(2)\n", + " self.J = range(3)\n", + " self.T = range(5) # en horas\n", + " self.V = range(3) # 3 tipos de vehiculos\n", + " \n", + " def init_data(self):\n", + " \"\"\"\n", + " Lista los parametros iniciales, definidos en \"Modelo Matematico\" en ISA v02\n", + " \n", + " i: almacen grande (depot)\n", + " j: almacen pequeño (customer)\n", + " v: tipo de vehiculo\n", + " t: tiempo\n", + " \"\"\"\n", + " # Parametros\n", + " # Nombres cortos confunden, pero matrices de varias dimensiones \n", + " # sin etiquetas confunden mas\n", + " \n", + " # Demanda\n", + " self.D_jt = [ [ random.choice([0,1,2,3]) for _ in self.I ] for _ in self.T ]\n", + " # Capacidades de vehiculos\n", + " self.VL_v = [ random.choice([10, 15, 20]) for _ in self.V ]\n", + " # distancia entre almacen i, j\n", + " self.d_ij = [ random.choice([25,50,100]) for _ in self.V ]\n", + " #self.r_ijvt = [ [ 0 for _ in self.V ] for " + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "ab559513-5c14-4dd2-a51d-7737114dfba1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([10, 10, 15])" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = VRP()\n", + "p.init_data()\n", + "np.array(p.VL_v)" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[25, 50, 50]" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p.d_ij" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "511ff788-0d1a-4ac7-9575-de182d236574", + "metadata": {}, + "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, - "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", + "id": "078280b5-70ef-4691-8798-a686d85d188c", "metadata": {}, "outputs": [], "source": [] @@ -27,7 +228,7 @@ { "cell_type": "code", "execution_count": null, - "id": "511ff788-0d1a-4ac7-9575-de182d236574", + "id": "611c9a0d-bb1a-48eb-af37-f033abe8ed66", "metadata": {}, "outputs": [], "source": [] @@ -35,7 +236,55 @@ { "cell_type": "code", "execution_count": null, - "id": "078280b5-70ef-4691-8798-a686d85d188c", + "id": "64c68216-b9f1-45f9-a0fe-3862ab106c24", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cb6bb08-1547-4b64-993f-b2c453535264", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b83d9e98-db8f-45cd-9eff-07d4194f7e07", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8c06031-9c55-4e13-a27b-91b0886902e6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e9483c22-243f-44e5-9a6d-09da92354554", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12952643-4a10-40bf-8af3-41319c744732", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b0306c4f-eb68-4009-9390-0f881c6a8cb4", "metadata": {}, "outputs": [], "source": [] diff --git a/test/VRPTW_GA.ipynb b/test/VRPTW_GA.ipynb new file mode 100644 index 0000000..042836e --- /dev/null +++ b/test/VRPTW_GA.ipynb @@ -0,0 +1,724 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# APLICACIONES EN CIENCIAS DE COMPUTACION\n", + "Dr. Edwin Villanueva" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Algoritmo genetico para resolver el VRPTW\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import matplotlib.pyplot as plt\n", + "import csv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Clase abstracta de un individuo de algoritmo genético" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "class Individual:\n", + " \"Clase abstracta para individuos de un algoritmo evolutivo.\"\n", + "\n", + " def __init__(self, chromosome):\n", + " self.chromosome = chromosome\n", + "\n", + " def crossover(self, other):\n", + " \"Retorna un nuevo individuo cruzando self y other.\"\n", + " raise NotImplementedError\n", + " \n", + " def mutate(self):\n", + " \"Cambia los valores de algunos genes.\"\n", + " raise NotImplementedError " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Clase concreta de un individuo del problema de las n-reinas" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [], + "source": [ + "class Individual_VRPTW(Individual):\n", + " \"Clase que implementa el individuo en VRPTW.\"\n", + "\n", + " def __init__(self, chromosome):\n", + " self.chromosome = chromosome[:]\n", + " self.fitness = -1\n", + " \n", + " def crossover_order(self, other):\n", + " \"\"\"\n", + " Copies a part of the child chromosome from the first parent and constructs \n", + " the remaining part by following the vertex ordering in the second parent\n", + " \"\"\"\n", + " cut_point1 = random.randrange(0, len(self.chromosome) + 1)\n", + " cut_point2 = random.randrange(cut_point1, len(self.chromosome) + 1)\n", + " \n", + " c1 = self.chromosome[:]\n", + " c2 = other.chromosome[:]\n", + " p1_rem = self.chromosome[:cut_point1] + self.chromosome[cut_point2:]\n", + " p2_rem = other.chromosome[:cut_point1] + other.chromosome[cut_point2:]\n", + " # Change the genes in the remaining part of the child...\n", + " for i in range(len(self.chromosome)):\n", + " if i not in range(cut_point1, cut_point2):\n", + " # ...following the vertex ordering in the second parent\n", + " for gene in other.chromosome:\n", + " if gene in p1_rem:\n", + " c1.chromosome[i] = gene\n", + " \n", + " # (now for the other child)\n", + " for gene in self.chromosome:\n", + " if gene in p2_rem:\n", + " c2.chromosome[i] = gene\n", + " \n", + " return [Individual_VRPTW(c1), Individual_VRPTW(c2)]\n", + " \n", + "\n", + " def crossover_onepoint(self, other):\n", + " \"Retorna dos nuevos individuos del cruzamiento de un punto entre self y other \"\n", + " c = random.randrange(len(self.chromosome))\n", + " ind1 = Individual_VRPTW(self.chromosome[:c] + other.chromosome[c:])\n", + " ind2 = Individual_VRPTW(other.chromosome[:c] + self.chromosome[c:])\n", + " return [ind1, ind2] \n", + " \n", + " def crossover_uniform(self, other):\n", + " chromosome1 = []\n", + " chromosome2 = []\n", + " \"Retorna dos nuevos individuos del cruzamiento uniforme entre self y other \"\n", + " for i in range(len(self.chromosome)):\n", + " if random.uniform(0, 1) < 0.5:\n", + " chromosome1.append(self.chromosome[i])\n", + " chromosome2.append(other.chromosome[i])\n", + " else:\n", + " chromosome1.append(other.chromosome[i])\n", + " chromosome2.append(self.chromosome[i])\n", + " ind1 = Individual_VRPTW(chromosome1)\n", + " ind2 = Individual_VRPTW(chromosome2)\n", + " return [ind1, ind2] \n", + "\n", + " def mutate_position(self):\n", + " mutated_ind = Individual_VRPTW(self.chromosome[:])\n", + " indexPos = random.randint(0, len(mutated_ind.chromosome)-1)\n", + " newPos = random.randint(0, len(mutated_ind.chromosome)-1)\n", + " mutated_ind.chromosome[indexPos] = newPos\n", + " return mutated_ind\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Funcion de fitness para evaluar un individuo del problema de las n-reinas" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness_VRPTW(chromosome):\n", + " \"\"\"Retorna el fitness de un cromosoma en el problema VRPTW (distancia total de todas las rutas) \"\"\"\n", + " n = len(chromosome) # No. of vertices\n", + " fitness = 10**6\n", + " # feasibility\n", + " # TODO: considerar todas las restricciones\n", + " # desirability\n", + " for i in range(0, n):\n", + " fitness -= distancia[i][i + 1]\n", + " \n", + " return fitness" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Funcion para evaluar toda una población de individuos con la funcion de fitnes especificada" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def evaluate_population(population, fitness_fn):\n", + " \"\"\" Evalua una poblacion de individuos con la funcion de fitness pasada \"\"\"\n", + " popsize = len(population)\n", + " for i in range(popsize):\n", + " if population[i].fitness == -1: # si el individuo no esta evaluado\n", + " population[i].fitness = fitness_fn(population[i].chromosome)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Funcion que selecciona con el metodo de la ruleta un par de individuos de population para cruzamiento " + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [], + "source": [ + "def select_parents_roulette(population):\n", + " popsize = len(population)\n", + " \n", + " # Escoje el primer padre\n", + " sumfitness = sum([indiv.fitness for indiv in population]) # suma total del fitness de la poblacion\n", + " pickfitness = random.uniform(0, sumfitness) # escoge un numero aleatorio entre 0 y sumfitness\n", + " cumfitness = 0 # fitness acumulado\n", + " for i in range(popsize):\n", + " cumfitness += population[i].fitness\n", + " if cumfitness > pickfitness: \n", + " iParent1 = i\n", + " break\n", + " \n", + " # Escoje el segundo padre, desconsiderando el padre ya escogido\n", + " sumfitness = sumfitness - population[iParent1].fitness # retira el fitness del padre ya escogido\n", + " pickfitness = random.uniform(0, sumfitness) # escoge un numero aleatorio entre 0 y sumfitness\n", + " cumfitness = 0 # fitness acumulado\n", + " for i in range(popsize):\n", + " if i == iParent1: continue # si es el primer padre \n", + " cumfitness += population[i].fitness\n", + " if cumfitness > pickfitness: \n", + " iParent2 = i\n", + " break \n", + " return (population[iParent1], population[iParent2])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Funcion que selecciona sobrevivientes para la sgte generacion, dada la poblacion actual y poblacion de hijos " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def select_survivors(population, offspring_population, numsurvivors):\n", + " next_population = []\n", + " population.extend(offspring_population) # une las dos poblaciones\n", + " isurvivors = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:numsurvivors]\n", + " for i in range(numsurvivors): next_population.append(population[isurvivors[i]])\n", + " return next_population" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Algoritmo Genetico \n", + "Recibe una poblacion inicial, funcion de fitness, numero de generaciones (ngen) y taza de mutación (pmut)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", + " \"Algoritmo Genetico \"\n", + " \n", + " popsize = len(population)\n", + " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness = [population[ibest[0]].fitness]\n", + " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", + " \n", + " for g in range(ngen): # Por cada generacion\n", + " \n", + " ## Selecciona las parejas de padres para cruzamiento \n", + " mating_pool = []\n", + " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", + " \n", + " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", + " offspring_population = []\n", + " for i in range(len(mating_pool)): \n", + " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", + " #offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", + " offspring_population.extend( mating_pool[i][0].crossover_order(mating_pool[i][1]) )\n", + "\n", + " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", + " for i in range(len(offspring_population)):\n", + " if random.uniform(0, 1) < pmut: \n", + " offspring_population[i] = offspring_population[i].mutate_position()\n", + " \n", + " ## Evalua la poblacion descendencia\n", + " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", + " \n", + " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", + " population = select_survivors(population, offspring_population, popsize)\n", + "\n", + " ## Almacena la historia del fitness del mejor individuo\n", + " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", + " bestfitness.append(population[ibest[0]].fitness)\n", + " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", + " \n", + " return population[ibest[0]], bestfitness " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " Algoritmo de Busqueda Genetica para el VRPTW " + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [], + "source": [ + "def genetic_algorithm_VRPTW(fitness_fn, num_depots=1, num_vehicles=1, vehicle_capacity=200, popsize=10, ngen=1000, pmut=0):\n", + " population = []\n", + " \n", + " # Crea la poblacion inicial con cromosomas aleatorios\n", + " for i in range(popsize):\n", + " chromosome = [j for j in range(1,num_vertices+1)]\n", + " random.shuffle(chromosome)\n", + " population.append(Individual_VRPTW(chromosome))\n", + " \n", + " return genetic_algorithm(population, fitness_fn, ngen, pmut)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def genetic_search_nqueens(fitness_fn, num_queens=10, popsize=10, ngen=100, pmut=0.5):\n", + " import random\n", + " population = []\n", + "\n", + " ## Crea la poblacion inicial con cromosomas aleatorios\n", + " for i in range(popsize):\n", + " chromosome = [j for j in range(1,num_queens+1)]\n", + " random.shuffle(chromosome)\n", + " population.append( Individual_nqueens(chromosome) )\n", + " \n", + " ## Crea la poblacion inicial con los siguientes cromosomas \n", + " #chromosomes = [[1,3,1,3,1,3,1,3,1,3],\n", + " # [2,4,2,4,2,4,2,4,2,4],\n", + " # [3,5,3,5,3,5,3,5,3,5],\n", + " # [4,6,4,6,4,6,4,6,4,6],\n", + " # [5,7,5,7,5,7,5,7,5,7],\n", + " # [6,8,6,8,6,8,6,8,6,8],\n", + " # [7,9,7,9,7,9,7,9,7,9],\n", + " # [8,10,8,10,8,10,8,10,8,10],\n", + " # [9,1,9,1,9,1,9,1,9,1],\n", + " # [10,2,10,2,10,2,10,2,10,2] ] \n", + " #for i in range(popsize):\n", + " # population.append( Individual_nqueens(chromosomes[i]) ) \n", + " \n", + " ## llama al algoritmo genetico para encontrar una solucion al problema de las n reinas\n", + " return genetic_algorithm(population, fitness_fn, ngen, pmut)\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Probando el Algoritmo genetico" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'distancia' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Input \u001b[0;32mIn [115]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mplt\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# busca solucion para el problema de 10 reinas. Usa 100 individuos aleatorios, 100 generaciones y taza de mutación de 0.5\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m best_ind, bestfitness \u001b[38;5;241m=\u001b[39m \u001b[43mgenetic_algorithm_VRPTW\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfitness_VRPTW\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 5\u001b[0m plt\u001b[38;5;241m.\u001b[39mplot(bestfitness)\n\u001b[1;32m 6\u001b[0m plt\u001b[38;5;241m.\u001b[39mshow()\n", + "Input \u001b[0;32mIn [113]\u001b[0m, in \u001b[0;36mgenetic_algorithm_VRPTW\u001b[0;34m(fitness_fn, num_vertices, num_depots, num_vehicles, popsize, ngen, pmut)\u001b[0m\n\u001b[1;32m 7\u001b[0m random\u001b[38;5;241m.\u001b[39mshuffle(chromosome)\n\u001b[1;32m 8\u001b[0m population\u001b[38;5;241m.\u001b[39mappend(Individual_VRPTW(chromosome))\n\u001b[0;32m---> 10\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mgenetic_algorithm\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpopulation\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfitness_fn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mngen\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpmut\u001b[49m\u001b[43m)\u001b[49m\n", + "Input \u001b[0;32mIn [10]\u001b[0m, in \u001b[0;36mgenetic_algorithm\u001b[0;34m(population, fitness_fn, ngen, pmut)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAlgoritmo Genetico \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 4\u001b[0m popsize \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlen\u001b[39m(population)\n\u001b[0;32m----> 5\u001b[0m \u001b[43mevaluate_population\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpopulation\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfitness_fn\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# evalua la poblacion inicial\u001b[39;00m\n\u001b[1;32m 6\u001b[0m ibest \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msorted\u001b[39m(\u001b[38;5;28mrange\u001b[39m(\u001b[38;5;28mlen\u001b[39m(population)), key\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m i: population[i]\u001b[38;5;241m.\u001b[39mfitness, reverse\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)[:\u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 7\u001b[0m bestfitness \u001b[38;5;241m=\u001b[39m [population[ibest[\u001b[38;5;241m0\u001b[39m]]\u001b[38;5;241m.\u001b[39mfitness]\n", + "Input \u001b[0;32mIn [7]\u001b[0m, in \u001b[0;36mevaluate_population\u001b[0;34m(population, fitness_fn)\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(popsize):\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m population[i]\u001b[38;5;241m.\u001b[39mfitness \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m: \u001b[38;5;66;03m# si el individuo no esta evaluado\u001b[39;00m\n\u001b[0;32m----> 6\u001b[0m population[i]\u001b[38;5;241m.\u001b[39mfitness \u001b[38;5;241m=\u001b[39m \u001b[43mfitness_fn\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpopulation\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mchromosome\u001b[49m\u001b[43m)\u001b[49m\n", + "Input \u001b[0;32mIn [109]\u001b[0m, in \u001b[0;36mfitness_VRPTW\u001b[0;34m(chromosome)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;66;03m# feasibility\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# TODO: considerar todas las restricciones\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;66;03m# desirability\u001b[39;00m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m0\u001b[39m, n):\n\u001b[0;32m----> 9\u001b[0m fitness \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[43mdistancia\u001b[49m[i][i \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fitness\n", + "\u001b[0;31mNameError\u001b[0m: name 'distancia' is not defined" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "best_ind, bestfitness = genetic_algorithm_VRPTW(fitness_VRPTW)\n", + "plt.plot(bestfitness)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Poblacion inicial, best_fitness = 44\n", + "generacion 0, best_fitness = 44\n", + "generacion 1, best_fitness = 44\n", + "generacion 2, best_fitness = 44\n", + "generacion 3, best_fitness = 44\n", + "generacion 4, best_fitness = 44\n", + "generacion 5, best_fitness = 44\n", + "generacion 6, best_fitness = 44\n", + "generacion 7, best_fitness = 44\n", + "generacion 8, best_fitness = 44\n", + "generacion 9, best_fitness = 44\n", + "generacion 10, best_fitness = 44\n", + "generacion 11, best_fitness = 44\n", + "generacion 12, best_fitness = 44\n", + "generacion 13, best_fitness = 44\n", + "generacion 14, best_fitness = 44\n", + "generacion 15, best_fitness = 44\n", + "generacion 16, best_fitness = 44\n", + "generacion 17, best_fitness = 44\n", + "generacion 18, best_fitness = 44\n", + "generacion 19, best_fitness = 44\n", + "generacion 20, best_fitness = 44\n", + "generacion 21, best_fitness = 44\n", + "generacion 22, best_fitness = 44\n", + "generacion 23, best_fitness = 44\n", + "generacion 24, best_fitness = 44\n", + "generacion 25, best_fitness = 44\n", + "generacion 26, best_fitness = 44\n", + "generacion 27, best_fitness = 44\n", + "generacion 28, best_fitness = 44\n", + "generacion 29, best_fitness = 44\n", + "generacion 30, best_fitness = 45\n", + "generacion 31, best_fitness = 45\n", + "generacion 32, best_fitness = 45\n", + "generacion 33, best_fitness = 45\n", + "generacion 34, best_fitness = 45\n", + "generacion 35, best_fitness = 45\n", + "generacion 36, best_fitness = 45\n", + "generacion 37, best_fitness = 45\n", + "generacion 38, best_fitness = 45\n", + "generacion 39, best_fitness = 45\n", + "generacion 40, best_fitness = 45\n", + "generacion 41, best_fitness = 45\n", + "generacion 42, best_fitness = 45\n", + "generacion 43, best_fitness = 45\n", + "generacion 44, best_fitness = 45\n", + "generacion 45, best_fitness = 45\n", + "generacion 46, best_fitness = 45\n", + "generacion 47, best_fitness = 45\n", + "generacion 48, best_fitness = 45\n", + "generacion 49, best_fitness = 45\n", + "generacion 50, best_fitness = 45\n", + "generacion 51, best_fitness = 45\n", + "generacion 52, best_fitness = 45\n", + "generacion 53, best_fitness = 45\n", + "generacion 54, best_fitness = 45\n", + "generacion 55, best_fitness = 45\n", + "generacion 56, best_fitness = 45\n", + "generacion 57, best_fitness = 45\n", + "generacion 58, best_fitness = 45\n", + "generacion 59, best_fitness = 45\n", + "generacion 60, best_fitness = 45\n", + "generacion 61, best_fitness = 45\n", + "generacion 62, best_fitness = 45\n", + "generacion 63, best_fitness = 45\n", + "generacion 64, best_fitness = 45\n", + "generacion 65, best_fitness = 45\n", + "generacion 66, best_fitness = 45\n", + "generacion 67, best_fitness = 45\n", + "generacion 68, best_fitness = 45\n", + "generacion 69, best_fitness = 45\n", + "generacion 70, best_fitness = 45\n", + "generacion 71, best_fitness = 45\n", + "generacion 72, best_fitness = 45\n", + "generacion 73, best_fitness = 45\n", + "generacion 74, best_fitness = 45\n", + "generacion 75, best_fitness = 45\n", + "generacion 76, best_fitness = 45\n", + "generacion 77, best_fitness = 45\n", + "generacion 78, best_fitness = 45\n", + "generacion 79, best_fitness = 45\n", + "generacion 80, best_fitness = 45\n", + "generacion 81, best_fitness = 45\n", + "generacion 82, best_fitness = 45\n", + "generacion 83, best_fitness = 45\n", + "generacion 84, best_fitness = 45\n", + "generacion 85, best_fitness = 45\n", + "generacion 86, best_fitness = 45\n", + "generacion 87, best_fitness = 45\n", + "generacion 88, best_fitness = 45\n", + "generacion 89, best_fitness = 45\n", + "generacion 90, best_fitness = 45\n", + "generacion 91, best_fitness = 45\n", + "generacion 92, best_fitness = 45\n", + "generacion 93, best_fitness = 45\n", + "generacion 94, best_fitness = 45\n", + "generacion 95, best_fitness = 45\n", + "generacion 96, best_fitness = 45\n", + "generacion 97, best_fitness = 45\n", + "generacion 98, best_fitness = 45\n", + "generacion 99, best_fitness = 45\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD4CAYAAADiry33AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAATz0lEQVR4nO3dYbBc513f8e/PV4kd23GtYDVGVtxrxk47AQKYO2k6pq3HtCHYqkgG3HFJS17AGGZw6xaoiaYzaeKSF9Q0uE4pMxqTkDY0aevS9ta0ZIKNhhkGQiTbJFEUGgUT4iBXchNIlQxKdvffF7tX3tzcq7v3nCvvOavvZ+aOdp/ds/ucOXt++t9nn/ucVBWSpMV1ybw7IEm6sAx6SVpwBr0kLTiDXpIWnEEvSQtu17w7sN4111xTy8vL8+6GJPXK0aNHn6uqPRs91rmgX15e5siRI/PuhiT1SpLPbPaYQzeStOAMeklacAa9JC04g16SFpxBL0kLbuagT7KU5Mkkj07u/3KSp5M8Nfn59k22e3OST01+3rxD/ZYkzWg70yvvBY4DV021/dOqemSzDZK8DPjnwApQwNEkq1X1hSadlSRt30xBn2QfcAfwDuAntvH63wN8qKo+P3mdDwGvB96/zX6qww7/wSme+Iz/d0ttvfLal7L/1Xt3/HVnregfBO4DXrqu/R1J3go8Brylqs6ue/w64LNT95+ZtH2NJHcDdwNcf/31M3ZJXfH2//EJnn7uSyTz7onUb/tfvXc+QZ9kP3Cqqo4muXXqoYPAs8CLgUPATwP3N+lEVR2avAYrKyteCaVnvjIY8f037+Nf/d1vm3dXJG1gli9jbwEOJPkj4APAbUneV1Una+ws8B7gNRts+zngFVP3903atECGo2LXJZbzUldtGfRVdbCq9lXVMnAX8HhV/f0k3wiQJMAbgI9vsPkHgdcl2Z1kN/C6SZsWyGBULC0Z9FJXtVnU7FeS7AECPAX8GECSFeDHqupHqurzSf4F8JHJNvevfTGrxTEcjazopQ7bVtBX1WHg8OT2bZs85wjwI1P33w28u3EP1XmDUbFk0Eud5V/GqjXH6KVuM+jV2rii96MkdZVnp1qzope6zaBXK1XF0DF6qdMMerUyHI3/vs2KXuoug16tDCZB7zx6qbsMerViRS91n0GvVs5V9M66kTrLs1OtWNFL3WfQq5XBaATgrBupwwx6tWJFL3WfQa9WBsO1MXqDXuoqg16tDEcGvdR1Br1aGZZBL3WdQa9Wnh+j96MkdZVnp1pxjF7qPoNerTjrRuo+g16tnJtH71o3UmcZ9GrFil7qPoNerQycXil1nkGvVpx1I3WfZ6dasaKXus+gVyvDyZexjtFL3WXQqxXn0UvdZ9CrlXNj9E6vlDrLoFcrA6dXSp1n0KuVoZcSlDrPs1OtWNFL3WfQq5WhlxKUOs+gVyvOo5e6z6BXKyODXuq8mYM+yVKSJ5M8uq79oSRnNtnmRUnem+RjSY4nOdi2w+oWx+il7ttORX8vcHy6IckKsPs829wJXFpV3wp8J/CjSZa320l1l9eMlbpvpqBPsg+4A3h4qm0JeAC47zybFnBFkl3AS4CvAF9s3Ft1zsBFzaTOm/XsfJBxoI+m2u4BVqvq5Hm2ewT4EnAS+GPg56rq8+uflOTuJEeSHDl9+vSMXVIXWNFL3bdl0CfZD5yqqqNTbXsZD8u8a4vNXwMMgb3ADcBPJvmm9U+qqkNVtVJVK3v27NlO/zVna2vdOEYvddeuGZ5zC3Agye3AZcBVwDHgLHAiCcDlSU5U1Y3rtv1B4Ner6qvAqSS/DawAf7hTO6D5Go5GJHCJQS911pYVfVUdrKp9VbUM3AU8XlW7q+raqlqetH95g5CH8XDNbQBJrgBeC3xyx3qvuRuMympe6rgd/wYtyYEk90/u/gJwZZJjwEeA91TVR3f6PTU/w1E5Pi913CxDN+dU1WHg8AbtV07dXgVWJ7fPMB7L14IaV/TOuJG6zDNUrVjRS91n0KuVwWjkGL3UcQa9WrGil7rPoFcrg6GzbqSuM+jVynBULHm9WKnTDHq1MhgVSzHopS4z6NXKsByjl7rOoFcrw6Hz6KWu8wxVKwNn3UidZ9CrleFoxC6/jJU6zaBXK1b0UvcZ9Gpl6OqVUucZ9GrFil7qPoNerQxdvVLqPM9QtWJFL3WfQa9Whq5eKXWeQa9WBkMreqnrDHq1MhyV8+iljjPo1cp4PXo/RlKXeYaqlYHz6KXOM+jVileYkrrPoFcrXjNW6j6DXq0MR8UlBr3UaQa9WnGtG6n7DHq14l/GSt1n0KsVK3qp+wx6tTJwHr3UeZ6hasWKXuo+g16NVZXz6KUeMOjV2HBUAFb0UsfNHPRJlpI8meTRde0PJTlznu1eneR3khxL8rEkl7XpsLpjMAn6JRc1kzpt1zaeey9wHLhqrSHJCrB7sw2S7ALeB/yDqvr9JN8AfLVhX9UxVvRSP8xU0SfZB9wBPDzVtgQ8ANx3nk1fB3y0qn4foKr+b1UNm3dXXXKuonfWjdRps56hDzIO9NFU2z3AalWdPM92rwQqyQeTPJFkw/8Uktyd5EiSI6dPn56xS5o3K3qpH7YM+iT7gVNVdXSqbS9wJ/CuLTbfBXwX8KbJv29M8t3rn1RVh6pqpapW9uzZs53+a44Go/H/+866kbptljH6W4ADSW4HLmM8Rn8MOAucSAJweZITVXXjum2fAX6rqp4DSPI/gZuBx3ao/5ojK3qpH7as6KvqYFXtq6pl4C7g8araXVXXVtXypP3LG4Q8wAeBb01y+eSL2b8JfGIH+685GgzXxugNeqnLdvxbtCQHktwPUFVfAN4JfAR4Cniiqn5tp99T83Guond6pdRp25leSVUdBg5v0H7l1O1VYHXq/vsYT7HUgnHWjdQPnqFqbK2iX4oVvdRlBr0aOxf0jtFLnWbQqzFn3Uj9YNCrsXPz6P0yVuo0g16NWdFL/WDQq7GBY/RSLxj0auz5it6PkdRlnqFqzIpe6geDXo0NJ1/GOkYvdZtBr8Zc60bqB4NejbnWjdQPBr0aGzi9UuoFg16NDV3UTOoFz1A1ZkUv9YNBr8aGXkpQ6gWDXo1Z0Uv9YNCrMZcplvrBoFdjzqOX+sGgV2OjMuilPjDo1djARc2kXvAMVWOO0Uv9YNCrsbUxemfdSN1m0Kux4WhEApcY9FKnGfRqbDAqq3mpBwx6NTYclePzUg8Y9GpsXNH7EZK6zrNUjVnRS/1g0KuxwWjkGL3UAwa9GrOil/rBoFdjg6GzbqQ+MOjV2HBULHm9WKnzZg76JEtJnkzy6Lr2h5Kc2WLb65OcSfJTTTuq7nHWjdQP2zlL7wWOTzckWQF2z7DtO4H/tY33Ug84Ri/1w0xBn2QfcAfw8FTbEvAAcN8W274BeBo41riX6qTBaMRSDHqp62at6B9kHOijqbZ7gNWqOrnZRkmuBH4aePv5XjzJ3UmOJDly+vTpGbukeRuOXLlS6oMtgz7JfuBUVR2datsL3Am8a4vN3wb8fFWddwy/qg5V1UpVrezZs2frXqsThqMRu/wyVuq8XTM85xbgQJLbgcuAqxgPw5wFTmT8q/vlSU5U1Y3rtv2rwA8k+ZfA1cAoyZ9X1b/ZqR3Q/Awco5d6Ycugr6qDwEGAJLcCP1VV+6efk+TMBiFPVf31qee8DThjyC+OoatXSr2w43PjkhxIcv9Ov666x4pe6odZhm7OqarDwOEN2q+cur0KrG7wnLdtu3fqtOGoePGLlubdDUlb8K9d1JgVvdQPBr0aG7p6pdQLBr0aGwyt6KU+MOjV2HBUzqOXesCgV2PjtW78CEld51mqxgbOo5d6waBXY65eKfWDQa/GvGas1A8GvRqzopf6waBXY47RS/1g0Kux4bC4xKCXOs+gV2PDsqKX+sCgV2MD59FLveBZqsZcj17qB4NejVSVs26knjDo1chwVABW9FIPGPRqZDAJ+iUXNZM6z6BXI1b0Un8Y9GrkXEXvrBup8zxL1YgVvdQfBr0aGYxGAM66kXrAoFcjVvRSfxj0amQwXBujN+ilrjPo1ci5it7plVLnGfRqxFk3Un94lqoRx+il/jDo1YizbqT+MOjVyFpFvxSDXuo6g16NDF3rRuoNg16NOEYv9cfMQZ9kKcmTSR5d1/5QkjObbPO3kxxN8rHJv7e17bC64flZNwa91HW7tvHce4HjwFVrDUlWgN3n2eY54O9U1Z8k+Rbgg8B1TTqqbnm+oveXQqnrZjpLk+wD7gAenmpbAh4A7ttsu6p6sqr+ZHL3GPCSJJc27666wope6o9Zy7EHGQf6aKrtHmC1qk7O+BrfDzxRVWfXP5Dk7iRHkhw5ffr0jC+neRpOplc6Ri9135ZBn2Q/cKqqjk617QXuBN41y5sk+WbgZ4Ef3ejxqjpUVStVtbJnz56ZOq75cq0bqT9mGaO/BTiQ5HbgMsZj9MeAs8CJjOdRX57kRFXduH7jybDPfwV+qKo+vWM911y51o3UH1tW9FV1sKr2VdUycBfweFXtrqprq2p50v7lTUL+auDXgLdU1W/vbNc1TwOnV0q9seNTJpIcSHL/5O49wI3AW5M8Nfn5izv9nnrhDV3UTOqN7UyvpKoOA4c3aL9y6vYqsDq5/TPAz7TqoTrJil7qD8sxNTJ0UTOpNwx6NWJFL/WHQa9Ghv7BlNQbBr0aWZtH7xIIUvd5lqoRlymW+sOgVyMDLzwi9YZBr0ZG5Ri91BcGvRp5fozeoJe6zqBXI8PRiAQuMeilzjPo1chgVFbzUk8Y9GpkOCrH56WeMOjVyLii9+Mj9YFnqhqxopf6w6BXI4PRyDF6qScMejViRS/1h0GvRgZDZ91IfWHQq5HhqFznRuoJg16NOOtG6g/PVDXiGL3UHwa9GnHWjdQfBr0asaKX+sOgVyMDg17qDYNejVjRS/1h0KuRoatXSr1h0KsRh26k/jDo1cjQefRSb3imqhEreqk/DHo1MnQevdQbBr0aGQyt6KW+MOjVyHBU7HJRM6kXDHo1Mp5H78dH6oOZz9QkS0meTPLouvaHkpw5z3YHk5xI8gdJvqdNZ9UdA+fRS72xaxvPvRc4Dly11pBkBdi92QZJXgXcBXwzsBf4jSSvrKphs+6qK/zLWKk/Zgr6JPuAO4B3AD8xaVsCHgB+EHjjJpt+H/CBqjoLPJ3kBPAa4Hda9vvrfPLZL/IP/8OTO/2y2sSzX/xzlmLQS30wa0X/IHAf8NKptnuA1ao6mc1P+OuA3526/8yk7WskuRu4G+D666+fsUtf67JdS9z08isbbavte+XLX8obb/66Qympg7YM+iT7gVNVdTTJrZO2vcCdwK070YmqOgQcAlhZWakmr7F8zRX82zd95050R5IWyiwV/S3AgSS3A5cxHqM/BpwFTkyq+cuTnKiqG9dt+zngFVP3903aJEkvkC1n3VTVwaraV1XLjL9YfbyqdlfVtVW1PGn/8gYhD7AK3JXk0iQ3ADcBv7eD/ZckbWE7s25mkuQAsFJVb62qY0n+E/AJYAD8uDNuJOmFlapGQ+IXzMrKSh05cmTe3ZCkXklytKpWNnrMP22UpAVn0EvSgjPoJWnBGfSStOA692VsktPAZ1q8xDXAczvUnT642PYX3OeLhfu8PX+pqvZs9EDngr6tJEc2++Z5EV1s+wvu88XCfd45Dt1I0oIz6CVpwS1i0B+adwdeYBfb/oL7fLFwn3fIwo3RS5K+1iJW9JKkKQa9JC24hQn6JK+fXID8RJK3zLs/F0KSVyT5zSSfSHIsyb2T9pcl+VCST03+3fQ6vn20/sL0SW5I8uHJsf6PSV487z7utCRXJ3kkySeTHE/y1xb5OCf5J5PP9MeTvD/JZYt4nJO8O8mpJB+fatvwuGbsocn+fzTJzU3fdyGCfnL92l8Avhd4FfD3JhcmXzQD4Cer6lXAa4Efn+znW4DHquom4LHJ/UWydmH6NT8L/PzkGghfAH54Lr26sP418OtV9VeAb2O8/wt5nJNcB/wjxsubfwuwxPjaF4t4nH8ZeP26ts2O6/cyvobHTYwvtfqLTd90IYKe8QXHT1TVH1bVV4APML4w+UKpqpNV9cTk9v9jfPJfx3hf3zt52nuBN8ylgxfA1IXpH57cD3Ab8MjkKQu1vwBJ/gLwN4BfAqiqr1TVn7LAx5nxtTFekmQXcDlwkgU8zlX1W8Dn1zVvdly/D/h3Nfa7wNVJvrHJ+y5K0F8HfHbq/oYXIV8kSZaB7wA+DLy8qk5OHnoWePm8+nUBPMj4wvSjyf1vAP60qgaT+4t4rG8ATgPvmQxZPZzkChb0OFfV54CfA/6YccD/GXCUxT/OazY7rjuWa4sS9BeVJFcC/wX4x1X1xenHajxfdiHmzE5fmH7efXmB7QJuBn6xqr4D+BLrhmkW7DjvZly93gDsBa7g64c3LgoX6rguStBfNBchT/IixiH/K1X1q5Pm/7P2K93k31Pz6t8OW7sw/R8xHo67jfHY9dWTX/FhMY/1M8AzVfXhyf1HGAf/oh7nvwU8XVWnq+qrwK8yPvaLfpzXbHZcdyzXFiXoPwLcNPmW/sWMv8hZnXOfdtxkfPqXgONV9c6ph1aBN09uvxn47y903y6ETS5M/ybgN4EfmDxtYfZ3TVU9C3w2yV+eNH034+suL+RxZjxk89okl08+42v7u9DHecpmx3UV+KHJ7JvXAn82NcSzPVW1ED/A7cD/Bj4N/LN59+cC7eN3Mf617qPAU5Of2xmPWz8GfAr4DeBl8+7rBdj3W4FHJ7e/Cfg94ATwn4FL592/C7C/3w4cmRzr/wbsXuTjDLwd+CTwceDfA5cu4nEG3s/4e4ivMv7N7Yc3O65AGM8m/DTwMcazkhq9r0sgSNKCW5ShG0nSJgx6SVpwBr0kLTiDXpIWnEEvSQvOoJekBWfQS9KC+//Rh3QID9ptGwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 343 ms, sys: 108 ms, total: 450 ms\n", + "Wall time: 329 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "# busca solucion para el problema de 10 reinas. Usa 100 individuos aleatorios, 100 generaciones y taza de mutación de 0.5\n", + "best_ind, bestfitness = genetic_search_nqueens(fitness_nqueens, 10, 100, 100, 0.90)\n", + "plt.plot(bestfitness)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Lectura de datos" + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CUST NO.XCOORD. YCOORD. DEMAND READY TIME DUE DATE SERVICE TIME\n", + "1 40 50 0 0 240 0 \n", + "2 25 85 20 145 175 10 \n", + "3 22 75 30 50 80 10 \n", + "4 22 85 10 109 139 10 \n", + "5 20 80 40 141 171 10 \n", + "6 20 85 20 41 71 10 \n", + "7 18 75 20 95 125 10 \n", + "8 15 75 20 79 109 10 \n", + "9 15 80 10 91 121 10 \n", + "10 10 35 20 91 121 10 \n", + "11 10 40 30 119 149 10 \n", + "12 8 40 40 59 89 10 \n", + "13 8 45 20 64 94 10 \n", + "14 5 35 10 142 172 10 \n", + "15 5 45 10 35 65 10 \n", + "16 2 40 20 58 88 10 \n", + "17 0 40 20 72 102 10 \n", + "18 0 45 20 149 179 10 \n", + "19 44 5 20 87 117 10 \n", + "20 42 10 40 72 102 10 \n", + "21 42 15 10 122 152 10 \n", + "22 40 5 10 67 97 10 \n", + "23 40 15 40 92 122 10 \n", + "24 38 5 30 65 95 10 \n", + "25 38 15 10 148 178 10 \n", + "26 35 5 20 154 184 10 \n", + "27 95 30 30 115 145 10 \n", + "28 95 35 20 62 92 10 \n", + "29 92 30 10 62 92 10 \n", + "30 90 35 10 67 97 10 \n", + "31 88 30 10 74 104 10 \n", + "32 88 35 20 61 91 10 \n", + "33 87 30 10 131 161 10 \n", + "34 85 25 10 51 81 10 \n", + "35 85 35 30 111 141 10 \n", + "36 67 85 20 139 169 10 \n", + "37 65 85 40 43 73 10 \n", + "38 65 82 10 124 154 10 \n", + "39 62 80 30 75 105 10 \n", + "40 60 80 10 37 67 10 \n", + "41 60 85 30 85 115 10 \n", + "42 58 75 20 92 122 10 \n", + "43 55 80 10 33 63 10 \n", + "44 55 85 20 128 158 10 \n", + "45 55 82 10 64 94 10 \n", + "46 20 82 10 37 67 10 \n", + "47 18 80 10 113 143 10 \n", + "48 2 45 10 45 75 10 \n", + "49 42 5 10 151 181 10 \n", + "50 42 12 10 104 134 10 \n", + "51 72 35 30 116 146 10 \n", + "52 55 20 19 83 113 10 \n", + "53 25 30 3 52 82 10 \n", + "54 20 50 5 91 121 10 \n", + "55 55 60 16 139 169 10 \n", + "56 30 60 16 140 170 10 \n", + "57 50 35 19 130 160 10 \n", + "58 30 25 23 96 126 10 \n", + "59 15 10 20 152 182 10 \n", + "60 10 20 19 42 72 10 \n", + "61 15 60 17 155 185 10 \n", + "62 45 65 9 66 96 10 \n", + "63 65 35 3 52 82 10 \n", + "64 65 20 6 39 69 10 \n", + "65 45 30 17 53 83 10 \n", + "66 35 40 16 11 41 10 \n", + "67 41 37 16 133 163 10 \n", + "68 64 42 9 70 100 10 \n", + "69 40 60 21 144 174 10 \n", + "70 31 52 27 41 71 10 \n", + "71 35 69 23 180 210 10 \n", + "72 65 55 14 65 95 10 \n", + "73 63 65 8 30 60 10 \n", + "74 2 60 5 77 107 10 \n", + "75 20 20 8 141 171 10 \n", + "76 5 5 16 74 104 10 \n", + "77 60 12 31 75 105 10 \n", + "78 23 3 7 150 180 10 \n", + "79 8 56 27 90 120 10 \n", + "80 6 68 30 89 119 10 \n", + "81 47 47 13 192 222 10 \n", + "82 49 58 10 86 116 10 \n", + "83 27 43 9 42 72 10 \n", + "84 37 31 14 35 65 10 \n", + "85 57 29 18 96 126 10 \n", + "86 63 23 2 87 117 10 \n", + "87 21 24 28 87 117 10 \n", + "88 12 24 13 90 120 10 \n", + "89 24 58 19 67 97 10 \n", + "90 67 5 25 144 174 10 \n", + "91 37 47 6 86 116 10 \n", + "92 49 42 13 167 197 10 \n", + "93 53 43 14 14 44 10 \n", + "94 61 52 3 178 208 10 \n", + "95 57 48 23 95 125 10 \n", + "96 56 37 6 34 64 10 \n", + "97 55 54 26 132 162 10 \n", + "98 4 18 35 120 150 10 \n", + "99 26 52 9 46 76 10 \n", + "100 26 35 15 77 107 10 \n", + "101 31 67 3 180 210 10 \n" + ] + } + ], + "source": [ + "with open('data/RC101.csv', newline='') as csvfile:\n", + " orders = csv.reader(csvfile)\n", + " for row in orders:\n", + " print(f\"{row[0]:8}{row[1]:8}{row[2]:8}{row[3]:8}{row[4]:12}{row[5]:12}{row[6]:12}\")\n", + " #print(\", \".join(row))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/test/data/RC101.csv b/test/data/RC101.csv new file mode 100644 index 0000000..ff64970 --- /dev/null +++ b/test/data/RC101.csv @@ -0,0 +1,102 @@ +CUST NO.,XCOORD.,YCOORD.,DEMAND,READY TIME,DUE DATE,SERVICE TIME +1,40,50,0,0,240,0 +2,25,85,20,145,175,10 +3,22,75,30,50,80,10 +4,22,85,10,109,139,10 +5,20,80,40,141,171,10 +6,20,85,20,41,71,10 +7,18,75,20,95,125,10 +8,15,75,20,79,109,10 +9,15,80,10,91,121,10 +10,10,35,20,91,121,10 +11,10,40,30,119,149,10 +12,8,40,40,59,89,10 +13,8,45,20,64,94,10 +14,5,35,10,142,172,10 +15,5,45,10,35,65,10 +16,2,40,20,58,88,10 +17,0,40,20,72,102,10 +18,0,45,20,149,179,10 +19,44,5,20,87,117,10 +20,42,10,40,72,102,10 +21,42,15,10,122,152,10 +22,40,5,10,67,97,10 +23,40,15,40,92,122,10 +24,38,5,30,65,95,10 +25,38,15,10,148,178,10 +26,35,5,20,154,184,10 +27,95,30,30,115,145,10 +28,95,35,20,62,92,10 +29,92,30,10,62,92,10 +30,90,35,10,67,97,10 +31,88,30,10,74,104,10 +32,88,35,20,61,91,10 +33,87,30,10,131,161,10 +34,85,25,10,51,81,10 +35,85,35,30,111,141,10 +36,67,85,20,139,169,10 +37,65,85,40,43,73,10 +38,65,82,10,124,154,10 +39,62,80,30,75,105,10 +40,60,80,10,37,67,10 +41,60,85,30,85,115,10 +42,58,75,20,92,122,10 +43,55,80,10,33,63,10 +44,55,85,20,128,158,10 +45,55,82,10,64,94,10 +46,20,82,10,37,67,10 +47,18,80,10,113,143,10 +48,2,45,10,45,75,10 +49,42,5,10,151,181,10 +50,42,12,10,104,134,10 +51,72,35,30,116,146,10 +52,55,20,19,83,113,10 +53,25,30,3,52,82,10 +54,20,50,5,91,121,10 +55,55,60,16,139,169,10 +56,30,60,16,140,170,10 +57,50,35,19,130,160,10 +58,30,25,23,96,126,10 +59,15,10,20,152,182,10 +60,10,20,19,42,72,10 +61,15,60,17,155,185,10 +62,45,65,9,66,96,10 +63,65,35,3,52,82,10 +64,65,20,6,39,69,10 +65,45,30,17,53,83,10 +66,35,40,16,11,41,10 +67,41,37,16,133,163,10 +68,64,42,9,70,100,10 +69,40,60,21,144,174,10 +70,31,52,27,41,71,10 +71,35,69,23,180,210,10 +72,65,55,14,65,95,10 +73,63,65,8,30,60,10 +74,2,60,5,77,107,10 +75,20,20,8,141,171,10 +76,5,5,16,74,104,10 +77,60,12,31,75,105,10 +78,23,3,7,150,180,10 +79,8,56,27,90,120,10 +80,6,68,30,89,119,10 +81,47,47,13,192,222,10 +82,49,58,10,86,116,10 +83,27,43,9,42,72,10 +84,37,31,14,35,65,10 +85,57,29,18,96,126,10 +86,63,23,2,87,117,10 +87,21,24,28,87,117,10 +88,12,24,13,90,120,10 +89,24,58,19,67,97,10 +90,67,5,25,144,174,10 +91,37,47,6,86,116,10 +92,49,42,13,167,197,10 +93,53,43,14,14,44,10 +94,61,52,3,178,208,10 +95,57,48,23,95,125,10 +96,56,37,6,34,64,10 +97,55,54,26,132,162,10 +98,4,18,35,120,150,10 +99,26,52,9,46,76,10 +100,26,35,15,77,107,10 +101,31,67,3,180,210,10 -- cgit v1.2.3 From 67fe87fe17bb5e04843b743ab0a9d79e826b3399 Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Fri, 22 Apr 2022 00:07:37 -0500 Subject: Add test/TSP.ipynb. Build sol little by little --- test/TSP.ipynb | 382 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 test/TSP.ipynb (limited to 'test') diff --git a/test/TSP.ipynb b/test/TSP.ipynb new file mode 100644 index 0000000..effca11 --- /dev/null +++ b/test/TSP.ipynb @@ -0,0 +1,382 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "234feb6e-4c52-443c-a3d6-6da8e903dd5c", + "metadata": {}, + "source": [ + "Travelling salesman problem\n", + "\n", + "TSP es *casi* (multi-depot) VRPTW pero:\n", + "- Solo 1 camion\n", + "- Todos los ciudades (aka. almacenes pequeños) tienen al menos 1 pedido\n", + "- Capacidad infinita\n", + "- Sin ventanas de tiempo (aka. plazos de entrega)\n", + "- Solo 1 deposito\n", + "\n", + "Cambios identificados, necesarios para adaptar el TSP a nuestro caso:\n", + "- Tramos no conectados -> distancia grande entre ellos\n", + "- Distancias no son euclidianas, usar \"geodistance\"\n", + "- [...]\n", + "\n", + "Refs:\n", + "\n", + "- [scikit-opt](https://github.com/guofei9987/scikit-opt)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "934ae28c-ccc1-4e63-832c-4f53ceb13f50", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "0fb6e4d9-d0cd-438c-b0a1-21a85a23de89", + "metadata": {}, + "source": [ + "Differential Evolution scikit-opt example" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "eda106bc-2411-4ace-acf0-d2b66dc2d127", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "min f(x1, x2, x3) = x1^2 + x2^2 + x3^2\n", + "s.t.\n", + " x1*x2 >= 1\n", + " x1*x2 <= 5\n", + " x2 + x3 = 1\n", + " 0 <= x1, x2, x3 <= 5\n", + "'''\n", + "\n", + "\n", + "def obj_func(p):\n", + " x1, x2, x3 = p\n", + " return x1 ** 2 + x2 ** 2 + x3 ** 2\n", + "\n", + "\n", + "constraint_eq = [\n", + " lambda x: 1 - x[1] - x[2]\n", + "]\n", + "\n", + "# r(x1, x2, x3) >= 0\n", + "constraint_ueq = [\n", + " lambda x: 1 - x[0] * x[1],\n", + " lambda x: x[0] * x[1] - 5\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4b3dcfaf-ab6b-42b7-9218-e58ea6828605", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "best_x: [1.01075314 0.99002837 0.00997163] \n", + " best_y: [2.00187751]\n" + ] + } + ], + "source": [ + "from sko.DE import DE\n", + "\n", + "de = DE(func=obj_func, n_dim=3, size_pop=50, max_iter=800, lb=[0, 0, 0], ub=[5, 5, 5],\n", + " constraint_eq=constraint_eq, constraint_ueq=constraint_ueq)\n", + "\n", + "best_x, best_y = de.run()\n", + "print('best_x:', best_x, '\\n', 'best_y:', best_y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b49859f-c3a3-49a4-a605-5ec880556dc5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "7563715b-c74b-4010-98c5-28c1e5b1410d", + "metadata": {}, + "source": [ + "Genetic Algorithm" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "03283268-a9af-4e26-a673-4c8225bf5fcb", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "\n", + "def schaffer(p):\n", + " '''\n", + " This function has plenty of local minimum, with strong shocks\n", + " global minimum at (0,0) with value 0\n", + " https://en.wikipedia.org/wiki/Test_functions_for_optimization\n", + " '''\n", + " x1, x2 = p\n", + " part1 = np.square(x1) - np.square(x2)\n", + " part2 = np.square(x1) + np.square(x2)\n", + " return 0.5 + (np.square(np.sin(part1)) - 0.5) / np.square(1 + 0.001 * part2)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "24da5ddc-04fe-4536-b5b9-48dca9a6118c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "best_x: [-2.08616263e-07 -8.94069698e-08] \n", + " best_y: [0.]\n" + ] + } + ], + "source": [ + "from sko.GA import GA\n", + "\n", + "ga = GA(func=schaffer, n_dim=2, size_pop=50, max_iter=800, prob_mut=0.001, lb=[-1, -1], ub=[1, 1], precision=1e-7)\n", + "best_x, best_y = ga.run()\n", + "print('best_x:', best_x, '\\n', 'best_y:', best_y)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "2e4903dc-6eff-4087-a986-1f6cf3470645", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# col: individuos, row: iterations\n", + "Y_history = pd.DataFrame(ga.all_history_Y)\n", + "fig, ax = plt.subplots(2, 1)\n", + "ax[0].plot(Y_history.index, Y_history.values, '.', color='red')\n", + "Y_history.min(axis=1).cummin().plot(kind='line')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bdfb384b-b2b5-4755-b869-3a1da68cedd9", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "730c1714-7f9d-427a-9ecd-eecd416c293d", + "metadata": {}, + "source": [ + "TSP" + ] + }, + { + "cell_type": "markdown", + "id": "9fb2ef00-3c16-4986-afa1-428fc43f5d36", + "metadata": {}, + "source": [ + "\"geodistance\" (using longitude, latitude): https://stackoverflow.com/questions/31632190/measuring-geographic-distance-with-scipy" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "id": "740a307c-7f4d-4978-a561-2424309cc310", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from scipy import spatial\n", + "import matplotlib.pyplot as plt\n", + "\n", + "num_points = 5\n", + "\n", + "points_coordinate = np.random.rand(num_points, 2) # generate coordinate of points\n", + "distance_matrix = spatial.distance.cdist(points_coordinate, points_coordinate, metric='euclidean')\n", + "\n", + "\n", + "def cal_total_distance(routine):\n", + " '''The objective function. input routine, return total distance.\n", + " cal_total_distance(np.arange(num_points))\n", + " '''\n", + " num_points, = routine.shape\n", + " return sum([distance_matrix[routine[i % num_points], routine[(i + 1) % num_points]] for i in range(num_points)])\n" + ] + }, + { + "cell_type": "code", + "execution_count": 182, + "id": "3b570dd4-09fa-41d8-8d80-ba0c6ae05fa5", + "metadata": {}, + "outputs": [], + "source": [ + "from sko.GA import GA_TSP\n", + "\n", + "ga_tsp = GA_TSP(func=cal_total_distance, n_dim=num_points, size_pop=50, max_iter=500, prob_mut=1)\n", + "best_points, best_distance = ga_tsp.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 183, + "id": "c4af7656-ace9-4594-ac32-3ccd027c7811", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(1, 2)\n", + "best_points_ = np.concatenate([best_points])\n", + "# \"path\"\n", + "best_points_coordinate = points_coordinate[best_points_, :]\n", + "ax[0].plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r')\n", + "ax[1].plot(ga_tsp.generation_best_Y)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f361519e-2397-4b70-be35-45dd14cc15af", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40f6c413-89f8-4934-a165-1183fc5458eb", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "089bbdae-063a-4a5c-8f7a-fb8bb26dc83c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f7266973-639c-42f9-86b6-3369ba04d03c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 180, + "id": "5127a9e8-17a8-4a07-b825-2aaf11a6270e", + "metadata": {}, + "outputs": [], + "source": [ + "from sko.ACA import ACA_TSP\n", + "\n", + "aca = ACA_TSP(func=cal_total_distance, n_dim=num_points,\n", + " size_pop=50, max_iter=200,\n", + " distance_matrix=distance_matrix)\n", + "\n", + "best_x, best_y = aca.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "id": "c9b939a8-3a5f-41d6-8263-25dacebc4602", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(1, 2)\n", + "best_points_ = np.concatenate([best_x, [best_x[0]]])\n", + "best_points_coordinate = points_coordinate[best_points_, :]\n", + "ax[0].plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r')\n", + "pd.DataFrame(aca.y_best_history).cummin().plot(ax=ax[1])\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- cgit v1.2.3 From 48b9f5cfbb91e555d88e094928c3f66000df338a Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Fri, 22 Apr 2022 00:14:07 -0500 Subject: Remove jupyter cells output --- test/TSP.ipynb | 87 ++++++++++------------------------------------------------ 1 file changed, 15 insertions(+), 72 deletions(-) (limited to 'test') diff --git a/test/TSP.ipynb b/test/TSP.ipynb index effca11..476619b 100644 --- a/test/TSP.ipynb +++ b/test/TSP.ipynb @@ -42,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "eda106bc-2411-4ace-acf0-d2b66dc2d127", "metadata": {}, "outputs": [], @@ -75,19 +75,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "4b3dcfaf-ab6b-42b7-9218-e58ea6828605", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "best_x: [1.01075314 0.99002837 0.00997163] \n", - " best_y: [2.00187751]\n" - ] - } - ], + "outputs": [], "source": [ "from sko.DE import DE\n", "\n", @@ -116,7 +107,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "03283268-a9af-4e26-a673-4c8225bf5fcb", "metadata": {}, "outputs": [], @@ -138,19 +129,10 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "id": "24da5ddc-04fe-4536-b5b9-48dca9a6118c", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "best_x: [-2.08616263e-07 -8.94069698e-08] \n", - " best_y: [0.]\n" - ] - } - ], + "outputs": [], "source": [ "from sko.GA import GA\n", "\n", @@ -161,23 +143,10 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "id": "2e4903dc-6eff-4087-a986-1f6cf3470645", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import pandas as pd\n", "import matplotlib.pyplot as plt\n", @@ -216,7 +185,7 @@ }, { "cell_type": "code", - "execution_count": 166, + "execution_count": null, "id": "740a307c-7f4d-4978-a561-2424309cc310", "metadata": {}, "outputs": [], @@ -241,7 +210,7 @@ }, { "cell_type": "code", - "execution_count": 182, + "execution_count": null, "id": "3b570dd4-09fa-41d8-8d80-ba0c6ae05fa5", "metadata": {}, "outputs": [], @@ -254,23 +223,10 @@ }, { "cell_type": "code", - "execution_count": 183, + "execution_count": null, "id": "c4af7656-ace9-4594-ac32-3ccd027c7811", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD4CAYAAADiry33AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAihUlEQVR4nO3dfbRcdX3v8fcnDyQNBIkkPOXMycE2VFJBsEfqWlCFVjDqvQnKWm3wlIurYKxKBUVbkCXa0PT6sBb13i4sRqBXb4ORK9gGjcaooAshmBOMpEkWEMODCamEJDyUh0DM9/6x9yQ7kznn7DlnzpnZez6vtWadmT17n/nNyeQzv/nu3/x+igjMzKy8xrW6AWZmNroc9GZmJeegNzMrOQe9mVnJOejNzEpuQqsbUGv69OnR09PT6mZYia1du/bpiJgx1o/r17aNpsFe120X9D09PfT397e6GVZikh5vxeP6tW2jabDXtUs3ZmYl56A3Mys5B72ZWck56K1jSapIukvSRkkbJF1eZ5/5kh6UtE5Sv6SzMvddLOmR9HLx2LbeLL+2OxlrNob2AldGxAOSpgJrJa2KiI2ZfX4ELI+IkHQqcBvwekmvBT4D9AKRHrs8InaP9ZMwG0oxevRLl0JPD4wbl/xcurTVLbISiIjtEfFAev15YBMws2af/4oDM/8dThLqAO8AVkXErjTcVwFzx6blZo1p/x790qWwcCG8+GJy+/HHk9sAfX2ta5eViqQe4HTg/jr3vQf4n8AxwLvTzTOBX2d220rNm0R67EJgIUB3d3dT22yWV/sH/TXXHAj5qhdfhL/+a9izByZPzn+ZNAnGj2/N8xiJpUuTv8MTT0B3Nyxe7De5JpJ0BHA7cEVEPFd7f0R8G/i2pLcC1wFvz/u7I2IJsASgt7fXc4JbS7R/0D/xRP3tu3fDJZc0/vsmTkwCv5E3iLxvInn2m9Dgn9yfaEaVpIkkIb80Iu4YbN+I+Kmk10maDmwDzs7c3QXcPVrtNBuJ9g/67u4k3Gp1dcE998DLL+e/7Nkz9D4vvAA7dw58/0gXahk/vrE3jn//9/qfaK65xkE/QpIE3AxsiojrB9jn94BfpSdj3wRMAnYCK4F/kDQt3fU84OoxaLZZw9o/6BcvPrhHCzBlCnzuczBr1ti2JQL27m3szaWRN5nq5ZlnDn7jqWegTzrWiDOBi4D1ktal2z4FdANExI3ABcD/kPQq8BLw5+nJ2V2SrgPWpMctiohdY9l4s7zaP+irvdYrroCnn4bjj4cvfrE1vVkpKf1MnAhTp47NY/b01P9E8zu/k/w9pk8fm3aUUETcA2iIfT4PfH6A+24BbhmFppk1VTGGV/b1wY03JtdXruysksXixcknmKyJE+Gll2DOHPjmN0deTjKzUitG0MOBk5h797a2HWOtrw+WLEnKVFLy81/+BX75y+T6ggVw/vnw5JOtbqmZtaniBH11WGSnBT0kYf/YY7BvX/Kzrw9OOQXuuy8pY/3gB0nv/qab3Ls3s0PkCnpJcyU9JGmzpKvq3P+P6Vwg6yQ9LOmZzH2/zdy3fNgt7dQe/WAmTIBPfALWr4fTToMPfADe/nbYsqXVLTOzNjJk0EsaD9wAvBOYA1woaU52n4j4WEScFhGnAf8EZMcjv1S9LyLmDbul1aD/7W+H/StK6/d+D3784+Q8xpo1SW//S1/y38rMgHw9+jOAzRGxJSJeAZYB8wfZ/0LgG81o3EE6uXSTx7hx8MEPwsaNcM458LGPwZlnwoYNrW6ZmbVYnqDPNacHgKRZwInAjzObJ6fTu66WdP4Axy1M9+nfsWNH/Va4dJNPVxfceWfyjdrNm+H00+G66+CVV1rdMjNrkWafjF0AfCsisjWDWRHRC7wP+JKk3609KCKWRERvRPTOmDHAms0u3eQnwfvel/TuL7gArr0W3vxm8HqlZh0pT9BvAyqZ213ptnoWUFO2iYht6c8tJHOBnN5wK8Glm+E45hj4xjeSaRSefhr+6I/gb/4mGYNvZh0jT9CvAWZLOlHSYSRhfsjoGUmvB6YB92W2TZM0Kb0+neQr5xtrj83FpZvhmzcvqdVfckkyHPPUU+EnP2l1q8xsjAwZ9BGxF7iMZBKnTcBtEbFB0iJJ2VE0C4BlmUUaAE4G+iX9ErgL+FzN6j35uXQzMkcdlXzx6kc/Ssbjn302fOhD8Nwhs/KaWcnkmusmIlYAK2q2XVtz+7N1jrsXOGUE7TvAPfrm+JM/gQcfhE9/OhmC+Z3vwFe+Au96V6tbZmajxN+M7USHHw7XXw/33gtHHgnvfjdcdFFSxzez0ilO0Lt003xveQs88EAyKmfZsmQahdtu8zQKZiVTvKB3j765Jk2Cv/s7WLs2mSTtz/8c3vMeT5JmViLFCXqXbkbXqacemCRt5cqkd3/zze7dm5VAcYLepZvRV50k7cEH4Y1vhEsvhXPP9SRpZgVXvKB3j370zZ4Nd90F//zP8POfe5I0s4IrTtC7dDO2xo2Dv/qr5ItWZ5+dTJJ21lnJtApmVijFCXqXblqjUknG2v/rv8Ijj3iSNLMCKl7Qu0c/9qRkVauNG+G97/UkaWYFU5ygd+mm9bKTpO3YkUyS9rd/60nSzNpccYLePfr2MW9e0rv/y7+EL3whGaHz05+2ulVmNoDiBP24cUkJwTX69nDUUfDVr8IPf5i8+b7tbfDhD3uSNLM2VJygh6R84x59e/nTP00WJ//Yx5I1a9/wBlixYujjzGzMFCvoJ0xw0Lej7CRpU6cemCRt585Wt8zMKGLQu3TTvqqTpH3608kkaSef7EnSzNpAsYLepZv2N2kSLFqUTJLW3Z1Mkvbe93qSNLMWKlbQu3RTHKeeCqtXJ6Nyvv99T5Jm1kLFC3qXbopjwgT45Cc9SZpZi+UKeklzJT0kabOkq+rc/4+S1qWXhyU9k7nvYkmPpJeLR9Ra9+iLyZOkmbXUkEEvaTxwA/BOYA5woaQ52X0i4mMRcVpEnAb8E3BHeuxrgc8AfwScAXxG0rRht9Y1+uLKTpL2trclwzH/+I89SZrZGMjToz8D2BwRWyLiFWAZMH+Q/S8EvpFefwewKiJ2RcRuYBUwd9itdemm+CoV+O53k0nSHn44mSTt7/8evv516OlJ3hB6emDp0la31Kw0JuTYZybw68ztrSQ99ENImgWcCPx4kGNn1jluIbAQoLu7e5DWunRTCtVJ0s49Fz760WQ4pnTgRO3jj8PChcn1vr7WtdOsJJp9MnYB8K2IaKjbHRFLIqI3InpnzJgx8I4u3ZTLMcck4+1nzDh0NM6LL8I117SmXWYlkyfotwGVzO2udFs9CzhQtmn02KG5dFNOTz9df/sTT4xtO8xKKk/QrwFmSzpR0mEkYb68didJrwemAfdlNq8EzpM0LT0Je166bXhcuimngcp1g5XxRkhSRdJdkjZK2iDp8jr79El6UNJ6SfdKemPmvsfS7eskeWJ+a2tDBn1E7AUuIwnoTcBtEbFB0iJJ8zK7LgCWRRz4DB4Ru4DrSN4s1gCL0m3D49JNOS1eDFOmHLxtypRk++jZC1wZEXOAtwAfqR1NBjwKvC0iTiF5HS+puf+cdLRZ72g21Gyk8pyMJSJWACtqtl1bc/uzAxx7C3DLMNt3MPfoy6l6wvWDH4QXXoBZs5KQH8UTsRGxHdieXn9e0iaSgQIbM/vcmzlkNUnp0axwcgV923CNvrz6+mDzZvjsZ5Nhl4cdNmYPLakHOB24f5DdLgG+l7kdwA8kBfCViKjt7Vd/d74RZWajqFhTILh0U26V9Lz9tuGfr2+UpCOA24ErIqLuqimSziEJ+r/NbD4rIt5E8kXCj0h6a71jc48oMxtFxQp6l27KrRr0v/714Ps1iaSJJCG/NCLuGGCfU4GbgPkRsX+C/YjYlv58Cvg2yRcLzdpS8YLepZvyGsOglyTgZmBTRFw/wD7dJNN5XBQRD2e2Hy5pavU6yWiy/xj1RpsNU7Fq9C7dlNvY9ujPBC4C1ktal277FNANEBE3AtcCRwNfTt4X2JuOsDkW+Ha6bQJwa0R8fywabTYcxQp6l27K7fDDYdq0MQn6iLgH0BD7XApcWmf7FuCNhx5h1p5curH2UqmMWY3erFMUL+jdoy83B71Z0xUr6F2jLz8HvVnTFSvoXbopv0oFdu5MZq80s6YoXtC7R19u1ZE3W7e2th1mJVKsoHfppvzG+EtTZp2gWEHv0k35OejNmq54Qe8efbnNTFeadNCbNU2xgt6lm/KbPDlZWtBBb9Y0xQp6l246Q6Xik7FmTVS8oHePvvw8lt6sqYoV9C7ddAYHvVlT5Qp6SXMlPSRps6SrBtjnzzILLd+a2f7bdAHldZIOWVS8IdXSzYFlaa2MKhV49ll4/vlWt8SsFIacvVLSeOAG4FxgK7BG0vKI2JjZZzZwNXBmROyWdEzmV7wUEac1p7Vpc/ftS3r3Vk7ZIZZzatfrNrNG5enRnwFsjogtEfEKsAyYX7PPB4AbImI37F91p/mq4e7yTbl5LL1ZU+UJ+plA9n/c1nRb1knASZJ+Jmm1pLmZ+yZL6k+3n1/vASQtTPfp37Fjx8AtqfboHfTl5qA3a6pmLTwyAZgNnA10AT+VdEpEPAPMiohtkl4H/FjS+oj4VfbgiFgCLAHo7e0duABfDXoPsSy3E04AyUFv1iR5evTbgErmdle6LWsrsDwiXo2IR4GHSYI/u4jyFuBu4PRht9alm84wcSIcf7yD3qxJ8gT9GmC2pBMlHQYsAGpHz/wbSW8eSdNJSjlbJE2TNCmz/UxgI8Pl0k3n8BBLs6YZMugjYi9wGbAS2ATcFhEbJC2SNC/dbSWwU9JG4C7gkxGxEzgZ6Jf0y3T757KjdRrm0k3ncNCbNU2uGn1ErABW1Gy7NnM9gI+nl+w+9wKnjLyZKffoO0elAitWJN+Z0KBreJvZEIr3zVhw0HeCSiVZZWr37la3xKzwihX0Lt10Dg+xNGuaYga9e/Tl19WV/PQslmYjVqygd+mmc7hHb9Y0xQp6l246x3HHJf/eDnqzEStm0LtHX37jxyffkHXQm41YsYLepZvO4rH0Zk1RrKB36aazOOjNmqKYQe8efWeorh3rhWbMRqRYQe/STWepVGDPHhhs6mozG1Kxgt49+s7iIZZmTVHMoHeNvjM46M2aolhB79JNZ3HQmzVFsYLepZvOMmMGTJrkoDcboWIGvUs3nUFK5rxx0JuNSDGD3j36zjGKY+klVSTdJWmjpA2SLq+zT5+kByWtl3SvpDdm7psr6SFJmyVdNSqNNGuCYgW9a/SdpzqWfnTsBa6MiDnAW4CPSJpTs8+jwNsi4hTgOtJF7CWNB24A3gnMAS6sc6xZWyhW0Lt003m6umDbtlH5N4+I7RHxQHr9eZKlMmfW7HNvRFRXP1kNpPMncwawOSK2RMQrwDJgftMbadYEuYI+z0dUSX+W+Qh8a2b7xZIeSS8Xj6i1Lt10nkol+ff+zW9G9WEk9QCnA/cPstslwPfS6zOBbE1pKzVvEunvXSipX1L/Dn/xy1pkyDVjMx9RzyV5Ma+RtDy7yLek2cDVwJkRsVvSMen21wKfAXqBANamxw5vfTiXbjpPdojlCSeMykNIOgK4HbgiIp4bYJ9zSIL+rEZ+d0QsIS339Pb2ei4Ha4k8Pfo8H1E/ANxQDfCIeCrd/g5gVUTsSu9bBcwddmtduuk8ozyWXtJEkpBfGhF3DLDPqcBNwPyI2Jlu3gZUMrt1pdvM2k6eoM/zEfUk4CRJP5O0WtLcBo7N//HWpZvOM4pBL0nAzcCmiLh+gH26gTuAiyLi4cxda4DZkk6UdBiwAFje9EaaNcGQpZsGfs9s4GySns1PJZ2S9+DcH29duuk806bBlCmj1aM/E7gIWC9pXbrtU0A3QETcCFwLHA18OXlfYG9E9EbEXkmXASuB8cAtEbFhNBppNlJ5gj7PR9StwP0R8SrwqKSHSYJ/G0n4Z4+9e7iNdemmA0mjNpY+Iu4BNMQ+lwKXDnDfCmBF0xtm1mR5Sjd5PqL+G2mgS5pOUsrZQtLbOU/SNEnTgPPSbcPj0k1n8gIkZiMyZNBHxF6g+hF1E3BbRGyQtEjSvHS3lcBOSRuBu4BPRsTOiNhF8iWTNellUbpteFy66UwOerMRyVWjr/cRNSKuzVwP4OPppfbYW4BbRtbMVDXoXbrpLJUKbN8Or74KEye2ujVmhVOsb8ZKSdi7R99ZKpVkOcEnn2x1S8wKqVmjbsaOg77zZIdYzprV2raMgr+7cwMbn6z7PS2zg8w54Ug+89//oOHjitWjh+SErIO+s3gBErMRKV6PfsIE1+g7TcmDfjg9NLNGFK9H79JN55k6FY48cjSnKzYrteIFvUs3nclDLM2GrZhB79JN53HQmw1bMYPePfrO46A3G7biBb1r9J2pUoGnnoI9e1rdErPCKV7Qu3TTmaojb3xC1qxhxQx69+g7T8mHWJqNpuIFvUs3nclBbzZsxQt6l246U1dX8tNBb9awYga9e/SdZ8oUOPpoB73ZMBQv6F266VweYmk2LMULepduOpeD3mxYihn07tF3Jge92bAUL+hduulclQrs3g0vvNDqlpgVSq6glzRX0kOSNku6qs7975e0Q9K69HJp5r7fZrbXLireOJduOpe/NGU2LEPORy9pPHADcC6wFVgjaXlEbKzZ9ZsRcVmdX/FSRJw24pZWuXTTubJDLH//91vbFrMCydOjPwPYHBFbIuIVYBkwf3SbNQiXbjqXvzRlNix5gn4mkP2ftTXdVusCSQ9K+pakSmb7ZEn9klZLOr/eA0hamO7Tv2PHjsFb4x5955qZvuwc9GYNadbJ2DuBnog4FVgFfC1z36yI6AXeB3xJ0u/WHhwRSyKiNyJ6Z8yYMfgjuUbfuSZNgmOPddCbNShP0G8Dsj30rnTbfhGxMyKq88feBPxh5r5t6c8twN3A6SNor0s3nc5DLM0alifo1wCzJZ0o6TBgAXDQ6BlJx2duzgM2pdunSZqUXp8OnAnUnsRtjEs3nc1Bb9awIUfdRMReSZcBK4HxwC0RsUHSIqA/IpYDH5U0D9gL7ALenx5+MvAVSftI3lQ+V2e0ToMtdummo1Uq8MMftroVZoUyZNADRMQKYEXNtmsz168Grq5z3L3AKSNs48Hco+9slQo8/zw8+yy85jWtbo1ZIfibsVYsHmJp1rDiBb1LN53NQW/WsGIGvXv0nctBb9aw4gW9Szed7fjjYdw4B71ZA4oX9C7ddLYJE+CEExz0Zg0oZtC7R9/ZPJberCHFC3qXbqxSGfFUxZIqku6StFHSBkmX19nn9ZLuk7RH0idq7ntM0vp0+u3+ETXGbJTlGkffViZMgAjYty+p1Vrn6eqCO+9MXgfScH/LXuDKiHhA0lRgraRVNV/o2wV8FDh/gN9xTkQ8PdwGmI2V4iXlhPS9yXX6zlWpwEsvwa5dw/4VEbE9Ih5Irz9PMm3HzJp9noqINcCrI2muWasVL+jHj09+unzTuZo8xFJSD8lke/c3cFgAP5C0VtLCQX53/im4zUZJ8YK+2qN30HeuJga9pCOA24ErIuK5Bg49KyLeBLwT+Iikt9bbqaEpuM1GSXGD3qWbztWkoJc0kSTkl0bEHY0cm5l++yng2yQrsZm1peIFvUs3duyxMHHiiIJekoCbgU0RcX2Dxx6ensBF0uHAecB/DLsxZqOsmKNuwEHfycaNS5YVHFmP/kzgImC9pHXptk8B3QARcaOk44B+4Ehgn6QrgDnAdODbyXsFE4BbI+L7I2mM2WgqbtC7dNPZRvilqYi4Bxh0bGZE/CfJimq1ngPeOOwHNxtjxSvduEdv4G/HmjWgeEHvGr3BgW/H7tvX6paYtb3iBb1LNwZJ0L/6Kjz1VKtbYtb2cgW9pLmSHpK0WdJVde5/v6Qd6bwf6yRdmrnvYkmPpJeLR9xil24MPC+9WQOGPBkraTxwA3AusBVYI2l5nUW+vxkRl9Uc+1rgM0AvyTcJ16bH7h52i126MTg46N/85ta2xazN5enRnwFsjogtEfEKsAyYn/P3vwNYFRG70nBfBcwdXlNTLt0YHAj6Ec5iadYJ8gT9TCD7+XgrNZM/pS6Q9KCkb0mqNHJsQ/OBuHRjAEcfDZMnu3RjlkOzTsbeCfRExKkkvfavNXJwQ/OBuHRjkExP3NXloDfLIU/QbwMqmdtd6bb9ImJnROxJb94E/GHeYxvm0o1VeSy9WS55gn4NMFvSiZIOAxYAy7M7SDo+c3MeydzeACuB8yRNkzSNZE6QlSNqsUs3VuWgN8tlyFE3EbFX0mUkAT0euCUiNkhaBPRHxHLgo5Lmkazaswt4f3rsLknXkbxZACyKiOGvFgEu3dgBlQo8+WTy6a76ujCzQ+Sa6yYiVgArarZdm7l+NXD1AMfeAtwygjYezKUbq6pUktfB9u1Jvd7M6iruN2Pdozd/acosl+IFvUs3VuWgN8uleEG/Mj2X+573QE8PLF3a0uZYCznozXIpVtAvXQqLFiXXI+Dxx2HhQod9p3rNa+CIIxz0ZkMoVtBfcw28/PLB2158MdlunUfyEEuzHIoV9E880dh2Kz8HvdmQihX03d2Nbbfyc9CbDalYQb94MUyZcvC2KVOS7daZKhX4zW/glVda3RKztlWsoO/rgyVLYNaspD47a1Zyu6+v1S2zVqlUkhPzTz7Z6paYta1c34xtK319DnY7oPqN2F//Ohlua2aHKFaP3qyWx9KbDclBb8XmoDcbkoPeiu2II+Cooxz0ZoNw0FvxeYil2aAc9FZ8DnqzQTnorfgc9GaDctBb8VUq8PTT8NJLrW6JWVty0FvxVUfebN3a2naYtalcQS9prqSHJG2WdNUg+10gKST1prd7JL0kaV16ubFZDTfbz0MszQY15DdjJY0HbgDOBbYCayQtj4iNNftNBS4H7q/5Fb+KiNOa01yzOhz0ZoPK06M/A9gcEVsi4hVgGTC/zn7XAZ8HXq5zn9noyU6DYGaHyBP0M4Hs/6Ct6bb9JL0JqETEd+scf6KkX0j6iaQ/rvcAkhZK6pfUv2PHjrxtN0tMngwzZjjozQYw4pOxksYB1wNX1rl7O9AdEacDHwdulXRk7U4RsSQieiOid8aMGSNtknWiSsUnY80GkCfotwGVzO2udFvVVOANwN2SHgPeAiyX1BsReyJiJ0BErAV+BZzUjIabHcRj6c0GlCfo1wCzJZ0o6TBgAbC8emdEPBsR0yOiJyJ6gNXAvIjolzQjPZmLpNcBs4EtTX8WZl1dDQe9pIqkuyRtlLRB0uV19nm9pPsk7ZH0iZr7co1GM2u1IUfdRMReSZcBK4HxwC0RsUHSIqA/IpYPcvhbgUWSXgX2AX8VEbua0XCzg1Qq8Mwz8F//lUx0ls9e4MqIeCAdNbZW0qqaEWW7gI8C52cPzDsazawd5Fp4JCJWACtqtl07wL5nZ67fDtw+gvaZ5ZMdYnnyybkOiYjtJOeRiIjnJW0iGWiwMbPPU8BTkt5dc/j+0WgAkqqj0Rz01nb8zVgrhxGOpZfUA5zOod8DGciQo9HM2oWD3sphBEEv6QiST55XRMRzzWyWhw5bO3DQWznMnJksGN/4CdmJJCG/NCLuaODQoUajAR46bO3BQW/lMHEiHHdcQ0EvScDNwKaIuL7BRxx0NJpZO8l1MtasEBofS38mcBGwXtK6dNungG6AiLhR0nFAP3AksE/SFcCciHiu3mi0pjwPsyZz0Ft5VCqwIX/WRsQ9gIbY5z9JyjL17jtkNJpZO3Lpxsqj2qOPaHVLzNqKg97Ko1KBF15IvjhlZvs56K08PC+9WV0OeisPLyloVpeD3srDPXqzuhz0Vh7HHQfjxzvozWo46K08xo+HE05w0JvVcNBbuXgBErNDOOitXBz0Zodw0Fu5VNeO9ZemzPZz0Fu5VCrw8svw9NOtbolZ23DQW7k8+mjy89hjoacHli5taXPM2kGuoM+7CLKkCySFpN7MtqvT4x6S9I5mNNqsrqVL4cYbk+sR8PjjsHChw9463pBBn1kE+Z3AHOBCSXPq7DcVuJzMUmzpfguAPwDmAl9Of59Z811zTVK2yXrxxWS7WQfL06PfvwhyRLwCVBdBrnUd8Hkg+z9tPrAsIvZExKPA5vT3mTXfE080tt2sQ+QJ+iEXQZb0JqASEd9t9Nj0eK+raSPX3d3YdrMOMeKTsZLGAdcDVw73d3hdTWuKxYthypSDt02Zkmw362B5gn6oRZCnAm8A7pb0GPAWYHl6QjbXAspmTdHXB0uWwKxZyULhs2Ylt/v6Wt0ys5bKs5Tg/kWQSUJ6AfC+6p0R8SwwvXpb0t3AJyKiX9JLwK2SrgdOAGYDP29e881q9PU52M1qDBn0EbG33iLIkhYB/RGxfJBjN0i6DdgI7AU+EhG/bVLbzcwsh1yLg9dbBDkirh1g37Nrbi8GXCQ1M2sRfzPWzKzkHPRmZiXnoDczKzlFm03nKmkH8PgoP8x0oNXTG7a6Da1+/Fa2YVZEjPkXNoZ4bbfDv8doKfNzg/Z5fgO+rtsu6MeCpP6I6B16z/K2odWP3y5taBdl/luU+blBMZ6fSzdmZiXnoDczK7lODfolrW4ArW9Dqx8f2qMN7aLMf4syPzcowPPryBq9mVkn6dQevZlZx3DQm5mVXKmDfqi1biV9XNJGSQ9K+pGkWWP5+Jn9DllrdyzbIOnP0r/DBkm3jnUbJHVLukvSL9J/i3c1uw3tKu9rpJ1JqqT/ftXX0OXp9tdKWiXpkfTntHS7JP3v9Dk/mC5c1NYkjU9fn99Jb58o6f70OXxT0mHp9knp7c3p/T0tbXhVRJTyQjLT5q+A1wGHAb8E5tTscw4wJb3+IeCbY/n46X5TgZ8Cq4HeFvwNZgO/AKalt49pQRuWAB9Kr88BHmv162csLnlfI+1+AY4H3pRenwo8nP47fgG4Kt1+FfD59Pq7gO8BIlm/4v5WP4ccz/HjwK3Ad9LbtwEL0us3Zl6/HwZuTK8vaGamjORS5h79kGvdRsRdEfFienM1ycIoY/b4qXpr7Y5lGz4A3BARuwEi4qkWtCGAI9PrrwGebHIb2lXe10hbi4jtEfFAev15YBPJkqHzga+lu30NOD+9Ph/4eiRWA0dJOn5sW52fpC7g3cBN6W0BfwJ8K92l9rlVn/O3gD9N92+pMgd9rvVqMy4h6WWM2eMPstbumLUBOAk4SdLPJK2WNLcFbfgs8BeStpJMh/3XTW5Du2r0Ndr20lLF6cD9wLERsT296z+BY9PrRXveXwL+BtiX3j4aeCYi9qa3s+3f/9zS+59N92+pMgd9bpL+AugFvjiGjznitXabZAJJ+eZs4ELgq5KOGuM2XAj8n4joIvlY/3/Tv48ViKQjgNuBKyLiuex9kdQyCjeWW9J/A56KiLWtbstIlPk/U671aiW9HbgGmBcRe8bw8Qdba3es2gBJb2R5RLwaEY+S1Fdnj3EbLiGpeRIR9wGTySxPWWKlWVNZ0kSSkF8aEXekm39TLcmkP6tlwSI97zOBeen/0WUkJZv/RVJuqi7clG3//ueW3v8aYOdYNriuVp8kGMWTJxOALcCJHDjR9Qc1+5xOcjJsdisev2b/u2n+ydg8f4O5wNfS69NJPnYePcZt+B7w/vT6ySQ1erX6NTTal0ZfI+16ITmp+nXgSzXbv8jBJ2O/kF5/NwefjP15q59Dzud5NgdOxv4/Dj4Z++H0+kc4+GTsba1ud0SUN+jTP/S7SHqovwKuSbctIum9A/wQ+A2wLr0sH8vHr9m36UGf828gkhLSRmB99cU7xm2YA/wsDbp1wHmtfu208jVatAtwFklZ5sHM/6V3kdSmfwQ8kv5fe23mNXdD+pzXj8brfpSeZzboXwf8HNichv6kdPvk9Pbm9P7XtbrdEeEpEMzMyq7MNXozM8NBb2ZWeg56M7OSc9CbmZWcg97MrOQc9GZmJeegNzMruf8PU+2ufdlBR3MAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "fig, ax = plt.subplots(1, 2)\n", "best_points_ = np.concatenate([best_points])\n", @@ -315,7 +271,7 @@ }, { "cell_type": "code", - "execution_count": 180, + "execution_count": null, "id": "5127a9e8-17a8-4a07-b825-2aaf11a6270e", "metadata": {}, "outputs": [], @@ -331,23 +287,10 @@ }, { "cell_type": "code", - "execution_count": 181, + "execution_count": null, "id": "c9b939a8-3a5f-41d6-8263-25dacebc4602", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "fig, ax = plt.subplots(1, 2)\n", "best_points_ = np.concatenate([best_x, [best_x[0]]])\n", -- cgit v1.2.3 From 2e0e9e102313ff7b0c040aa7008be59263f40731 Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Fri, 22 Apr 2022 00:17:22 -0500 Subject: Stop tracking test/.ipynb_checkpoints --- test/.ipynb_checkpoints/GA-checkpoint.ipynb | 112 ---------------------------- 1 file changed, 112 deletions(-) delete mode 100644 test/.ipynb_checkpoints/GA-checkpoint.ipynb (limited to 'test') diff --git a/test/.ipynb_checkpoints/GA-checkpoint.ipynb b/test/.ipynb_checkpoints/GA-checkpoint.ipynb deleted file mode 100644 index bab966d..0000000 --- a/test/.ipynb_checkpoints/GA-checkpoint.ipynb +++ /dev/null @@ -1,112 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "2fd45b3a-9a24-4782-812c-08223edb750e", - "metadata": {}, - "source": [ - "# Prueba del algoritmo genetico" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f6b4829a-9001-410c-b20c-01c65c777d8a", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "511ff788-0d1a-4ac7-9575-de182d236574", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "078280b5-70ef-4691-8798-a686d85d188c", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b3ad92de-b2ed-4f21-a696-1fa2981f89dc", - "metadata": {}, - "outputs": [], - "source": [ - "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", - " \"Algoritmo Genetico \"\n", - " \n", - " popsize = len(population)\n", - " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", - " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", - " bestfitness = [population[ibest[0]].fitness]\n", - " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", - " \n", - " for g in range(ngen): # Por cada generacion\n", - " \n", - " ## Selecciona las parejas de padres para cruzamiento \n", - " mating_pool = []\n", - " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", - " \n", - " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", - " offspring_population = []\n", - " for i in range(len(mating_pool)): \n", - " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", - " offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", - "\n", - " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", - " for i in range(len(offspring_population)):\n", - " if random.uniform(0, 1) < pmut: \n", - " offspring_population[i] = offspring_population[i].mutate_position()\n", - " \n", - " ## Evalua la poblacion descendencia\n", - " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", - " \n", - " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", - " population = select_survivors(population, offspring_population, popsize)\n", - "\n", - " ## Almacena la historia del fitness del mejor individuo\n", - " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", - " bestfitness.append(population[ibest[0]].fitness)\n", - " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", - " \n", - " return population[ibest[0]], bestfitness " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} -- cgit v1.2.3 From 76292bcc75723ad0e31be0c066800d792de8d720 Mon Sep 17 00:00:00 2001 From: Mitsuo Tokumori Date: Thu, 5 May 2022 22:39:23 -0500 Subject: Clear clutter. No more test/data/ directory --- test/GA.ipynb | 361 ------------------------ test/TSP.ipynb | 325 ---------------------- test/VRPTW_GA.ipynb | 724 ------------------------------------------------ test/data/RC101.csv | 102 ------- test/mitsuo.ipynb | 771 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 771 insertions(+), 1512 deletions(-) delete mode 100644 test/GA.ipynb delete mode 100644 test/TSP.ipynb delete mode 100644 test/VRPTW_GA.ipynb delete mode 100644 test/data/RC101.csv create mode 100644 test/mitsuo.ipynb (limited to 'test') diff --git a/test/GA.ipynb b/test/GA.ipynb deleted file mode 100644 index 9d73164..0000000 --- a/test/GA.ipynb +++ /dev/null @@ -1,361 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "2fd45b3a-9a24-4782-812c-08223edb750e", - "metadata": {}, - "source": [ - "# Prueba del algoritmo genetico" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "45972b70-b2a6-48f2-aafa-9f660548079a", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import random" - ] - }, - { - "cell_type": "markdown", - "id": "34eab22f-a400-4a14-9ac4-047d87dff69f", - "metadata": {}, - "source": [ - "Data" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "id": "a5736dba-4c38-4b7f-9a1a-963bdb006236", - "metadata": {}, - "outputs": [], - "source": [ - "class Ciudad:\n", - " regiones = {\n", - " 'costa': {\n", - " 'plazoentrega': 1\n", - " },\n", - " 'sierra': {\n", - " 'plazoentrega': 2\n", - " },\n", - " 'selva': {\n", - " 'plazoentrega': 3\n", - " }\n", - " }\n", - " def __init__(self, nombre, region, longitud, latitud):\n", - " self.nombre = nombre\n", - " self.region = region\n", - " self.x = longitud\n", - " self.y = latitud" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "id": "8ee9610f-d128-4d1b-9458-ca9048073f20", - "metadata": {}, - "outputs": [], - "source": [ - "class Road_network:\n", - " def __init__(self, cities, distances):\n", - " \"\"\"Grafo completo del pais\n", - " \n", - " Params\n", - " ------\n", - " \n", - " cities: list\n", - " Lista de objetos Ciudad\n", - " \n", - " routes: dict\n", - " (Aun no se como implementar esto)\n", - " \"\"\"\n", - " \n", - " self.cities = cities\n", - " self.routes = {}" - ] - }, - { - "cell_type": "code", - "execution_count": 102, - "id": "7dd72c93-acba-46f9-ac99-8c3d1a8cfa67", - "metadata": {}, - "outputs": [], - "source": [ - "class Vehiculo:\n", - " tipos = {\n", - " 1: {\n", - " 'cargamax': 50\n", - " },\n", - " 2: {\n", - " 'cargamax': 100\n", - " },\n", - " 3: {\n", - " 'cargamax': 200\n", - " }\n", - " }\n", - " \n", - " def __init__(self):\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": 96, - "id": "474a3596-f75d-411e-bf4c-20b8b8259434", - "metadata": {}, - "outputs": [], - "source": [ - "class Pedido:\n", - " def __init__(self, cliente, cantidad):\n", - " self.cliente = cliente\n", - " self.cantidad = cantidad" - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "id": "7602722f-9026-44dc-b922-e17a7d3af45b", - "metadata": {}, - "outputs": [], - "source": [ - "class Cliente:\n", - " def __init__(self, nombre, ciudad):\n", - " self.nombre = nombre\n", - " self.ciudad = ciudad" - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "id": "f6b4829a-9001-410c-b20c-01c65c777d8a", - "metadata": {}, - "outputs": [], - "source": [ - "class VRP:\n", - " def __init__(self):\n", - " # Conjuntos\n", - " self.I = range(2)\n", - " self.J = range(3)\n", - " self.T = range(5) # en horas\n", - " self.V = range(3) # 3 tipos de vehiculos\n", - " \n", - " def init_data(self):\n", - " \"\"\"\n", - " Lista los parametros iniciales, definidos en \"Modelo Matematico\" en ISA v02\n", - " \n", - " i: almacen grande (depot)\n", - " j: almacen pequeño (customer)\n", - " v: tipo de vehiculo\n", - " t: tiempo\n", - " \"\"\"\n", - " # Parametros\n", - " # Nombres cortos confunden, pero matrices de varias dimensiones \n", - " # sin etiquetas confunden mas\n", - " \n", - " # Demanda\n", - " self.D_jt = [ [ random.choice([0,1,2,3]) for _ in self.I ] for _ in self.T ]\n", - " # Capacidades de vehiculos\n", - " self.VL_v = [ random.choice([10, 15, 20]) for _ in self.V ]\n", - " # distancia entre almacen i, j\n", - " self.d_ij = [ random.choice([25,50,100]) for _ in self.V ]\n", - " #self.r_ijvt = [ [ 0 for _ in self.V ] for " - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "id": "ab559513-5c14-4dd2-a51d-7737114dfba1", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([10, 10, 15])" - ] - }, - "execution_count": 82, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p = VRP()\n", - "p.init_data()\n", - "np.array(p.VL_v)" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "id": "2c3c85e0-a90c-4fda-86f7-778d7328c74d", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[25, 50, 50]" - ] - }, - "execution_count": 83, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "p.d_ij" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "511ff788-0d1a-4ac7-9575-de182d236574", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "078280b5-70ef-4691-8798-a686d85d188c", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "611c9a0d-bb1a-48eb-af37-f033abe8ed66", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "64c68216-b9f1-45f9-a0fe-3862ab106c24", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9cb6bb08-1547-4b64-993f-b2c453535264", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b83d9e98-db8f-45cd-9eff-07d4194f7e07", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b8c06031-9c55-4e13-a27b-91b0886902e6", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e9483c22-243f-44e5-9a6d-09da92354554", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12952643-4a10-40bf-8af3-41319c744732", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b0306c4f-eb68-4009-9390-0f881c6a8cb4", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b3ad92de-b2ed-4f21-a696-1fa2981f89dc", - "metadata": {}, - "outputs": [], - "source": [ - "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", - " \"Algoritmo Genetico \"\n", - " \n", - " popsize = len(population)\n", - " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", - " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", - " bestfitness = [population[ibest[0]].fitness]\n", - " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", - " \n", - " for g in range(ngen): # Por cada generacion\n", - " \n", - " ## Selecciona las parejas de padres para cruzamiento \n", - " mating_pool = []\n", - " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", - " \n", - " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", - " offspring_population = []\n", - " for i in range(len(mating_pool)): \n", - " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", - " offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", - "\n", - " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", - " for i in range(len(offspring_population)):\n", - " if random.uniform(0, 1) < pmut: \n", - " offspring_population[i] = offspring_population[i].mutate_position()\n", - " \n", - " ## Evalua la poblacion descendencia\n", - " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", - " \n", - " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", - " population = select_survivors(population, offspring_population, popsize)\n", - "\n", - " ## Almacena la historia del fitness del mejor individuo\n", - " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", - " bestfitness.append(population[ibest[0]].fitness)\n", - " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", - " \n", - " return population[ibest[0]], bestfitness " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/test/TSP.ipynb b/test/TSP.ipynb deleted file mode 100644 index 476619b..0000000 --- a/test/TSP.ipynb +++ /dev/null @@ -1,325 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "234feb6e-4c52-443c-a3d6-6da8e903dd5c", - "metadata": {}, - "source": [ - "Travelling salesman problem\n", - "\n", - "TSP es *casi* (multi-depot) VRPTW pero:\n", - "- Solo 1 camion\n", - "- Todos los ciudades (aka. almacenes pequeños) tienen al menos 1 pedido\n", - "- Capacidad infinita\n", - "- Sin ventanas de tiempo (aka. plazos de entrega)\n", - "- Solo 1 deposito\n", - "\n", - "Cambios identificados, necesarios para adaptar el TSP a nuestro caso:\n", - "- Tramos no conectados -> distancia grande entre ellos\n", - "- Distancias no son euclidianas, usar \"geodistance\"\n", - "- [...]\n", - "\n", - "Refs:\n", - "\n", - "- [scikit-opt](https://github.com/guofei9987/scikit-opt)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "934ae28c-ccc1-4e63-832c-4f53ceb13f50", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "0fb6e4d9-d0cd-438c-b0a1-21a85a23de89", - "metadata": {}, - "source": [ - "Differential Evolution scikit-opt example" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eda106bc-2411-4ace-acf0-d2b66dc2d127", - "metadata": {}, - "outputs": [], - "source": [ - "'''\n", - "min f(x1, x2, x3) = x1^2 + x2^2 + x3^2\n", - "s.t.\n", - " x1*x2 >= 1\n", - " x1*x2 <= 5\n", - " x2 + x3 = 1\n", - " 0 <= x1, x2, x3 <= 5\n", - "'''\n", - "\n", - "\n", - "def obj_func(p):\n", - " x1, x2, x3 = p\n", - " return x1 ** 2 + x2 ** 2 + x3 ** 2\n", - "\n", - "\n", - "constraint_eq = [\n", - " lambda x: 1 - x[1] - x[2]\n", - "]\n", - "\n", - "# r(x1, x2, x3) >= 0\n", - "constraint_ueq = [\n", - " lambda x: 1 - x[0] * x[1],\n", - " lambda x: x[0] * x[1] - 5\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b3dcfaf-ab6b-42b7-9218-e58ea6828605", - "metadata": {}, - "outputs": [], - "source": [ - "from sko.DE import DE\n", - "\n", - "de = DE(func=obj_func, n_dim=3, size_pop=50, max_iter=800, lb=[0, 0, 0], ub=[5, 5, 5],\n", - " constraint_eq=constraint_eq, constraint_ueq=constraint_ueq)\n", - "\n", - "best_x, best_y = de.run()\n", - "print('best_x:', best_x, '\\n', 'best_y:', best_y)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9b49859f-c3a3-49a4-a605-5ec880556dc5", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "7563715b-c74b-4010-98c5-28c1e5b1410d", - "metadata": {}, - "source": [ - "Genetic Algorithm" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "03283268-a9af-4e26-a673-4c8225bf5fcb", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "\n", - "\n", - "def schaffer(p):\n", - " '''\n", - " This function has plenty of local minimum, with strong shocks\n", - " global minimum at (0,0) with value 0\n", - " https://en.wikipedia.org/wiki/Test_functions_for_optimization\n", - " '''\n", - " x1, x2 = p\n", - " part1 = np.square(x1) - np.square(x2)\n", - " part2 = np.square(x1) + np.square(x2)\n", - " return 0.5 + (np.square(np.sin(part1)) - 0.5) / np.square(1 + 0.001 * part2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "24da5ddc-04fe-4536-b5b9-48dca9a6118c", - "metadata": {}, - "outputs": [], - "source": [ - "from sko.GA import GA\n", - "\n", - "ga = GA(func=schaffer, n_dim=2, size_pop=50, max_iter=800, prob_mut=0.001, lb=[-1, -1], ub=[1, 1], precision=1e-7)\n", - "best_x, best_y = ga.run()\n", - "print('best_x:', best_x, '\\n', 'best_y:', best_y)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2e4903dc-6eff-4087-a986-1f6cf3470645", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "import matplotlib.pyplot as plt\n", - "\n", - "# col: individuos, row: iterations\n", - "Y_history = pd.DataFrame(ga.all_history_Y)\n", - "fig, ax = plt.subplots(2, 1)\n", - "ax[0].plot(Y_history.index, Y_history.values, '.', color='red')\n", - "Y_history.min(axis=1).cummin().plot(kind='line')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bdfb384b-b2b5-4755-b869-3a1da68cedd9", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "730c1714-7f9d-427a-9ecd-eecd416c293d", - "metadata": {}, - "source": [ - "TSP" - ] - }, - { - "cell_type": "markdown", - "id": "9fb2ef00-3c16-4986-afa1-428fc43f5d36", - "metadata": {}, - "source": [ - "\"geodistance\" (using longitude, latitude): https://stackoverflow.com/questions/31632190/measuring-geographic-distance-with-scipy" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "740a307c-7f4d-4978-a561-2424309cc310", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "from scipy import spatial\n", - "import matplotlib.pyplot as plt\n", - "\n", - "num_points = 5\n", - "\n", - "points_coordinate = np.random.rand(num_points, 2) # generate coordinate of points\n", - "distance_matrix = spatial.distance.cdist(points_coordinate, points_coordinate, metric='euclidean')\n", - "\n", - "\n", - "def cal_total_distance(routine):\n", - " '''The objective function. input routine, return total distance.\n", - " cal_total_distance(np.arange(num_points))\n", - " '''\n", - " num_points, = routine.shape\n", - " return sum([distance_matrix[routine[i % num_points], routine[(i + 1) % num_points]] for i in range(num_points)])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3b570dd4-09fa-41d8-8d80-ba0c6ae05fa5", - "metadata": {}, - "outputs": [], - "source": [ - "from sko.GA import GA_TSP\n", - "\n", - "ga_tsp = GA_TSP(func=cal_total_distance, n_dim=num_points, size_pop=50, max_iter=500, prob_mut=1)\n", - "best_points, best_distance = ga_tsp.run()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c4af7656-ace9-4594-ac32-3ccd027c7811", - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots(1, 2)\n", - "best_points_ = np.concatenate([best_points])\n", - "# \"path\"\n", - "best_points_coordinate = points_coordinate[best_points_, :]\n", - "ax[0].plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r')\n", - "ax[1].plot(ga_tsp.generation_best_Y)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f361519e-2397-4b70-be35-45dd14cc15af", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "40f6c413-89f8-4934-a165-1183fc5458eb", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "089bbdae-063a-4a5c-8f7a-fb8bb26dc83c", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f7266973-639c-42f9-86b6-3369ba04d03c", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5127a9e8-17a8-4a07-b825-2aaf11a6270e", - "metadata": {}, - "outputs": [], - "source": [ - "from sko.ACA import ACA_TSP\n", - "\n", - "aca = ACA_TSP(func=cal_total_distance, n_dim=num_points,\n", - " size_pop=50, max_iter=200,\n", - " distance_matrix=distance_matrix)\n", - "\n", - "best_x, best_y = aca.run()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c9b939a8-3a5f-41d6-8263-25dacebc4602", - "metadata": {}, - "outputs": [], - "source": [ - "fig, ax = plt.subplots(1, 2)\n", - "best_points_ = np.concatenate([best_x, [best_x[0]]])\n", - "best_points_coordinate = points_coordinate[best_points_, :]\n", - "ax[0].plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r')\n", - "pd.DataFrame(aca.y_best_history).cummin().plot(ax=ax[1])\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/test/VRPTW_GA.ipynb b/test/VRPTW_GA.ipynb deleted file mode 100644 index 042836e..0000000 --- a/test/VRPTW_GA.ipynb +++ /dev/null @@ -1,724 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# APLICACIONES EN CIENCIAS DE COMPUTACION\n", - "Dr. Edwin Villanueva" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "tags": [] - }, - "source": [ - "## Algoritmo genetico para resolver el VRPTW\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 140, - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "import matplotlib.pyplot as plt\n", - "import csv" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Clase abstracta de un individuo de algoritmo genético" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "class Individual:\n", - " \"Clase abstracta para individuos de un algoritmo evolutivo.\"\n", - "\n", - " def __init__(self, chromosome):\n", - " self.chromosome = chromosome\n", - "\n", - " def crossover(self, other):\n", - " \"Retorna un nuevo individuo cruzando self y other.\"\n", - " raise NotImplementedError\n", - " \n", - " def mutate(self):\n", - " \"Cambia los valores de algunos genes.\"\n", - " raise NotImplementedError " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Clase concreta de un individuo del problema de las n-reinas" - ] - }, - { - "cell_type": "code", - "execution_count": 105, - "metadata": {}, - "outputs": [], - "source": [ - "class Individual_VRPTW(Individual):\n", - " \"Clase que implementa el individuo en VRPTW.\"\n", - "\n", - " def __init__(self, chromosome):\n", - " self.chromosome = chromosome[:]\n", - " self.fitness = -1\n", - " \n", - " def crossover_order(self, other):\n", - " \"\"\"\n", - " Copies a part of the child chromosome from the first parent and constructs \n", - " the remaining part by following the vertex ordering in the second parent\n", - " \"\"\"\n", - " cut_point1 = random.randrange(0, len(self.chromosome) + 1)\n", - " cut_point2 = random.randrange(cut_point1, len(self.chromosome) + 1)\n", - " \n", - " c1 = self.chromosome[:]\n", - " c2 = other.chromosome[:]\n", - " p1_rem = self.chromosome[:cut_point1] + self.chromosome[cut_point2:]\n", - " p2_rem = other.chromosome[:cut_point1] + other.chromosome[cut_point2:]\n", - " # Change the genes in the remaining part of the child...\n", - " for i in range(len(self.chromosome)):\n", - " if i not in range(cut_point1, cut_point2):\n", - " # ...following the vertex ordering in the second parent\n", - " for gene in other.chromosome:\n", - " if gene in p1_rem:\n", - " c1.chromosome[i] = gene\n", - " \n", - " # (now for the other child)\n", - " for gene in self.chromosome:\n", - " if gene in p2_rem:\n", - " c2.chromosome[i] = gene\n", - " \n", - " return [Individual_VRPTW(c1), Individual_VRPTW(c2)]\n", - " \n", - "\n", - " def crossover_onepoint(self, other):\n", - " \"Retorna dos nuevos individuos del cruzamiento de un punto entre self y other \"\n", - " c = random.randrange(len(self.chromosome))\n", - " ind1 = Individual_VRPTW(self.chromosome[:c] + other.chromosome[c:])\n", - " ind2 = Individual_VRPTW(other.chromosome[:c] + self.chromosome[c:])\n", - " return [ind1, ind2] \n", - " \n", - " def crossover_uniform(self, other):\n", - " chromosome1 = []\n", - " chromosome2 = []\n", - " \"Retorna dos nuevos individuos del cruzamiento uniforme entre self y other \"\n", - " for i in range(len(self.chromosome)):\n", - " if random.uniform(0, 1) < 0.5:\n", - " chromosome1.append(self.chromosome[i])\n", - " chromosome2.append(other.chromosome[i])\n", - " else:\n", - " chromosome1.append(other.chromosome[i])\n", - " chromosome2.append(self.chromosome[i])\n", - " ind1 = Individual_VRPTW(chromosome1)\n", - " ind2 = Individual_VRPTW(chromosome2)\n", - " return [ind1, ind2] \n", - "\n", - " def mutate_position(self):\n", - " mutated_ind = Individual_VRPTW(self.chromosome[:])\n", - " indexPos = random.randint(0, len(mutated_ind.chromosome)-1)\n", - " newPos = random.randint(0, len(mutated_ind.chromosome)-1)\n", - " mutated_ind.chromosome[indexPos] = newPos\n", - " return mutated_ind\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Funcion de fitness para evaluar un individuo del problema de las n-reinas" - ] - }, - { - "cell_type": "code", - "execution_count": 109, - "metadata": {}, - "outputs": [], - "source": [ - "def fitness_VRPTW(chromosome):\n", - " \"\"\"Retorna el fitness de un cromosoma en el problema VRPTW (distancia total de todas las rutas) \"\"\"\n", - " n = len(chromosome) # No. of vertices\n", - " fitness = 10**6\n", - " # feasibility\n", - " # TODO: considerar todas las restricciones\n", - " # desirability\n", - " for i in range(0, n):\n", - " fitness -= distancia[i][i + 1]\n", - " \n", - " return fitness" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Funcion para evaluar toda una población de individuos con la funcion de fitnes especificada" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "def evaluate_population(population, fitness_fn):\n", - " \"\"\" Evalua una poblacion de individuos con la funcion de fitness pasada \"\"\"\n", - " popsize = len(population)\n", - " for i in range(popsize):\n", - " if population[i].fitness == -1: # si el individuo no esta evaluado\n", - " population[i].fitness = fitness_fn(population[i].chromosome)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Funcion que selecciona con el metodo de la ruleta un par de individuos de population para cruzamiento " - ] - }, - { - "cell_type": "code", - "execution_count": 103, - "metadata": {}, - "outputs": [], - "source": [ - "def select_parents_roulette(population):\n", - " popsize = len(population)\n", - " \n", - " # Escoje el primer padre\n", - " sumfitness = sum([indiv.fitness for indiv in population]) # suma total del fitness de la poblacion\n", - " pickfitness = random.uniform(0, sumfitness) # escoge un numero aleatorio entre 0 y sumfitness\n", - " cumfitness = 0 # fitness acumulado\n", - " for i in range(popsize):\n", - " cumfitness += population[i].fitness\n", - " if cumfitness > pickfitness: \n", - " iParent1 = i\n", - " break\n", - " \n", - " # Escoje el segundo padre, desconsiderando el padre ya escogido\n", - " sumfitness = sumfitness - population[iParent1].fitness # retira el fitness del padre ya escogido\n", - " pickfitness = random.uniform(0, sumfitness) # escoge un numero aleatorio entre 0 y sumfitness\n", - " cumfitness = 0 # fitness acumulado\n", - " for i in range(popsize):\n", - " if i == iParent1: continue # si es el primer padre \n", - " cumfitness += population[i].fitness\n", - " if cumfitness > pickfitness: \n", - " iParent2 = i\n", - " break \n", - " return (population[iParent1], population[iParent2])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Funcion que selecciona sobrevivientes para la sgte generacion, dada la poblacion actual y poblacion de hijos " - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "def select_survivors(population, offspring_population, numsurvivors):\n", - " next_population = []\n", - " population.extend(offspring_population) # une las dos poblaciones\n", - " isurvivors = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:numsurvivors]\n", - " for i in range(numsurvivors): next_population.append(population[isurvivors[i]])\n", - " return next_population" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Algoritmo Genetico \n", - "Recibe una poblacion inicial, funcion de fitness, numero de generaciones (ngen) y taza de mutación (pmut)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "def genetic_algorithm(population, fitness_fn, ngen=100, pmut=0.1):\n", - " \"Algoritmo Genetico \"\n", - " \n", - " popsize = len(population)\n", - " evaluate_population(population, fitness_fn) # evalua la poblacion inicial\n", - " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", - " bestfitness = [population[ibest[0]].fitness]\n", - " print(\"Poblacion inicial, best_fitness = {}\".format(population[ibest[0]].fitness))\n", - " \n", - " for g in range(ngen): # Por cada generacion\n", - " \n", - " ## Selecciona las parejas de padres para cruzamiento \n", - " mating_pool = []\n", - " for i in range(int(popsize/2)): mating_pool.append(select_parents_roulette(population)) \n", - " \n", - " ## Crea la poblacion descendencia cruzando las parejas del mating pool con Recombinación de 1 punto\n", - " offspring_population = []\n", - " for i in range(len(mating_pool)): \n", - " #offspring_population.extend( mating_pool[i][0].crossover_onepoint(mating_pool[i][1]) )\n", - " #offspring_population.extend( mating_pool[i][0].crossover_uniform(mating_pool[i][1]) )\n", - " offspring_population.extend( mating_pool[i][0].crossover_order(mating_pool[i][1]) )\n", - "\n", - " ## Aplica el operador de mutacion con probabilidad pmut en cada hijo generado\n", - " for i in range(len(offspring_population)):\n", - " if random.uniform(0, 1) < pmut: \n", - " offspring_population[i] = offspring_population[i].mutate_position()\n", - " \n", - " ## Evalua la poblacion descendencia\n", - " evaluate_population(offspring_population, fitness_fn) # evalua la poblacion inicial\n", - " \n", - " ## Selecciona popsize individuos para la sgte. generación de la union de la pob. actual y pob. descendencia\n", - " population = select_survivors(population, offspring_population, popsize)\n", - "\n", - " ## Almacena la historia del fitness del mejor individuo\n", - " ibest = sorted(range(len(population)), key=lambda i: population[i].fitness, reverse=True)[:1]\n", - " bestfitness.append(population[ibest[0]].fitness)\n", - " print(\"generacion {}, best_fitness = {}\".format(g, population[ibest[0]].fitness))\n", - " \n", - " return population[ibest[0]], bestfitness " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - " Algoritmo de Busqueda Genetica para el VRPTW " - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "metadata": {}, - "outputs": [], - "source": [ - "def genetic_algorithm_VRPTW(fitness_fn, num_depots=1, num_vehicles=1, vehicle_capacity=200, popsize=10, ngen=1000, pmut=0):\n", - " population = []\n", - " \n", - " # Crea la poblacion inicial con cromosomas aleatorios\n", - " for i in range(popsize):\n", - " chromosome = [j for j in range(1,num_vertices+1)]\n", - " random.shuffle(chromosome)\n", - " population.append(Individual_VRPTW(chromosome))\n", - " \n", - " return genetic_algorithm(population, fitness_fn, ngen, pmut)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "def genetic_search_nqueens(fitness_fn, num_queens=10, popsize=10, ngen=100, pmut=0.5):\n", - " import random\n", - " population = []\n", - "\n", - " ## Crea la poblacion inicial con cromosomas aleatorios\n", - " for i in range(popsize):\n", - " chromosome = [j for j in range(1,num_queens+1)]\n", - " random.shuffle(chromosome)\n", - " population.append( Individual_nqueens(chromosome) )\n", - " \n", - " ## Crea la poblacion inicial con los siguientes cromosomas \n", - " #chromosomes = [[1,3,1,3,1,3,1,3,1,3],\n", - " # [2,4,2,4,2,4,2,4,2,4],\n", - " # [3,5,3,5,3,5,3,5,3,5],\n", - " # [4,6,4,6,4,6,4,6,4,6],\n", - " # [5,7,5,7,5,7,5,7,5,7],\n", - " # [6,8,6,8,6,8,6,8,6,8],\n", - " # [7,9,7,9,7,9,7,9,7,9],\n", - " # [8,10,8,10,8,10,8,10,8,10],\n", - " # [9,1,9,1,9,1,9,1,9,1],\n", - " # [10,2,10,2,10,2,10,2,10,2] ] \n", - " #for i in range(popsize):\n", - " # population.append( Individual_nqueens(chromosomes[i]) ) \n", - " \n", - " ## llama al algoritmo genetico para encontrar una solucion al problema de las n reinas\n", - " return genetic_algorithm(population, fitness_fn, ngen, pmut)\n", - " " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Probando el Algoritmo genetico" - ] - }, - { - "cell_type": "code", - "execution_count": 115, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'distancia' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Input \u001b[0;32mIn [115]\u001b[0m, in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpyplot\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mplt\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# busca solucion para el problema de 10 reinas. Usa 100 individuos aleatorios, 100 generaciones y taza de mutación de 0.5\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m best_ind, bestfitness \u001b[38;5;241m=\u001b[39m \u001b[43mgenetic_algorithm_VRPTW\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfitness_VRPTW\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 5\u001b[0m plt\u001b[38;5;241m.\u001b[39mplot(bestfitness)\n\u001b[1;32m 6\u001b[0m plt\u001b[38;5;241m.\u001b[39mshow()\n", - "Input \u001b[0;32mIn [113]\u001b[0m, in \u001b[0;36mgenetic_algorithm_VRPTW\u001b[0;34m(fitness_fn, num_vertices, num_depots, num_vehicles, popsize, ngen, pmut)\u001b[0m\n\u001b[1;32m 7\u001b[0m random\u001b[38;5;241m.\u001b[39mshuffle(chromosome)\n\u001b[1;32m 8\u001b[0m population\u001b[38;5;241m.\u001b[39mappend(Individual_VRPTW(chromosome))\n\u001b[0;32m---> 10\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mgenetic_algorithm\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpopulation\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfitness_fn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mngen\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpmut\u001b[49m\u001b[43m)\u001b[49m\n", - "Input \u001b[0;32mIn [10]\u001b[0m, in \u001b[0;36mgenetic_algorithm\u001b[0;34m(population, fitness_fn, ngen, pmut)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAlgoritmo Genetico \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 4\u001b[0m popsize \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlen\u001b[39m(population)\n\u001b[0;32m----> 5\u001b[0m \u001b[43mevaluate_population\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpopulation\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfitness_fn\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# evalua la poblacion inicial\u001b[39;00m\n\u001b[1;32m 6\u001b[0m ibest \u001b[38;5;241m=\u001b[39m \u001b[38;5;28msorted\u001b[39m(\u001b[38;5;28mrange\u001b[39m(\u001b[38;5;28mlen\u001b[39m(population)), key\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m i: population[i]\u001b[38;5;241m.\u001b[39mfitness, reverse\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)[:\u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 7\u001b[0m bestfitness \u001b[38;5;241m=\u001b[39m [population[ibest[\u001b[38;5;241m0\u001b[39m]]\u001b[38;5;241m.\u001b[39mfitness]\n", - "Input \u001b[0;32mIn [7]\u001b[0m, in \u001b[0;36mevaluate_population\u001b[0;34m(population, fitness_fn)\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(popsize):\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m population[i]\u001b[38;5;241m.\u001b[39mfitness \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m: \u001b[38;5;66;03m# si el individuo no esta evaluado\u001b[39;00m\n\u001b[0;32m----> 6\u001b[0m population[i]\u001b[38;5;241m.\u001b[39mfitness \u001b[38;5;241m=\u001b[39m \u001b[43mfitness_fn\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpopulation\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mchromosome\u001b[49m\u001b[43m)\u001b[49m\n", - "Input \u001b[0;32mIn [109]\u001b[0m, in \u001b[0;36mfitness_VRPTW\u001b[0;34m(chromosome)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;66;03m# feasibility\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# TODO: considerar todas las restricciones\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;66;03m# desirability\u001b[39;00m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m0\u001b[39m, n):\n\u001b[0;32m----> 9\u001b[0m fitness \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[43mdistancia\u001b[49m[i][i \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m]\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fitness\n", - "\u001b[0;31mNameError\u001b[0m: name 'distancia' is not defined" - ] - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "best_ind, bestfitness = genetic_algorithm_VRPTW(fitness_VRPTW)\n", - "plt.plot(bestfitness)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 141, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Poblacion inicial, best_fitness = 44\n", - "generacion 0, best_fitness = 44\n", - "generacion 1, best_fitness = 44\n", - "generacion 2, best_fitness = 44\n", - "generacion 3, best_fitness = 44\n", - "generacion 4, best_fitness = 44\n", - "generacion 5, best_fitness = 44\n", - "generacion 6, best_fitness = 44\n", - "generacion 7, best_fitness = 44\n", - "generacion 8, best_fitness = 44\n", - "generacion 9, best_fitness = 44\n", - "generacion 10, best_fitness = 44\n", - "generacion 11, best_fitness = 44\n", - "generacion 12, best_fitness = 44\n", - "generacion 13, best_fitness = 44\n", - "generacion 14, best_fitness = 44\n", - "generacion 15, best_fitness = 44\n", - "generacion 16, best_fitness = 44\n", - "generacion 17, best_fitness = 44\n", - "generacion 18, best_fitness = 44\n", - "generacion 19, best_fitness = 44\n", - "generacion 20, best_fitness = 44\n", - "generacion 21, best_fitness = 44\n", - "generacion 22, best_fitness = 44\n", - "generacion 23, best_fitness = 44\n", - "generacion 24, best_fitness = 44\n", - "generacion 25, best_fitness = 44\n", - "generacion 26, best_fitness = 44\n", - "generacion 27, best_fitness = 44\n", - "generacion 28, best_fitness = 44\n", - "generacion 29, best_fitness = 44\n", - "generacion 30, best_fitness = 45\n", - "generacion 31, best_fitness = 45\n", - "generacion 32, best_fitness = 45\n", - "generacion 33, best_fitness = 45\n", - "generacion 34, best_fitness = 45\n", - "generacion 35, best_fitness = 45\n", - "generacion 36, best_fitness = 45\n", - "generacion 37, best_fitness = 45\n", - "generacion 38, best_fitness = 45\n", - "generacion 39, best_fitness = 45\n", - "generacion 40, best_fitness = 45\n", - "generacion 41, best_fitness = 45\n", - "generacion 42, best_fitness = 45\n", - "generacion 43, best_fitness = 45\n", - "generacion 44, best_fitness = 45\n", - "generacion 45, best_fitness = 45\n", - "generacion 46, best_fitness = 45\n", - "generacion 47, best_fitness = 45\n", - "generacion 48, best_fitness = 45\n", - "generacion 49, best_fitness = 45\n", - "generacion 50, best_fitness = 45\n", - "generacion 51, best_fitness = 45\n", - "generacion 52, best_fitness = 45\n", - "generacion 53, best_fitness = 45\n", - "generacion 54, best_fitness = 45\n", - "generacion 55, best_fitness = 45\n", - "generacion 56, best_fitness = 45\n", - "generacion 57, best_fitness = 45\n", - "generacion 58, best_fitness = 45\n", - "generacion 59, best_fitness = 45\n", - "generacion 60, best_fitness = 45\n", - "generacion 61, best_fitness = 45\n", - "generacion 62, best_fitness = 45\n", - "generacion 63, best_fitness = 45\n", - "generacion 64, best_fitness = 45\n", - "generacion 65, best_fitness = 45\n", - "generacion 66, best_fitness = 45\n", - "generacion 67, best_fitness = 45\n", - "generacion 68, best_fitness = 45\n", - "generacion 69, best_fitness = 45\n", - "generacion 70, best_fitness = 45\n", - "generacion 71, best_fitness = 45\n", - "generacion 72, best_fitness = 45\n", - "generacion 73, best_fitness = 45\n", - "generacion 74, best_fitness = 45\n", - "generacion 75, best_fitness = 45\n", - "generacion 76, best_fitness = 45\n", - "generacion 77, best_fitness = 45\n", - "generacion 78, best_fitness = 45\n", - "generacion 79, best_fitness = 45\n", - "generacion 80, best_fitness = 45\n", - "generacion 81, best_fitness = 45\n", - "generacion 82, best_fitness = 45\n", - "generacion 83, best_fitness = 45\n", - "generacion 84, best_fitness = 45\n", - "generacion 85, best_fitness = 45\n", - "generacion 86, best_fitness = 45\n", - "generacion 87, best_fitness = 45\n", - "generacion 88, best_fitness = 45\n", - "generacion 89, best_fitness = 45\n", - "generacion 90, best_fitness = 45\n", - "generacion 91, best_fitness = 45\n", - "generacion 92, best_fitness = 45\n", - "generacion 93, best_fitness = 45\n", - "generacion 94, best_fitness = 45\n", - "generacion 95, best_fitness = 45\n", - "generacion 96, best_fitness = 45\n", - "generacion 97, best_fitness = 45\n", - "generacion 98, best_fitness = 45\n", - "generacion 99, best_fitness = 45\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CPU times: user 343 ms, sys: 108 ms, total: 450 ms\n", - "Wall time: 329 ms\n" - ] - } - ], - "source": [ - "%%time\n", - "# busca solucion para el problema de 10 reinas. Usa 100 individuos aleatorios, 100 generaciones y taza de mutación de 0.5\n", - "best_ind, bestfitness = genetic_search_nqueens(fitness_nqueens, 10, 100, 100, 0.90)\n", - "plt.plot(bestfitness)\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Lectura de datos" - ] - }, - { - "cell_type": "code", - "execution_count": 139, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CUST NO.XCOORD. YCOORD. DEMAND READY TIME DUE DATE SERVICE TIME\n", - "1 40 50 0 0 240 0 \n", - "2 25 85 20 145 175 10 \n", - "3 22 75 30 50 80 10 \n", - "4 22 85 10 109 139 10 \n", - "5 20 80 40 141 171 10 \n", - "6 20 85 20 41 71 10 \n", - "7 18 75 20 95 125 10 \n", - "8 15 75 20 79 109 10 \n", - "9 15 80 10 91 121 10 \n", - "10 10 35 20 91 121 10 \n", - "11 10 40 30 119 149 10 \n", - "12 8 40 40 59 89 10 \n", - "13 8 45 20 64 94 10 \n", - "14 5 35 10 142 172 10 \n", - "15 5 45 10 35 65 10 \n", - "16 2 40 20 58 88 10 \n", - "17 0 40 20 72 102 10 \n", - "18 0 45 20 149 179 10 \n", - "19 44 5 20 87 117 10 \n", - "20 42 10 40 72 102 10 \n", - "21 42 15 10 122 152 10 \n", - "22 40 5 10 67 97 10 \n", - "23 40 15 40 92 122 10 \n", - "24 38 5 30 65 95 10 \n", - "25 38 15 10 148 178 10 \n", - "26 35 5 20 154 184 10 \n", - "27 95 30 30 115 145 10 \n", - "28 95 35 20 62 92 10 \n", - "29 92 30 10 62 92 10 \n", - "30 90 35 10 67 97 10 \n", - "31 88 30 10 74 104 10 \n", - "32 88 35 20 61 91 10 \n", - "33 87 30 10 131 161 10 \n", - "34 85 25 10 51 81 10 \n", - "35 85 35 30 111 141 10 \n", - "36 67 85 20 139 169 10 \n", - "37 65 85 40 43 73 10 \n", - "38 65 82 10 124 154 10 \n", - "39 62 80 30 75 105 10 \n", - "40 60 80 10 37 67 10 \n", - "41 60 85 30 85 115 10 \n", - "42 58 75 20 92 122 10 \n", - "43 55 80 10 33 63 10 \n", - "44 55 85 20 128 158 10 \n", - "45 55 82 10 64 94 10 \n", - "46 20 82 10 37 67 10 \n", - "47 18 80 10 113 143 10 \n", - "48 2 45 10 45 75 10 \n", - "49 42 5 10 151 181 10 \n", - "50 42 12 10 104 134 10 \n", - "51 72 35 30 116 146 10 \n", - "52 55 20 19 83 113 10 \n", - "53 25 30 3 52 82 10 \n", - "54 20 50 5 91 121 10 \n", - "55 55 60 16 139 169 10 \n", - "56 30 60 16 140 170 10 \n", - "57 50 35 19 130 160 10 \n", - "58 30 25 23 96 126 10 \n", - "59 15 10 20 152 182 10 \n", - "60 10 20 19 42 72 10 \n", - "61 15 60 17 155 185 10 \n", - "62 45 65 9 66 96 10 \n", - "63 65 35 3 52 82 10 \n", - "64 65 20 6 39 69 10 \n", - "65 45 30 17 53 83 10 \n", - "66 35 40 16 11 41 10 \n", - "67 41 37 16 133 163 10 \n", - "68 64 42 9 70 100 10 \n", - "69 40 60 21 144 174 10 \n", - "70 31 52 27 41 71 10 \n", - "71 35 69 23 180 210 10 \n", - "72 65 55 14 65 95 10 \n", - "73 63 65 8 30 60 10 \n", - "74 2 60 5 77 107 10 \n", - "75 20 20 8 141 171 10 \n", - "76 5 5 16 74 104 10 \n", - "77 60 12 31 75 105 10 \n", - "78 23 3 7 150 180 10 \n", - "79 8 56 27 90 120 10 \n", - "80 6 68 30 89 119 10 \n", - "81 47 47 13 192 222 10 \n", - "82 49 58 10 86 116 10 \n", - "83 27 43 9 42 72 10 \n", - "84 37 31 14 35 65 10 \n", - "85 57 29 18 96 126 10 \n", - "86 63 23 2 87 117 10 \n", - "87 21 24 28 87 117 10 \n", - "88 12 24 13 90 120 10 \n", - "89 24 58 19 67 97 10 \n", - "90 67 5 25 144 174 10 \n", - "91 37 47 6 86 116 10 \n", - "92 49 42 13 167 197 10 \n", - "93 53 43 14 14 44 10 \n", - "94 61 52 3 178 208 10 \n", - "95 57 48 23 95 125 10 \n", - "96 56 37 6 34 64 10 \n", - "97 55 54 26 132 162 10 \n", - "98 4 18 35 120 150 10 \n", - "99 26 52 9 46 76 10 \n", - "100 26 35 15 77 107 10 \n", - "101 31 67 3 180 210 10 \n" - ] - } - ], - "source": [ - "with open('data/RC101.csv', newline='') as csvfile:\n", - " orders = csv.reader(csvfile)\n", - " for row in orders:\n", - " print(f\"{row[0]:8}{row[1]:8}{row[2]:8}{row[3]:8}{row[4]:12}{row[5]:12}{row[6]:12}\")\n", - " #print(\", \".join(row))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.2" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/test/data/RC101.csv b/test/data/RC101.csv deleted file mode 100644 index ff64970..0000000 --- a/test/data/RC101.csv +++ /dev/null @@ -1,102 +0,0 @@ -CUST NO.,XCOORD.,YCOORD.,DEMAND,READY TIME,DUE DATE,SERVICE TIME -1,40,50,0,0,240,0 -2,25,85,20,145,175,10 -3,22,75,30,50,80,10 -4,22,85,10,109,139,10 -5,20,80,40,141,171,10 -6,20,85,20,41,71,10 -7,18,75,20,95,125,10 -8,15,75,20,79,109,10 -9,15,80,10,91,121,10 -10,10,35,20,91,121,10 -11,10,40,30,119,149,10 -12,8,40,40,59,89,10 -13,8,45,20,64,94,10 -14,5,35,10,142,172,10 -15,5,45,10,35,65,10 -16,2,40,20,58,88,10 -17,0,40,20,72,102,10 -18,0,45,20,149,179,10 -19,44,5,20,87,117,10 -20,42,10,40,72,102,10 -21,42,15,10,122,152,10 -22,40,5,10,67,97,10 -23,40,15,40,92,122,10 -24,38,5,30,65,95,10 -25,38,15,10,148,178,10 -26,35,5,20,154,184,10 -27,95,30,30,115,145,10 -28,95,35,20,62,92,10 -29,92,30,10,62,92,10 -30,90,35,10,67,97,10 -31,88,30,10,74,104,10 -32,88,35,20,61,91,10 -33,87,30,10,131,161,10 -34,85,25,10,51,81,10 -35,85,35,30,111,141,10 -36,67,85,20,139,169,10 -37,65,85,40,43,73,10 -38,65,82,10,124,154,10 -39,62,80,30,75,105,10 -40,60,80,10,37,67,10 -41,60,85,30,85,115,10 -42,58,75,20,92,122,10 -43,55,80,10,33,63,10 -44,55,85,20,128,158,10 -45,55,82,10,64,94,10 -46,20,82,10,37,67,10 -47,18,80,10,113,143,10 -48,2,45,10,45,75,10 -49,42,5,10,151,181,10 -50,42,12,10,104,134,10 -51,72,35,30,116,146,10 -52,55,20,19,83,113,10 -53,25,30,3,52,82,10 -54,20,50,5,91,121,10 -55,55,60,16,139,169,10 -56,30,60,16,140,170,10 -57,50,35,19,130,160,10 -58,30,25,23,96,126,10 -59,15,10,20,152,182,10 -60,10,20,19,42,72,10 -61,15,60,17,155,185,10 -62,45,65,9,66,96,10 -63,65,35,3,52,82,10 -64,65,20,6,39,69,10 -65,45,30,17,53,83,10 -66,35,40,16,11,41,10 -67,41,37,16,133,163,10 -68,64,42,9,70,100,10 -69,40,60,21,144,174,10 -70,31,52,27,41,71,10 -71,35,69,23,180,210,10 -72,65,55,14,65,95,10 -73,63,65,8,30,60,10 -74,2,60,5,77,107,10 -75,20,20,8,141,171,10 -76,5,5,16,74,104,10 -77,60,12,31,75,105,10 -78,23,3,7,150,180,10 -79,8,56,27,90,120,10 -80,6,68,30,89,119,10 -81,47,47,13,192,222,10 -82,49,58,10,86,116,10 -83,27,43,9,42,72,10 -84,37,31,14,35,65,10 -85,57,29,18,96,126,10 -86,63,23,2,87,117,10 -87,21,24,28,87,117,10 -88,12,24,13,90,120,10 -89,24,58,19,67,97,10 -90,67,5,25,144,174,10 -91,37,47,6,86,116,10 -92,49,42,13,167,197,10 -93,53,43,14,14,44,10 -94,61,52,3,178,208,10 -95,57,48,23,95,125,10 -96,56,37,6,34,64,10 -97,55,54,26,132,162,10 -98,4,18,35,120,150,10 -99,26,52,9,46,76,10 -100,26,35,15,77,107,10 -101,31,67,3,180,210,10 diff --git a/test/mitsuo.ipynb b/test/mitsuo.ipynb new file mode 100644 index 0000000..653663c --- /dev/null +++ b/test/mitsuo.ipynb @@ -0,0 +1,771 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "956275e8-e4e6-4a03-afe5-31eca1c3272b", + "metadata": {}, + "source": [ + "# Testing possible algorithms to solve MDHVRPTW" + ] + }, + { + "cell_type": "markdown", + "id": "234feb6e-4c52-443c-a3d6-6da8e903dd5c", + "metadata": { + "tags": [] + }, + "source": [ + "Travelling salesman problem\n", + "\n", + "TSP es *casi* MDHVRPTW (*Multi-Depot Heterogeneous VRP with Time Windows) *del profe* pero:\n", + "- Solo 1 camion\n", + "- Todos los ciudades (aka. almacenes pequeños) tienen al menos 1 pedido\n", + "- Capacidad infinita (1 solo tipo de vehiculo)\n", + "- Sin ventanas de tiempo (aka. plazos de entrega)\n", + "- Solo 1 deposito\n", + "- No hay entregas parciales\n", + " - Relajar la restriccion de que la demanda de los \"customers\" debe ser satisfecha al 100% por\n", + " un solo camion. Entonces, si un \"customer\" requiere 8 paquetes, se le puede entregar solo 5,\n", + " y quedan pendientes 3. **Esto modifica la solucion, ahora es una lista donde los nodos a visitar\n", + " ya no son unicos**. Se debe terminar la solucion cuando ya no hayan pedidos pendientes (paquetes por entregar > 0).\n", + "- No hay \"trasvaces\"\n", + " - F\n", + "\n", + "Cambios identificados, necesarios para adaptar el TSP a nuestro caso:\n", + "- Tramos no conectados -> distancia grande entre ellos\n", + "- Distancias no son euclidianas, usar \"geodistance\"\n", + "- [...]" + ] + }, + { + "cell_type": "markdown", + "id": "6ce403ac-eb32-4f74-ae8d-41cb70fe4a20", + "metadata": { + "tags": [] + }, + "source": [ + "## Posibilidades\n", + "\n", + "Una manera de implementar \n", + "\n", + "- [scikit-opt](https://github.com/guofei9987/scikit-opt)" + ] + }, + { + "cell_type": "markdown", + "id": "98fe5cbb-4fb3-478b-b22f-c14a0408e638", + "metadata": { + "tags": [] + }, + "source": [ + "## NetworkX to find all_pairs_shortest_path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b854709-fe5c-4c5a-8a05-b2e438c92a1a", + "metadata": {}, + "outputs": [], + "source": [ + "import networkx as nx\n", + "G = nx.Graph()\n", + "G.add_edge(1, 2) # default edge data=1\n", + "G.add_edge(2, 3, weight=0.9) # specify edge data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44bf2120-1e55-4c1d-b806-3e66227483a3", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "G.add_edge('y', 'x', function=math.cos)\n", + "G.add_node(math.cos) # any hashable can be a node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ed6d6e2-921a-4376-8f8e-c6731385d561", + "metadata": {}, + "outputs": [], + "source": [ + "elist = [(1, 2), (2, 3), (1, 4), (4, 2)]\n", + "G.add_edges_from(elist)\n", + "elist = [('a', 'b', 5.0), ('b', 'c', 3.0), ('a', 'c', 1.0), ('c', 'd', 7.3)]\n", + "G.add_weighted_edges_from(elist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16aad098-3702-4d81-889b-3dc8b3e46ca7", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "#G = nx.cubical_graph()\n", + "subax1 = plt.subplot(121)\n", + "nx.draw(G) # default spring_layout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cc6e56b-3dcf-45fe-9127-0cd63f01ccec", + "metadata": {}, + "outputs": [], + "source": [ + "print(G.adj)" + ] + }, + { + "cell_type": "markdown", + "id": "bad6e2e8-cff5-4a7d-9e3f-f37bae5dff2d", + "metadata": {}, + "source": [ + "## Pre-processing" + ] + }, + { + "cell_type": "markdown", + "id": "22af16ef-7df6-49c8-8e55-157069c03830", + "metadata": {}, + "source": [ + "La data del profe es muy tedioso de leer. Formato raro. Pasar primero a csv.\n", + "\n", + "Distancia entre nodos:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "db46bd0b-46c7-4125-bfff-33205c578e27", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'/home/mitsuo/docs/courses/2022-1/INF226_DP1/project/code/DP_project/test'" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%pwd" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b87961d0-f9b4-417e-9138-3db1b0a36d2f", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "import csv\n", + "import math\n", + "import random\n", + "\n", + "import networkx as nx\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "aeca1be3-1394-4ae1-b488-6abe8bd1e808", + "metadata": {}, + "outputs": [], + "source": [ + "def degreesToRadians(degrees):\n", + " return degrees * math.pi / 180\n", + "\n", + "def distanceInKmBetweenEarthCoordinates(lat1, lon1, lat2, lon2):\n", + " earthRadiusKm = 6371 # Avg. radius\n", + "\n", + " dLat = degreesToRadians(lat2-lat1)\n", + " dLon = degreesToRadians(lon2-lon1)\n", + "\n", + " lat1 = degreesToRadians(lat1)\n", + " lat2 = degreesToRadians(lat2)\n", + "\n", + " a = math.sin(dLat/2) * math.sin(dLat/2) \\\n", + " + math.sin(dLon/2) * math.sin(dLon/2) * math.cos(lat1) * math.cos(lat2)\n", + " c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));\n", + " return earthRadiusKm * c\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "80a0fef2-ae25-40e3-94ab-e3d07b9b60c0", + "metadata": {}, + "outputs": [], + "source": [ + "class Node:\n", + " \"\"\"\n", + " \n", + " Attributes\n", + " ----------\n", + " lat : float\n", + " Latitud (angulo de los Paralelos) en grados sexagesimales\n", + " lon : float\n", + " Longitud (angulo de los Meridianos) en grados sexagesimales\n", + " x : float\n", + " Aproximacion local, en Km respecto (\"Lima\": -12.04591952,-77.03049615 (lat, long))\n", + " x = (longitud - (-77.03049615)) * (pi / 180) * earthRadiusKm\n", + " y : float\n", + " Aproximacion local, en Km respecto (\"Lima\")\n", + " y = (latitud - (-12.04591952)) * (pi / 180) * earthRadiusKm\n", + " demand : float\n", + " Cantidad de paquetes (facil cambiar a int)\n", + " *_time : float\n", + " Cantidades de tiempo en minutos\n", + " \n", + " Notes\n", + " -----\n", + " Web Mercator projection (BAD):\n", + " \n", + " x = floor(256 / (2 * math.pi) * 2**(zoom_level) * (lon + math.pi))\n", + " y = floor(265 / (2 * math.pi) * 2**(zoom_level) * (math.pi - math.ln(math.tan( math.pi / 4 + lat / 2 ))))\n", + " \n", + " x = R * lon\n", + " y = R * ln(tan(pi/4 + lat/2)\n", + " \n", + " Both `lon` and `lat` in radians.\n", + " \n", + " \"Lima\": -12.04591952,-77.03049615 (lat, long)\n", + " \"\"\"\n", + " def __init__(self, id: int, ubigeo, lat, lon, is_depot,\n", + " demand, ready_time, due_time, service_time):\n", + " super()\n", + " self.id = id\n", + " self.ubigeo = ubigeo\n", + "\n", + " if is_depot:\n", + " self.is_depot = True\n", + " else:\n", + " self.is_depot = False\n", + " \n", + " earthRadiusKm = 6371 # Avg. radius\n", + " zoom_level = 1\n", + " lima_lat = (-12.04591952)\n", + " lima_lon = (-77.03049615)\n", + " \n", + " self.lat = lat\n", + " self.lon = lon\n", + " self.x = (lon - lima_lon) * (math.pi / 180) * earthRadiusKm\n", + " self.y = (lat - lima_lat) * (math.pi / 180) * earthRadiusKm\n", + " #self.lat *= (math.pi / 180)\n", + " #self.lon *= (math.pi / 180)\n", + " #self.x = 256 / (2 * math.pi) * 2**(zoom_level) * (self.lon + math.pi)\n", + " #self.y = 256 / (2 * math.pi) * 2**(zoom_level) * (math.pi - math.log(math.tan( math.pi / 4 + self.lat / 2 )))\n", + " self.x = round(self.x, 3)\n", + " self.y = round(self.y, 3)\n", + " self.demand = demand\n", + " self.ready_time = 0 #ready_time\n", + " self.due_time = due_time\n", + " self.service_time = service_time" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "fd72a504-3538-4b43-9e90-bef4299ca83d", + "metadata": {}, + "outputs": [], + "source": [ + "nodes = []\n", + "\n", + "with open('data/VRPTW_python/inf226.oficinas_mod.csv', newline='') as csvfile:\n", + " orders = csv.reader(csvfile)\n", + " count = 1\n", + " id = 0\n", + " for row in orders:\n", + " if count >= 2:\n", + " ubigeo, dept, prov, latitud, longitud, region_natural, is_depot = row[:7]\n", + " demand, ready_time, due_time, service_time = row[7:]\n", + " nodes.append(Node(\n", + " id, ubigeo, float(latitud), float(longitud), int(is_depot),\n", + " #int(100 * random.random()), 0, int(5000 + 500 * (1.5 - random.random())), service_time=60\n", + " demand=float(demand), ready_time=0, due_time=float(due_time), service_time=60\n", + " ))\n", + " id += 1\n", + " count += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8a9cb3eb-d434-44de-a179-01464ba7bbf8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id': 34, 'ubigeo': '040101', 'is_depot': True, 'lat': -16.39881421, 'lon': -71.537019649, 'x': 610.847, 'y': -484.02, 'demand': 0.0, 'ready_time': 0, 'due_time': 8000.0, 'service_time': 60}\n", + "{'id': 122, 'ubigeo': '130101', 'is_depot': True, 'lat': -8.11176389, 'lon': -79.02868652, 'x': -222.189, 'y': 437.458, 'demand': 0.0, 'ready_time': 0, 'due_time': 8000.0, 'service_time': 60}\n", + "{'id': 134, 'ubigeo': '150101', 'is_depot': True, 'lat': -12.04591952, 'lon': -77.03049615, 'x': 0.0, 'y': 0.0, 'demand': 0.0, 'ready_time': 0, 'due_time': 8000.0, 'service_time': 60}\n" + ] + } + ], + "source": [ + "for node in nodes:\n", + " if node.is_depot:\n", + " print(node.__dict__)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "79fcde2d-d0df-4cca-8334-3ffd7a0da997", + "metadata": {}, + "outputs": [], + "source": [ + "node_num = len(nodes)\n", + "\n", + "tramos = []\n", + "with open('../data/inf226.tramos.v.2.0.csv', newline='') as f:\n", + " rows = csv.reader(f)\n", + " count = 1\n", + " for row in rows:\n", + " if count >= 2:\n", + " tramos.append([row[0], row[1]])\n", + " count += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "945de058-6fc3-44c1-8d59-227064323bae", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "7008\n" + ] + }, + { + "data": { + "text/plain": [ + "[['010201', '010301'],\n", + " ['010301', '010201'],\n", + " ['010201', '010401'],\n", + " ['010401', '010201'],\n", + " ['010201', '010501']]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(len(tramos))\n", + "tramos[:5]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e6895a35-ff22-48a1-88a8-ceb8344f36cb", + "metadata": {}, + "outputs": [], + "source": [ + "node_dist_mat = np.zeros((node_num, node_num))\n", + "\n", + "nodes_d = dict(zip([n.ubigeo for n in nodes], nodes))\n", + "for ubigeo1, ubigeo2 in tramos:\n", + " #if ubigeo1 in nodes_d.keys() and ubigeo2 in nodes_d.keys():\n", + " id1 = nodes_d[ubigeo1].id\n", + " id2 = nodes_d[ubigeo2].id\n", + " n1 = nodes[id1]\n", + " n2 = nodes[id2]\n", + " node_dist_mat[id1][id2] = round(distanceInKmBetweenEarthCoordinates(n1.lat, n1.lon, n2.lat, n2.lon), 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "b971e3b3-cea5-43b8-9c57-5bbb83180ee6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(196, 196)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "node_dist_mat.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "abc75da4-fed7-493e-ae9d-f5daba33c693", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 0. , 86.349, 0. , 137.864],\n", + " [ 86.349, 0. , 0. , 146.07 ],\n", + " [ 0. , 0. , 0. , 0. ],\n", + " [137.864, 146.07 , 0. , 0. ]])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "node_dist_mat[:4, :4]" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "e818c9bb-28cb-475d-b8b5-98dfe4d11f91", + "metadata": {}, + "outputs": [], + "source": [ + "# depots are '040101', '130101', '150101'\n", + "\n", + "depots = []\n", + "customers = []\n", + "for n in nodes:\n", + " if n.is_depot:\n", + " depots.append(n)\n", + " else:\n", + " customers.append(n)\n", + "depots_customers = depots + customers\n", + "\n", + "with open('data/VRPTW_python/pedidosperu195.txt', 'w', newline='') as csvfile:\n", + " spamwriter = csv.writer(csvfile, delimiter=' ', quoting=csv.QUOTE_MINIMAL)\n", + " i = 0\n", + " for node in depots_customers:\n", + " spamwriter.writerow([\n", + " #node.id,\n", + " i,\n", + " node.x, node.y,\n", + " node.demand, node.ready_time, node.due_time, node.service_time\n", + " ])\n", + " i += 1" + ] + }, + { + "cell_type": "markdown", + "id": "4cf94976-9003-4b9a-a600-ad9b48d3e60e", + "metadata": {}, + "source": [ + "### Transformar a matriz conexa de nodos \"customer\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac9f4ce7-7f54-4d26-9bbf-75252f083046", + "metadata": {}, + "outputs": [], + "source": [ + "for n in nodes[:5]:\n", + " print(n.__dict__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3f18eaf-a962-454f-99d4-67bf71067e39", + "metadata": {}, + "outputs": [], + "source": [ + "count = 0\n", + "for n in nodes:\n", + " if n.demand:\n", + " print(n.__dict__)\n", + " count += 1\n", + "count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4308a3df-27ca-4910-bff3-1302c8fb589d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14d8d583-7766-421b-96cc-ec95ad9604e6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f85c9cab", + "metadata": {}, + "outputs": [], + "source": [ + "#node_dist_mat = np.zeros((node_num, node_num))\n", + "elist = []\n", + "\n", + "nodes_d = dict(zip([n.ubigeo for n in nodes], nodes))\n", + "for ubigeo1, ubigeo2 in tramos:\n", + " #if ubigeo1 in nodes_d.keys() and ubigeo2 in nodes_d.keys():\n", + " id1 = nodes_d[ubigeo1].id\n", + " id2 = nodes_d[ubigeo2].id\n", + " n1 = nodes[id1]\n", + " n2 = nodes[id2]\n", + " #node_dist_mat[id1][id2] = round(distanceInKmBetweenEarthCoordinates(n1.lat, n1.lon, n2.lat, n2.lon), 3)\n", + " dist = round(distanceInKmBetweenEarthCoordinates(n1.lat, n1.lon, n2.lat, n2.lon), 3)\n", + " elist.append((ubigeo1, ubigeo2, dist))\n", + " \n", + "G = nx.Graph()\n", + "G.add_weighted_edges_from(elist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3c522d4", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(len(list(nodes_d)))\n", + "print(len(list(G.nodes)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86771f42", + "metadata": {}, + "outputs": [], + "source": [ + "G['010201']['010301']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "001a04b8", + "metadata": {}, + "outputs": [], + "source": [ + "node_dist_mat[nodes_d['010201'].id, nodes_d['010301'].id]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "71e54f4d", + "metadata": {}, + "outputs": [], + "source": [ + "G['010201']['250301']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ebe3cdc", + "metadata": {}, + "outputs": [], + "source": [ + "path1 = nx.shortest_path(G, source='010201', target='250301', weight='weight')\n", + "path1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cca62d40", + "metadata": {}, + "outputs": [], + "source": [ + "path2 = nx.shortest_path(G, source='010201', target='250301')\n", + "path2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "756f1845", + "metadata": {}, + "outputs": [], + "source": [ + "l1, l2 = 0, 0\n", + "for i in range(len(path1)):\n", + " if i == 0:\n", + " continue\n", + " l1 += G[path1[i-1]][path1[i]]['weight']\n", + " l2 += G[path2[i-1]][path2[i]]['weight']\n", + "print(l1, l2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e124757", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# https://stackoverflow.com/a/63169428/7498073\n", + "H = nx.subgraph(G, path1)\n", + "nx.draw(H, with_labels=True, font_weight='bold', node_color='lightblue', node_size=500)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5ded33b", + "metadata": {}, + "outputs": [], + "source": [ + "len_path = dict(nx.all_pairs_dijkstra(G, weight='weight'))\n", + "#for node, (dist, path) in len_path:\n", + "# print(f\"{node}: {dist} [{path}]\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3361d460", + "metadata": {}, + "outputs": [], + "source": [ + "print(len_path['010201'][0]['250301'])\n", + "print(len_path['010201'][1]['250301'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba3d4ae7-c6b5-484a-a1b4-0f6ffe1890b6", + "metadata": {}, + "outputs": [], + "source": [ + "help(G)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "596bf42a-3600-4446-a904-a4e9080d2f2b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "132bea6b-c50c-4406-8e2f-2279a87e9cbf", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf5cac1d-9ae4-4423-ab96-48728c14fa01", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00f4cd39-c093-4397-ae96-cb3ae2a433c6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ff3f7473-6418-4f4a-828f-172f2996ba54", + "metadata": {}, + "source": [ + "## Pruebitas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6956f235-0401-4a67-8ed2-d2b3fd07b3bf", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ab3843c-faba-46a0-9f7b-97897430ba67", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e45dd91b-fc32-4da3-a340-d3dc888b1335", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5fdfcaa8-9000-48d7-b3ab-4d2f2efc2bcc", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} -- cgit v1.2.3