From 4d2d53da56d01c8258209d9089fd6c18cf5005c4 Mon Sep 17 00:00:00 2001 From: Wu Han Date: Wed, 6 Jan 2021 19:26:53 +0000 Subject: [PATCH] [workshop] Add notebook --- Workshop - 1 (Random, BFS, DFS, DP).ipynb | 1592 ++++++++++++ Workshop - 2 (UCS, A, Hill-Climbing).ipynb | 1420 ++++++++++ Workshop - 3 (Game).ipynb | 122 + Workshop - 3 (Game)/ab-pruning.py | 191 ++ Workshop - 3 (Game)/minimax.py | 204 ++ Workshop - 3 (LP).ipynb | 252 ++ Workshop - 4 (TSP SA).ipynb | 1026 ++++++++ Workshop - 5 (ACO, PSO).ipynb | 1022 ++++++++ Workshop - 5 (PSO, ACO).ipynb | 2278 +++++++++++++++++ Workshop - 6 (GA, SOM).ipynb | 1317 ++++++++++ images/ab-pruning.png | Bin 0 -> 41494 bytes images/minimax.png | Bin 0 -> 42780 bytes images/pwd.png | Bin 0 -> 20694 bytes images/solutions.png | Bin 0 -> 44087 bytes images/terminal.png | Bin 0 -> 56215 bytes images/tsp.jpg | Bin 0 -> 72792 bytes .dockerignore => template/.dockerignore | 0 .gitignore => template/.gitignore | 0 Dockerfile => template/Dockerfile | 0 README.md => template/README.md | 3 + {data => template/data}/hard/dsj1000.tsp | 0 {data => template/data}/medium/a280.tsp | 0 {data => template/data}/medium/pcb442.tsp | 0 {data => template/data}/simple/att48.tsp | 0 {data => template/data}/simple/st70.tsp | 0 {data => template/data}/simple/ulysses16.tsp | 0 main.py => template/main.py | 6 +- {model => template/model}/anneal_model.py | 2 +- {model => template/model}/base_model.py | 0 {model => template/model}/my_model.py | 0 template/output/.gitignore | 8 + requirements.txt => template/requirements.txt | 0 template/utils/load_data.py | 21 + template/utils/tsp.py | 139 + {utils => template/utils}/visualize_tsp.py | 0 35 files changed, 9599 insertions(+), 4 deletions(-) create mode 100644 Workshop - 1 (Random, BFS, DFS, DP).ipynb create mode 100644 Workshop - 2 (UCS, A, Hill-Climbing).ipynb create mode 100644 Workshop - 3 (Game).ipynb create mode 100644 Workshop - 3 (Game)/ab-pruning.py create mode 100644 Workshop - 3 (Game)/minimax.py create mode 100644 Workshop - 3 (LP).ipynb create mode 100644 Workshop - 4 (TSP SA).ipynb create mode 100644 Workshop - 5 (ACO, PSO).ipynb create mode 100644 Workshop - 5 (PSO, ACO).ipynb create mode 100644 Workshop - 6 (GA, SOM).ipynb create mode 100644 images/ab-pruning.png create mode 100644 images/minimax.png create mode 100644 images/pwd.png create mode 100644 images/solutions.png create mode 100644 images/terminal.png create mode 100644 images/tsp.jpg rename .dockerignore => template/.dockerignore (100%) rename .gitignore => template/.gitignore (100%) rename Dockerfile => template/Dockerfile (100%) rename README.md => template/README.md (83%) rename {data => template/data}/hard/dsj1000.tsp (100%) rename {data => template/data}/medium/a280.tsp (100%) rename {data => template/data}/medium/pcb442.tsp (100%) rename {data => template/data}/simple/att48.tsp (100%) rename {data => template/data}/simple/st70.tsp (100%) rename {data => template/data}/simple/ulysses16.tsp (100%) rename main.py => template/main.py (96%) rename {model => template/model}/anneal_model.py (98%) rename {model => template/model}/base_model.py (100%) rename {model => template/model}/my_model.py (100%) create mode 100644 template/output/.gitignore rename requirements.txt => template/requirements.txt (100%) create mode 100644 template/utils/load_data.py create mode 100644 template/utils/tsp.py rename {utils => template/utils}/visualize_tsp.py (100%) diff --git a/Workshop - 1 (Random, BFS, DFS, DP).ipynb b/Workshop - 1 (Random, BFS, DFS, DP).ipynb new file mode 100644 index 0000000..0ca228b --- /dev/null +++ b/Workshop - 1 (Random, BFS, DFS, DP).ipynb @@ -0,0 +1,1592 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Append template path to sys path\n", + "sys.path.append(os.getcwd() + \"/template\") " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.load_data import load_data\n", + "from utils.load_data import log\n", + "from utils.visualize_tsp import plotTSP\n", + "from utils.tsp import TSP\n", + "from utils.tsp import TSP_Bench\n", + "from utils.tsp import TSP_Bench_ALL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workshop Starts Here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"TSP\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"solutions\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get familiar with your dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are problems at different levels. **3 simple, 2 medium, 1 hard**." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16 = np.array(load_data(\"./template/data/simple/ulysses16.tsp\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[38.24, 20.42],\n", + " [39.57, 26.15],\n", + " [40.56, 25.32],\n", + " [36.26, 23.12],\n", + " [33.48, 10.54],\n", + " [37.56, 12.19],\n", + " [38.42, 13.11],\n", + " [37.52, 20.44],\n", + " [41.23, 9.1 ],\n", + " [41.17, 13.05],\n", + " [36.08, -5.21],\n", + " [38.47, 15.13],\n", + " [38.15, 15.35],\n", + " [37.51, 15.17],\n", + " [35.49, 14.32],\n", + " [39.36, 19.56]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ulysses16[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(ulysses16[:, 0], ulysses16[:, 1])\n", + "for i in range(0, 16):\n", + " plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: In Order" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]\n" + ] + } + ], + "source": [ + "simple_sequence = list(range(0, 16))\n", + "print(simple_sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([simple_sequence], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: Random Permutation" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[9, 8, 3, 7, 0, 13, 15, 4, 11, 10, 2, 14, 12, 6, 5, 1]\n" + ] + } + ], + "source": [ + "random_permutation = np.random.permutation(16).tolist()\n", + "print(random_permutation)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([random_permutation], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Best Solution" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]\n", + "plotTSP([best_ulysses16], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Fitness (Sum of all Distances)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def dist(node_0, node_1, coords):\n", + " \"\"\"\n", + " Euclidean distance between two nodes.\n", + " \"\"\"\n", + " coord_0, coord_1 = coords[node_0], coords[node_1]\n", + " return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 0: [38.24 20.42]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 0:\", ulysses16[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 1: [39.57 26.15]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 1:\", ulysses16[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance Between 5.882329470541408\n" + ] + } + ], + "source": [ + "print(\"Distance Between\", dist(0, 1, ulysses16))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness(solution, coords):\n", + " N = len(coords)\n", + " cur_fit = 0\n", + " for i in range(len(solution)):\n", + " cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)\n", + " return cur_fit" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Order Fitness:\t 104.42225210207233\n", + "Random Fitness:\t 147.23709375479442\n", + "Best Fitness:\t 74.10873595815309\n" + ] + } + ], + "source": [ + "print (\"Order Fitness:\\t\", fitness(simple_sequence, ulysses16))\n", + "print (\"Random Fitness:\\t\", fitness(random_permutation, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Random Model" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyRandomModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " random_solutions = []\n", + " for i in range(0, max_it):\n", + " solution = np.random.permutation(self.N).tolist()\n", + " random_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 109.76627855420857\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, max_it=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Minimum Spanning Tree (Depth First)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyDFSModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " MST_solutions = []\n", + " # Depth First: Set one city as starting point, iterate to the end, then select next city as starting point.\n", + " for i in range(0, self.N):\n", + " solution = []\n", + " solution.append(i)\n", + " unvisited_list = list(range(0, self.N))\n", + " cur_city = i\n", + "# print(\"[starting]\", i)\n", + " for steps in range(self.N - 1):\n", + "# print(unvisited_list)\n", + " unvisited_list.remove(cur_city)\n", + " closest_neighbour = -1\n", + " shortest_distance = math.inf\n", + " for j in unvisited_list:\n", + " if(self.dist(cur_city, j) < shortest_distance):\n", + " closest_neighbour = j\n", + " shortest_distance = self.dist(cur_city, j)\n", + " solution.append(closest_neighbour)\n", + " cur_city = closest_neighbour\n", + " MST_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'\n", + "model = MyDFSModel()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Minimum Spanning Tree (Breadth First)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyBFSModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " UCS_solutions = []\n", + " \n", + " for i in range(0, self.N):\n", + " solution = [i]\n", + " UCS_solutions.append(solution)\n", + " \n", + " # Breadth First: Set each city as starting point, then go to next city simultaneously\n", + " for step in range(0, self.N - 1):\n", + " # print(\"[step]\", step)\n", + " unvisited_list = list(range(0, self.N))\n", + " # For each search path\n", + " for i in range(0, self.N):\n", + " cur_city = UCS_solutions[i][-1]\n", + " unvisited_list = list( set(range(0, self.N)) - set(UCS_solutions[i]) )\n", + " # print(unvisited_list)\n", + " closest_neighbour = -1\n", + " shortest_distance = math.inf\n", + " for j in unvisited_list:\n", + " if(self.dist(cur_city, j) < shortest_distance):\n", + " closest_neighbour = j\n", + " shortest_distance = self.dist(cur_city, j)\n", + " UCS_solutions[i].append(closest_neighbour)\n", + "\n", + " for i in range(0, self.N):\n", + " self.fitness_list.append(self.fitness(UCS_solutions[i]))\n", + " \n", + " self.best_solution = UCS_solutions[ self.fitness_list.index(min(self.fitness_list)) ]\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'\n", + "model = MyBFSModel()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dynamic Programming (DFS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Costs a lot of memory" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyDPDModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def getMST(self, node):\n", + " MST = []\n", + " distances = []\n", + " for i in range(0, self.N):\n", + " if i != node:\n", + " MST.append(i)\n", + " distances.append(self.dist(node, i))\n", + " return [x for _,x in sorted(zip(distances, MST))]\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " MST_solutions = []\n", + "\n", + " # Depth First: Set one city as starting point, iterate to the end, then select next city as starting point.\n", + " MSTs = []\n", + " for i in range(0, self.N):\n", + " MSTs.append([-1] * self.N)\n", + " for i in range(0, self.N):\n", + " solution = []\n", + " solution.append(i)\n", + " unvisited_list = list(range(0, self.N))\n", + " cur_city = i\n", + " # print(\"[starting]\", i)\n", + " for steps in range(self.N - 1):\n", + " # print(unvisited_list)\n", + " unvisited_list.remove(cur_city)\n", + " if MSTs[cur_city][0] == -1:\n", + " MST = self.getMST(cur_city)\n", + " MSTs[cur_city] = MST\n", + " \n", + " for j in MSTs[cur_city]:\n", + " if(j in unvisited_list):\n", + " solution.append(j)\n", + " cur_city = j\n", + " break\n", + " # print(solution)\n", + " MST_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'\n", + "model = MyDPDModel()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dynamic Programming (BFS)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyDPBModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def getMST(self, node):\n", + " MST = []\n", + " distances = []\n", + " for i in range(0, self.N):\n", + " if i != node:\n", + " MST.append(i)\n", + " distances.append(self.dist(node, i))\n", + " return [x for _,x in sorted(zip(distances, MST))]\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " MST_solutions = []\n", + " \n", + " for i in range(0, self.N):\n", + " solution = [i]\n", + " MST_solutions.append(solution)\n", + " \n", + " MSTs = []\n", + " for i in range(0, self.N):\n", + " MSTs.append([-1] * self.N)\n", + "\n", + " # Breadth First: Set each city as starting point, then go to next city simultaneously\n", + " for step in range(0, self.N - 1):\n", + " # print(\"[step]\", step)\n", + " unvisited_list = list(range(0, self.N))\n", + " # For each search path\n", + " for i in range(0, self.N):\n", + " cur_city = MST_solutions[i][-1]\n", + " unvisited_list = list( set(range(0, self.N)) - set(MST_solutions[i]) )\n", + "\n", + " if MSTs[cur_city][0] == -1:\n", + " MST = self.getMST(cur_city)\n", + " MSTs[cur_city] = MST\n", + "\n", + " for j in MSTs[cur_city]:\n", + " if(j in unvisited_list):\n", + " MST_solutions[i].append(j)\n", + " break\n", + "\n", + " for i in range(0, self.N):\n", + " self.fitness_list.append(self.fitness(MST_solutions[i]))\n", + " \n", + " self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'\n", + "model = MyDPBModel()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your Smart Model" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your Model" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_problem = './template/data/simple/ulysses16.tsp'\n", + "model = MyModel()" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[*] [Node] 16, [Best] 148.6111649037806\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test All Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_path = './template/data'" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_results(best_solutions, times, title):\n", + " fig = plt.figure()\n", + " nodes = [len(s) for s in best_solutions]\n", + " data = np.array([[node, time] for node, time in sorted(zip(nodes, times))])\n", + " plt.plot(data[:, 0], data[:, 1], 'o-')\n", + " fig.suptitle(title, fontsize=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Random Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 728128.1926675908\n", + "[*] Running for: 0.47 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 30174.692642901202\n", + "[*] Running for: 0.24 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] [Node] 1000, [Best] 526435341.8268128\n", + "[*] Running for: 0.92 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 123505.12211442963\n", + "[*] Running for: 0.04 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 98.36043449906845\n", + "[*] Running for: 0.02 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 3030.2458377657613\n", + "[*] Running for: 0.06 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "print(\"Random Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Random Model\")" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 58952.967129705365\n", + "[*] Running for: 31.01 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 3088.6042241002488\n", + "[*] Running for: 7.16 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.02 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 39236.884898455035\n", + "[*] Running for: 0.04 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 761.6890898866324\n", + "[*] Running for: 0.11 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyDFSModel()\n", + "\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXAAAAEVCAYAAAD5IL7WAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAArQUlEQVR4nO3deXwV1f3/8dcnIYSwhrAECPsOomwp7ooLglvBtVprtdrS/tpvazcX1C62RUFbq92sWNdutlYWiwgqilvdwCBbSAibEAgJS1hCyHp+f8xEY7iBm3XuvXk/H4/7uHfOzNz5zJybz52cc+aOOecQEZHoExd0ACIiUj9K4CIiUUoJXEQkSimBi4hEKSVwEZEopQQuIhKllMClUZjZMjNr1jGpZvaUmTkz69+c25Vg6luOpgQeIfxEVP1RYmYFZvaRmf3FzC40s/gA42u2ZGlmPw9xPKo/tjR1DH4cN/rbu7Ee68ab2TfM7A0z22tmZWaWb2ar/Pr8YhOELC1Mq6ADkKPc4z/HA8nACcD1wM3AcjO7zjmXHVBsze0NYFmI8kL/eQYwC8htpnjC4n/RLgSm4MX6IrAdaI1Xn18GhgMvBBSixAgl8AjjnPt5zTIzSwV+D1wFvGpm6c65/OaOLQDLQh2PKs65ncDO5gsnbNfiJe+PgbOdc/urzzSztsDJQQQmsUVNKFHAObcLuAbvbLQPcGfNZcwsxczuM7NMMys2s/1mttTMLgix7KdNA2Z2sZn9z8yKzGyfmf3HzIbUWN4BN/iTm4/VlGFmrczsTjPb4DcDbTOz2WbWuuFH4qhtHdWsY2b9/bKnzGyomf3Lb7qoNLOJ/jIDzWyOmeX4x2qvma02sz+bWRd/mWXAk/7bPlmjCac/x3aa//xUzeQN4Jw77Jx7vZZ9utbMXjezQjM74tfn3WaWGGLZaWb2NzPL9uuvyMxWmNn3zOyov+1qx2ugmX3Xb84p9ve1apkUM5tpZmvM7LD/OfrYzGaZWbsQ79ls9S1H0xl4lHDOVZrZr4CJwLVm9gPn/5CNmfXDS+79gbeAxUA74BJgsZl90zn3WIi3vRy4EJjnrz8GuAI4x8xOc85l+cvdA0wDRgMP81kTRiFH+wdwJvAScAC4CLgN6A58re57Xm+DgPeBbODvQBJwwMx6Ah8CHYFFwPNAG2AAXlPVH4A9wFN4+zcVWACsrPbehcfZ9h7/eWhdAjazJ/CO0XY/rkLgFOCXwHlmNsk5V15tlVlApb+fuUAn4Fy8OvqCvz+hPIxXRy/iHYMKf/sDgNeBfsAK4BG8k7yhwA+APwNFNd4rUuq7ZXLO6REBD8B51XHMZRKBMn/ZAdXKl+H9IV9TY/lkvMRTDKRWK7+xanvAJTXWucUvX1qj/Cm/vH8tsS3z568AUqqVtwNy8JJEjzCPxc/991rmv6756F9bTHhfYlX7dm+I9/6uP++WEPPaAUkhjtONdazLsUCpXyd/xfui7Hecdaq2Nbd6DDWOxy01ygeFeJ844Gl/+ZNrqcPc6p+favP/58+fEWJeV6BNU9S3HvV/BB6AHn5FhJHA/eXy/GUn+NOj/ennall+qj//29XKqpLF0hDLx/t/gK560gmVLGusV/UHfX6IefcQ4sviGPtYlbBqe0ysLaZqCTwPSAzx3lUJfHoYcdQrgfvrXo3XPl897j14/+1cGmL5DLwv5+Ra6mQ38EGY2x7nb++nNcqrjtctIdYZ78/LAOLC2Eaj1bce9X+oCSX6mP9cNQb3VP+5k5n9PMTy3fznESHmvVGzwDlXYWZv4zVBjAW21jG+5SHKtvnPnev4Xve4Y3RiHsfHzrmSEOUvAPcCfzSzycAS4B1gnfOzT2Nwzv3bzOYB5wBn4B3LM/CaoqaZ2TN4XwzO79QcjZekv29mod6yhBp16LfX34rXbDEQ7+y3urRawvsgRNkp/vMS51zlsffucxqzvqWOlMCjiJm1AVL8yQL/uYv/PMl/1KZ9iLJdtSyb5z93qlOAgHOuMERxVbttc45jzwtV6JzbamYT8M7yp+A1bwBsM7NfO+d+11gBOOfKgJf9R9XwwiuAJ4Cv4p2Nz8dLdIb3ZfuzcN7bzJLx2vIH4CXkZ4C9eMc6Ga8p7KiOT1+oY5PsP9dpSGYE1XeLpAQeXc7Aq7NdzrktflnVKIdb6pF8Umsp71HjvaNRrWfTzrlM4Etm1grvzPd8vKaVh82syDn3eJME5FwF8G8zOxG4G6/DcT6fHecM59y4MN/u63jJ+6j/UszsVLwEXmsoIcoK/efaztolAmkYYZTwh4Xd5U/+o9qs9/znM+vxtmeH2E483hcFeO2hVSr855g5q3LOlTvnVjjnZuON3QaviaNKU+3zQf/Z/DgOAWuBE8wspda1Pm+w//x8iHlH1WsYqj5Hk0MNQZTIpIqKAmbWHXgWbwjhJ3htuAA455bjDR283MxuqmX9E/33qOlcM7ukRtn/4bV/v+6cq97+XTU0rm+9diJCmNl4MwvVNFT138jhamX12md/LPekWsZi9wC+4U++WW3Wg3hXaj7hN4/UXK+zmVU/O9/iP0+ssdxYvCtU68Q5twJvFMoY4PYQ2+/iN+FJBFETSoSp1hEZx2eX0p+B98f9AXCdc253jdW+DLwGPG5m38MbF1wI9AZOAkbhdXbWvHrzv8A8v7MtB++P90K8ttRv11h2KV6H2WNm9jzeWWShc+4P9d7ZYFwPfNPvqN0I7MP7wroUr6PwoWrLvouX0L/vdxhWtR3/3oW4QKeak/GaMPL87Wz2ywcAF+ONSV8A/KdqBefcE2Y2Hu+4bzSzJXhf1in+emfhXVj0LX+VZ/Dq4yEzOwfYAAzBG/s/F/hS+IfkU1/BG11yr5ld4b82/30vwLv8f0s93leaStDDYPTwHhw9VK4Eb1TCCuAxvA63Wod3AR3wrtBcARzCG/u9Ge9ijelAu2rL3uhv40a8P/h38S7QKMT7l3xoLdv4IZDpx+aALdXmLaOWYZDUcTgenw0j/PlxlnuK2ocRPlXLOifjXaDyMd4XVTHel9eTwKgQy0/xj8+hanXT/zhx9QG+g9dJmYV3gUsp3rDCRXiJMmRd+vWxEO/LthTvS+MD4FfA8BrLjsQbVZPv198KvLbxkMcg1PEKsf0uwGw/7iP+Z2IlMBNo2xT1rUf9H+YfcGlBzPt1vSeBrznnngo2GhGpL7WBi4hEKSVwEZEopQQuIhKl1AYuIhKldAYuIhKllMBFRKKUEriISJRSAhcRiVJK4CIiUUoJXEQkSimBi4hEKSVwEZEo1aw/J9u1a1fXv3//5tykiEjUW7FixW7nXLea5c2awPv378/y5aHugSoiIrUxs5A3F1cTiohIlFICFxGJUkrgIiJRSglcRCRKKYGLiESpsEahmFky8Be8u5s74Ca8m57+C+8GqluAq51z+5oiSBGRaDQ/I5cHlmSxo7CYXslJ3Dp5GNPGpjXa+4d7Bv4wsNg5NxwYjXdn8juApc65IcBSf1pERPCS94y5q8ktLMYBuYXFzJi7mvkZuY22jeMmcDPrBJwFPA7gnCt1zhUCU4Gn/cWeBqY1WlQiIlHugSVZFJdVfK6suKyCB5ZkNdo2wjkDHwAUAE+aWYaZ/cXM2gGpzrmd/jJ5QGqolc1supktN7PlBQUFjRO1iEiE21FYXKfy+ggngbcCxgGPOOfGAkXUaC5x3o01Q95c0zk3xzmX7pxL79btqCtBRURiypGyCh59Y2Ot83slJzXatsLpxNwObHfOve9P/wcvge8ys57OuZ1m1hPIb7SoRESiTGWl47+rdnD/4ixyC4sZ0aMDm3YXUVJe+ekySQnx3Dp5WKNt87gJ3DmXZ2bbzGyYcy4LOA9Y5z9uAGb5zwsaLSoRkSjy3qY93Lsok1Xb9zOyZ0fuv/IkTh/ctclHoZjX+nGchczG4A0jbA1sAr6G1/zyb6AvsBVvGOHeY71Penq6049ZiUisyMk/xKyX1vNq5i56dmrDjy8YxmVj04iLs0bdjpmtcM6l1ywPaxy4c24lcNTKeGfjIiItyu5DJTz86gb+8cEnnzaL3HzGANokxDdrHM36c7IiItGsuLSCJ97ZzCPLNlJcVsGXJ/TllvOH0LV9YiDxKIGLiBxHZaVjXkYuv345i537jzBpZCq3TxnO4O7tA41LCVxE5BjeydnNzBczWbfzACf17sRDXxrDyQO7BB0WoAQuIhJS9q6D3Lcok9ezCkhLTuLha8Zw6Um9Gr2DsiGUwEVEqsk/cITfvprNvz7cRrvEVtx50XC+emr/Zu+gDIcSuIgIcLi0nMfe3Myjb26ktLySG07rz/fOHULndq2DDq1WSuAi0qJVVDr+s2Ibv3k5m/yDJVx0Yg9umzyc/l3bBR3acSmBi0iL9UZ2Afe+mEnWroOM7ZvMI18Zx/h+KUGHFTYlcBFpcdbtOMB9L2Xy1obd9E1py5+uG8eFo3pgFjkdlOFQAheRFiNv/xF+83IW//loOx3bJPCTS0bylVP6ktgq8joow6EELiIx71BJOY++sZHH3tpEZSV848yBfGfiYDq1TQg6tAZRAheRmFVeUcmzH27joVez2X2olEtH9+K2ycPok9I26NAahRK4iMQc5xyvrc/nvpfWk5N/iAn9U/jLDSMY0yc56NAalRK4iMSU1dv3M3PROt7btJeBXdvx6PXjuWBkatR1UIZDCVxEYkJuYTG/XpLFvIxcUtq15hdTT+DaCX1JiA/nzpHRSQlcRKLagSNl/On1jTzxzmYM+H8TB/H/Jg6iY5vo7qAMhxK4iESlsopK/v7eVn73Wg57i0q5fGwaP5o8jLRGvGlwpFMCF5Go4pxjydpdzF68ns27izh1YBfuungEo9I6BR1as1MCF5GokfHJPu5dlMmHW/YxuHt7nrgxnXOGdY/JDspwKIGLSMTbtvcwsxevZ+GqnXRtn8jMy0bxpfQ+tIrhDspwKIGLSMQqPFzKH17L4Zl3txIXB987dzDTzx5E+0SlLlACF5EIVFJewV/f3crvX8vhwJEyrhrfmx9OGkaPTm2CDi2iKIGLSMRwzvHi6p3cvziLT/Ye5swhXbnzohGM6Nkx6NAikhK4iESE5Vv2MnNRJhmfFDK8RweevmkCZw/tFnRYES2sBG5mW4CDQAVQ7pxLN7MU4F9Af2ALcLVzbl/ThCkisWrz7iJmv7SexWvz6N4hkfuvOIkrxvcmPoJuHhyp6nIGfo5zbne16TuApc65WWZ2hz99e6NGJyIxa29RKb9buoG/vbeV1q3i+OGkoXz9zAG0ba2GgXA15EhNBSb6r58GlqEELiLHcaSsgqf+t4U/vp5DUUk5X/pCX34waQjdO6iDsq7CTeAOeNnMHPCoc24OkOqc2+nPzwNSQ61oZtOB6QB9+/ZtYLgiEq0qKx3/XbWD+xdnkVtYzLnDu3PHhcMZmtoh6NCiVrgJ/AznXK6ZdQdeMbP11Wc655yf3I/iJ/s5AOnp6SGXEZHY9u7GPdy7KJPVufsZ2bMj9195EqcP7hp0WFEvrATunMv1n/PNbB4wAdhlZj2dczvNrCeQ34RxikgUysk/xKyX1vNq5i56dmrDg1ePZtqYNOLUQdkojpvAzawdEOecO+i/vgD4BfACcAMwy39e0JSBikj02H2ohIdezeafH2wjKSGeWycP4+YzBtAmITpvHhypwjkDTwXm+T8W0wr4h3NusZl9CPzbzG4GtgJXN12YIhINiksreOKdzTyybCPFZRVcd3JfvnfeELq2Tww6tJh03ATunNsEjA5Rvgc4rymCEpHoUlHpmJeRy6+XZJF34AiTRqZyx4XDGdStfdChxTQNuBSRBnl7w27uXZTJup0HGN27Ew9fM4aTB3YJOqwWQQlcROolK+8g972UybKsAtKSk3j4mjFcelIvdVA2IyVwEamT/ANHePCVbP69fBvtEltx50XD+eqp/dVBGQAlcBEJS1FJOY+9tYk5b26irKKSG08bwHfPHUzndq2DDq3FUgIXkWOqqHQ8t3wbv3klm4KDJVx0Yg9umzyc/l3bBR1ai6cELiIhOedYll3ArEXrydp1kHF9k/nzV8Yxvl9K0KGJTwlcRI6ydsd+7lu0nrdzdtM3pS1/um4cF47q0WJvHhyplMBF5FM79xfzm5ezef6j7XRKSuCnl4zkK6f0o3Wrln3z4EilBC4iHCop58/LNvKXtzdRWQnfOHMg35k4mE5tE4IOTY5BCVykBSuvqOSfH27j4Vez2X2olC+O7sWtk4fRJ6Vt0KFJGJTARVog5xxLM/O576VMNhYUMaF/Cn+5YQRj+iQHHZrUgRK4SAuzevt+Zi5ax3ub9jKwazvmXD+eSSNT1UEZhZTARVqI7fsO8+slWcxfuYOUdq35xdQTuHZCXxLi1UEZrZTARWLc/uIy/rQshyff2YIB3544iG9NHETHNuqgjHZK4CIxqrS8kn+8v5WHl25g3+EyLh+Xxo8vGEav5KSgQ5NGogQuEmOccyxZm8esl9azZc9hThvUhTsvGsGotE5BhyaNTAlcJIZkfLKPmS9msnzrPoZ0b8+TN36BicO6qYMyRimBi8SAT/YcZvaS9by4aidd2ydy72UncnV6b1qpgzKmKYGLRLHCw6X84bUcnn53C/FxxvfOG8L0swbSPlF/2i2BalkkCpWUV/DXd7fy+9dyOHCkjKvG9+aHk4bRo1OboEOTZqQELhJFnHO8uHonsxevZ9veYs4a2o0ZFw5nRM+OQYcmAVACF4kSH27Zy8wXM1m5rZDhPTrwzE0TOGtot6DDkgApgYtEuM27i5j90noWr80jtWMi9195EleM6028bh7c4imBi0SovUWl/G7pBv723lZat4rjh5OG8vUzB9C2tf5sxRP2J8HM4oHlQK5z7hIzGwA8C3QBVgDXO+dKmyZMkZbjSFkFT76zhT+9nkNRaTnXTOjL988fQvcO6qCUz6vLV/ktQCZQ1VsyG/itc+5ZM/szcDPwSCPHJ9JiVFY6Xvh4Bw8sySK3sJhzh3dnxoXDGZLaIejQJEKFlcDNrDdwMTAT+KF5l3WdC3zZX+Rp4OcogYvUy7sb9zBz0TrW5B7ghF4deeDKkzhtcNegw5IIF+4Z+EPAbUDVqUAXoNA5V+5PbwfSQq1oZtOB6QB9+/atd6AisSgn/yCzXlrPq5n59OzUhgevHs20MWnEqYNSwnDcBG5mlwD5zrkVZjaxrhtwzs0B5gCkp6e7uq4vEosKDpbw0KvZPPvhNpIS4rltyjBuOn0AbRLigw5Nokg4Z+CnA180s4uANnht4A8DyWbWyj8L7w3kNl2YIrGhuLSCx9/exCPLNnKkvJLrTu7LLecNoUv7xKBDkyh03ATunJsBzADwz8B/7Jy7zsyeA67EG4lyA7Cg6cIUiW4VlY65H23nNy9nk3fgCBeMTOX2C4czqFv7oEOTKNaQAaW3A8+a2a+ADODxxglJJLa8taGAexetJ3PnAUb37sTvrh3LhAEpQYclMaBOCdw5twxY5r/eBExo/JBEYkNW3kHuXZTJG9kF9O6cxO+uHcslJ/ZUB6U0Gl3SJdLIdh04woMvZ/Pcim20T2zFXReN4Kun9SOxlToopXEpgYs0kqKScua8uYk5b26ivLKSG08bwHfPHUzndq2DDk1ilBK4SANVVDqeW76N37ySTcHBEi4+sSe3TRlGvy7tgg5NYpwSuEg9OedYll3AfYsyyd51iHF9k/nzV8Yxvp86KKV5KIGL1MPaHfu5b9F63s7ZTb8ubXnkunFMGdVDNw+WZqUELlIHO/cX8+sl2czN2E6npAR+eslIvnJKP1q30s2DpfkpgYuE4eCRMh59YxOPvbUJ52D6mQP59jmD6ZSUEHRo0oIpgYscQ1lFJc9+uI2HXslmT1EpXxzdi1snD6NPStugQxNRAhcJxTnHq5n5zHopk40FRUwYkMITF41gdJ/koEMT+ZQSuEgNq7YXMvPFTN7fvJeB3dox5/rxTBqZqg5KiThK4CK+7fsO88CSLBas3EFKu9b8cuoJXDOhLwnx6qCUyKQELi3e/uIy/rQshyff2YIB3544iG9NHETHNuqglMimBC4tVml5JX9/fyu/W7qBwuIyLhubxo8vGEav5KSgQxMJixK4tDjOORavyWP24vVs2XOY0wZ14c6LRjAqrVPQoYnUiRK4tCgffbKPmS9msmLrPoZ0b8+TN36BicO6qYNSopISuLQIn+w5zOwl63lx1U66tk/kvstP5KrxvWmlDkqJYkrgEtMKD5fy+9dyeObdLbSKi+N75w3hm2cNpF2iPvoS/fQplphUUl7BM//byu9f28DBknKuHt+HH14wlNSObYIOTaTRKIFLTHHOsXDVTu5fsp5te4s5a2g3Zlw4nBE9OwYdmkijUwKXmPHhlr3MfDGTldsKGd6jA8/cNIGzhnYLOiyRJqMELlFvU8EhZi9ez5K1u0jtmMj9V57EFeN6E6+bB0uMUwKXqDI/I5cHlmSxo7CY1E5tGNKtHe9u2ktiqzh+NGkoN585gLat9bGWlkGfdIka8zNymTF3NcVlFQDk7T9C3v4jnDYohYevGUe3DokBRyjSvDQIVqLGA0uyPk3e1W3dU6zkLS3ScRO4mbUxsw/M7GMzW2tm9/jlA8zsfTPLMbN/mVnrpg9XWrIdhcV1KheJdeGcgZcA5zrnRgNjgClmdgowG/itc24wsA+4ucmiFAG61nKWrR+fkpbquAnceQ75kwn+wwHnAv/xy58GpjVFgCIA5RWVtI4/elRJUkI8t04eFkBEIsELqw3czOLNbCWQD7wCbAQKnXPl/iLbgbRa1p1uZsvNbHlBQUEjhCwt0RPvbCa38Ag3ntaPtOQkDEhLTuK+y09k2tiQHz2RmBfWKBTnXAUwxsySgXnA8HA34JybA8wBSE9Pd/WIUVq4T/Yc5sFXspk0MpWfXXoCP//iqKBDEokIdRqF4pwrBF4HTgWSzazqC6A3kNu4oYl4l8bfOW81reLi+OXUUfrZV5FqwhmF0s0/88bMkoBJQCZeIr/SX+wGYEETxSgt2NyPcnk7Zze3TxlGj076ISqR6sJpQukJPG1m8XgJ/9/OuYVmtg541sx+BWQAjzdhnNIC7T5Uwi9fXMf4fp257uR+QYcjEnGOm8Cdc6uAsSHKNwETmiIoEYBfLlxHUUk5sy4/kTj9ronIUXQlpkSk17PyWbByB9+eOJghqR2CDkckIimBS8QpKinn7nlrGNy9Pd8+Z1DQ4YhELP2YlUScB1/JJrewmOe+dSqJreKDDkckYukMXCLKx9sKefKdzXzllL58oX9K0OGIRDQlcIkYZRWV3P78Krp1SOS2KWFfKybSYqkJRSLGY29tYn3eQR69fjwd2yQEHY5IxNMZuESEzbuLePjVDUw5oQeTT+gRdDgiUUEJXALnnOPOuatp3SqOe6aeEHQ4IlFDCVwC99zy7by7aQ8zLhxBakddLi8SLiVwCVTBwRJmLspkQv8UrvlCn6DDEYkqSuASqHv+u5bi0gru1eXyInWmBC6BWZq5i4WrdvLdcwczuHv7oMMRiTpK4BKIQyXl3D1/DcNSO/DNs3W5vEh9aBy4BOLXS7LIO3CEP143jtatdB4hUh/6y5Fmt2LrPp5+dwtfPaUf4/p2DjockailBC7NqrS8khlzV9GjYxtu1eXyIg2iJhRpVo++sZHsXYd4/IZ02ifq4yfSEDoDl2aTk3+I37+Ww8Un9eS8EalBhyMS9ZTApVlUVnqXy7dJiONnl44MOhyRmKAELs3i2Q+38cGWvdx98Ui6d9Dl8iKNQQlcmlz+gSPc91Impw7swlXpvYMORyRmKIFLk/vZC2spKa/k3stPxEyXy4s0FiVwaVJL1ubx0po8bjlvCAO6tgs6HJGYogQuTebAkTJ+umANw3t0YPpZA4MORyTmHDeBm1kfM3vdzNaZ2Vozu8UvTzGzV8xsg/+sS+rkc+5fvJ6CgyXMvuIkEuJ1riDS2ML5qyoHfuScGwmcAnzHzEYCdwBLnXNDgKX+tAgAy7fs5W/vfcKNpw1gdJ/koMMRiUnHTeDOuZ3OuY/81weBTCANmAo87S/2NDCtiWKUKFNSXsHtz68iLTmJH10wNOhwRGJWnf6vNbP+wFjgfSDVObfTn5UHhLy0zsymm9lyM1teUFDQkFglSvzp9Y1sLCjiV5eNop0ulxdpMmEncDNrDzwPfN85d6D6POecA1yo9Zxzc5xz6c659G7dujUoWIl8G3Yd5E/Lcpg6phfnDOsedDgiMS2sBG5mCXjJ++/Oubl+8S4z6+nP7wnkN02IEi0qKx13zF1Nu8RW/OQSXS4v0tTCGYViwONApnPuwWqzXgBu8F/fACxo/PAkmvz9/a2s2LqPuy8eSdf2iUGHIxLzwmmgPB24HlhtZiv9sjuBWcC/zexmYCtwdZNEKFFh5/5iZi/O4ozBXbliXFrQ4Yi0CMdN4M65t4Harn8+r3HDkWjknOOnC9ZSXlnJvZfpcnmR5qKrK6TBFq/J45V1u/jB+UPp26Vt0OGItBhK4NIg+w+X8dMX1nJCr47cfMaAoMMRaVE0SFcaZNbiTPYWlfLkjV+glS6XF2lW+ouTentv0x7++cE2bj5jAKPSOgUdjkiLowQu9XKkrII7566mT0oSPzhfl8uLBEFNKFIvf3gth027i/jrzRNIah0fdDgiLZLOwKXO1ucd4M9vbOTycWmcOUQ/jyASFCVwqZOKSscdz6+mY1ICd1+sy+VFgqQELnXyzLtbWLmtkJ9eMpKUdq2DDkekRVMCl7DlFhbzwJIszhrajaljegUdjkiLpwQuYXHO8ZP5a3AOZk4bpcvlRSKAEriEZeGqnby2Pp8fXTCUPim6XF4kEiiBy3EVHi7lnv+u5aTenfja6bpcXiRSaBy4HNfMFzPZd7iMZ246mfg4NZ2IRAqdgcsx/S9nN8+t2M70swYyslfHoMMRkWqUwKVWR8oqmDFvNf27tOWW84YEHY6I1KAmFKnVQ69uYOuew/zj6yfTJkGXy4tEGp2BS0hrd+znsbc2cdX43pw2uGvQ4YhICErgcpSKSseMuavp3DaBuy4eEXQ4IlILJXA5ypPvbGbV9v387NITSG6ry+VFIpUSuHzOtr2H+c3L2Zw7vDuXnNQz6HBE5BiUwOVTzjnumr+GOINf6nJ5kYinBC6fWrByB29mF3Dr5GGkJScFHY6IHIcSuACwt6iUXyxcx5g+yVx/av+gwxGRMBw3gZvZE2aWb2ZrqpWlmNkrZrbBf+7ctGFKU/vVwnUcKC5j1hUn6nJ5kSgRzhn4U8CUGmV3AEudc0OApf60RKk3swuYm5HLt84exPAeulxeJFocN4E7594E9tYongo87b9+GpjWuGFJczlcWs5d81czsGs7/u/cwUGHIyJ1UN828FTn3E7/dR6QWtuCZjbdzJab2fKCgoJ6bk6aym9fyWbb3mLuu/xEXS4vEmUa3InpnHOAO8b8Oc65dOdcerduuoN5JFm9fT+Pv72Zayf04eSBXYIOR0TqqL4JfJeZ9QTwn/MbLyRpDuUVldwxdxVd2idyx4W6XF4kGtU3gb8A3OC/vgFY0DjhSHN5/O3NrN1xgF988QQ6JSUEHY6I1EM4wwj/CbwLDDOz7WZ2MzALmGRmG4Dz/WmJElv3FPHgK9lMGpnKlFE9gg5HROrpuL8H7py7tpZZ5zVyLNIMnHPcOW81CfFx/HKqLpcXiWa6oUMLMT8jlweWZJFbWAzAlePS6NGpTcBRiUhD6FL6FmB+Ri4z5q7+NHkDvLh6J/MzcgOMSkQaSgm8BXhgSRbFZRWfKysuq+SBJVkBRSQijUFNKDGstLySN7MLPnfmXd2OWspFJDoogccY5xwrtu5j/spcFq7aSeHhMuIMKkNcatVLPxkrEtWUwGNETv5B5mfsYMHHuWzbW0ybhDguGNmDy8amsbeohLvnr/1cM0pSQjy3Th4WYMQi0lBK4FEs/8ARXvh4B/NX5rIm9wBxBqcP7soPzh/KBSf0oH3iZ9UbHxfHA0uy2FFYTK/kJG6dPIxpY9MCjF5EGkoJPMocKiln8Zo8FqzM5Z2c3VQ6OKl3J35yyUguHd2T7h1CDw2cNjZNCVskxiiBR4GyCq8zcl5GLq9m7uJIWSV9UpL4v3MGM3VsGoO6tQ86RBEJgBJ4hHLO8dEn+5ifsYOFq3aw73AZndsmcNX4Pkwbm8a4vsm6ilKkhVMCjzA5+YdYsDKXBSt38Mnew7RJiGPSyB5MG9OLs4Z2IyFeQ/dFxKMEHgHyDx7hvx97V0auzt3/aWfkLecNYfKoz3dGiohUUWYIyKGScpasyWN+tc7IE9M6cffFI/ji6F5076jfKRGRY1MCb0ZlFZW8taGAeRk7eGVdHkfKKundOYnvnDOYqWPSGNxdnZEiEj4l8CbmdUYWssC/MnJvUSmd2yZw5fjeXDY2jXF9O6szUkTqRQm8iWwsOMSCjFzm+52Ria3imDQylWlj0jhraDdat1JnpIg0jBJ4I6rqjFywMpdV2/djBqcP6sp3zx3MlFE96NBGty4TkcajBN5ARSXlLFmbx7yMzzojR6V15O6LR3Dp6F6kqjNSRJqIEng9lFVU8vaG3czLyOWVdbsoLqugd+ckvj1xMNPG9mJw9w5BhygiLYASeJicc2RsK2R+xmedkcltE7h8XBqXjU1jfD91RopI81ICP45NBYeYv3IHC1bmsnWP1xl5/ohUpo1N42x1RopIgJTAQyg4WMLCVTuYn5HLx35n5GmDuvCdc7zOyI7qjBSRCKAE7isqKefldXnMy9jBOzm7qah0jOzZkbsu8jojdQd3EYk0LTqBV3VGzl+Zy8trvc7ItOQkvnnWQKaNTWNoqjojRSRyNSiBm9kU4GEgHviLc25Wo0RVzfyM3LDuJHOs5T4/rw1XpfdhX1EpC1ftZE9RKZ2SErhsXBrTxqSR3q8zcXHqjBSRyGfOhbjbbTgrmsUD2cAkYDvwIXCtc25dbeukp6e75cuXh72N+Rm5zJi7+qh7Od53+YmfS+KhlmuTEMdPLxlJaUUl9y1aT0l55efeO95g8qgeTBuTxtnDupHYKj7suEREmpOZrXDOpR9V3oAEfirwc+fcZH96BoBz7r7a1qlrAj991mvkFhYfVR5vRveOiVQ6R0Ul7C0qCXnX9WPp2akN7844r24riYgEoLYE3pAmlDRgW7Xp7cDJITY8HZgO0Ldv3zptYEeI5A1Q4RxnDO5KfJxhZvzzg0/q9L4AefuP1HkdEZFI0uSdmM65OcAc8M7A67Jur+SkkGfgaclJPHDV6E+n38wuqHU5IOS8Xv48EZFo1ZCrUHKBPtWme/tljebWycNISvh823RSQjy3Th4W9nLhvoeISLRpyBn4h8AQMxuAl7ivAb7cKFH5qjoqjzcKJZzlwhnJIiISTerdiQlgZhcBD+ENI3zCOTfzWMvXtRNTRESaphMT59wiYFFD3kNEROpHv8QkIhKllMBFRKKUEriISJRSAhcRiVINGoVS542ZFQBbw1i0K7C7icOJRNrvlkX73XI0dJ/7Oee61Sxs1gQeLjNbHmrITKzTfrcs2u+Wo6n2WU0oIiJRSglcRCRKRWoCnxN0AAHRfrcs2u+Wo0n2OSLbwEVE5Pgi9QxcRESOI+ISuJlNMbMsM8sxszuCjqexmFkfM3vdzNaZ2Vozu8UvTzGzV8xsg//c2S83M/udfxxWmdm4YPegYcws3swyzGyhPz3AzN739+9fZtbaL0/0p3P8+f0DDbwBzCzZzP5jZuvNLNPMTm0J9W1mP/A/42vM7J9m1iYW69vMnjCzfDNbU62szvVrZjf4y28wsxvqEkNEJXD/Ppt/BC4ERgLXmtnIYKNqNOXAj5xzI4FTgO/4+3YHsNQ5NwRY6k+DdwyG+I/pwCPNH3KjugXIrDY9G/itc24wsA+42S+/Gdjnl//WXy5aPQwsds4NB0bj7X9M17eZpQHfA9Kdc6Pwfqn0GmKzvp8CptQoq1P9mlkK8DO8u5lNAH5WlfTD4pyLmAdwKrCk2vQMYEbQcTXRvi7AuyF0FtDTL+sJZPmvH8W7SXTV8p8uF20PvJt9LAXOBRYChndRQ6ua9Q4sAU71X7fyl7Og96Ee+9wJ2Fwz9livbz671WKKX38LgcmxWt9Af2BNfesXuBZ4tFr555Y73iOizsAJfZ/NmLvzgv9v4ljgfSDVObfTn5UHpPqvY+lYPATcBlT6012AQudcuT9dfd8+3W9//n5/+WgzACgAnvSbjv5iZu2I8fp2zuUCvwY+AXbi1d8KYr++q9S1fhtU75GWwGOembUHnge+75w7UH2e876CY2pYkJldAuQ751YEHUszawWMAx5xzo0Fivjs32kgZuu7MzAV7wusF9COo5sZWoTmqN9IS+BNfp/NIJlZAl7y/rtzbq5fvMvMevrzewL5fnmsHIvTgS+a2RbgWbxmlIeBZDOruqFI9X37dL/9+Z2APc0ZcCPZDmx3zr3vT/8HL6HHen2fD2x2zhU458qAuXifgViv7yp1rd8G1XukJfBP77Pp91JfA7wQcEyNwswMeBzIdM49WG3WC0BVz/MNeG3jVeVf9XuvTwH2V/vXLGo452Y453o75/rj1edrzrnrgNeBK/3Fau531fG40l8+6s5SnXN5wDYzq7p79nnAOmK8vvGaTk4xs7b+Z75qv2O6vqupa/0uAS4ws87+fy8X+GXhCboTIESnwEVANrARuCvoeBpxv87A+3dqFbDSf1yE1963FNgAvAqk+Msb3oicjcBqvF79wPejgcdgIrDQfz0Q+ADIAZ4DEv3yNv50jj9/YNBxN2B/xwDL/TqfD3RuCfUN3AOsB9YAfwUSY7G+gX/itfOX4f3HdXN96he4yd//HOBrdYlBV2KKiESpSGtCERGRMCmBi4hEKSVwEZEopQQuIhKllMBFRKKUEriISJRSAhcRiVJK4CIiUer/A6Cavx8XovULAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Depth First Search\")" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 58952.967129705365\n", + "[*] Running for: 33.78 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 3088.6042241002488\n", + "[*] Running for: 7.97 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.02 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 39236.884898455035\n", + "[*] Running for: 0.06 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 761.6890898866324\n", + "[*] Running for: 0.14 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyBFSModel()\n", + "\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Breadth First Search\")" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dynamic Progrmaming\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 58952.967129705365\n", + "[*] Running for: 2.05 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 3088.6042241002488\n", + "[*] Running for: 0.55 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] [Node] 1000, [Best] 22449665.175576296\n", + "[*] Running for: 32.57 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 39236.884898455035\n", + "[*] Running for: 0.01 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 761.6890898866324\n", + "[*] Running for: 0.02 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyDPDModel()\n", + "\n", + "print(\"Dynamic Progrmaming\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Dynamic Programming (Depth First)\")" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dynamic Progrmaming\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 58952.967129705365\n", + "[*] Running for: 7.77 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 3088.6042241002488\n", + "[*] Running for: 2.04 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.04 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 39236.884898455035\n", + "[*] Running for: 0.02 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 761.6890898866324\n", + "[*] Running for: 0.04 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyDPBModel()\n", + "\n", + "print(\"Dynamic Progrmaming\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Dynamic Programming (Breadth First)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conclusions (Random, BFS, DFS, DP)" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [], + "source": [ + "# Simple\n", + "# ulysses16: 77 (BFS), 84 (DFS)\n", + "# att48: 39236 (BFS), 40763 (DFS)\n", + "# st70: 761 (BFS), 901 (DFS)\n", + "\n", + "# Medium\n", + "# a280: 3088 (BFS), 3558 (DFS)\n", + "# pcb442: 58952 (BFS), 61984 (DFS)\n", + "\n", + "# Hard\n", + "# dsj1000: time-out (DP-BFS) 23,552,227 (DP-DFS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

1. All different models get the same results every time (except random).

\n", + "

2. All different models have an exponential time complexity (except random).

\n", + "

3. Depth First Seach is a little faster than Breadth First Search, but Breadth First get better results.

\n", + "

4. Only dynamic programming solves the problem with 1000 cities (Fast).

" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "# In the next workshop \n", + "# Will try to solve the problem with 1000 cities faster, and get better results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 2 (UCS, A, Hill-Climbing).ipynb b/Workshop - 2 (UCS, A, Hill-Climbing).ipynb new file mode 100644 index 0000000..87fb41b --- /dev/null +++ b/Workshop - 2 (UCS, A, Hill-Climbing).ipynb @@ -0,0 +1,1420 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Append template path to sys path\n", + "sys.path.append(os.getcwd() + \"/template\") " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.load_data import load_data\n", + "from utils.load_data import log\n", + "from utils.visualize_tsp import plotTSP\n", + "from utils.tsp import TSP\n", + "from utils.tsp import TSP_Bench\n", + "from utils.tsp import TSP_Bench_ALL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workshop Starts Here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"TSP\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"solutions\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get familiar with your dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are problems at different levels. **3 simple, 2 medium, 1 hard**." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16 = np.array(load_data(\"./template/data/simple/ulysses16.tsp\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[38.24, 20.42],\n", + " [39.57, 26.15],\n", + " [40.56, 25.32],\n", + " [36.26, 23.12],\n", + " [33.48, 10.54],\n", + " [37.56, 12.19],\n", + " [38.42, 13.11],\n", + " [37.52, 20.44],\n", + " [41.23, 9.1 ],\n", + " [41.17, 13.05],\n", + " [36.08, -5.21],\n", + " [38.47, 15.13],\n", + " [38.15, 15.35],\n", + " [37.51, 15.17],\n", + " [35.49, 14.32],\n", + " [39.36, 19.56]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ulysses16[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXIAAAD6CAYAAAC8sMwIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAb3ElEQVR4nO3dfXRV9b3n8feXgE6sYmQgEE/AqMjzQ8AIMnVQ6gRQGQS0DhlqYUCo3tIZqQW1XV0+rGthgRaxdunoQEXrlduOCCykIPIwVqsyATJAx0b0EgshQlCyLkIcIH7nj5wggQSSnId99snntVYW5+xzsveHh3zO5rd/e29zd0REJLzaBB1ARERioyIXEQk5FbmISMipyEVEQk5FLiIScipyEZGQU5GLSNKY2RIzO2hmu4LOkk4siHnkHTt29Ly8vKRvV0SCdeTIETIyMtizZw99+/YNOk7obN269ZC7dzpzedsgwuTl5VFcXBzEpkUkYGVlZYwZM0Yd0AJm9llDyzW0IiIScipyEZGQU5GLiAB79+5lxIgR9OnTh759+7Jo0aKgIzVZIGPkIiKppm3btjz11FMMHjyYI0eOcO2111JYWEifPn2CjnZe2iMXkaQpKipi2LBhlJaWkpuby+LFi4OOdEpOTg6DBw8G4JJLLqF3796Ul5cHnKpptEcuIgm1Yns5C9aVsr+qmssHTue5OU8yblAk6FjnVFZWxvbt2xk6dGjQUZpERS4iCbNiezkPL99J9YkaAMqrqnl4+U6AlC3zr776ijvuuIOnn36a9u3bBx2nSTS0IiIJs2Bd6akSr1N9ooYF60oDSnRuJ06c4I477mDSpElMmDAh6DhNpiIXkYTZX1XdrOVBcnemTZtG7969+elPfxp0nGZRkYtIwlyeldms5UF67733eOWVV9i4cSP5+fnk5+ezZs2aoGM1icbIRSRhZo/qWW+MHCCzXQazR/UMMNW36h2IzcrkjW37Unbs/lxU5CKSMHWleHpZzh7VMyXKMowHYhvT5CI3s67Ay0BnwIEX3H2RmT0KTAcqo2/9ubuH4/8jIpJw4wZFUrIYz3UgNhXznktz9shPAg+4+zYzuwTYambro68tdPcn4x9PRCQxwnQg9nyafLDT3SvcfVv08RHgIyBcH1siIlFhOhB7Pi2atWJmecAg4MPooplmtiN694/LGvmeGWZWbGbFlZWVDb1FRCRpZo/qSWa7jHrLUulAbHM0u8jN7GLgdeB+d/9X4DngaiAfqACeauj73P0Fdy9w94JOnc66wYWkua+//pohQ4YwcOBA+vbtyyOPPBJ0JGnlxg2KMHdCfyJZmRgQycpk7oT+oRsfh2bOWjGzdtSW+KvuvhzA3Q+c9vqLwOq4JpS0cOGFF7Jx40YuvvhiTpw4wQ033MAtt9zC9ddfH3Q0acVS9UBsczV5j9zMDFgMfOTuvz5tec5pbxsP6KaqchYz4+KLLwZqT4M+ceIEtf+kRCRWzRla+S5wN/A9MyuJft0KzDeznWa2AxgBzEpEUAm/mpoa8vPzyc7OprCwMDRXlhNJdU0eWnH3d4GGdqE0Z1yaJCMjg5KSEqqqqhg/fjy7du2iX79+QccSCT1da0WSLisrixEjRrB27dqgo4ikBRW5JEVlZSVVVVUAVFdXs379enr16hVsKJE0oWutSFJUVFQwefJkampq+Oabb7jrrrsYM2ZM0LFE0oKKXBLmzCvLPbJkdVpM9RJJNSpySYh0urKcSKrTGLkkRNhu8SUSZipySYh0urKcSKpTkUtCpNOV5URSnYpcEiKdriwnkup0sFMSIpVv8SWSblTkkjDpcmU5kVSnoRURkZBTkYs0Q2lpKfn5+ae+2rdvz9NPP53Qba5du5aePXvSvXt35s2bl9BtSThpaEWkGXr27ElJSQlQe1neSCTC+PHjE7a9mpoafvzjH7N+/Xpyc3O57rrrGDt2LH369EnYNiV8tEcu0kIbNmzg6quv5oorrkjYNrZs2UL37t256qqruOCCC5g4cSIrV65M2PYknFTkIi20bNkyioqKErqN8vJyunbteup5bm4u5eXlCd2mhI+KXKQFjh8/zqpVq/j+978fdBQRFblIS/zpT39i8ODBdO7cOaHbiUQi7N2799Tzffv2EYloSqfUpyIXaYHXXnst4cMqANdddx27d+9mz549HD9+nGXLljF27NiEb7elpk6dSnZ2dr1b+D366KNEIpFTM33WrNHdIeNNRS7STEePHmX9+vVMmDAh4dtq27Ytzz77LKNGjaJ3797cdddd9O3bN+HbbakpU6Y0eAu/WbNmUVJSQklJCbfeemsAydKbph+KnMeZN8iYPaonX3zxRRK3N5CPP/44YduLp+HDh1NWVhZ0jFZHe+Qi51B3g4zyqmqcb2+QsWJ7YmaOJHt7yfLss88yYMAApk6dyuHDh4OOk3aaXORm1tXMNpnZ/zWzv5rZf4su72Bm681sd/TXyxIXVyS5kn2DjHS8Icd9993Hp59+SklJCTk5OTzwwANBR0o7zdkjPwk84O59gOuBH5tZH+AhYIO7XwNsiD4XSQvJvkFGOt6Qo3PnzmRkZNCmTRumT5/Oli1bgo6Udppc5O5e4e7boo+PAB8BEeB2YGn0bUuBcXHOKBKYZN8gIx1vyFFRUXHq8RtvvFFvRovER4vGyM0sDxgEfAh0dve6v6nPgcROrBVJomTfICPsN+QoKipi2LBhlJaWkpuby+LFi5kzZw79+/dnwIABbNq0iYULFwYdM+2YuzfvG8wuBv4X8IS7LzezKnfPOu31w+5+1ji5mc0AZgB069bt2s8++yym4CLJ0tCslUReZz3Z24tV2PKGmZltdfeCs5Y3p8jNrB2wGljn7r+OLisFbnL3CjPLATa7+zl3HwoKCry4uLhZvwERST11s2xOP0Cb2S6DuRP6q8wToLEib86sFQMWAx/VlXjUKmBy9PFkQJdmE2kl0nGWTRg154Sg7wJ3AzvNrCS67OfAPOAPZjYN+Ay4K64JRSRlpeMsmzBqcpG7+7uANfLyzfGJIyJhcnlWJuUNlHaYZ9mEkc7sFJEWC/ssm3Sha62ISIvVHdDUrJVgqchFJCbjBkVU3AHT0IqISMipyEVEQk5FLiIScipyEZGQU5GLiIScilxEJORU5CIiIaciFxEJORW5iEjIqchFREJORS6SYqZOnUp2dna9e1vOnj2bXr16MWDAAMaPH09VVVVwASXlqMhFmqGhkv3lL3/JgAEDyM/PZ+TIkezfvz+mbUyZMoW1a9fWW1ZYWMiuXbvYsWMHPXr0YO7cuTFtQ9KLilykGRoq2dmzZ7Njxw5KSkoYM2YMjz/+eEzbGD58OB06dKi3bOTIkbRtW3uNu+uvv559+/adeq2hD5c//vGP9O3blzZt2qDbKqY/FblIMzRUsu3btz/1+OjRo9TeFTFxlixZwi233HLqeUMfLv369WP58uUMHz48oVkkNegytiJx8Itf/IKXX36ZSy+9lE2bNiVsO0888QRt27Zl0qRJp5YNHz6csrKyeu/r3bt3wjJI6tEeuUgcPPHEE+zdu5dJkybx7LPPJmQbL730EqtXr+bVV19N+F6/hIuKXCSOJk2axOuvvx739a5du5b58+ezatUqLrroorivX8JNRd7KNHRgrM5TTz2FmXHo0KEAkoXX7t27Tz1euXIlvXr1iml9RUVFDBs2jNLSUnJzc1m8eDEzZ87kyJEjFBYWkp+fz7333htrbEkjGiNvZaZMmcLMmTP54Q9/WG/53r17eeutt+jWrVtAycKhqKiIzZs3c+jQIXJzc3nsscdYs2YNpaWltGnThiuuuILnn3++2etdsb382/teDpzOc3OerHf7tGnTpsXztyFpRkXeyjR0YAxg1qxZzJ8/n9tvvz35oVJYvYLNymT2nCd57bX696eMtWRXbC/n4eU7qT5RA0B5VTUPL98J0KR7YTb04dKhQwd+8pOfUFlZyW233UZ+fj7r1q2LKaekriYXuZktAcYAB929X3TZo8B0oDL6tp+7+5p4h5TEWrlyJZFIhIEDBwYdJaXEWrBNtWBd6alt1Kk+UcOCdaWNbud8e/AA48ePj1tGSW3NGSN/CRjdwPKF7p4f/VKJh8yxY8f41a9+FfNJLOnoXAUbT/urqpu1vO4DpryqGufbD5gV28vjmkvCo8lF7u7vAF8mMIsE4NNPP2XPnj0MHDiQvLw89u3bx+DBg/n888+Djha45hZsS12eldms5cn6gJHwiMeslZlmtsPMlpjZZXFYnyRR//79OXjwIGVlZZSVlZGbm8u2bdvo0qVL0NEC19yCbanZo3qS2S6j3rLMdhnMHtWzwfcn6wNGwiPWIn8OuBrIByqApxp7o5nNMLNiMyuurKxs7G2SYA1NbZOGNbdgW2rcoAhzJ/QnkpWJAZGsTOZO6N/o+PjpHyTffP0VlW/8ivIX7+XAkn/g/fffj2s2CQdz96a/2SwPWF13sLOpr52poKDAdSGf5Dlr5sWonnE9WJfOUvHP7vSDsIfe/DUX5vYlu+BWHv+PPSnscRlZWVmB5pPGLVq0iBdffBF3Z/r06dx///3N+n4z2+ruBWcuj2n6oZnluHtF9Ol4YFcs65P4S9bMi3Q1blAk5f6c6vLMXbmV8r1/ZcB//jlzRvdKuZxS365du3jxxRfZsmULF1xwAaNHj2bMmDF079495nU3eWjFzF4D3gd6mtk+M5sGzDeznWa2AxgBzIo5kcSVDoylp3GDIvz3cd0Y1KMbPUpf4bGpY7jnnns4evRo0NGkER999BFDhw7loosuom3bttx4440sX748LutuzqyVInfPcfd27p7r7ovd/W537+/uA9x97Gl755IidGAsfZ08eZJt27Zx3333sX37dr7zne8wb968oGNJI/r168ef//xnvvjiC44dO8aaNWvYu3dvXNata62kuWTNvJDky83NJTc3l6FDhwJw5513sm3btoBTSWN69+7Ngw8+yMiRIxk9ejT5+flkZGSc/xubQEWe5pI186K1ycvLo3///uTn51NQcNaxp6To0qULXbt2pbS0dphsw4YN9OnTJ5As0jTTpk1j69atvPPOO1x22WX06NEjLuvVtVbSXN0BsFSbeZEONm3aRMeOHQPN8Jvf/IZJkyZx/PhxrrrqKn73u98FmkfO7eDBg2RnZ/P3v/+d5cuX88EHH8RlvSryViAVZ15IyzQ0HVJTecPjjjvu4IsvvqBdu3b89re/jdtUURW5SAuYGSNHjsTM+NGPfsSMGTMSvk1NJQ2fsz54n1mWkL8rFblIC7z77rtEIhEOHjxIYWEhvXr1SviNjltylUQJTjI/eHWwU6QFIpHaH8Ts7GzGjx/Pli1bEr5NTSUNl2Sew6EiF2mmo0ePcuTIkVOP33rrrQZvnRdvmkoaLsn84FWRizTTgQMHuOGGGxg4cCBDhgzhtttuY/Tohi7VH1+aShouyfzg1Ri5SBOcedDqsZfWJH1cWlNJw2X2qJ71xsghcR+8KnKR80il2SKaShoeyfzgVZGLnIdmi0hLJeuDN9Rj5DU1NQwaNIgxY8YEHUXSmGaLSKoLdZEvWrSI3r17Bx1D0pxmi0iqC22R79u3jzfffJN77rkn6CiS5jRbRFJdaMfI77//fubPn39qPq9Iomi2iKS6UBb56tWryc7O5tprr2Xz5s1Bx5FWQLNFJJWFcmjlvffeY9WqVeTl5TFx4kQ2btzID37wg6BjiYgEwtw96RstKCjweF16c/PmzTz55JOsXr06LusTEUlVZrbV3c+6k0ko98hFRORboRkjb+iC+uMGRbjpppu46aabgo4nIhKYUOyR150iXV5VjfPtKdIrtpcHHU1EpNkWLlxI37596devH0VFRXz99dcxra/JRW5mS8zsoJntOm1ZBzNbb2a7o79eFlOaRiTzur4iIolUXl7OM888Q3FxMbt27aKmpoZly5bFtM7m7JG/BJx5rc6HgA3ufg2wIfo87nSKtIikk5MnT1JdXc3Jkyc5duwYl19+eUzra3KRu/s7wJdnLL4dWBp9vBQYF1OaRugUaRFJF5FIhJ/97Gd069aNnJwcLr30UkaOHBnTOmMdI+/s7hXRx58DnWNcX4N0irSIpIvDhw+zcuVK9uzZw/79+zl69Ci///3vY1pn3A52eu2E9EYnpZvZDDMrNrPiysrKZq173KAIcyf0J5KViQGRrEzmTuivM+1EJHTefvttrrzySjp16kS7du2YMGECf/nLX2JaZ6zTDw+YWY67V5hZDnCwsTe6+wvAC1B7QlBzN6RTpEUkHXTr1o0PPviAY8eOkZmZyYYNGygoOOscn2aJdY98FTA5+ngysDLG9YmIpLWhQ4dy5513MnjwYPr3788333zDjBkzYlpnk/fIzew14Cago5ntAx4B5gF/MLNpwGfAXTGlERFJU/VParyRea/NiNsoQ5OL3N2LGnnp5rgkERFJU4m+72sozuwUEQmzRJ/UqCIXEUmwRJ/UqCIXEUmwRJ/UqCIXEUmwRJ/UGJrL2IqIhFWi7/uqIhcRSYJEntSooRURkZBTkYuIhJyKXEQk5FTkIiIhpyIXEQk5FbmISMipyEVEQk5FLiIScipyEZGQU5GLiIScilxEJORU5CIiIaciFxEJORW5iEjIqchFREJORS4iEnIqchGRkIvLHYLMrAw4AtQAJ929IB7rFRGR84vnrd5GuPuhOK5PRESaQEMrIiIhF68id+AtM9tqZjPitE4REWmCeA2t3ODu5WaWDaw3s7+5+zunvyFa8DMAunXrFqfNiohIXPbI3b08+utB4A1gSAPvecHdC9y9oFOnTvHYrIiIEIciN7PvmNkldY+BkcCuWNcrIiJNE4+hlc7AG2ZWt75/cve1cViviIg0QcxF7u7/AgyMQxYREWkBTT8UEQk5FbmISMipyEVEQk5FLiIScipyEZGQU5GLiIScilxEJORU5CIiIaciFxEJORW5iEjIqchFREJORS4iEnIqchGRkFORi4iEnIpcRCTkVOQiIiGnIhcRCTkVuYhIyKnIRURCTkUuIhJyKnIRkZBTkYuIhFxcitzMRptZqZl9YmYPxWOdIiLSNDEXuZllAL8FbgH6AEVm1ifW9YqISNPEY498CPCJu/+Lux8HlgG3x2G9IiLSBPEo8giw97Tn+6LLREQkCZJ2sNPMZphZsZkVV1ZWJmuzIiJpLx5FXg50Pe15bnRZPe7+grsXuHtBp06d4rBZERGB+BT5/wauMbMrzewCYCKwKg7rFRGRJmgb6wrc/aSZzQTWARnAEnf/a8zJRESkSWIucgB3XwOsice6RESkeXRmp4hIyKnIRURCTkUuIhJyKnIRkZBTkYuIhJyKXEQk5FTkIiIhpyIXEQk5FbmISMipyEVEQk5FLiIScipyEZGQU5GLiIScilxEJORU5CIiIaciFxEJORW5iEjIqcglbqZOnUp2djb9+vU7tezLL7+ksLCQa665hsLCQg4fPhxgQpH0pCKXuJkyZQpr166tt2zevHncfPPN7N69m5tvvpl58+YFlE4kfanIJW6GDx9Ohw4d6i1buXIlkydPBmDy5MmsWLEigGQi6U1FLgl14MABcnJyAOjSpQsHDhwIOJFI+lGRS9KYGWYWdAyRtKMil4Tq3LkzFRUVAFRUVJCdnR1wIpH0E1ORm9mjZlZuZiXRr1vjFUzSw9ixY1m6dCkAS5cu5fbbbw84kUj6icce+UJ3z49+rYnD+iSkioqKGDZsGKWlpeTm5rJ48WIeeugh1q9fzzXXXMPbb7/NQw89FHRMkbTTNugAEm4rtpezYF0p+6uquXzgdJ6b8yTjBkXqvWfDhg0BpRNpHeKxRz7TzHaY2RIzuywO65OQWLG9nIeX76S8qhoHyquqeXj5TlZsLw86mkirct4iN7O3zWxXA1+3A88BVwP5QAXw1DnWM8PMis2suLKyMl75JUAL1pVSfaKm3rLqEzUsWFcaUCKR1um8Qyvu/h+asiIzexFYfY71vAC8AFBQUOBNDSipa39VdbOWi0hixDprJee0p+OBXbHFkTC5PCuzWctFJDFiHSOfb2Y7zWwHMAKYFYdMEhKzR/Uks11GvWWZ7TKYPapnQIlEWqeYZq24+93xCiLhUzc75dSslaxMZo/qedasFRFJLE0/lJiMGxRRcYsETKfoi4iEnIpcRCTkVOQiIiGnIhcRCTkVuYhIyJl78k+yNLNK4LOkb7hxHYFDQYdohLK1TCpng9TOp2wtk4xsV7h7pzMXBlLkqcbMit29IOgcDVG2lknlbJDa+ZStZYLMpqEVEZGQU5GLiIScirzWC0EHOAdla5lUzgapnU/ZWiawbBojFxEJOe2Ri4iEXKsqcjP7N2a2xcz+j5n91cweO+P1Z8zsq1TKZmYvmdkeMyuJfuWnWD4zsyfM7GMz+8jM/msKZfvzaX9u+81sRQplu9nMtkWzvWtm3VMo2/ei2XaZ2VIzC+ziemaWYWbbzWx19PmVZvahmX1iZv9sZhcEla2RfDOj2dzMOiYtiLu3mi/AgIujj9sBHwLXR58XAK8AX6VSNuAl4M5U/bMD/gvwMtAm+lp2qmQ74z2vAz9MlWzAx0Dv6PJ/AF5KkWz/DtgL9IgufxyYFuC/u58C/wSsjj7/AzAx+vh54L6gsjWSbxCQB5QBHZOVo1XtkXutuj3udtEvN7MMYAEwJ9WyBZXnTOfIdx/wuLt/E33fwRTKBoCZtQe+B6xIoWwOtI8uvxTYnyLZaoDj7v5xdPl64I5kZwMws1zgNuB/RJ8btX+P/zP6lqXAuCCyRfPUywfg7tvdvSzZWVpVkcOp/wqVAAeB9e7+ITATWOXuFSmYDeAJM9thZgvN7MIUy3c18J+iN9b+k5ldk0LZ6owDNrj7v6ZQtnuANWa2D7gbmJcK2YAtQFszqzux5U6gaxDZgKep3bn6Jvr83wJV7n4y+nwfEOTF8J+mfr7AtLoid/cad88HcoEhZjYc+D7wm0CD0WC2fsDDQC/gOqAD8GCK5bsQ+Nprz2h7EViSQtnqFAGvBZELGs02C7jV3XOB3wG/ToVsQF9gIrDQzLYAR6jdS08qMxsDHHT3rcnedlOkWr5WV+R13L0K2ETtvUa7A5+YWRlwkZl9EmC007ONdveK6H+B/x+1P/BDgswG9fNRu1e0PPrSG8CAgGIBZ2UjesBpCPBmgLGAetluAQae9r+Gf6Z2bDowZ/ybe9/d/727DwHeoXY8P9m+C4yN/kwuo3ZIZRGQddrB11ygPIBs0EA+M/t9QFlaV5GbWSczy4o+zgQKga3u3sXd89w9Dzjm7kHMIGgo29/MLCe6zKgdItiV7GznykftuPOI6NtuJIAf+nNkg9qhgdXu/nWyc50j20fApWbWI/q2umWpkO1vZpYdXXYhtf8DfD7Z2dz9YXfPjf5MTgQ2uvskaj9s7oy+bTKwMtnZzpHvB0FkgdZ3z84cYGn04GYb4A/uvjrgTHUazGZmG82sE7UzDEqAe1Ms37vAq2Y2C/iK2rHflMgWfW0iAY0/RzX25zYdeN3MvgEOA1NTKNuC6NBBG+A5d98YQLbGPAgsM7N/BLYDiwPOU4/VTr+dA3QBdpjZGndP+M+EzuwUEQm5VjW0IiKSjlTkIiIhpyIXEQk5FbmISMipyEVEQk5FLiIScipyEZGQU5GLiITc/wdYchCIkkcAEgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(ulysses16[:, 0], ulysses16[:, 1])\n", + "for i in range(0, 16):\n", + " plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: In Order" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]\n" + ] + } + ], + "source": [ + "simple_sequence = list(range(0, 16))\n", + "print(simple_sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([simple_sequence], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: Random Permutation" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[4, 15, 11, 6, 9, 13, 5, 3, 2, 12, 14, 8, 10, 1, 7, 0]\n" + ] + } + ], + "source": [ + "random_permutation = np.random.permutation(16).tolist()\n", + "print(random_permutation)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([random_permutation], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Best Solution" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]\n", + "plotTSP([best_ulysses16], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Fitness (Sum of all Distances)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def dist(node_0, node_1, coords):\n", + " \"\"\"\n", + " Euclidean distance between two nodes.\n", + " \"\"\"\n", + " coord_0, coord_1 = coords[node_0], coords[node_1]\n", + " return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 0: [38.24 20.42]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 0:\", ulysses16[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 1: [39.57 26.15]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 1:\", ulysses16[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance Between 5.882329470541408\n" + ] + } + ], + "source": [ + "print(\"Distance Between\", dist(0, 1, ulysses16))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness(solution, coords):\n", + " N = len(coords)\n", + " cur_fit = 0\n", + " for i in range(len(solution)):\n", + " cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)\n", + " return cur_fit" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Order Fitness:\t 104.42225210207233\n", + "Random Fitness:\t 128.48861505039284\n", + "Best Fitness:\t 74.10873595815309\n" + ] + } + ], + "source": [ + "print (\"Order Fitness:\\t\", fitness(simple_sequence, ulysses16))\n", + "print (\"Random Fitness:\\t\", fitness(random_permutation, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Random Model" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyRandomModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " random_solutions = []\n", + " for i in range(0, max_it):\n", + " solution = np.random.permutation(self.N).tolist()\n", + " random_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 103.2048389639759\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, max_it=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Uniform Cost Search" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyUCSModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def getMST(self, node):\n", + " MST = []\n", + " distances = []\n", + " for i in range(0, self.N):\n", + " if i != node:\n", + " MST.append(i)\n", + " distances.append(self.dist(node, i))\n", + " return [x for _,x in sorted(zip(distances, MST))]\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " UCS_solutions = []\n", + " UCS_losses = []\n", + " \n", + " for i in range(0, self.N):\n", + " solution = [i]\n", + " UCS_solutions.append(solution)\n", + " UCS_losses.append(math.inf)\n", + " \n", + " MSTs = []\n", + " for i in range(0, self.N):\n", + " MSTs.append([-1] * self.N)\n", + "\n", + " # Breadth First: Set each city as starting point, then go to next city simultaneously\n", + " min_loss = math.inf\n", + " while(len(UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]) != self.N):\n", + " unvisited_list = list(range(0, self.N))\n", + " min_loss = min(UCS_losses)\n", + " # For each search path\n", + " for i in range(0, self.N):\n", + " if UCS_losses[i] == min_loss:\n", + " cur_city = UCS_solutions[i][-1]\n", + " unvisited_list = list( set(range(0, self.N)) - set(UCS_solutions[i]) )\n", + " if MSTs[cur_city][0] == -1:\n", + " MST = self.getMST(cur_city)\n", + " MSTs[cur_city] = MST\n", + "\n", + " for j in MSTs[cur_city]:\n", + " if(j in unvisited_list):\n", + " UCS_solutions[i].append(j)\n", + "\n", + " N = len(UCS_solutions[i])\n", + " cur_fit = 0\n", + " for k in range(len(UCS_solutions[i])):\n", + " coord_0, coord_1 = self.coords[UCS_solutions[i][k % N]], self.coords[UCS_solutions[i][(k + 1) % N]]\n", + " cur_fit += math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)\n", + " UCS_losses[i] = cur_fit\n", + "# if(UCS_losses[i] < min_loss):\n", + "# min_loss = UCS_losses[i]\n", + " break\n", + " self.best_solution = UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyUCSModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A star" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Heuristic" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyASModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def getMST(self, node):\n", + " MST = []\n", + " distances = []\n", + " for i in range(0, self.N):\n", + " if i != node:\n", + " MST.append(i)\n", + " distances.append(self.dist(node, i))\n", + " return [x for _,x in sorted(zip(distances, MST))]\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " MST_solutions = []\n", + " \n", + " for i in range(0, self.N):\n", + " solution = [i]\n", + " MST_solutions.append(solution)\n", + " \n", + " # Breadth First: Set each city as starting point, then go to next city simultaneously\n", + " for step in range(0, self.N - 1):\n", + "# print(\"[step]\", step)\n", + " unvisited_list = list(range(0, self.N))\n", + " # For each search path\n", + " for i in range(0, self.N):\n", + " cur_city = MST_solutions[i][-1]\n", + " unvisited_list = list( set(range(0, self.N)) - set(MST_solutions[i]) )\n", + " closest_neighbour = -1\n", + " min_f = math.inf\n", + " \n", + " for j in unvisited_list:\n", + " g = self.dist(cur_city, j)\n", + " sub_unvisited_list = unvisited_list.copy()\n", + " sub_unvisited_list.remove(j)\n", + "\n", + " sub_cur_city = self.getMST(j)[0]\n", + " h = 0\n", + " while len(sub_unvisited_list) > 0:\n", + " if(len(unvisited_list) == 2):\n", + " break\n", + " else:\n", + " for k in self.getMST(sub_cur_city):\n", + " if k in sub_unvisited_list:\n", + " h = h + self.dist(sub_cur_city, k)\n", + " sub_cur_city = k\n", + " sub_unvisited_list.remove(k)\n", + " break\n", + " # Get f(x) = g(x) + h(x)\n", + "\n", + " f = g + h\n", + " if(f < min_f):\n", + " closest_neighbour = j\n", + " min_f = f\n", + " MST_solutions[i].append(closest_neighbour)\n", + "\n", + " for i in range(0, self.N):\n", + " self.fitness_list.append(self.fitness(MST_solutions[i]))\n", + " \n", + " self.best_solution = MST_solutions[ self.fitness_list.index(min(self.fitness_list)) ]\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 77.02641196679659\n", + "[*] Running for: 0.24 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyASModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hill Climbing" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Heuristic Iteration" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "import numpy as np\n", + "from model.base_model import Model\n", + "\n", + "class MyHillClimbModel(Model):\n", + "\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def random_tour(self):\n", + " return np.random.permutation(self.N).tolist()\n", + "\n", + " def all_pairs(self, size, shuffle=random.shuffle):\n", + " r1 = list(range(size))\n", + " r2 = list(range(size))\n", + " if shuffle:\n", + " shuffle(r1)\n", + " shuffle(r2)\n", + " for i in r1:\n", + " for j in r2:\n", + " yield (i,j)\n", + "\n", + " def move_operator(self, tour):\n", + " '''generator to return all possible variations\n", + " where the section between two cities are swapped'''\n", + " for i,j in self.all_pairs(len(tour)):\n", + " if i != j:\n", + " copy=tour[:]\n", + " if i < j:\n", + " copy[i:j+1]=reversed(tour[i:j+1])\n", + " else:\n", + " copy[i+1:]=reversed(tour[:j])\n", + " copy[:j]=reversed(tour[i+1:])\n", + " if copy != tour: # no point returning the same tour\n", + " yield copy\n", + "\n", + " def fit(self, max_it=100):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + "\n", + " self.best_solution = self.random_tour()\n", + " best_score = -self.fitness(self.best_solution)\n", + "\n", + " num_evaluations = 0\n", + "\n", + " while num_evaluations < max_it:\n", + " # examine moves around our current position\n", + " move_made = False\n", + " for next_solution in self.move_operator(self.best_solution):\n", + " if num_evaluations >= max_it:\n", + " print(\"Max iteration reached:\", max_it)\n", + " break\n", + "\n", + " # see if this move is better than the current\n", + " next_score = -self.fitness(next_solution)\n", + " num_evaluations += 1\n", + " if next_score > best_score:\n", + " self.best_solution = next_solution\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + " best_score=next_score\n", + " move_made=True\n", + " break # depth first search\n", + "\n", + " if not move_made:\n", + " break # we couldn't find a better move (must be at a local maximum)\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 75.20004295930718\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyHillClimbModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your Smart Model" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your Model" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_problem = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[*] [Node] 16, [Best] 148.18952217033015\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test All Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_path = './template/data'" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_results(best_solutions, times, title):\n", + " fig = plt.figure()\n", + " nodes = [len(s) for s in best_solutions]\n", + " data = np.array([[node, time] for node, time in sorted(zip(nodes, times))])\n", + " plt.plot(data[:, 0], data[:, 1], 'o-')\n", + " fig.suptitle(title, fontsize=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Random Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 726650.2719896487\n", + "[*] Running for: 0.38 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 31046.898980759102\n", + "[*] Running for: 0.22 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] [Node] 1000, [Best] 531016891.20882976\n", + "[*] Running for: 1.06 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 121918.36235964627\n", + "[*] Running for: 0.07 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 96.82217370013487\n", + "[*] Running for: 0.02 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 3084.202093710709\n", + "[*] Running for: 0.08 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "\n", + "print(\"Random Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEVCAYAAADwyx6sAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAg20lEQVR4nO3deXxU9b3/8deHsEVQkEUKgQAKRRAXMLLcatVaBWwVrLUFbKutFW+v1K60cm3V2lpr6bWtv3ptcalXBXcuUqHideliFSRKZZWCSEICZV8EAmT5/P44J3QYJmRCJpmZM+/n4zGPyXzPd2a+Zw6858xnzveMuTsiIpL9WqR7ACIikhoKdBGRiFCgi4hEhAJdRCQiFOgiIhGhQBcRiQgFumQUM7vWzNzMrk33WLKVmf3JzBp9PLKZrTOzdSkYkjQTBXqEhcEYe6k2s+3hf/hrzczSPcZsZ2a3x7y+jx6l3/kx/dY14xAlh7RM9wCkWfwovG4F9AOuAM4HioDJ6RpUxFQBnzWzm9x9Z4Ll14d99H9Omoz20HOAu98eXm5x988DFwI1wH+YWd80Dy8qXgDygavjF5jZicCVwB+ae1CSWxToOcjd/wa8BxhwduwyMzvbzH5tZu+G5Zn9ZrbazP4rDCbi+h+qeZvZhWE550Mz221mc81sYKIxmFk/M3vGzHaY2V4ze8PMPnW0cYdje87MNpvZATMrMbP/NrPuCfo+Eo6rr5lNNrMV4bqsM7P/rC03mdlVZvZWOIbNZvYbM8tvwMtZ60WgDPhqgmVfBNoCDxxl3VqY2b+b2SIz2xOOZ5GZfc3MEv4/NbPxZva2mVWEY3/MzHocbZBmNsrM5pnZ1vA1fN/MpplZx+RXVTKVPv5JZdzt6wlKMn8GXiZ40z8b+DYwxsyGu/uHCR7n08BY4I/Ab4FBwKXAOWY2yN231nY0s/7Am0DnsP/fCUpBs8PbRzCzTwPPEbwJPQuUhOP6GjDWzM519w8S3PUXwAUEe8cvAZcDdwKtzWw78LPwef8KXAzcCOSFj9sQ1cDDwK1mVuTuxTHLrgc+IHg96/IYMBFYDzwIOMF2+G/gXOL2/M3sW8A9wE7g0fB6FPAGsCvRE5jZbcDtwHaCTxSbgTOA7wKXmtlId9+d5PpKJnJ3XSJ6IQgFT9D+cYIAOgB0j1vWG8hLcJ/rwsf7flz7tWF7FXBR3LK7wmXfi2t/KWz/Rlz72NoxA9fGtLcHtoVjPi/uPt8P+78U1/5I2L4OKIhp7whsBfYCW4CBMcvaACvC1+WkJF/j28Pn+Wr42lUDv4tZPiJcfgvBDpQD6+IeY0LY/g7QPqa9HVAcLpsY094HOEgQzH1i2lsQvOkdsd0JymxOEPgd69iGv4xrXxc/Vl0y+5L2AejShBv3X+F4e3i5E3gqDIMa4OsNeCwj2PN7Na69NgweT3CfvuGyZ2PaeoZta0n8xvGnBIF+ddg2M0H/lgR7vw4UxrTXBvp1Ce7zcLjsjgTLbguXnZ/k63Io0MPbfwR2A+3C2w8RvNn1OEqg/1/YfkmCx78oXPZqTNstYduPEvQ/meBNxePa/ze8z2l1rMdiYHNcmwI9yy4queSG2+Ju1wbd7+M7mlkr4AZgPEHZpAOHf9dSUMdzFCdoWx9ex9beh4TXr7t7dYL7/IngCJxYQ8PrV+M7u3uVmf2FYK91CFCaxLg2hNdvJ1hWHl73TLAsGQ8Ao4HxZvYM8HlgrrtvMLO6/r8NJXiD/VOCZX8mCOghcf1rlx3G3dea2XqCTwuxRhKU164ys6sSPE9roKuZdXb3bXWMUzKcAj0HuHvtF4DtCP5jPwT81sxK3D0+JJ8iqN2uBZ4H/klQggD4JkFZIpGdCZ63KvzuMS+muUN4vamOx/lngrba+2ys4z617R0TLEtUT65KYlmrOp6rPn8gWLevho/RjqN8GRrqAGx394PxC8LXcCtwUlx/OPprGB/onQn+v8e/ucerLW9JFlKg5xB33wu8bGaXEdRr/8fMBrj7PgAzKyII85eBMe5eG26ER1p8LwXDqA3RbnUs/8hR7pNoGUD3uH5p4+6VZvZ74GaCvfwy6viiN8YuoJOZtXL3w76kDvfquxCUcWL7Q/AaLk/weHW9hi3cvVP9ayHZSoct5iB3X0Kw19gT+FbMon7h9ZzYMA8NIzjOurEWh9fnmlleguUXHOU+RywLA++88OY7jR1citQepdITeLiO0lKsxQT/Fz+eYNnHCT7hxK5b7d/xpSnM7GSgV4LHWQCcaGan1TMWyWIK9Nz1E4JSyndjji9fF15fENvRzE4C7kvFk7p7GcGXgH2Jm6VqZmNJEFIEhxVuByaY2Yi4Zd8MH+tld4+vn6eFu79PUEe/Arg3ibs8HF7fZWbH1TaGf/8svPlQTP8ZBPXwr5tZn5j+LYBpJP5//cvw+oFEx6qbWbsEr61kGZVccpS7l5vZb4FvEJRSpgKLgL8BnzGzN4DXCT7WjwFW8a8vExvrRoLj0H9lZpcA7/KvUxL8Abgsbqx7zOwrwDPAn8MvG0sJjkO/hKBmfEOKxpYS7v5SA/rODN/MPgcsN7PZBHv44wjerJ5y9xkx/deZ2c3AfwGLzewpgpLKKILvEZYQHF8e+xyvhPe5C1htZvMIjg5qT1BvP59ge48+lvWVzKA99Nx2F7APuMnMuoWlgcuB+wkOs7uJYFLLgwRhET8J6Zi4+2qC47OfAz5G8KbSiyDAZtVxn+fDvvPCsXwXGEgwielsd1+birGl0QSCN7ptBG9O/w7sIPgUMzG+s7vfE7Z/QHDo6FeAZcC/hfc7grvfTVDCmUvwWn4TuIrgyKXpwA9StzqSDube6LNsiohIBtAeuohIRCjQRUQiQoEuIhIRCnQRkYhQoIuIRIQCXUQkIhToIiIRoUAXEYkIBbqISEQo0EVEIkKBLiISEQp0EZGISNvpc7t06eJ9+vRJ19OLiGSlt99+e6u7d020LG2B3qdPH4qLE/1+r4iI1MXMSupappKLiEhEKNBFRCJCgS4iEhEKdBGRiFCgi4hERNqOchERyTWzF5czbf4qNuysoEfHfKaMGsC4IQUpe3wFuohIM5i9uJyps5ZSUVkNQPnOCqbOWgqQslBXyUVEpBlMm7/qUJjXqqisZtr8VSl7DgW6iEgz2LCzokHtx0KBLiLSxOYu2Vjnsh4d81P2PKqhi4g0kQNV1dw5dyWPvllCYad8Nu0+wIGqmkPL81vlMWXUgJQ9nwJdRKQJlGzby40z32FZ+W6uP68vU0adyrylG3WUi4hINpm7ZCM3P7eEFi2MB75UxMWDugHB0SypDPB4CnQRkRSJLbGc1asjv5k4hJ4nHtdsz69AFxFJgUQlltYtm/e4EwW6iEgj1VViaW4KdBGRY5TuEku8ej8PmNnDZrbZzJbVsdzM7F4zW2NmS8xsaOqHKSKSWUq27eXK+9/g0TdLuP68vjx9w8i0hjkkt4f+CPAb4NE6lo8B+oeX4cD94bWISCRlSoklXr2B7u5/MbM+R+kyFnjU3R1YYGYdzay7u9c9NUpEJAtlWoklXipq6AXA+pjbZWHbEYFuZpOASQCFhYUpeGoRkeaRCUex1KdZvxR19+nAdICioiJvzucWETlWmVpiiZeKQC8HesXc7hm2iYhktUwvscRLRaDPASab2ZMEX4buUv1cRLJdNpRY4tUb6Gb2BHAB0MXMyoDbgFYA7v5bYB5wKbAG2Ad8uakGKyLSHLKlxBIvmaNcJtSz3IEbUzYiEZE0ybYSSzzNFBURITtLLPEU6CKS87K1xBJPgS4iOSvbSyzxFOgikpOiUGKJp0AXkZwTlRJLPAW6iOSMqJVY4inQRSQnRLHEEk+BLiKRF9USSzwFuohEVtRLLPEU6CISSblQYomnQBeRyMmVEks8BbqIREaulVjiKdBFJBJyscQST4EuIlkvV0ss8RToIpK1cr3EEk+BLiJZSSWWIynQRSTrqMSSmAJdRLKGSixHp0AXkaygEkv9FOgikvFUYkmOAl1EMpZKLA2jQBeRjKQSS8Mp0EUk46jEcmwU6CKSMVRiaRwFuohkBJVYGk+BLiJppxJLaijQRSRtVGJJLQW6iKSFSiypp0AXkWanEkvTSOrt0MxGm9kqM1tjZjcnWF5oZq+Z2WIzW2Jml6Z+qCKS7Q5UVXPr88u4ceY7nHJSe+bedK7CPIXq3UM3szzgPuBioAxYZGZz3H1FTLcfAE+7+/1mNgiYB/RpgvGKSJZSiaXpJVNyGQascfe1AGb2JDAWiA10B04I/+4AbEjlIEUku6nE0jySCfQCYH3M7TJgeFyf24GXzOzrQDvgk4keyMwmAZMACgsLGzpWEckyOoqleaXq884E4BF37wlcCjxmZkc8trtPd/cidy/q2rVrip5aRDJRyba9XHn/Gzz6ZgnXn9eXp28YqTBvYsnsoZcDvWJu9wzbYl0HjAZw9zfNrC3QBdicikGKSHZRiSU9kgn0RUB/M+tLEOTjgYlxfUqBi4BHzGwg0BbYksqBikjmU4klveoNdHevMrPJwHwgD3jY3Zeb2R1AsbvPAb4DPGBm3yL4gvRad/emHLiIZBYdxZJ+SU0scvd5BIcixrbdGvP3CuBjqR2aiGQLlVgyg2aKisgxU4klsyjQReSYqMSSeRToItJgKrFkJgW6iCRNJZbMpkAXkaSoxJL5FOgiUi+VWLKDAl1E6qQSS3ZRoItIQiqxZB8FuogcQSWW7KRAF5FDVGLJbgp0EQFUYokCBbqIqMQSEQp0kRymEku0KNBFcpRKLNGjQBfJQSqxRJMCXSSHqMQSbQp0kRyhEkv0KdBFcoBKLLlBgS4SYSqx5BYFukhEqcSSexToIhGkEktuUqCLRIhKLLlNgS4SESqxiAJdJAJUYhFQoItkNZVYJJYCXSRLqcQi8RToIllIJRZJRIEukkVUYpGjUaCLZAmVWKQ+Sf1rMLPRZrbKzNaY2c119Pmcma0ws+VmNjO1wxTJbXOXbOTT977O+u0VPPClIm751CCFuRyh3j10M8sD7gMuBsqARWY2x91XxPTpD0wFPubuO8zspKYasEguUYlFGiKZksswYI27rwUwsyeBscCKmD7XA/e5+w4Ad9+c6oGK5BqVWKShkgn0AmB9zO0yYHhcn48CmNnfgDzgdnd/Mf6BzGwSMAmgsLDwWMYrkhN0FIsci1R9KdoS6A9cAPQE/mJmp7v7zthO7j4dmA5QVFTkKXpukchQiUUaI5lALwd6xdzuGbbFKgMWunsl8IGZ/YMg4BelZJQiOUAlFmmsZAJ9EdDfzPoSBPl4YGJcn9nABOD3ZtaFoASzNoXjFIk0lVgkFeoNdHevMrPJwHyC+vjD7r7czO4Ait19TrjsEjNbAVQDU9x9W1MOXCQKVGKRVDL39JSyi4qKvLi4OC3PLZIJVGKRY2Fmb7t7UaJlmikqkgYqsUhTUKCLNCOVWKQpKdBFmolKLNLUFOgizUAlFmkOCnSRJqQSizQnBbpIE1GJRZqbAl2kCajEIumgQBdJIZVYJJ0U6CIpohKLpJsCXSQFVGKRTKBAF2kElVgkkyjQRY6RSiySaRToIsdAJRbJRAp0kQZQiUUymQJdJEkqsUimU6CLJEElFskGCnSRo1CJRbKJAl2kDiqxSLZRoIskoBKLZCMFukgMlVgkmynQRUIqsUi2U6CLoBKLRIMCXXKaSiwSJQp0yVkqsUjUKNAlJ6nEIlGkQJecohKLRJkCXXKGSiwSdQp0yQkqsUguUKBLpKnEIrkkqc+bZjbazFaZ2Rozu/ko/a40MzezotQNUeTYlGzby5X3v8Gjb5Zw/Xl9efqGkQpzibR699DNLA+4D7gYKAMWmdkcd18R1+944BvAwqYYqEhDqMQiuSiZPfRhwBp3X+vuB4EngbEJ+v0YuBvYn8LxiTTIgapqbn1+GTfOfIdTTmrP3JvOVZhLzkgm0AuA9TG3y8K2Q8xsKNDL3ece7YHMbJKZFZtZ8ZYtWxo8WJGjUYlFcl2jvxQ1sxbAPcC19fV19+nAdICioiJv7HNLbpu9uJxp81exYWcFHY9rxb4DVbRt3VIlFslZyQR6OdAr5nbPsK3W8cBg4E9mBvARYI6ZXe7uxakaqEis2YvLmTprKRWV1QDs2FeJGXz/on4Kc8lZyZRcFgH9zayvmbUGxgNzahe6+y537+Lufdy9D7AAUJhLk5o2f9WhMK/lDg+9vi49AxLJAPUGurtXAZOB+cBK4Gl3X25md5jZ5U09QJF4W/ccoHxnRcJlG+poF8kFSdXQ3X0eMC+u7dY6+l7Q+GGJHKmmxnliUSk/f3FVnX16dMxvxhGJZBbNFJWssKx8F7fMXsa763cy8uTOXDCgC796ec1hZZf8VnlMGTUgjaMUSS8FumS03fsrueelf/Dom+vo1K4Nv/r8WYw9qwdmRrcT8g8d5dKjYz5TRg1g3JCC+h9UJKIU6JKR3J05727gxy+sZNveA3xxRG++c8kAOuS3OtRn3JACBbhIDAW6ZJw1m/dw6/PLeOP9bZzRswO/v/YcTu/ZId3DEsl4CnTJGBUHq/nNa6uZ/pe1tG2Vx4/HDWbisELyWli6hyaSFRTokhFeWbmJ2+Ysp2xHBZ8ZUsDUSwfS9fg26R6WSFZRoEtale+s4EdzlvPSik30O6k9T04awYiTO6d7WCJZSYEuaXGwqoaHXv+Ae19ZDcD3R5/Kdef21U/CiTSCAl2a3YK12/jh7GWs3ryHiwd147bLBumsiCIpoECXZrN1zwF+Om8ls94pp+eJ+Tz4pSI+qRNpiaSMAl2aXHWNM/OtUqa9+B4VldXceOEpTL6wP/mt89I9NJFIUaBLk1patosfzF7Ku2W7+LdTOnPH2MH0O6l9uoclEkkKdGkSuyoqueelVTy2oIRO7drw6/FncfmZwZR9EWkaCnRJKXfn+b9v4CdzV7J97wG+NLIP377ko5zQtlX9dxaRRlGgS8qs2fwhP5y9nDfXbuNMTdkXaXYKdGm0ioPV/L9XV/PAX9eS3yqPn4wbzARN2Rdpdgp0aZSXVwRT9st3VnDl0J5MvfRUurTXlH2RdFCgyzEp27GP2+es4OWVm+h/UnuemjSC4ZqyL5JWCnRpkINVNTz4+lrufWU1hnHzmGDKfqs8TdkXSTcFuiTtzfe38cPnl7Fm8x5GndaNWy87jQL9hqdIxlCgS722fBhM2f/fxcGU/YeuKeKigZqyL5JpFOhSp+oaZ+bCEn4+fxX7K6uZfGE/brywn6bsi2QoBboktKRsJz+YvYwlZbv4WL9gyv4pXTVlXySTKdDlMLsqKvnF/FU8vrCELu3bcO+EIVx2RndN2RfJAgp0AYIp+7P/Xs6dc1eyfe9BrtGUfZGso0DPQbMXlzNt/io27KygR8d8vjiikNdWbWHhB9s5s1dHHvnyMAYXaMq+SLZRoOeY2YvLmTprKRWV1UDwm54/e3EV+a1a8NMrTmf8Ob1ooSn7IllJgZ5jps1fdSjMY3U4rjUThxemYUQikiqa3pdDyndWUL6zIuGyTbv2N/NoRCTVktpDN7PRwK+BPOBBd/9Z3PJvA18FqoAtwFfcvSTFY5VjUF3j/GX1FmYsKOHV9zbX2a+HZnyKZL16A93M8oD7gIuBMmCRmc1x9xUx3RYDRe6+z8y+Bvwc+HxTDFiSs3XPAZ4uXs/MhaWU7aigS/vWfO2CU+jcrjXT5v/jsLJLfqs8powakMbRikgqJLOHPgxY4+5rAczsSWAscCjQ3f21mP4LgC+kcpCSHHdn4QfbmbGwlBeXbaSy2hl5cmduHnMqlwz6CK1bBhW2Tu3aHHaUy5RRAxg3pCDNoxeRxkom0AuA9TG3y4DhR+l/HfDHRAvMbBIwCaCwUF/ApcquikpmvVPGjIWlrNm8hxPatuSLI/owcXhhwh9kHjekQAEuEkEpPcrFzL4AFAHnJ1ru7tOB6QBFRUWeyufORUvKdvL4ghLmvLuB/ZU1nNmrIz//7BlcdkYPnW9FJAclE+jlQK+Y2z3DtsOY2SeBW4Dz3f1AaoYn8fYdrOIP727g8QWlLC3fRX6rPMadVcDVw3vr9ztFclwygb4I6G9mfQmCfDwwMbaDmQ0BfgeMdve6D6WQY7Z604fMWFjKc++U8eH+Kj7arT0/uvw0rhhaoOn5IgIkEejuXmVmk4H5BIctPuzuy83sDqDY3ecA04D2wDPhSZxK3f3yJhx3TjhQVc385Zt4fEEJb32wndZ5LRhz+ke4enhvzulzok6YJSKHSaqG7u7zgHlxbbfG/P3JFI8rp63fvo+Zb5Xy9KL1bNt7kMJOx3HzmFO56uyedNYPMItIHTT1P0NU1zivvreZGQtL+PM/tmDARQO78YURvTmvXxedX0VE6qVAT7PNu/fz1KL1PPFWKRt27eek49vw9U/0Z8KwXnTvoNmbIpI8BXoauDtvvL+NGQtLeGn5JqpqnPP6d+HWywZx0cButMrTKXZEpOEU6M1o576DPPt2GTMXlrJ26146HteKr5zblwnDCunbpV26hyciWU6B3sTcncXrgwlALyzZyMGqGs7ufSK/vKgfYwZ3p20rTQASkdRQoDeRPQeqeP7v5Ty+oJSVG3fTrnUenyvqydXDezOw+wnpHp6IRJACPcVWbtzNjIUlzF68gT0HqhjY/QTuvGIwY88qoH0bvdwi0nSUMCmwv7KaPy7byOMLSnm7ZAetW7bg02d05+rhvRla2FETgESkWSjQG2Hd1r3MfKuUZ4rXs2NfJX27tOMHnxrIlUN7cmK71ukenojkGAV6A1VV1/Dyyk3MWFjKX1dvJa+FccmgYALQyJM7awKQiKSNAj1JG3dV8MRb63lqUSmbdh+ge4e2fPvij/L5c3rR7YS26R6eiIgC/Whqapy/rtnK4wtKeGXlJhw4/6Nd+cm43lw4oCstNQFIRDKIAj2BbXsO8Ew4Aah0+z46t2vNDeefwoRzCinsfFy6hycikpACPeTuFJfs4PEFJfxx6T85WF3DsL6d+O6oAYw6rRttWmoCkIhktpwL9NmLyw/7geTJnziFympnxoJSVm36kOPbtGTi8EKuHl5I/27Hp3u4IiJJy6lAn724nKmzllJRWQ1A+c4Kps5aBsDpBR24+8rTuezMHhzXOqdeFhGJiEgmV/xe+JRRAxg3pIC7X3zvUJjH6np8G/7w9XPTMFIRkdSJXKAn2gv/3nNLmLGghI279ie8z9YP9ZvWIpL9Infc3bT5q47YCz9YVUNxyQ6Oa534i80eHfVDEiKS/SIX6Bt2VtS57KdXnE5+3Olq81vlMWXUgKYelohIk4tcyaVz+9Zs3XPwiPYeHfMZN6QAIGF9XUQk20Uq0J8pXs/2vQcxwGPaY/fCxw0pUICLSCRFouRSU+NMm/8eU55dwshTOnPnZwZT0DEfAwo65nPXZ05XiItI5GX9Hvr+ymq+88y7zF2ykfHn9OLH4wbTKq8FE4f1TvfQRESaVVYH+pYPD3D9o8W8W7aTqWNOZdLHT9aPSYhIzsqqQI+dMNT1+DZUVtdQUVnN/VcPZfTg7ukenohIWmVNoMdPGNocTgb69sX9FeYiImTRl6KJJgwBPLWoLA2jERHJPFkT6HVNGDraRCIRkVySVKCb2WgzW2Vma8zs5gTL25jZU+HyhWbWJ9UDrWt6vqbti4gE6g10M8sD7gPGAIOACWY2KK7bdcAOd+8H/BK4O9UDnTJqgKbti4gcRTJ76MOANe6+1t0PAk8CY+P6jAX+J/z7WeAiS/Hxg+OGFHDXZ07XhCERkTokc5RLAbA+5nYZMLyuPu5eZWa7gM7A1thOZjYJmARQWFjY4MFq2r6ISN2a9UtRd5/u7kXuXtS1a9fmfGoRkchLJtDLgV4xt3uGbQn7mFlLoAOwLRUDFBGR5CQT6IuA/mbW18xaA+OBOXF95gDXhH9/FnjV3R0REWk29dbQw5r4ZGA+kAc87O7LzewOoNjd5wAPAY+Z2RpgO0Hoi4hIM0pq6r+7zwPmxbXdGvP3fuCq1A5NREQawtJVGTGzLUBJEl27EHe0TI7QeucWrXduacx693b3hEeVpC3Qk2Vmxe5elO5xNDetd27ReueWplrvrDmXi4iIHJ0CXUQkIrIh0KenewBpovXOLVrv3NIk653xNXQREUlONuyhi4hIEjI60Os7D3s2M7NeZvaama0ws+Vm9o2wvZOZ/Z+ZrQ6vTwzbzczuDV+LJWY2NL1rcOzMLM/MFpvZC+HtvuF59NeE59VvHbY3+Xn2m4uZdTSzZ83sPTNbaWYjc2Rbfyv8973MzJ4ws7ZR3N5m9rCZbTazZTFtDd6+ZnZN2H+1mV2T6LmOJmMDPcnzsGezKuA77j4IGAHcGK7fzcAr7t4feCW8DcHr0D+8TALub/4hp8w3gJUxt+8GfhmeT38Hwfn1oRnOs9+Mfg286O6nAmcSrH+kt7WZFQA3AUXuPphgpvl4orm9HwFGx7U1aPuaWSfgNoKz2Q4Dbqt9E0iau2fkBRgJzI+5PRWYmu5xNeH6Pg9cDKwCuodt3YFV4d+/AybE9D/UL5suBCd3ewX4BPACYAQTLFrGb3eC002MDP9uGfazdK/DMaxzB+CD+LHnwLauPa12p3D7vQCMiur2BvoAy451+wITgN/FtB/WL5lLxu6hk/g87JE8GXr40XIIsBDo5u4bw0X/BLqFf0fl9fgV8D2gJrzdGdjp7lXh7dj1Ouw8+0DtefazTV9gC/D7sNT0oJm1I+Lb2t3LgV8ApcBGgu33NtHf3rUaun0bvd0zOdBzgpm1B54Dvunuu2OXefA2HZnDkMzs08Bmd3873WNpZi2BocD97j4E2Mu/Pn4D0dvWAGG5YCzBG1oPoB1HliVyQnNt30wO9GTOw57VzKwVQZjPcPdZYfMmM+seLu8ObA7bo/B6fAy43MzWEfyU4ScIassdw/Pow+HrFZXz7JcBZe6+MLz9LEHAR3lbA3wS+MDdt7h7JTCL4N9A1Ld3rYZu30Zv90wO9GTOw561zMwITju80t3viVkUe275awhq67XtXwq/IR8B7Ir5OJcV3H2qu/d09z4E2/NVd78aeI3gPPpw5Dpn/Xn23f2fwHozq/1F84uAFUR4W4dKgRFmdlz47712vSO9vWM0dPvOBy4xsxPDTzeXhG3JS/cXCfV8yXAp8A/gfeCWdI8nxet2LsFHsCXA38PLpQQ1w1eA1cDLQKewvxEc9fM+sJTgyIG0r0cj1v8C4IXw75OBt4A1wDNAm7C9bXh7Tbj85HSPuxHrexZQHG7v2cCJubCtgR8B7wHLgMeANlHc3sATBN8TVBJ8IrvuWLYv8JVw/dcAX27oODRTVEQkIjK55CIiIg2gQBcRiQgFuohIRCjQRUQiQoEuIhIRCnQRkYhQoIuIRIQCXUQkIv4/Acszqig8bpgAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Random Model\")" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Uniform Cost Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 58952.967129705365\n", + "[*] Running for: 47.11 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 3088.6042241002488\n", + "[*] Running for: 9.48 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.04 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 39236.884898455035\n", + "[*] Running for: 0.08 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 77.12688501241215\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 761.6890898866324\n", + "[*] Running for: 0.17 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyUCSModel()\n", + "\n", + "print(\"Uniform Cost Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Uniform Cost Search\")" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A Star Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.01 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.01 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.02 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.00 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 77.02641196679659\n", + "[*] Running for: 0.27 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 60.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyASModel()\n", + "\n", + "print(\"A Star Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"A Star Search\")" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hill-Climbing Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 534598.7236016603\n", + "[*] Running for: 0.54 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "Max iteration reached: 1000\n", + "[*] [Node] 280, [Best] 20166.72717957085\n", + "[*] Running for: 0.27 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "Max iteration reached: 1000\n", + "[*] [Node] 1000, [Best] 447129851.29925376\n", + "[*] Running for: 1.22 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "Max iteration reached: 1000\n", + "[*] [Node] 48, [Best] 48649.76285824257\n", + "[*] Running for: 0.04 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 73.99982631274877\n", + "[*] Running for: 0.01 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "Max iteration reached: 1000\n", + "[*] [Node] 70, [Best] 1628.8466328473826\n", + "[*] Running for: 0.06 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyHillClimbModel()\n", + "\n", + "print(\"Hill-Climbing Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Hill-Climbing Search\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conclusions" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "# Simple\n", + "# ulysses16: 77.12 (UCS-BFS), 77.02 (A-Star)\n", + "# att48: 39236 (UCS-BFS), 47853 (A-Star)\n", + "# st70: 761 (UCS-BFS), time-out (A-Star)\n", + "\n", + "# Medium\n", + "# a280: 3088 (UCS-BFS), time-out (A-Star)\n", + "# pcb442: 58952 (UCS-BFS), time-out (A-Star)\n", + "\n", + "# Hard\n", + "# dsj1000: time-out (UCS-BFS), 542,620,572 (Hill-Climbing)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

1. UCS is the slowest one, and gets the same result as BFS, DFS, DP

\n", + "

1. A-Star can only solve problems with number of cities < 50.

\n", + "

2. Hill-Climbing gets different results every time (Heuristic).

\n", + "

3. Hill-Climbing is the fastest one till now. (faster than Dynamic Programming, but worse results).

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 3 (Game).ipynb b/Workshop - 3 (Game).ipynb new file mode 100644 index 0000000..e855941 --- /dev/null +++ b/Workshop - 3 (Game).ipynb @@ -0,0 +1,122 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a terminal here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Change working directory" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```bash\n", + "$ cd Workshop\\ -\\ 3\\ \\(Game\\)/\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run the game" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```bash\n", + "$ python3 minimax.py\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```bash\n", + "$ python3 ab-pruning.py\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reading Materials" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "https://stackabuse.com/minimax-and-alpha-beta-pruning-in-python/" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 3 (Game)/ab-pruning.py b/Workshop - 3 (Game)/ab-pruning.py new file mode 100644 index 0000000..348101a --- /dev/null +++ b/Workshop - 3 (Game)/ab-pruning.py @@ -0,0 +1,191 @@ +# We'll use the time module to measure the time of evaluating +# game tree in every move. It's a nice way to show the +# distinction between the basic Minimax and Minimax with +# alpha-beta pruning :) +import time + +class Game: + def __init__(self): + self.initialize_game() + + def initialize_game(self): + self.current_state = [['.','.','.'], + ['.','.','.'], + ['.','.','.']] + + # Player X always plays first + self.player_turn = 'X' + + def draw_board(self): + for i in range(0, 3): + for j in range(0, 3): + print('{}|'.format(self.current_state[i][j]), end=" ") + print() + print() + + # Determines if the made move is a legal move + def is_valid(self, px, py): + if px < 0 or px > 2 or py < 0 or py > 2: + return False + elif self.current_state[px][py] != '.': + return False + else: + return True + + # Checks if the game has ended and returns the winner in each case + def is_end(self): + # Vertical win + for i in range(0, 3): + if (self.current_state[0][i] != '.' and + self.current_state[0][i] == self.current_state[1][i] and + self.current_state[1][i] == self.current_state[2][i]): + return self.current_state[0][i] + + # Horizontal win + for i in range(0, 3): + if (self.current_state[i] == ['X', 'X', 'X']): + return 'X' + elif (self.current_state[i] == ['O', 'O', 'O']): + return 'O' + + # Main diagonal win + if (self.current_state[0][0] != '.' and + self.current_state[0][0] == self.current_state[1][1] and + self.current_state[0][0] == self.current_state[2][2]): + return self.current_state[0][0] + + # Second diagonal win + if (self.current_state[0][2] != '.' and + self.current_state[0][2] == self.current_state[1][1] and + self.current_state[0][2] == self.current_state[2][0]): + return self.current_state[0][2] + + # Is whole board full? + for i in range(0, 3): + for j in range(0, 3): + # There's an empty field, we continue the game + if (self.current_state[i][j] == '.'): + return None + + # It's a tie! + return '.' + + def max_alpha_beta(self, alpha, beta): + maxv = -2 + px = None + py = None + + result = self.is_end() + + if result == 'X': + return (-1, 0, 0) + elif result == 'O': + return (1, 0, 0) + elif result == '.': + return (0, 0, 0) + + for i in range(0, 3): + for j in range(0, 3): + if self.current_state[i][j] == '.': + self.current_state[i][j] = 'O' + (m, min_i, in_j) = self.min_alpha_beta(alpha, beta) + if m > maxv: + maxv = m + px = i + py = j + self.current_state[i][j] = '.' + + # Next two ifs in Max and Min are the only difference between regular algorithm and minimax + if maxv >= beta: + return (maxv, px, py) + + if maxv > alpha: + alpha = maxv + + return (maxv, px, py) + + def min_alpha_beta(self, alpha, beta): + + minv = 2 + + qx = None + qy = None + + result = self.is_end() + + if result == 'X': + return (-1, 0, 0) + elif result == 'O': + return (1, 0, 0) + elif result == '.': + return (0, 0, 0) + + for i in range(0, 3): + for j in range(0, 3): + if self.current_state[i][j] == '.': + self.current_state[i][j] = 'X' + (m, max_i, max_j) = self.max_alpha_beta(alpha, beta) + if m < minv: + minv = m + qx = i + qy = j + self.current_state[i][j] = '.' + + if minv <= alpha: + return (minv, qx, qy) + + if minv < beta: + beta = minv + + return (minv, qx, qy) + + def play_alpha_beta(self): + while True: + self.draw_board() + self.result = self.is_end() + + if self.result != None: + if self.result == 'X': + print('The winner is X!') + elif self.result == 'O': + print('The winner is O!') + elif self.result == '.': + print("It's a tie!") + + + self.initialize_game() + return + + if self.player_turn == 'X': + + while True: + start = time.time() + (m, qx, qy) = self.min_alpha_beta(-2, 2) + end = time.time() + print('Evaluation time: {}s'.format(round(end - start, 7))) + print('Recommended move: X = {}, Y = {}'.format(qx, qy)) + + px = int(input('Insert the X coordinate: ')) + py = int(input('Insert the Y coordinate: ')) + + qx = px + qy = py + + if self.is_valid(px, py): + self.current_state[px][py] = 'X' + self.player_turn = 'O' + break + else: + print('The move is not valid! Try again.') + + else: + (m, px, py) = self.max_alpha_beta(-2, 2) + self.current_state[px][py] = 'O' + self.player_turn = 'X' + +def main(): + g = Game() + g.play_alpha_beta() + +if __name__ == "__main__": + main() diff --git a/Workshop - 3 (Game)/minimax.py b/Workshop - 3 (Game)/minimax.py new file mode 100644 index 0000000..9d59560 --- /dev/null +++ b/Workshop - 3 (Game)/minimax.py @@ -0,0 +1,204 @@ +# We'll use the time module to measure the time of evaluating +# game tree in every move. It's a nice way to show the +# distinction between the basic Minimax and Minimax with +# alpha-beta pruning :) +import time + +class Game: + def __init__(self): + self.initialize_game() + + def initialize_game(self): + self.current_state = [['.','.','.'], + ['.','.','.'], + ['.','.','.']] + + # Player X always plays first + self.player_turn = 'X' + + def draw_board(self): + for i in range(0, 3): + for j in range(0, 3): + print('{}|'.format(self.current_state[i][j]), end=" ") + print() + print() + + # Determines if the made move is a legal move + def is_valid(self, px, py): + if px < 0 or px > 2 or py < 0 or py > 2: + return False + elif self.current_state[px][py] != '.': + return False + else: + return True + + # Checks if the game has ended and returns the winner in each case + def is_end(self): + # Vertical win + for i in range(0, 3): + if (self.current_state[0][i] != '.' and + self.current_state[0][i] == self.current_state[1][i] and + self.current_state[1][i] == self.current_state[2][i]): + return self.current_state[0][i] + + # Horizontal win + for i in range(0, 3): + if (self.current_state[i] == ['X', 'X', 'X']): + return 'X' + elif (self.current_state[i] == ['O', 'O', 'O']): + return 'O' + + # Main diagonal win + if (self.current_state[0][0] != '.' and + self.current_state[0][0] == self.current_state[1][1] and + self.current_state[0][0] == self.current_state[2][2]): + return self.current_state[0][0] + + # Second diagonal win + if (self.current_state[0][2] != '.' and + self.current_state[0][2] == self.current_state[1][1] and + self.current_state[0][2] == self.current_state[2][0]): + return self.current_state[0][2] + + # Is whole board full? + for i in range(0, 3): + for j in range(0, 3): + # There's an empty field, we continue the game + if (self.current_state[i][j] == '.'): + return None + + # It's a tie! + return '.' + + # Player 'O' is max, in this case AI + def max(self): + + # Possible values for maxv are: + # -1 - loss + # 0 - a tie + # 1 - win + + # We're initially setting it to -2 as worse than the worst case: + maxv = -2 + + px = None + py = None + + result = self.is_end() + + # If the game came to an end, the function needs to return + # the evaluation function of the end. That can be: + # -1 - loss + # 0 - a tie + # 1 - win + if result == 'X': + return (-1, 0, 0) + elif result == 'O': + return (1, 0, 0) + elif result == '.': + return (0, 0, 0) + + for i in range(0, 3): + for j in range(0, 3): + if self.current_state[i][j] == '.': + # On the empty field player 'O' makes a move and calls Min + # That's one branch of the game tree. + self.current_state[i][j] = 'O' + (m, min_i, min_j) = self.min() + # Fixing the maxv value if needed + if m > maxv: + maxv = m + px = i + py = j + # Setting back the field to empty + self.current_state[i][j] = '.' + return (maxv, px, py) + + # Player 'X' is min, in this case human + def min(self): + + # Possible values for minv are: + # -1 - win + # 0 - a tie + # 1 - loss + + # We're initially setting it to 2 as worse than the worst case: + minv = 2 + + qx = None + qy = None + + result = self.is_end() + + if result == 'X': + return (-1, 0, 0) + elif result == 'O': + return (1, 0, 0) + elif result == '.': + return (0, 0, 0) + + for i in range(0, 3): + for j in range(0, 3): + if self.current_state[i][j] == '.': + self.current_state[i][j] = 'X' + (m, max_i, max_j) = self.max() + if m < minv: + minv = m + qx = i + qy = j + self.current_state[i][j] = '.' + + return (minv, qx, qy) + + def play(self): + while True: + self.draw_board() + self.result = self.is_end() + + # Printing the appropriate message if the game has ended + if self.result != None: + if self.result == 'X': + print('The winner is X!') + elif self.result == 'O': + print('The winner is O!') + elif self.result == '.': + print("It's a tie!") + + self.initialize_game() + return + + # If it's player's turn + if self.player_turn == 'X': + + while True: + + start = time.time() + (m, qx, qy) = self.min() + end = time.time() + print('Evaluation time: {}s'.format(round(end - start, 7))) + print('Recommended move: X = {}, Y = {}'.format(qx, qy)) + + px = int(input('Insert the X coordinate: ')) + py = int(input('Insert the Y coordinate: ')) + + (qx, qy) = (px, py) + + if self.is_valid(px, py): + self.current_state[px][py] = 'X' + self.player_turn = 'O' + break + else: + print('The move is not valid! Try again.') + + # If it's AI's turn + else: + (m, px, py) = self.max() + self.current_state[px][py] = 'O' + self.player_turn = 'X' + +def main(): + g = Game() + g.play() + +if __name__ == "__main__": + main() diff --git a/Workshop - 3 (LP).ipynb b/Workshop - 3 (LP).ipynb new file mode 100644 index 0000000..213dabf --- /dev/null +++ b/Workshop - 3 (LP).ipynb @@ -0,0 +1,252 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "np.set_printoptions(suppress=True)\n", + "from scipy.optimize import linprog" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Feasible Example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{align}\n", + "\\max f=4x_1+x_2 \\\\\n", + "\\text{s.t.} -x_1 + 2x_2 &\\leq 4 \\\\\n", + "2x_1 + 3x_2 &\\leq 12 \\\\\n", + "x_1 - x_2 &\\leq 3 \\\\\n", + "\\text{and } x_1, x_2 \\geq 0\n", + "\\end{align}" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "c = [-4, -1, 0, 0, 0]\n", + "A = [[-1, 2, 0, 0, 0], [2, 3, 0, 0, 0], [1, -1, 0, 0, 0]]\n", + "b = [4, 12, 3]\n", + "\n", + "x0_bounds = (0, None)\n", + "x1_bounds = (0, None)\n", + "x2_bounds = (None, None)\n", + "x3_bounds = (None, None)\n", + "x4_bounds = (None, None)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " con: array([], dtype=float64)\n", + " fun: -17.999999976555795\n", + " message: 'Optimization terminated successfully.'\n", + " nit: 4\n", + " slack: array([5.8 , 0.00000002, 0. ])\n", + " status: 0\n", + " success: True\n", + " x: array([4.19999999, 1.2 , 0. , 0. , 0. ])\n" + ] + } + ], + "source": [ + "res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds, x2_bounds, x3_bounds, x4_bounds])\n", + "\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Infeasible Example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{align}\n", + "\\min f = x_1 - 2x_2 + 3x_3 \\\\\n", + "s.t. -2x_1 + x_2 + 3x_3 & = 2 \\\\\n", + "3x_1 + 3x_2 + 4x_3 & = 1 \\\\\n", + "\\end{align}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "c = [-1, 2, -3]\n", + "A = [[-2, 1, 3], [3, 3, 4]]\n", + "b = [2, 1]\n", + "\n", + "x0_bounds = (0, None)\n", + "x1_bounds = (0, None)\n", + "x2_bounds = (0, None)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " con: array([ 0. , -4.56053464])\n", + " fun: -0.6099904044751114\n", + " message: 'The algorithm terminated successfully and determined that the problem is infeasible.'\n", + " nit: 4\n", + " slack: array([], dtype=float64)\n", + " status: 2\n", + " success: False\n", + " x: array([0.2893146 , 0.75265113, 0.60865936])\n" + ] + } + ], + "source": [ + "res = linprog(c, A_eq=A, b_eq=b, bounds=[x0_bounds, x1_bounds, x2_bounds,])\n", + "\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

Assignment

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\\begin{align}\n", + "\\min f = 3x_1 - x_2 \\\\\n", + "s.t. 2x_1 + x_2 & \\geq 2 \\\\\n", + "x_1 + 3x_2 & \\leq 3 \\\\\n", + "x_2 & \\leq 4 \\\\\n", + "\\text{and } x_1, x_2 \\geq 0\n", + "\\end{align}" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "c = [-3, 1]\n", + "A = [[-2, -1], [1, 3], [0, 1]]\n", + "b = [-2, 3, 4]\n", + "\n", + "x0_bounds = (0, None)\n", + "x1_bounds = (0, None)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " con: array([], dtype=float64)\n", + " fun: -8.999999998556428\n", + " message: 'Optimization terminated successfully.'\n", + " nit: 4\n", + " slack: array([4., 0., 4.])\n", + " status: 0\n", + " success: True\n", + " x: array([3., 0.])\n" + ] + } + ], + "source": [ + "res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds])\n", + "\n", + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 4 (TSP SA).ipynb b/Workshop - 4 (TSP SA).ipynb new file mode 100644 index 0000000..a34f740 --- /dev/null +++ b/Workshop - 4 (TSP SA).ipynb @@ -0,0 +1,1026 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Append template path to sys path\n", + "sys.path.append(os.getcwd() + \"/template\") " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.load_data import load_data\n", + "from utils.load_data import log\n", + "from utils.visualize_tsp import plotTSP\n", + "from utils.tsp import TSP\n", + "from utils.tsp import TSP_Bench\n", + "from utils.tsp import TSP_Bench_ALL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workshop Starts Here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"TSP\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"solutions\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get familiar with your dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are problems at different levels. **3 simple, 2 medium, 1 hard**." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16 = np.array(load_data(\"./template/data/simple/ulysses16.tsp\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[38.24, 20.42],\n", + " [39.57, 26.15],\n", + " [40.56, 25.32],\n", + " [36.26, 23.12],\n", + " [33.48, 10.54],\n", + " [37.56, 12.19],\n", + " [38.42, 13.11],\n", + " [37.52, 20.44],\n", + " [41.23, 9.1 ],\n", + " [41.17, 13.05],\n", + " [36.08, -5.21],\n", + " [38.47, 15.13],\n", + " [38.15, 15.35],\n", + " [37.51, 15.17],\n", + " [35.49, 14.32],\n", + " [39.36, 19.56]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ulysses16[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(ulysses16[:, 0], ulysses16[:, 1])\n", + "for i in range(0, 16):\n", + " plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: In Order" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]\n" + ] + } + ], + "source": [ + "simple_sequence = list(range(0, 16))\n", + "print(simple_sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXIAAAD4CAYAAADxeG0DAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAA6j0lEQVR4nO3deVhUZf/H8fcNIgguqCDuIJrmmua+t7j0lKWVltuTWmn5qFlZmVrxU9PMNjRNM0uzXLK0NLVyX0MUNfcdxB1RUZRNYO7fHwOEsijMcmbg+7ourpgzM+d8TPzO4V6V1hohhBDOy8XoAEIIISwjhVwIIZycFHIhhHByUsiFEMLJSSEXQggnV8SIi/r4+OiAgAAjLi2EEE5r165dl7XWvnceN6SQBwQEEBYWZsSlhRDCaSmlIrM7Lk0rQgjh5KSQCyGEk5NCLoQQTk4KuRBCODkp5EII4eSkkAshbGp+VBQBISG4bNxIQEgI86OijI5U4Bgy/FAIUTjMj4pi0NGjxJtMAEQmJTHo6FEA+vj5GRmtQJE7ciGEzYwJD88o4uniTSbGhIcblKhgkjtyIYTNnE5KyvZ4ZGICaqwCoHrp6nQM7EjH6h15OOBhShcrbc+IBYIUciGETZi0iSLJV0l2K5PlOR9XE082HMCa8DWcjDnJyV0nmblrZpbXubm40bF6R3OhD+xIHd86KKXsEd+pKCN2CGrSpImWKfpCFFy7zu+iyTdNwPdR3OuMIYl/i6+niwuzatXKto38VuotdpzbwZqTa1gTvoaQsyG5Xqd+ufp0COxAx8COtPNvh1dRrzzlnB8VxZjwcE4nJVHV3Z0JgYEO3XavlNqltW6S5bgUciGENXVf3J0lh5cAED86nqVXY61WLCOvRbI2fC1rws2F/mrC1RxfW8q9VMbdfIfADlTzrnbb3fydHbGQ+4eMI7C4kCulqgDzAD9AA7O01lOUUv8HDASi0146Wmu9KrdzSSEXouCJiIkgcGogANP+M40hzYbY9frxyfFsPb01425+b9TeXF9ftNVSbrllbY/3d3fnVMuWtoppkZwKeV7ayFOAEVrr3UqpEsAupdSatOe+0Fp/ao2gQgjn8+7ad/l428cARL8djY+nj90zeLp50ql6JzoEdmDwtcEcij5029eBSwdISEnIeP2tIqWyPU9OHbSO7J4Ludb6AnAh7fsbSqnDQCVbBRNCOL6rCVcpO7ksACNajuDTTta/n0tOTebE1RP/FuXL/xbnFFNKns5VsURF6vrWpY5vHX5wSeWqzjoCu6q7u7Wi202+Rq0opQKARkAo0BoYqpR6AQjDfNcek817BgGDAKpWrZrfvEIIBzEzbCaDVw4G4MSwE1QvU/2e3peQnMDRK0dvu1s+GH2QY1eO5TlDYOlA6vjWoY5PHfN/fetwv8/9lHAvcdf3Ns2hjXxCYGCecxgtz52dSqniwCZggtZ6qVLKD7iMud18PFBBa/1ibueQNnIhnFdiSiJeE70waRPdanVjTtc5HLlyJEtTRuT1bPdAyFV6Mc5cmO8rex8eRTxs8CcppKNWlFJuwArgL63159k8HwCs0FrXy+08UsiFcExaay7HX769KF8+xMFLB4mKy9saKUVdi1LHt05GU0b6V2DpQIq4yBSW/LC4s1OZx+18CxzOXMSVUhXS2s8BngYOWBpWCGEdWmvO3TiXpRnjUPQhriVey9O5XJQLJm3C28ObMW3HZBToKqWq4KJktQ8j5eVjsTXwX2C/UuqftGOjgV5KqYaYm1ZOAa9YMZ8QIpNUUyoR1yKyNGMcij5024iMe1HOq1yWZow6vnUo51XutvHWO87toPns5pi0id97/U6Xml2s/ccSFsrLqJWtQHZzY3MdMy6EyNmt1Fscv3L8tjvl9C9N3vqvqpaqmm3HX37XLtFa8/RPT7Ps6DLcXNyIHRVrs7ZqYRlpqBLCiuKT4zly2dzxd/DSwYyhcieunsjzuWqUqZFtYc7rNPT8OHn1JDW+rAHAjCdm8GqTV21+TZF/UsiFyMW1xGvZNmOciT2Tp/O4KJccR2QUdS1qo/T5M+KvEXy+3dwNduWdK5QplnXRK+FYpJCLQkNrzaW4S1k6/Q5FHyI6PvruJ8jE080z28Ic4B2Aq4urjf4EtnU5/jK+n/gCMLL1SCZ1mGRwInGvpJALm7H1GF2tNWdiz/zbjJFp1l9sUmyezlXao/RtHX7pX5VKVCoUy6ZO2zGNYX8MAyBieAQB3gHGBhJ5IoVc2ER+tvhKMaUQHhOebVNGUmre1r8oX7x8tiMyfL18LfuDFTAJyQl4TvQEoEedHizusdjgRCI/pJALm8hpi6/+e7fSN6R7ns8X4B2QbcdfKY/sFz4Sd/fr4V95ZvEzAIQNDKNxxcYGJxL5JYVc2EROK8ilpC0bWqtsrSzNGLXK1qKYWzF7xiyUUk2p1JpWi5MxJ2lYviG7Bu2SCT1OTgq5sAlvkogh6ypy/h7FOBVk/81MhFnImRBafdcKgJW9V/L4fY8bnEhYgxRyYVXJqcmU/rg0cd4tcK39Lqnq3x8xZ11ZriDQWtNlQRdWnVhFsSLFiBkZg3sR51uuVWRPfp8SVrPz3E6KfliUuOQ4Qp76kO/r1Mff3R2FedcVR95CqyA7fuU4LuNcWHViFbOfnE38mHgp4gWM3JELqxj4+0Bm756Nu6s7saNiKepalBbkPEJF2MfwP4czNXQqAFffuZrv6frCsUkhFxa5lniN0h+bi8PkDpN5u/XbBicSAJfiLuH3qflD9P127zPu4XEGJxK2JIVc5NvSw0t5dvGzgEwicSTB24N54683AIh8PZKqpWRHroJOCrnIM601LWa3YMf5HbSo1IK/X/q7UMx+dHRxt+Io/lFxAHrV68WCZxcYnEjYixRykScRMREETjWPPFn63FKerv20wYkEwC+HfqHHzz0A2D1oN40qNDI4kbAnKeTink3eNpmRa0cCEDMyBm8Pb2MDCVJMKVSfWp3T10/TtGJTtr+8XSb3FEJSyMVd3Uq9RfGJxUk2JTPwwYHMenKW0ZEEsPX0VtrOaQvAX33/olP1TgYnEkaRQi5ytf3sdlp+2xKAHS/voGmlpgYnElprOv3YibXhaynpXpLot6Mdbk1zYV9SyEWOBvw2gLl751K8aHGuvnMVN1c3oyMVekcuH6H29NoAzOk6h/4N+xsbSDgEKeQii5iEGMpMNu8K83mnz3mj5RsGJxIA/1v5P2aEzQDg2shrsvKjyCCFXNxm8cHFPP/L8wCcGn4Kf29/gxMZz9YbZNzteu9ULMOQufcDMPahsXzQ/gObXVs4JynkAjC3uzae1Zg9F/fQtmpbNvXfJGPDyd8GGda+3pATEeD7KGf6zqVyycpWv6ZwfjJOSXDy6klcxrmw5+IelvVcxuYBm6WIp8lpg4wx4eF2ux6uHvg3Gi9FXOTonu/IlVJVgHmAH6CBWVrrKUqpMsBPQABwCnhOax1j/ajCFiZumciY9WMAuP7udUq6lzQ4kWPJaYOMnI7b6nqRiQmosQovNy/aB7Snvb/568EKD0ontMhT00oKMEJrvVspVQLYpZRaA/QH1mmtJyml3gXeBUZaP6qwpqSUJDwmeAAwuMlgvnriK4MTOaaq7u5EZlNcdeJFjl4+Si2fWna5XgmdQDW/BuyL2seq46tYdXxVtu93Va48FPCQudAHtKdZpWZ4FPGwakbheJTW+dutRSm1DJiW9vWQ1vqCUqoCsFFrnetPd5MmTXRYWFi+risst+30NtrMaQPArkG7eLDCgwYnclx3tlkDFNEppByeBNHrANj36j7q+9W32fU8XVxyXMv9WuI1tp3exqbITWw8tZGd53fe9Rqtq7TOKPStqrSieNHiVskubE8ptUtr3STL8fwUcqVUALAZqAec1lp7px1XQEz64zveMwgYBFC1atXGkZGReb6usFzfpX2Zv38+pT1Kc+ntSxRxkf7uu8k8isQz9SZxR4M5+vxXXIm/krFtGlhvA2NrjpKJuxVHyNkQNp7ayKbITWw9vfWu72lSsUlG001b/7Z3XYrB3qN6CjOrFXKlVHFgEzBBa71UKXUtc+FWSsVorXNdvV7uyO3vSvwVfD7xAWDqY1MZ1nyYwYmclxpr7ghOfj+ZIi5F2HV+F02++fffVshLIbSo3MKoeHmSmJLIjnM72HRqE5sizV8pppRc31O/XP2MO/porwa8FXnxnn+DEJaxSiFXSrkBK4C/tNafpx07ijStOLSF+xfSe2lvAM68cUZGP1goITkBz4meFCtSjPgx8RnH90ftp8HMBhmPN/bbSPuA9kZEtJrk1GR2X9idUeQ3ndpEXHLcvy9ovhA8ymd5n7+7O6datrRj0sIhp0J+z8MP05pNvgUOpxfxNMuBfmnf9wOWWRJUWI/Wmvoz6tN7aW8eDngY0wcmKeJWUMytGDte3kFCSgKj143OOF7frz46SHN4yGEAHvr+IdRYxeqTqw1Kajk3VzeaV27OO63fYXKHyfSp3+f2F7iXy/Z9thrVI7J3z3fkSqk2wBZgP5D+e9RoIBRYDFQFIjEPP7ya27nkjtz2jl85Ts1pNQFY0WsFT9R8wuBEBc/odaP5aOtHOS4mdvLqSWp8WSPj8bKey3iq1lP2jJhvN5JuMPefuQSHBhMek3XM/JCmQxjWbBidj1/NdpSN3JHbhlU7Oy0lhdy2xm8azwcbzdO4Y9+NpYR7CYMTFVweH3qQlJpE/Oh4irkVy/Y1p6+f5v5p95OQkgDA4u6L6VG3hz1j5kprzcZTG5kSOoVlR7P+Qt3Ovx2vN3+dp2o9hauL623P5XWUjbCMFPJCIDElkWITzMVkWLNhTP3PVIMTFXwpphTcxpsn5Oig3P8tXbhxgXoz6nE1wfwL6/fdvueFB16wecY7nb9xnhk7ZxAcGszNWzdve65MsTK83vx1XmnyCuW8sm82uZOMWrEfKeQF3ObIzbSfa+5Y2/PKHhqWb2hsoELk2JVj1JpWi/4P9GdOtzl3fX10XDSNvm7EuRvnAPi6y9cMajzIJtmSU5NZengpU0KnEHI2JMvzPer0YHjz4bSq0kqWZXACUsgLsOd/fp7FhxZTzqsc5948J2PDDfBl6Je89udredqp52rCVVrMbsHxq8cBCO4czPAWwy3KcfDSQaaETuGb3d9kee5+n/t5vfnr9G3QF6+iXhZdRxhDCnkBdDn+Mr6f+ALw1eNfMbjpYIMTFW61vqzFsavHuPrOVUoXy3UqxW1ik2JpN6cde6P2AvDRox/xbpt37/q+u3VIDm06lGHNh1GzbM17/0MIhyaFvID5Ye8PvPCbuX313JvnqFiiosGJhNYal3HmEb2mD0x5bqqIuxVHh3kd2H5uOwDvt3ufsQ+NRSmV0SEZHBrM8qPLs7y3vX97hjcfnm2HpCg4pJAXECZtovb02hy7coxO1TvxZ58/pW3TgZy/cZ5Kn1fi0WqPsvaFtfk6R0JyAh3ndWTb2W3ZPp+fDklRMORUyKUx1Ylk3q/xjz5/8FiNxwxOJO5UsURFFj67kF5LerHowCJ61ut51/ekd0gGhwaz/ez2HF83uPFgpj0xDRcl2wiI28kduZN4f/37fLjlQwBujropnVUOruMPHVkbvpazb5ylUslKtz134NIBpmyfwuw9s7O8r7ZPbYY3H35bh2RyajJ9lvbh50M/A9D/gf7Mfmq2NKEUQtK04qTS1/UAeLPFm3zW+TODE4l7lb64VnDnYKbumGpxh2SqKZUXl73IvH3zAHi+7vP8+MyPMkqpEJFC7oQ2RGzgkXmPANZd81rYhtaaDac2MCV0SrYdkg8FPMTw5sN5suaTFt1Nm7SJISuHMHPXTACerPkkvzz3C0Vdi+b7nMI5SCF3Ms/+9CxLjyylcsnKnBp+Sn6NdkDnYs/x1c6vmBI65fYVAYGyxcoyvPlwavnU4vlfnmfKY1N4rflrVr2+1pq3Vr/F59vNa9h1qNaB33v/LjsCFWBSyJ3EpbhL+H1qnt48q8ssBjYeaHAiAeZ26iWHlzAldEq2HZLP1X2O4c2H07JyyyyjiAYsG8Dcf+ZydOhRm4zp1lrz/ob3mbBlAgCtKrdizQtr8HTztPq1hLGkkDuBuf/MZcCyAQBcGHGB8sWzrvMs7COvHZJ3c+dmFLagtWbilom8t+E9ABqVb8Sm/ptk0bQCRAq5AzNpEzWm1iDiWgRP3PcEK3qvMDpSoRKbFMucPXOYEjqFiGsRWZ63xgzJ9E5rd1d3Et9LtCTuPfk85HNGrB4BQK2ytQh5KSRPs02FY5JC7qAORR+i7ld1AVjddzUdq3c0OFHBZq8OyeyEnQ+j6TdNGdl6JJM6TLLquXMyY+cM/rfqfwBUKVmF3a/sxsfTxy7XFtYnhdwBjVo7iknbzP+g40bHSZumDeTWIenj6cPw5sMZ1HiQ3WZIjlk3holbJxL6cijNKjWzyzXh9mY7H08f9g/eL013TkgKuQOJT47Ha6K5bfWdVu/wccePDU5UMFjSIWlPnhM8SUhJyHUzClvJvH+rl5sXR4Yeke3/nIgUcgexNnwtHX8wN58cGHyAuuXqGpzIeeXWIVnHt05Gh6Sj/aaTl80obOXXw7/yzOJnAFAoTr52kmqlqxmSRdw7KeQO4KmFT/H7sd8J8A7g5GsnZc2MPLhbh+SwZsMY2myo0yzZmr6n6gsNXuD7p783LMcfx//g8QWPZzy21RBJYR1SyA108eZFKnxWAYDvnvqOAY0GGJzIsWmtWR+xnimhU/j92O9Znn8o4CFeb/46XWp2ceqJUtN3TGfoH0P5s8+fdK7R2dAs6yPW8+i8RzMey2+LjkkKuUFm757NwN/Nk3oujriIX3HZy/BO6R2SwaHBxCfH3/acER2S9lR7Wm2OXDnC1y+eYOLZS4bve7nt9DbazGmT8Xj3oN00qtDI7jlE9qSQ21mqKZWAKQGcjT1Lt1rd+LXnr0ZHcgjJqcn8cugXpoROIfRcaJbnHaVDMp2tNxbWWuMyoyPUegtc/51ab/RO9DvP7aTZ7H9H1YS8FEKLyi0MySL+ZXEhV0p9B3QBLmmt66Ud+z9gIBCd9rLRWutVdztXQS/kBy4doP4M8wJX615YxyPVHjE4kXH2R+1nSugUvt3zbZbn6vjW4fXmr9OnQR+H65AEcxEfdPQo8SZTxjFrFthUUypXEq5Qf/dBLqVm/dDyd3fnVMuWOWazx871ey/upeHXDTMeb+q/iXb+7ax+HXFvrFHI2wE3gXl3FPKbWutP8xKmIBfyt1a/xWch5qVmjRheZqT0Dsng0GBOXTuV5flhzYYxrNkw7it7n/3D5UNASAiRSUlZjpd1SeEd191E3YwiKi7tK+37S3GX8n6hdusgu45vbYLN5nbr+33up2XllrSs3JIrJRoy/mKCzT5gsnM4+jB1vqqT8XjNf9fQIbCDTa4lcmaVphWlVACwQgp5VnG34ij+UXEARrcZzYRHJxicyLacrUNSa82VhCucvHqS8JhwwmPCORlzkpMx5sdnY89mfdM9FNjslPMqh5+XH37F/fDz8qN88fK3PU7/r6+XL0VciuT4gVFSJ9D0zGeEnA25ve+g+ULwyDqZJ7c7eGs5cfUE93357wfx771+p0vNLja9pviXLbd6G6qUegEIA0ZorWOscE6n8teJv3hsvnnbtcNDDnO/z/0GJ7K+c7HnmL5zOlNCpxjaIXkj6Ya5AOdQkPPLVblSvUx1qpeuTmDpQAJLBzIpGaJNWV/r71GMU1Yc/z0hMDDbJpyvaj1In4ez7vvpsnEj2V39dDYfBtZWo0wNdJAm8lokNafV5MmFTwLwc4+f6V6nu82vL7JnaSGfAYwHdNp/PwNezO6FSqlBwCCAqlWrWnhZx6C15rH5j7H65Gpqlq3J4SGHC8TY8PQOyeDQYHac25Hl+efrPs/w5sNpUblFvjokE1MSiYiJuL0gXwvn5FVzQb6Veivf2f1L+VO9THUCvQPN/y0dmFGc87polF8ObeQTAgPznS876c0h6W3eOvEixS/9Tp9287N9fWX3opxJyvr/qKq7u1Vz5cbf25+k95I4F3uOejPq0ePnHgD88PQP9G3Q1245hJlFTSv3+tydCkLTSvpu6QDfd/ueFx54weBEObtbx9i+qH1MDZ2abYdkXd+6DG8+PEuHZIophchrkRl3xLf99+pJbty6ke+85YuXp3rp6rcV5PRiXM6rnF1Hs9irUzGzdeHr6PBDB77o/AWvt3g9y/Pqqw4ON8rlUtwlGs5syIWbFwBZS99WbNVGXkFrfSHt+zeA5lrru24b7uyFfGbYTAavHAzApbcu4evla3CinGU38sINE6Uiv+HyqUVZXl+zbE08inhwLvYcVxKu5Pu6ZYqVybgbTi/C6QW5YomKDtFu7sheWv4S3+35LktTXXpn+uTeu5h+Ocnwced3uhJ/hWazm2U0c335ny8Z2myowakKDmuMWlkIPAT4AFFAUNrjhpibVk4Br6QX9tw4ayFPNaVS6fNKRMVF0aNODxb3WGx0pLvKqSONxIsQ2ivX9xYvWjyjvfjOgly1VFXZI9LG7tyMYl/UPh6Y+QDvtX2P8Y+MNzhd7q4nXqfNnDYcuHQAgI87fMw7rd8xOJXzkwlBFso8nnZjv420D2hvbKB7lFPHmAJutm7mkOO3hVliSiLFJhTDzcWN+DHxhi+0lR83b93kke8fYef5nQAEtQ8iqH2QQ0z2ckY5FXLn75mzg9f/fD2jiCeMSXCaIg45d4BVdXeXIu7gPIp4EDYwjGRTMiU/KgmYf/6cSfGixdkxcAfxo+Np79+esZvG4jLOhZFrRmLETWRBJYU8FzeSbqDGKqaETiGofRA6SDvdDuUTAgPxdLn9r9kWIy+EbTSu2JjOgZ1JSEng6y5fO93PX7pibsXY2H8jiWMS+U+N/zD578m4jHNh2KphUtCtQJpWcrDq+CqeWPAE4PxLexox8kJYx+nrp/EP9qeIKkKKTikwO0klpybT85eeLD2yFIAXG73IN09+UyCG79qStJHfI601HeZ1YP2p9dTxrcP+wfvlh0sYQmuNyzjzz17K+ykUGV8EfB/Fv9H4AvOhnGpKpd9v/Zi/3zxmvle9Xsx7eh5FXKwxV7HgkTbye3A29iwu41xYf2o985+Zz8H/HZQiLgzT6rtWAFx95yquLq582mcP1HqLyKQkNBCZlMSgo0eZHxVlbFALuLq48uMzP5L6QSoDHxzIwgMLcRvvRrdF3UhOTTY6nsXmR0UREBKCy8aNBISE2OzvSqpUmmk7plHliyoAXH77Mr3r9zY4kSjMlhxawvaz21ny3JKMGalfRifcNgkIIN5kYkx4/pcmcBQuyoVZT87C9IGJ4c2Hs+zoMop+WJTOP3QmKcX2Sw/YQvocDnt88Bb6Qp5iSqHs5LIM+2MYvev1RgdpynqWNTqWKMRiEmLo/nN3WlRuQYB3AO+seQf/YH8iE7MfsWKPNVbsRSlF8GPBmD4wMarNKFaHr8Zjggdtv2ubZY0fRzcmPPy2iXhguw/eQt1GvufCHh6c9SAAWwZsoU3VNnd5hxC2ER4TzqIDi1h0YBH7L+3P9jVurZaQ7FYmy3F7rHpoFK01H27+kA82fgBA4wqN2dBvAyXcSxic7O7Uxg2YZ2zccRwwPfRQ/s4pnZ23G7JqCF/t/AqAxDGJuBex34JDovC6FHeJXw79wqIDi9hyekuOrxvcZDCvNH6FBn4NMibP2HqjC0f3ybZPeGeteXZobZ/a/P3S33h7eBsbKhtbIrfQbm47myw3LIU8TWxSLKUmlQLgw4c/ZEy7MYbkEM4lr0M4b966yfKjy1l0YFG267UDlPYoTc96PelZryetq7Tm7zN/025uu1zXJ5GhpP9uWg3m1S53DdrlEM2h0XHRlPv032WcZww4zohT5636wSuFHFh+dDldF3UF4Piw49QoU8PuGYTzye1OuIdPadaGr81oFkk2ZR1poVAZBbtz9c7Z/vaXPh3fx9OH6Lejszwvsvpuz3e8tPwlwLyZx75X9xmyublJm3hywZOsOmHe5XLrgK20rtoaMP/sjAo/yZnERKp4ePBRYHWLPngLdSHXWtN+bnu2nN5Cw/IN2T1ot6z1IO5JUkoSgaE7OJ+cmvXJbBYee/y+x3m+7vN0rdWVUh6l7vk6dy6QJe7dgv0L6LO0D2BeEuDwkMNULlnZLtfO/NtBbguDqbGKsIFhNK7Y2KLr2XKHIIeWPjMOYNGzi3i+3vMGJxL2pLXmasJVIq5FEBETQcS1CMJjwjMeh8eEk6qzKdKZ5bTlm4cf5988T4USFSzK+P769wHY++peKeL50Lt+b3rX782SQ0vo/nN3qnxRBVflyonXThDgHWCTa+46v4sm35jraduqbVnfb/1d/+72XNxjcSHPSYH+qQneHswbf70BwJV3rlCmWNYef+H4UkwpnI09ay7AacU4cyGOirNsXG6lEpWoVroa1byrEVg6kGre1TIeVyxRkeqhO7JdCtjf3cPiIn44+jAfbvmQt1q+RQO/Bhadq7B7ts6z6CDNymMr6bKwC9WmVAPg2NBjVtvw+1riNap+UTVj45Szb5ylUslK9/Tefy7+Y5UM2SmQhTw5NZmyk8ty49YN+j3Qj7nd5hodqdC7kXTjtrviiJgIwq/9W5gtGSPs7uqebSEOLB1IgHeAxSMbctpT09KFx1JNqRk703/S6ROLziX+9UTNJ9BBmrXha+n4Q0dqTjOvk3Rg8AHqlqubr3NqremztA8LDywEYHXf1XSs3jFP55BCngdh58No+k1TAP5+8W9aVimY42vtzaRNXLx5MeMuOPNdccS1CE5fP23R+X09fTOKceZCXM27GlVKVTF0E4s799S01miRwKnmD4K40XEWZxRZdQjsgA7SGcMB680w70K555U9NCzf8J7PM2/vPPr91g+A0W1GM+HRCfnKs+finny9714UqEL+yopXmLVrFkVcihA3Ok52sLlDYkpixj6b2d0VX0u8lu9zK1SOhbha6Wr4evo6dQdzHz8/qw7z+2bXN5y+fpp1L6wrEKsZOrK2/m3RQZrQs6G0+LYFjb5uBEDoy6E0q9Qsx/cdij5E3a/Md/D1y9Vn58Cd+Z5vElg6MGP7O1soEIX8euJ1vD/2BmDSo5MY2WaksYFsJL3j7s7Ousx3x3ftuMtFSfeS2bYTVytdjQDvACk4VnL+xnkGrRjEM7Wf4ZFqjxgdp9BoXrk5OkhnzOhuPrs5AJv7b6atf9uM18XdiuP+6fdzNvYsACdfO0lgacua0RqVbySFPDe/Hv6VZxY/A0D4a+FUK13N4ES5SzGlcOb6mWwLcXhMOJfiLll0/kolKpkLcTZtxhWKV5BNjw2mtabS5+bOsSXPLTE4TeHUqEIjdJDm4KWD1JtRzzwLE3O799IjS5kZNhOApc8t5enaT1vlmg3LN2TJYdv9fTttIdda0+rbVmw/t52mFZsS+nKo3X51j02Kva3TLnMhjoiJICEl/9txubu651iIq3lXy9PYZOF4OszrACCTfhxA3XJ10UGa41eOU3NaTTr92AmAx2s8zoreK6xaT/LSJp8fTlPIM09Nrujmyrm9YyF6O7/0+IVn6zybp3OZtIkLNy7k2DxxJvaMRVkzd9zdOYqiSskquLm6WXR+4Zx+P/o760+tZ8EzC/Dx9DE6jsC8WFn6qJaKJSpy8cZFVp1Yhcs4F5Y8t4Rnaj9jleukF3KttU1uOJ1iZmd2U6RJTeT/KpSgqdv1bO+Kryddz3e+zB13dxbiat7V8PH0ceqOO2F/6Wv8POD3AP+8+o/RcQq9pJQkmnzThAOXDgBw8H8HqeNrHgp6NvYsdabXyRgrPv+Z+RbvT5C+25OlE8iceop+QEhIthMyspsina6Ue6kcR1H4e/tLx52wq/Qp+KYPTHITYLDR60bz0daPAJjXbR7/feC/2b4u6mYUDWY2yOi3+vapb3mx0Yv5vq4aq/ijzx88VuOx/J/D0in6SqnvgC7AJa11vbRjZYCfgADgFPCc1jom3ylzkNPC+cqjPKYg2YFbOLaBvw8EzKMfpIgbZ/XJ1XT+sTMAfer34Yenf8j178OvuB9Rb0VxOf4yTb9pykvLX+Kl5S8x7T/TGNJsSL4y7Lmwx6JCnpO87BA0F7gzwbvAOq31fcC6tMdWV9U9+7GbOR0XwlGEng1l9u7ZTO4w2eIhbCJ/zsWeQ41VdP6xMyXdS3Jt5DV+fObHe/5Q9fH0IWJ4BDEjY6jtU5uhfwxFjVV8+venec5iq0lB91zItdabgat3HO4KfJ/2/fdAN+vEut2EwEA8XW6Pao0p0kLY0q3UW7T4tgWebp683fpto+MUOimmFNp814bKX5hXQgwbGMb1d6/ne+SXt4c3h4YcIvbdWBpXaMzba95GjVWM3zSee22ittU0fUv37PTTWl9I+/4ikOPUN6XUIKVUmFIqLDo6b0Ov+vj5MatWLfzd3VGYd9goLLuiCOflNdELgGsjrxkbpBD6eOvHuI13Y9uZbUx/fDo6SFtt5cES7iUIGxRG3Og42lZtywcbP8BlnAuj1o7KtaC7u7pz/Opxq2S4U546O5VSAcCKTG3k17TW3pmej9Fal77beRxhqzchbGnilomMWT/GKmtQi3u39fRW2s4xz9J84r4nWN5rOS7ZLUFsRYkpiXRd2JXV4asBeK3ZawQ/Fpyl6abF7BaEngtFW9Cvl1Nnp6V/wiilVIW0C1QALJuWKEQBcPzKccasH8P/mv5PiridRMdFo8aqjCJ+6a1LrOi9wuZFHMCjiAd//fcvbr13i261ujF1x1RcxrkwcPlATPrfIdONyjeyWQZL/5TLgX5p3/cDlll4PiGcmkmbMiaYTH98usFpCj6TNtFlQZeMvTK3DNiCDtL4evnaPYubqxu/9vyV5PeT6VWvF7P3zMZ1nCt9l/Yl1ZTKrbLmDZldNm4kICSE+VGWraOf2T0XcqXUQiAEqKWUOquUegmYBHRUSh0HOqQ9FqLQqjvdvFrejVE3DE5S8M3YOQPXca6sPL6Sjx79CB2kaVO1jdGxKOJShAXPLiD1g1RebPQi8/fPp8jMzsxNKAse5dFAZFISg44etVoxd4oJQUI4g/R1qy2d9CFyt/vCbhrPMjdZtanShg39Nzj0Fnlaa0ptWMUNF68sz/m7u3Oq5b3vmVBo9+wUwh6ibkbR77d+PFbjMSniNnI98TpVvqiSr23WjKSU4mY2RRxynuyYV7bvCRCiECj/WXkAVvVeZXCSgkdrTd+lffH+2Jsbt27wZ58/0UHaKYp4OltPapRCLoSFuizoAsCFERdkCr6V/bjvR1zGuTB//3zebf0uOkjTuUZno2Plma0nNUrTihAWWH1yNSuPr2RO1zmUL17e6DgFxuHowxkbU9crV4+wgWH53mbNEdhq39d0UsiFyKebt27S+cfO3FfmPvo37G90nAIh7lYctafXztgT4MSwE1QvU93gVNZh7X1fM5OmFSHyqcRHJQA4MvSIwUmcn9aaIauGUPyj4pyJPcOS55agg3SBKeK2JnfkQuTDa3+8BsDRoUftMnuwIPvtyG88/ZN5b8zBTQYz/fHp0teQR1LIhcij3Rd28+WOLxn30Dhqlq1pdBynFRETQeBUc2df5ZKVOTLkCF5Fsx+mJ3InhVyIPEhOTc6YjPJ++/cNTuOcklKSaPpNU/Zf2g/AgcEHqFuursGpnJv8TihEHvh8Yt40OXFMosFJnNN769/DY4IH+y/t5/tu36ODtBRxK5A7ciHu0echnxObFEvISyFOPRTOCGtOrqHTj50A6F2vd5526BF3J4VciHsQERPBiNUjGNBwAC0qtzA6jtM4f+M8lT43z8AsXrQ4Z944g7eHt7GhCiAp5ELchdY6o1Puu67fGZzGOaSYUnjk+0fYcnoLADsH7qRJxSxrPQkrkTZyIe6iySxzAZIt2+7NJ9s+wW28G1tOb2Haf6ahg7QUcRuTO3IhcvHTgZ/YfXE3vz3/W7437S0s/j7zN62/aw3A4zUe5/fev8sYezuRQi5EDq7EX6Hnkp60929P1/u7Gh3HYV2Ov4zvJ//uyBP1VhTlvMoZmKjwkY9LIXKQPtRwQ78NBidxTCZtouvCrhlFfHP/zeggLUXcAHJHLkQ2nvv5OcC8eYEMk8tqZthMBq8cDMDERyYyqu0ogxMVblLIhbjDhogN/HzoZ2Y8McOpNi+whz0X9vDgrAcBaFW5FRv7b8TN1c3gVEIKuRCZJCQn8Mi8R6hYoiKvNnnV6DgO43ridfyD/bmedB2AM2+coXLJyganEumkjVyITDwnegJw+vXTBidxDFprXvj1Bbw/9uZ60nX+6PMHOkhLEXcwckcuRJqRa0YC5kWcXF1cDU5jvPn75tP3174AjGw9kkkdJhmcSOTEKoVcKXUKuAGkAilaaxn9L5zK/qj9TP57MqPajCr0izgduXyE2tNrA1DHtw67Bu3Co4iHwalEbqx5R/6w1vqyFc8nhF2kmlJpMLMBABMfnWhwGuPEJ8dTZ3odIq9HAgVrm7WCTtrIRaFX+Qtze2/86HiDkxhDa82wP4bhNdGLyOuR/NLjF9lmzclY645cA6uVUhr4Wms9y0rnFcKmpu+YzsWbF9nUfxPF3IoZHcfulh1ZRrefugHwSuNXmPHEDBk374SsVcjbaK3PKaXKAWuUUke01pszv0ApNQgYBFC1alUrXVaI/Dsbe5ahfwylV71etPNvZ3Qcu8q8zVrFEhU5OvQoxYsWNziVyC+ltbbuCZX6P+Cm1vrTnF7TpEkTHRYWZtXrCpEXWmtcxplbFnWQdf8NOLKklCSaz27O3qi9AOwfvJ965eoZnErcK6XUruwGk1jcRq6U8lJKlUj/HugEHLD0vELYUts5bQG48s4Vg5PYzwcbPsBjggd7o/Yyp+scdJCWIl5AWKNpxQ/4Na1drQiwQGv9pxXOK4RN/HbkN7ad2cbi7ospU6yM0XFsbm34Wjr+0BGAnnV7suDZBdIOXsBYXMi11uHAA1bIIoTNXUu8xtM/PU2Tik3oUbeH0XFsKvM2a15uXpx986xss1ZAycxOUaiU/rg0ADte3mFwEttJMaXQYV4HNkVuAmSbtcJAxpGLQqP/b/0BODX8VIFtWvj0709xG+/GpshNTH1sqmyzVkjIHbkoFLad3sb3e78nuHMw/t7+RsexuszbrD1W/TFW9F4h68UUIlLIRYGXlJJEmzlt8PbwZniL4UbHsaor8Vfw/cQXjXkIpWyzVjhJ04oo8DwmmBd8in472uAk1mPSJrot6obPJz5oNJv6b5Jt1goxuSMXBVrQhiAA9ryyhyIuBePH/euwr3l1pXnTiw8f/pAx7cYYnEgYrWD8ZAuRjSOXjzBu8zheb/46Dcs3NDqOxf65+A+Nvm4EQMvKLdnUf5NssyYAKeSigDJpU8aa2l889oXBaSwTmxRLQHAAMYkxgHn3oiqlqhicSjgSaSMXBdJ9X94HwM1RNw1Okn9aa/r/1p9Sk0oRkxjDqt6r0EFairjIQu7IRYHz7e5vCY8JZ81/1+BV1MvoOPmyYP8C+iztA8Dbrd5mcsfJBicSjkwKuShQLty4wMu/v0zXWl3pENjB6Dh5dvTyUe6ffj8AtX1qs/uV3bLNmrgrKeSiwNBaU/HzigD81vM3Y8PkUXxyPPW+qkfEtQgAjg87To0yNQxOJZyFtJGLAqPTj50A86QYZ6G1Zvifw/Ga6EXEtQh+7vEzOkhLERd5InfkokBYdXwVa8PX8sPTPzjNpJjlR5fTdVFXAAY+OJCvu3xdYNeAEbYlhVw4vRtJN3hiwRPU9a1L3wZ9jY5zV5HXIgmYEgBAheIVODbsmGyzJiwihVw4vZKTSgLmbcsc2a3UW7SY3YI9F/cAss2asB5pIxdO7dUV5qnqx4cdd+hmiaANQbh/6M6ei3v47qnvZJs1YVVyRy6c1s5zO/l619d89OhHDts5uC58HR1+MA+DfL7u8yx8dqFDf+AI5ySFXDil5NRkms1uRlHXorzb5l2j42Rx4caFjKGQxYoU49yb5yhdrLTBqURBJYVcOKUSH5UA4MaoGwYnuV2KKYVOP3Riw6kNgHlLuaaVmhqcShR00kYunM6krZNISk1ix8s7KOpa1Og4GT4P+Ry38W5sOLWBKY9NQQdpKeLCLuSOXDiVE1dPMGrdKF5p/IrDFMntZ7fT8tuWAHSu3pmVvVfKNmvCrqSQC6ehtc5Y1XBml5kGpzFvs+b3qR+pOhWAiyMu4lfcz+BUojCyStOKUuoxpdRRpdQJpZTj9TyJAqHBjAYAxL4ba2gOkzbxzE/P4POJD6k6lY39NqKDtBRxYRiL78iVUq7AdKAjcBbYqZRarrU+ZOm5hUj3474fORB9gJW9V1LCvYRhOb7Z9Q2DVgwCYPzD43mv3XuGZREinTWaVpoBJ7TW4QBKqUVAV0AKubCK6Lho/vvrf+kY2JHH73vckAx7L+6l4dcNAWheqTlbBmyRbdaEw7BGIa8EnMn0+CzQ/M4XKaUGAYMAqlataoXLisKi3KfmRbD+6vuX3a8dmxRL4JRAriRcAWSbNeGY7Db8UGs9S2vdRGvdxNfX116XFU4ufXXA82+et+uMSK01A5YNoNSkUlxJuMLK3itlmzXhsKxxR34OyPzTXTntmBAWWRu+luVHlzP7ydlUKFHBbtdddGARvZb0AuCtlm/xSadP7HZtIfLDGoV8J3CfUqoa5gLeE+hthfOKQizuVhwdf+hINe9qvPTgS3a5ZuZt1mqVrcWeV/ZQzK2YXa4thCUsLuRa6xSl1FDgL8AV+E5rfdDiZKJQK/6ReX3uE6+dsPm1EpITqD+jPidjTgJwbOgx7it7n82vK4S1WGVCkNZ6FbDKGucS4o0/3wDg8JDDuCjbdeNorRmxegRfbP8CgMXdF9Ojbg+bXU8IW5GZncKh/HPxH4JDg/mg3Qfc73O/za6z4tgKnlz4JAAvP/gys7rMkuVlhdOSQi4cRoophUZfNwJg7MNjbXKNzNus+Xn5cXzYcUMnGAlhDVLIhcMo94l5vHjimESrn/tW6i1aftuS3Rd2A7Dv1X3U96tv9esIYQRZxlY4hODtwcQkxrDtxW24F3G36rnHbhyL+4fu7L6wm2+f+hYdpKWIiwJF7siF4U5dO8Ubf71Bvwf60apKK6udd0PEBh6Z9wgAPer04KfuP0k7uCiQpJALQ2mtqTalGgBzu821yjkv3rxIhc/ME4g8inhw7s1zlClWxirnFsIRSSEXhmo+27wsT8zIGIvPlWpKpfOPnVkXsQ6A0JdDaVapmcXnFcLRSRu5MMzPB39m5/mdLH1uKd4e3had64uQLygyvgjrItYR3DkYHaSliItCQ+7IhSGuJlzluV+eo02VNjxd++l8nyfzNmsdAzvyR58/ZJs1UehIIReGKDu5LACbB2zO1/uvJlyl/KflSTYlA3BhxAXKFy9vtXxCOBNpWhF21+sX88qCp18/nedRJCZtovvi7pSdXJZkUzIb+m1AB2kp4qJQkztyYVebIzez6OAipv1nWp7X9p69ezYDfx8IwNiHxvJB+w9sEVEIpyOFXNhNQnIC7ee2p5xXOYY0G3LP79sXtY8HZj4AQNOKTdn64laKuha1VUwhnI4UcmE3nhM9AfNuP/fiRtINqk+tTnR8NACRr0dStZRsEyjEnaSNXNjFqLWjAPMaJ3cbVaK15sVlL1JyUkmi46NZ0WsFOkhLERciB3JHLmzu4KWDTNo2ibdbvX3XNU5+OvATPZf0BODNFm/yWefP7BFRCKcmhVzYVKoplXoz6gEwuePkHF937Moxak2rBUDNsjX555V/ZJs1Ie6RFHJhU/7B/gDEjY7L9vmE5AQemPkAx68eB2SbNSHyQ9rIhc3MDJvJuRvnWP/CejzdPLM8P+KvEXhO9OT41eMsenYROkhLERciH+SOXNjE2dizDF45mO51uvNwtYdvey7zNmsvNnqR2U/OluVlhbCAFHJhdVprqnxhnuzzc4+fM46fvn46o6mlnFc5Tgw7IdusCWEFUsiF1T009yEALr99GTBvs9b6u9aEnQ8DYO+re2ng18CoeEIUOBa1kSul/k8pdU4p9U/a1+PWCiac07Ijy9h8ejMLn11IWc+yjNs0DvcP3Qk7H8bsJ2ejg7QUcSGszBp35F9orT+1wnmEk7ueeJ1uP3WjUflG+Hn5ocaa27271+7OTz1+wkVJ37oQtiBNK8Ii86OiGBMezumkJHTiRfB9lD0X1/HIvEco6lqUCyMuyDZrQtiYNQr5UKXUC0AYMEJrbfmeXcIpzI+KYtDRo8SbTOYDHuWh1lsAbH9qAs0rNzcwnRCFh9Ja5/4CpdYC2S32PAbYDlwGNDAeqKC1fjGH8wwCBgFUrVq1cWRkpAWxhSMICAkhMikpy3F/d3dOtWxpQCIhCjal1C6tdZM7j9/1jlxr3eEeL/ANsCKX88wCZgE0adIk908P4RROZ1PEczsuhLANS0etVMj08GnggGVxhDOp6u6ep+NCCNuwdBjBZKXUfqXUPuBh4A0rZBJOYkJgIJ4ut/8Iebq4MCEw0KBEQhROFnV2aq3/a60gwvn08fMDyBi1UtXdnQmBgRnHhRD2IcMPhUX6+PlJ4RbCYDJDQwghnJwUciGEcHJSyIUQwslJIRdCCCcnhVwIIZzcXafo2+SiSkUDjjRH3wfzUgOOSLLljyNnA8fOJ9nyxx7Z/LXWvnceNKSQOxqlVFh26xc4AsmWP46cDRw7n2TLHyOzSdOKEEI4OSnkQgjh5KSQm80yOkAuJFv+OHI2cOx8ki1/DMsmbeRCCOHk5I5cCCGcnBRyIYRwcoWqkCulPJRSO5RSe5VSB5VSY+94fqpS6qYjZVNKzVVKRSil/kn7auhg+ZRSaoJS6phS6rBS6jUHyrYl0/+380qp3xwo26NKqd1p2bYqpWo4ULZH0rIdUEp9r5QybJVUpZSrUmqPUmpF2uNqSqlQpdQJpdRPSqmiRmXLId/QtGxaKeVjtyBa60LzBSigeNr3bkAo0CLtcRPgB+CmI2UD5gLdHfX/HTAAmAe4pD1XzlGy3fGaJcALjpINOAbUTjv+P2Cug2RrBZwBaqYdHwe8ZODP3ZvAAmBF2uPFQM+072cCg43KlkO+RkAAcArwsVeOQnVHrs3S77jd0r60UsoV+AR4x9GyGZXnTrnkGwyM01qb0l53yYGyAaCUKgk8AvzmQNk0UDLteCngvINkSwVuaa2PpR1fAzxr72wASqnKwBPA7LTHCvPf4y9pL/ke6GZEtrQ8t+UD0Frv0VqfsneWQlXIIeNXoX+AS8AarXUoMBRYrrW+4IDZACYopfYppb5QShm2IWYO+aoDzyulwpRSfyil7nOgbOm6Aeu01rEOlO1lYJVS6izwX2CSI2QDdgBFlFLpMxS7A1WMyAYEY765MqU9Lgtc01qnpD0+C1QyIFe6YG7PZ5hCV8i11qla64ZAZaCZUqod0AP40tBgZJutHjAKuB9oCpQBRjpYPncgUZunJn8DfOdA2dL1AhYakQtyzPYG8LjWujIwB/jcEbIBdYGewBdKqR3ADcx36XallOoCXNJa77L3te+Fo+UrdIU8ndb6GrAB86bRNYATSqlTgKdS6oSB0TJne0xrfSHtV+AkzP/gmxmZDW7Ph/muaGnaU78CDQyKBWTJRlqHUzNgpYGxgNuy/Qd4INNvDT9hbps2zB0/cyFa67Za62bAZszt+fbWGngq7d/kIsxNKlMA70ydr5WBcwZkg2zyKaV+NChL4SrkSilfpZR32vfFgI7ALq11ea11gNY6AIjXWhsxgiC7bEeUUhXSjinMTQQH7J0tt3yY250fTntZewz4R59LNjA3DazQWifaO1cu2Q4DpZRSNdNeln7MEbIdUUqVSzvmjvk3wJn2zqa1HqW1rpz2b7InsF5r3Qfzh033tJf1A5bZO1su+foakQUK3+bLFYDv0zo3XYDFWusVBmdKl202pdR6pZQv5hEG/wCvOli+rcB8pdQbwE3Mbb8OkS3tuZ4Y1P6cJqf/bwOBJUopExADvOhA2T5JazpwAWZordcbkC0nI4FFSqkPgT3AtwbnuY0yD799BygP7FNKrdJa2/zfhEzRF0IIJ1eomlaEEKIgkkIuhBBOTgq5EEI4OSnkQgjh5KSQCyGEk5NCLoQQTk4KuRBCOLn/B14KGtJzkpaXAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([simple_sequence], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: Random Permutation" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[6, 1, 13, 11, 15, 14, 9, 8, 0, 12, 7, 5, 4, 3, 10, 2]\n" + ] + } + ], + "source": [ + "random_permutation = np.random.permutation(16).tolist()\n", + "print(random_permutation)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([random_permutation], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Best Solution" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]\n", + "plotTSP([best_ulysses16], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Fitness (Sum of all Distances)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def dist(node_0, node_1, coords):\n", + " \"\"\"\n", + " Euclidean distance between two nodes.\n", + " \"\"\"\n", + " coord_0, coord_1 = coords[node_0], coords[node_1]\n", + " return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 0: [38.24 20.42]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 0:\", ulysses16[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 1: [39.57 26.15]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 1:\", ulysses16[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance Between 5.882329470541408\n" + ] + } + ], + "source": [ + "print(\"Distance Between\", dist(0, 1, ulysses16))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness(solution, coords):\n", + " N = len(coords)\n", + " cur_fit = 0\n", + " for i in range(len(solution)):\n", + " cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)\n", + " return cur_fit" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Order Fitness:\t 104.42225210207233\n", + "Random Fitness:\t 165.05253084971622\n", + "Best Fitness:\t 74.10873595815309\n" + ] + } + ], + "source": [ + "print (\"Order Fitness:\\t\", fitness(simple_sequence, ulysses16))\n", + "print (\"Random Fitness:\\t\", fitness(random_permutation, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Random Model" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyRandomModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " random_solutions = []\n", + " for i in range(0, max_it):\n", + " solution = np.random.permutation(self.N).tolist()\n", + " random_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 102.73430244116014\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, max_it=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulated Annealing" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MySAModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " self.iteration = 0\n", + "\n", + " def init(self, nodes, *args):\n", + " super().init(nodes)\n", + "\n", + " T, stopping_temperature, alpha = args\n", + "\n", + " self.T = math.sqrt(self.N) if T == -1 else T\n", + " self.alpha = 0.995 if alpha == -1 else alpha\n", + " self.stopping_temperature = 1e-8 if stopping_temperature == -1 else stopping_temperature\n", + "\n", + " self.T_save = self.T # save inital T to reset if batch annealing is used\n", + "\n", + " def initial_solution(self):\n", + " \"\"\"\n", + " Greedy algorithm to get an initial solution (closest-neighbour).\n", + " \"\"\"\n", + " cur_node = random.choice(self.nodes) # start from a random node\n", + " solution = [cur_node]\n", + "\n", + " free_nodes = set(self.nodes)\n", + " free_nodes.remove(cur_node)\n", + " while free_nodes:\n", + " next_node = min(free_nodes, key=lambda x: self.dist(cur_node, x)) # nearest neighbour\n", + " free_nodes.remove(next_node)\n", + " solution.append(next_node)\n", + " cur_node = next_node\n", + "\n", + " cur_fit = self.fitness(solution)\n", + " if cur_fit < self.best_fitness: # If best found so far, update best fitness\n", + " self.best_fitness = cur_fit\n", + " self.best_solution = solution\n", + " self.fitness_list.append(cur_fit)\n", + " return solution, cur_fit\n", + "\n", + " def p_accept(self, candidate_fitness):\n", + " \"\"\"\n", + " Probability of accepting if the candidate is worse than current.\n", + " Depends on the current temperature and difference between candidate and current.\n", + " \"\"\"\n", + " return math.exp(-abs(candidate_fitness - self.cur_fitness) / self.T)\n", + "\n", + " def accept(self, candidate):\n", + " \"\"\"\n", + " Accept with probability 1 if candidate is better than current.\n", + " Accept with probabilty p_accept(..) if candidate is worse.\n", + " \"\"\"\n", + " candidate_fitness = self.fitness(candidate)\n", + " if candidate_fitness < self.cur_fitness:\n", + " self.cur_fitness, self.cur_solution = candidate_fitness, candidate\n", + " if candidate_fitness < self.best_fitness:\n", + " self.best_fitness, self.best_solution = candidate_fitness, candidate\n", + " else:\n", + " if random.random() < self.p_accept(candidate_fitness):\n", + " self.cur_fitness, self.cur_solution = candidate_fitness, candidate\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Execute simulated annealing algorithm.\n", + " \"\"\"\n", + " # Initialize with the greedy solution.\n", + " self.cur_solution, self.cur_fitness = self.initial_solution()\n", + "\n", + " self.log(\"Starting annealing.\")\n", + " while self.T >= self.stopping_temperature and self.iteration < max_it:\n", + " candidate = list(self.cur_solution)\n", + " l = random.randint(1, self.N - 1)\n", + " i = random.randint(0, self.N - l)\n", + " candidate[i : (i + l)] = reversed(candidate[i : (i + l)])\n", + " self.accept(candidate)\n", + " self.T *= self.alpha\n", + " self.iteration += 1\n", + "\n", + " self.fitness_list.append(self.cur_fitness)\n", + "\n", + " self.log(f\"Best fitness obtained: {self.best_fitness}\")\n", + " improvement = 100 * (self.fitness_list[0] - self.best_fitness) / (self.fitness_list[0])\n", + " self.log(f\"Improvement over greedy heuristic: {improvement : .2f}%\")\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "# Set hyper-parameters\n", + "T = -1\n", + "stopping_T = -1\n", + "alpha = 0.99" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 74.19894280657067\n", + "[MySAModel] Improvement over greedy heuristic: 28.71%\n", + "[*] [Node] 16, [Best] 74.19894280657067\n", + "[*] Running for: 0.02 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MySAModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, T, stopping_T, alpha, max_it=1000)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your Smart Model" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Naive Random Solution\")\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your Model" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[MyModel] Naive Random Solution\n", + "[*] [Node] 16, [Best] 154.5735310725095\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test All Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_results(best_solutions, times, title):\n", + " fig = plt.figure()\n", + " nodes = [len(s) for s in best_solutions]\n", + " data = np.array([[node, time] for node, time in sorted(zip(nodes, times))])\n", + " plt.plot(data[:, 0], data[:, 1], 'o-')\n", + " fig.suptitle(title, fontsize=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_path = './template/data'" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Random Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 721524.9399929157\n", + "[*] Running for: 0.42 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 31159.560032157442\n", + "[*] Running for: 0.26 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] [Node] 1000, [Best] 524396404.5171182\n", + "[*] Running for: 0.87 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 123105.46532911454\n", + "[*] Running for: 0.05 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 103.01947175501947\n", + "[*] Running for: 0.02 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 3084.3745918065306\n", + "[*] Running for: 0.05 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "\n", + "print(\"Random Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Random Model\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "# Set hyper-parameters\n", + "T = -1\n", + "stopping_T = -1\n", + "alpha = 0.8" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Simulated Annealing\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 62562.051863573186\n", + "[MySAModel] Improvement over greedy heuristic: 0.02%\n", + "[*] [Node] 442, [Best] 62562.051863573186\n", + "[*] Running for: 0.09 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 3398.6263568993063\n", + "[MySAModel] Improvement over greedy heuristic: 0.00%\n", + "[*] [Node] 280, [Best] 3398.6263568993063\n", + "[*] Running for: 0.05 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 24551747.27729817\n", + "[MySAModel] Improvement over greedy heuristic: 0.00%\n", + "[*] [Node] 1000, [Best] 24551747.27729817\n", + "[*] Running for: 0.33 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 39264.14564540566\n", + "[MySAModel] Improvement over greedy heuristic: 1.37%\n", + "[*] [Node] 48, [Best] 39264.14564540566\n", + "[*] Running for: 0.01 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 76.04759446489814\n", + "[MySAModel] Improvement over greedy heuristic: 20.61%\n", + "[*] [Node] 16, [Best] 76.04759446489814\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[MySAModel] Starting annealing.\n", + "[MySAModel] Best fitness obtained: 832.1275912241616\n", + "[MySAModel] Improvement over greedy heuristic: 4.06%\n", + "[*] [Node] 70, [Best] 832.1275912241616\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MySAModel()\n", + "\n", + "print(\"Simulated Annealing\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model, T, stopping_T, alpha, max_it=1000)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAEVCAYAAADuAi4fAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAzr0lEQVR4nO3dd3xUVdrA8d9DSEgIvZPQe5U2gFixIFjBsiu2BUEQy+quuxbUfXXVd1fXfdd1FVdRWcSGFczaWAVZK5qE0AUJRUjohFATSHneP+6NDsOETMgkNzN5vp/PfCb33HNnnjt38sy955yZI6qKMcaY6FXL6wCMMcZULkv0xhgT5SzRG2NMlLNEb4wxUc4SvTHGRDlL9MYYE+Us0ZeDiIwXERWR8V7H4k9EHnTjGu51LKESkQ5uzDO9jiUSlPbeE5GNIrLRm6gih4jMdF+/DhV8nIUiEnFj0mt0oheRGBGZJCL/FZEcESkQkR0iskxEXhCRS7yOsSqF65+hKojI826sh0SkkdfxmJ/5fSipiHx+nHodRKS4pG5VxljT1PY6AK+ISAzwPjAKyAU+ALKAOKA3cDXQA0jx22wOsAjYWpWxmqOJSH1gLKBAAnAt8LSnQXnnHK8DOI5C4HQR6a6qa4KsvwEQt16NzUVVoSa/uFfhJPmlwJmqutd/pYjUBYb6l7l1jqpnPHE1UA/4G3ArMIkamuhVdZ3XMRzH+8AYnIR+p/8K90TreiAVSAKSqzq4mqQmN92c4t7PDEzyAKp6SFU/8y8rq51UROqJyBMisllE8kRkiYiMcevUFpH7RGStiOSLyDoRuTXwecvqB3DXLQxlB0VkjIi8IiI/iMhB95YuIreJSK2AugqMcxc3+F16bwyo10RE/iwi37v7uFdE5ovIeaXEUF9E/iYiWe5+rxaRO6jYe28SUAz8Hfg3cJKIDA1W0b85SkRuFJHlbhzbRWS6iDQMsk3J8UwUkcdFZJOIHBaRTBG5W0SklOcaKiJvi8g2ETnivg+eE5GkIHUHiciTIrLUbTbMd98b/ycijUN9IYK10fu/h0TkLLddeb+I7BORD0SkZymP1U1E3hGRPe575WsRubCs9+RxrAS+AcaJSGzAugtxEvzzZezfL0Xkc/d9lucev6kiUqeU+ueKyBdu/DkiMldEepTxHCEft0hVk8/od7v33cL0eLHAJ0AT4D2cJqCrgHfcJHgzzhXCR8Bh4BfAUyKyU1XfCFMMgR7FSYjfAtlAQ+Bs4ElgMHCdX90/4px99XPX57rlJfeISHtgIdAB+AL4GEgELgI+FpEbVfV5v/p1gPnucy0FXgUaAX8AzjyRHRKRAcAg4BNV3SxOZ+7lwGR3P0vzF2AkzgfDf4CzcD4wuuC8JoFigXk4yegjnOaFMTivaTzO6+Uf1wRgOs6xTQE2A11xzmYvFpGTVXWT3yaTgEuB/wKf4nzwDQLuAM4XkaGqur/MF+T4LgJGu/E/C/QCLgAGi0gvVd3lF38P4GugMU4z5jKgE05z5YcViOF5YIYbx9t+5ZOAA8DrwAPBNhSRPwFTgV3Aa27984E/ASNF5DxVPeJX/wrgDeCIe78VOA3nw2ZZKc9R3uMWmVS1Rt6AAThviGLgZeAyoH0Z24zHaRceH1C+0S3/N1DHr/x0tzwH5xK1kd+6Tu7zZ4TyHH7rFVgYUPagWz48oLxzkO1rAS+59YcGrJvplnco5bkXuq/X2IDyRsASIA9o6Vd+r/t47wC1/Mo7uq+J4lxRlee4Petud5W7XBvnH/oA0CBI/ZJ92gS08yuvDXzurhtSyvH8EEjwK2+B88GXC8T6lXdzj2UmkBzwWOcARcCcgPL2QEyQeCe6z313Od57G0upWwicE7Duz+66uwLK57vlNwWUn++Wl/qePM7/ySM4JwJ7gXl+65Pd2J53l7MADXiMYX7HrVXAcfu3u+5ev/J6OCdvBYAv4LGe8NuHDn7lJ3LcFgbGGgm3Gtt0o6oZOJ142937d4CNIrJbROaIyMUn8LC/UdXDfs/xBbAB5yzpblXN9Vu3HvgK6CNOe2XYaZD2W1UtxjljB+cMNyQi0g/nLPwdVZ0d8Ji5OGdl8Thn1yWux/lguMt93pL6G4B/hPrcfjEk4rTP78U500RVC3GuFBKBa46z+UPqd2bmbvcvd3FIKdvcpqp5ftvswLlaawh096t3E84VwO2qmu3/AKo6H+dM8WJxOpFLyn9U1aIgzzkD2Ec5js1xzHaf39909/6nfRaRtjhXNZnAc/6VVfUjnCuOE6KqB3HOxkfIz6O5JgAxHL/ZZoJ7/4iqbvN7vELgdzjvqxv86o/GuZp+TVXTAh7rQYL3rZX7uEWqmtx0g6q+KSJzcC7jT8M5yz8N5xJ9jIjMwjmLCWXoV26wxApswTmDTQ+yLhvnGLRy/w4rEWmK0wl2Ac4VRGJAlfJ0gA1z7xuKyINB1jd373u6z10fp1lkcymvy0JKuWQ/jrFAfeA5Vc33K5+J888/CfhnKdsG/vODc5kOzgdxoL2qmhniNiWvzZkiMjjINi1wEls33PeB22Z9I84+9cL58PA/8QpH52So+9zfvf/G/wPZz5fAuRWI43lgCjBRRB7AuWpZpqrfHWebge79gsAVqvqDiGQBHUWkoTp9bCX1/xuk/l4RWcKxzYXlPm6RqkYnegBVLcBps/0P/DQa4HKcM6tf4Zw5zg3hoUobjVPoPk+w9YXufWBHVYWJM7Y8FedD5jtgFk5zSSFOU8vtQNAOrVI0de9HuLfS1HPvSzo5t5dSb1sp5ccz2b2f6V+oqitEJB0YJCK+IGd04NfX4Kfk9Q92RRWsfmnblLw2d3J89fz+fgOnjX49zlXCNpx2YoDfUL5jU5rcwAJVLXT7kv3jL+tYlVYeElVdLCKLca7wFuE0W/26jM1KYiptKPNWoB3Oe3kvJ/Z+O5HjFpFqfKIP5F5OvykifYH7cS5p51ZhCCVnVMccGynfF4NuwEnyf1TVBwMeZxhOoi+Pkg+q21U1lGaXkvotS1nfqjxPLiIn8XNzwzelDHwB58MgWKKvTCX72lBV95VVWUR8OEn+U+B8tzmiZF0t4K5KibJ0JTGXdqxKKy+P6Tj9K8/i9OW8Ukb9kte0FRDsirB1QL0Teb+V67hFshrbRh+CkhEPpWaUSrLHvW8bZJ2vHI/Txb1/J8i60ka8lLQZBzvDXeTenx7Kk6szYiQTSBaRzkGqDA/lcfyUnM0vBF4s5ZYHXCUiVX0GVq7Xhp+PTYp/kncNwfkSWFVa4t4Pk4Bht67TwvAcrwEHgTbAW/79VaXIcO+HB64QkS7u42zwe5zF7v0x721xhtD2D/Ic5T1uEavGJnoRuUpERgR7Y4tIK5z2XnBGZlSlNJyz+qvF+dJWSUxNcIYIhmqjez/cv9Adnji1lG1Khpy2C1zhNod8AVzmDkk7hoj0FZEWfkX/wnmPPeb/OotIR+C2snfhp/oJOB2tRcA1qnpDsBvOh1o9nGGtVelpnNEeT4jIMcN1RSRORPyTyUb3fnhAvRbAtEqKsVRuJ/VCnA+gGwNiGkXF2udLnmM/zhcUL8W5Ui7LDPf+fhEp6f8paVr9K8776kW/+u/hnCRd7V4x+XuQn5t2/JX3uEWsmtx0MxSn+WKbiHyJMzoGnOaOC3HOqt7j6LG/lU5Vt4rIqzhj3JeIyAdAA5wO1c9xOoxDMQun7fHvInIWsBZnfPBFwLvAlUG2me9u87yIvINzVZOrqiXfOr0ap3PsRRG5DWfcei7O2dVJQB+cDq4dbv3/w+nYvhxYLCLzcNpUf+nuS6i/JXSlu92/VXXLceq9gDOCajJlfBEnnFR1tfvhNwNYKSIfAz/g9L20wzlj3Inzkxrg9J18hfOh+TVOZ2dLnKGMa3A68KvaLW5Mz4jIBfw8jv5ynP+D0fzcrHhCVPXLctT9WkT+gtOMtUJE3sa5Ijgf5332JfC4X/0DIjIZp+/jCxHxH0ffB+f9dkbAc5T3uEUur8d3enXDaRq5BaezdQ1OO+URnDfHhzgJo1bANuMJcSyz37qFlDLullLGreN0xD2OM764ZJzvVJwP5vKMo++FM0RsB84/STpO230HShnDjvOFne9xOgY1cL9wRr3c6z7WAZzmkg04X7KZDCQG1G+A81MF2UA+sBpnhEyn0mIIEtNXbt1LQqi7xq3b/3ivsbtuuLvuwXIcz6Cvtbuur/t8P7qvXw6wAmfI4tkBdZsAz7jPlY/TDv0noG6w5y/Pe6+0un7rj3kPueU9cE4Cct33yzc4Jz2/d7cZE+L/VsnzPxJi/WPG0futG4uT1Pe7r9NK4D4gvpT6I9z6h3DO8N9z9+t474PyHLeFpcVanW/iBm+MMUG5V5hXAz00+I+TmWquxrbRG2N+JiK13L6pwPJzcJrOVlmSj1w1uY3eGPOzOGCziHyG07xWiPNz3SNwmg9v8TA2U0HWdGOMKRnN8nec7420wekr2IXTifmoOj8ZYiKUJXpjjIly1kZvjDFRzhK9McZEOUv0xhgT5SzRG2NMlLNEb4wxUc4SvTHGRLmQEr2IjBKRNSKSKSL3BFk/xZ2dfYmIfCkivdzyDuLM3L7EvT0b7h0wxhhzfGWOo3e/SPEDzjfksnB+ee8qVV3lV6eBuj/cLyKXADer6ih3jsj3VbVPJcVvjDGmDKH8BMIQIFOdyawRkdk4P1n6U6LXo2dnScT5lbgT0qxZM+3QocOJbm6MMTVSenr6LlVtHmxdKIk+mZ8nFAbnrH5oYCURuQXnJ27jcL5GXaKjiGTg/Azw/ar6RZBtJ+POINSuXTvS0qp6JjhjjIlsIvJjaevC1hmrqtNUtTNwNz/PILMVaKeqA3A+BF4TkQZBtp2uqj5V9TVvHvQDyRhjzAkKJdFnc/T8pW3cstLMxplVCFU9rKq73b/TcSZXOGbKLmOMMZUnlESfCnQVkY4iEocz40uKfwUR6eq3eCHOtHWISHO3MxcR6YQzld36cARujDEmNGW20atqoYjcCswDYoAZqrpSRB4C0lQ1BbhVRM7FmWh3DzDO3fwM4CERKcCZb3KKquZUxo4YY4wJrtr9TLHP51PrjDXGmPIRkXRV9QVbZzNMGWOMx+ZmZPP4vDVsyc0jqVECd47szpgByWF7fEv0xhjjobkZ2Ux9dzl5BUUAZOfmMfXd5QBhS/b2WzfGGOOhx+et+SnJl8grKOLxeeGbi90SvTHGeGhLbl65yk+EJXpjjPFIYVExdeNigq5LapQQtuexRG+MMR7Yl1/AhJfSOHikiNq15Kh1CbEx3Dmye9ieyzpjjTGmim3OOcTEl1JZv/Mgj17Wl/jYGBt1Y4wx0SJj0x4mzUrjcGExL00YwqldmgHhG2ETjCV6Y4ypIh8s28odby6hZYN4Zk8eTJcW9arkeS3RG2NMJVNVnlm4jsfnrWFQ+8ZMv24QTevVqbLnt0RvjDGV6EhhMffNWc5b6VmM7p/EY5efRHxs8JE2lcUSvTHGVJLcQ0eY8ko6i9bncPs5XfnNuV0RkbI3DDNL9MYYUwk27jrIhJmpZO3J4+9X9q/UztayWKI3xpgw+25DDpNfTkOAVycNZXCHJp7GY4neGGPCaE5GFne/vZw2TRL41/jBtG+a6HVIluiNMSYcVJUnPvmBfyzIZFinpjx77SAa1o31OizAEr0xxlRYfkERd729jJSlW/ilrw2PjOlLXO3q8wszluiNMaYCdh84zOSX00n/cQ93j+rBlDM7eTKy5ngs0RtjzAnK3LGf62emsmPfYZ65ZiAX9G3tdUhBWaI3xpgT8FXmLqa8kk6d2jG8ceMw+rdt5HVIpQqpEUlERonIGhHJFJF7gqyfIiLLRWSJiHwpIr381k11t1sjIiPDGbwxxnjh9e82MW7GdyQ1TGDuLadU6yQPIZzRi0gMMA0YAWQBqSKSoqqr/Kq9pqrPuvUvAf4GjHIT/ligN5AEfCoi3VT16HmzjDEmAhQXK499vJrnPl/Pmd2a8/TVA6gfXz1G1hxPKGf0Q4BMVV2vqkeA2cBo/wqqus9vMRFQ9+/RwGxVPayqG4BM9/GMMSai5B0p4qZX03nu8/Vcd3J7Xhzni4gkD6G10ScDm/2Ws4ChgZVE5BbgDiAOONtv20UB23r3PWBjjDkBO/blc8OsNJZn7+V/LurF9ad2qHYja44nbAM9VXWaqnYG7gbuL8+2IjJZRNJEJG3nzp3hCskYYyps1ZZ9jJ72FZk7DvD8dT4mnNYxopI8hJbos4G2fstt3LLSzAbGlGdbVZ2uqj5V9TVv3jyEkIwxpvItWL2dXzz7Narw1pRhnNurpdchnZBQEn0q0FVEOopIHE7naop/BRHp6rd4IbDW/TsFGCsidUSkI9AV+K7iYRtjTOWa+dUGbngpjY7NE3nv1lPpndTQ65BOWJlt9KpaKCK3AvOAGGCGqq4UkYeANFVNAW4VkXOBAmAPMM7ddqWIvAmsAgqBW2zEjTGmOissKubh91fx0jc/MqJXS54c25+6cZH9lSNR1bJrVSGfz6dpaWleh2GMqYEOHC7k168t5rM1O5l0ekfuOb8nMbUioz1eRNJV1RdsXWR/TBljTJhk5+YxcWYqa3cc4H8v7cM1Q9t7HVLYWKI3xtR4y7JymfhSGvlHiph5/WBO7xpdg0Is0RtjarSPV2zlN28soVm9Orx2w1C6tqzvdUhhZ4neGFMjqSrPfb6eRz9azYB2jZh+nY/m9et4HValsERvjKlxCoqK+cPcFcxO3cxFJ7Xmr7/oR3xsjNdhVRpL9MaYGmXvoQJufi2drzJ38+uzu/Dbc7tRK0JG1pwoS/TGmBpj0+5DXD/zOzblHOKvv+jHFYPaeB1SlbBEb4ypEdJ/zGHSrHSKVXl54lBO7tTU65CqjCV6Y0zUe29JNne+vYzkRgnMGD+Yjs0SvQ6pSlmiN8ZELVXlH/MzeeLTHxjSsQnPXTuIxolxXodV5SzRG2Oi0uHCIu55ZzlzMrK5fGAb/nRZH+rUjt6RNcdjid4YE3VyDh7hxpfTSN24h9+f141bzuoScb8hH06W6I0xUWXdzgNMmJnK1r35PHXVAC7ul+R1SJ6zRG+MiRpfr9vFlJfTiY2pxeuTTmZQ+8Zeh1QtWKI3xkSFN9M2c++7y+nYLJEZ4wfTtkldr0OqNizRG2MiWnGx8vh/1vDPhes4vWsznr56IA0TYr0Oq1qxRG+MiVj5BUXc8eYSPly+jauHtuOPl/QmNiaUGVJrFkv0xpiItGN/PpNmpbMsK5f7L+zJxNM61uiRNcdjid4YE3HWbNvPhJmp5Bw8wrPXDmJk71Zeh1StWaI3xkSUhWt2cOtrGSTWieGtKcPok9zQ65CqPUv0xpiI8fI3G3kgZSXdWzVgxngfrRsmeB1SRAip10JERonIGhHJFJF7gqy/Q0RWicgyEZkvIu391hWJyBL3lhLO4I0xNUNRsfLQv1fxh/dWclb3Frw9ZZgl+XIo84xeRGKAacAIIAtIFZEUVV3lVy0D8KnqIRG5CfgLcKW7Lk9V+4c3bGNMTXHwcCG3vZ7B/NU7mHBqR+67sCcxUT5RSLiF0nQzBMhU1fUAIjIbGA38lOhV9TO/+ouAa8MZpDGmZtq6N4+JM9NYvW0fD4/uzXXDOngdUkQKpekmGdjst5zllpVmIvCR33K8iKSJyCIRGVP+EI0xNdGK7L2MmfYVm3IOMWP8YEvyFRDWzlgRuRbwAWf6FbdX1WwR6QQsEJHlqrouYLvJwGSAdu3ahTMkY0wE+s/Kbdw+ewlNEuN4+6Yh9GjVwOuQIlooZ/TZQFu/5TZu2VFE5FzgPuASVT1cUq6q2e79emAhMCBwW1Wdrqo+VfU1b968XDtgjIkeqsoLX6znxlfS6dayHnNuOcWSfBiEkuhTga4i0lFE4oCxwFGjZ0RkAPAcTpLf4VfeWETquH83A07Fr23fGGNKFBQVc9/cFTzywfeM6t2K2ZOH0aJ+vNdhRYUym25UtVBEbgXmATHADFVdKSIPAWmqmgI8DtQD3nK/grxJVS8BegLPiUgxzofKowGjdYwxhn35Bdzy6mK+WLuLm4Z35s7zulPLRtaEjaiq1zEcxefzaVpamtdhGGOqyOacQ0yYmcqGXQf506V9+eXgtmVvZI4hIumq6gu2zr4Za4zxzOJNe5g8K40jhcXMmjiEUzo38zqkqGSJ3hjjiX8v3cLv3lpK64bxzJ48mC4t6nkdUtSyRG+MqVKqyrTPMvnrf37A174x03/lo0linNdhRTVL9MaYKnOksJip7y7nncVZjOmfxGNXnESd2jFehxX1LNEbY6rEnoNHmPJKOt9uyOG353bjtnO62EQhVcQSvTGm0m3YdZAJM1PJ3pPHk2P7M7r/8X5FxYSbJXpjTKX6dv1ubnwlnVoivDZpKL4OTbwOqcaxRG+MqTTvpGdxz7vLaNekLjPGD6Z900SvQ6qRLNEbY8KuuFh54tMfeGpBJqd0bso/rxlEw7qxXodVY1miN8aEVX5BEb9/aynvL9vKlb62PHJpH2JjQprMzlQSS/TGmLDZdeAwk2elsXhTLlPP78HkMzrZyJpqwBK9MSYs1m7fz/UzU9l14DDPXjuQUX1aex2ScVmiN8ZU2Bdrd3LzK4uJj4vhjcnD6Ne2kdchGT+W6I0xFfLat5v4w3sr6NqiHi+OH0xyowSvQzIBLNEbY05IUbHy6Eff8/wXGxjevTlPXTWA+vE2sqY6skRvjCm3Q0cKuX32Ej5ZtZ1xw9rzh4t6UdtG1lRbluiNMeWyfV8+E19KZdWWfTx4cS/Gn9rR65BMGSzRG2NCtnLLXibOTGN/fgEvjPNxdo+WXodkQmCJ3hgTkvnfb+fXr2fQMCGWt6acQq+kBl6HZEJkid4Yc1yqyr++2sgjH6yid1JDXhzno0WDeK/DMuVgid4YU6rComIeen8Vs775kfN6teTvY/tTN87SRqQJqZtcREaJyBoRyRSRe4Ksv0NEVonIMhGZLyLt/daNE5G17m1cOIM3xlSe/fkFTHwpjVnf/MiNZ3Ti2WsHWZKPUGUeNRGJAaYBI4AsIFVEUlR1lV+1DMCnqodE5CbgL8CVItIEeADwAQqku9vuCfeOGGPCJ2vPISbOTCNz5wH+fFlfrhrSzuuQTAWEckY/BMhU1fWqegSYDYz2r6Cqn6nqIXdxEdDG/Xsk8Imq5rjJ/RNgVHhCN8ZUhqWbcxkz7Wu27M3jpeuHWJKPAqEk+mRgs99ylltWmonAR+XZVkQmi0iaiKTt3LkzhJCMMZXho+VbuXL6NyTE1eLdm07htK7NvA7JhEFYG9xE5FqcZpozy7Odqk4HpgP4fD4NZ0zGmLKpKs/+dz2Pfbyage0aMf1XPprVq+N1WCZMQkn02UBbv+U2btlRRORc4D7gTFU97Lft8IBtF55IoMaYynGksJg/zF3BG2mbubhfEo9fcRLxsTFeh2XCKJSmm1Sgq4h0FJE4YCyQ4l9BRAYAzwGXqOoOv1XzgPNEpLGINAbOc8uMMdXA3kMFjJvxHW+kbea2s7vw5JX9LclHoTLP6FW1UERuxUnQMcAMVV0pIg8BaaqaAjwO1APecmeT2aSql6hqjog8jPNhAfCQquZUyp4YY8rlx90HuX5mKptzDvG3X/bjsoFtyt7IRCRRrV5N4j6fT9PS0rwOw5iolroxh8mz0lDguWsHMbRTU69DMhUkIumq6gu2zr79YEwNMzcjm7veXkabxgm8OH4wHZsleh2SqWSW6I2pIVSVv3+6lifnr+XkTk149tpBNKob53VYpgpYojemBsgvKOLud5bx3pItXD6wDX++rC9xtW2ikJrCEr0xUW73gcPc+HI6aT/u4c6R3bl5eGfcQROmhrBEb0wUy9xxgAkzU9m+L59pVw/kwpNaex2S8YAlemOi1FeZu7jplXTiatfi9cknM7BdY69DMh6xRG9MFHojdRP3zVlBp+aJvDhuMG2b1PU6JOMhS/TGRJHiYuUv89bw7H/XcXrXZky7ZiAN4mO9Dst4zBK9MVEi70gRv31jCR+v3MY1Q9vxx0t6UzvGRtYYS/TGRIUd+/K5YVYay7P3cv+FPZl4WkcbWWN+YonemAi3ets+JvwrlT2HCph+nY8RvVp6HZKpZizRGxPBPluzg1+/lkFinRjemjKMPskNvQ7JVEOW6I2JULO+2ciDKSvp2boBL44bTKuG8V6HZKopS/TGRJiiYuXh91cx8+uNnNuzBU+OHUBiHftXNqWzd4cxEeTA4UJuez2DBat3MPG0jtx7QU9ialmnqzk+S/TGRIgtuXlMfCmNH7bv5+Exfbju5PZeh2QihCV6YyLA8qy9THwplUNHipgxfjBndmvudUgmgliiN6aam7dyG7+ZvYQmiXG8c9NQureq73VIJsJYojemmlJVnv9iPX/+aDX92jTi+V/5aF6/jtdhmQhkid6YaqigqJj/eW8lr3+3iQv7tub/ftmP+NgYr8MyEcoSvTHVzN68Am55dTFfZu7ilrM687sR3allI2tMBYT0i0ciMkpE1ohIpojcE2T9GSKyWEQKReSKgHVFIrLEvaWEK3BjotHmnENc/s+v+XbDbh6/4iTuHNnDkrypsDLP6EUkBpgGjACygFQRSVHVVX7VNgHjgd8HeYg8Ve1f8VCNiW7pP+5h8qw0CouVWROGMqxzU69DMlEilKabIUCmqq4HEJHZwGjgp0SvqhvddcWVEKMxUS9l6RZ+/9ZSWjeMZ8b4wXRuXs/rkEwUCaXpJhnY7Lec5ZaFKl5E0kRkkYiMCVZBRCa7ddJ27txZjoc2JrKpKk/NX8ttr2fQv00j5tx8qiV5E3ZV0RnbXlWzRaQTsEBElqvqOv8KqjodmA7g8/m0CmIyxnOHC4uY+s5y3s3I5tIByTx6eV/q1LaRNSb8Qkn02UBbv+U2bllIVDXbvV8vIguBAcC6425kTJTbc/AIN76czncbc7hjRDd+fXYXmyjEVJpQmm5Sga4i0lFE4oCxQEijZ0SksYjUcf9uBpyKX9u+MTXR+p0HuPSZr1iSlcuTY/tz2zldLcmbSlXmGb2qForIrcA8IAaYoaorReQhIE1VU0RkMDAHaAxcLCJ/VNXeQE/gObeTthbwaMBoHWNqlG/W7WbKK+nE1BJenzSUQe2beB2SqQFEtXo1ift8Pk1LS/M6DGPC7q20zdw7ZzntmyYyY9xg2jWt63VIJoqISLqq+oKts2/GGlPJiouV//tkDdM+W8epXZryzDWDaJgQ63VYpgaxRG9MJcovKOJ3by7lg+VbGTu4LQ+P6UNsTEhfSDcmbCzRG1NJdu4/zKRZaSzNyuXeC3ow6fRO1ulqPGGJ3phK8MP2/Vz/r1R2HzzMP68ZxKg+rbwOydRgluiNCbP//rCTW19dTHxcDG/eOIyT2jTyOiRTw1miNyaMXln0Iw+krKRri3rMGD+YpEYJXodkjCV6Y8KhqFj504ff8+KXGzire3Oeunog9erYv5epHuydaEwFHTxcyO2zl/Dp99sZf0oH7r+wJ7VtZI2pRizRG1MB2/bmM/GlVL7fuo8/XtKbcad08DokY45hid6YE7Qiey8TX0rlQH4hL44bzFk9WngdkjFBWaI35gR8umo7t83OoFFCLG/fdAo9WzfwOiRjSmWJ3phyUFVe/HID//vh9/RNbsgLv/LRokG812EZc1yW6I0JUWFRMQ/+eyWvLNrEqN6teOLK/iTE2UQhpvqzRG9MCPblF3Draxl8/sNObjyzE3eP7EGtWvZzBiYyWKI3pgybcw4x8aVU1u88yKOX9WXskHZeh2RMuViiN+Y4MjbtYdKsNA4XFvPShCGc2qWZ1yEZU26W6I0pxQfLtnLHm0to0aAOsyefTJcW9b0OyZgTYonemACqyjML1/H4vDUMat+Y6dcNomm9Ol6HZcwJs0RvjJ8jhcXcN2c5b6VncUm/JP5yxUnEx9rIGhPZLNEb48o9dIQpr6SzaH0Ot5/Tld+c29UmCjFRwRK9McDGXQeZMDOVrD15/P3K/owZkOx1SMaETUg/sScio0RkjYhkisg9QdafISKLRaRQRK4IWDdORNa6t3HhCtyYcPluQw5jnvmKPYeO8MoNQy3Jm6hT5hm9iMQA04ARQBaQKiIpqrrKr9omYDzw+4BtmwAPAD5AgXR32z3hCd+YipmTkcXdby+nTeMEZowfTIdmiV6HZEzYhXJGPwTIVNX1qnoEmA2M9q+gqhtVdRlQHLDtSOATVc1xk/snwKgwxG1Mhagqf/vPGn77xlIGtW/MnJtPtSRvolYobfTJwGa/5SxgaIiPH2zbY66LRWQyMBmgXTv71qGpXPkFRdz19jJSlm7hF4Pa8L+X9iWutk0UYqJXteiMVdXpwHQAn8+nHodjotjuA4eZNCuNxZtyuWtUd246s7ONrDFRL5REnw209Vtu45aFIhsYHrDtwhC3NSasMnfs5/qZqezYd5hnrhnIBX1bex2SMVUilOvVVKCriHQUkThgLJAS4uPPA84TkcYi0hg4zy0zpkp9uXYXlz7zNXlHinnjxmGW5E2NUuYZvaoWisitOAk6BpihqitF5CEgTVVTRGQwMAdoDFwsIn9U1d6qmiMiD+N8WAA8pKo5lbQvxgAwNyObx+etYUtuHkmNEji1S1PeWZxNl+b1eHG8jzaN63odojFVSlSrV5O4z+fTtLQ0r8MwEWpuRjZT311OXkHRUeU9WtXnrSnDqB8f61FkxlQuEUlXVV+wdTbUwESVx+etOSbJgzNxiCV5U1NZojdRZUtuXtDyrbn5VRyJMdVHtRheaUxF7diXz3Ofr6e0hsikRglVGo8x1YklehPRtuTm8ex/1zE7dTNFxYqvfSOWZ+/jcOHPX9JOiI3hzpHdPYzSGG9ZojcRaXPOIZ5ZuI630zejClcMasPNw7vQrmndY0bd3Dmyu/1QmanRLNGbiLJx10GmfZbJuxnZxIhw5eC2TDmz81FDJscMSLbEbowfS/QmImTu2M/TCzJJWbqF2Jha/GpYe248ozOtGsZ7HZox1Z4lelOtrd62j6cWZPLh8q3E147hhtM7ccPpHWlR3xK8MaGyRG+qpRXZe/nH/LX8Z9V26tWpzc3DOzPxtE40SYzzOjRjIo4lelOtZGzaw1MLMlmwegcN4mtz+zlduf7UDjSqawnemBNlid5UC99tyOGpBWv5Yu0uGteN5c6R3bluWHsa2LdZjakwS/TGM6rKN+t2848Fa1m0Podm9eKYen4Prj25PYl17K1pTLjYf5OpcqrK52t38Y/5a0n/cQ8t6tfhfy7qxVVD2pEQF+N1eMZEHUv0psqoKvO/38FTC9ayNGsvSQ3jeXh0b37ha0t8rCV4YyqLJXpT6YqLlf+s2sZTCzJZuWUfbZsk8OfL+nL5wDY2V6sxVcASvak0RcXKh8u38vSCTNZs30/HZon89Rf9GN0/idgYS/DGVBVL9CbsCouKSVm6hac/y2T9zoN0bVGPJ8f256KTkoipZRNxG1PVLNGbsDlSWMycjCyeWbiOH3cfoker+jxzzUBG9W5FLUvwxnjGEr2psMOFRbyVlsU/F64jOzePvskNmX7dIM7t2dISvDHVgCV6c8LyC4p4/btNPPff9Wzbl8+Ado145NI+DO/WHBFL8MZUFyElehEZBTwJxAAvqOqjAevrALOAQcBu4EpV3SgiHYDvgTVu1UWqOiVMsRuPHDpSyKuLNvHc5+vZdeAwQzo24a+/6MepXZpagjemGioz0YtIDDANGAFkAakikqKqq/yqTQT2qGoXERkLPAZc6a5bp6r9wxu28cKBw4XM+mYjL3yxgZyDRzi1S1OePnsAJ3dq6nVoxpjjCOWMfgiQqarrAURkNjAa8E/0o4EH3b/fBp4WO7WLGnvzCpj51UZmfLWBvXkFDO/enF+f3ZVB7Rt7HZoxJgShJPpkYLPfchYwtLQ6qlooInuBktO8jiKSAewD7lfVLyoWsqksgVPw3Ty8M9v25TPzq43sP1zIuT1bcts5XTipTSOvQzXGlENld8ZuBdqp6m4RGQTMFZHeqrrPv5KITAYmA7Rr166SQzLBzM3IZuq7y8krKAIgOzeP++auAOCCvq249ayu9Epq4GWIxpgTFMrXE7OBtn7LbdyyoHVEpDbQENitqodVdTeAqqYD64BugU+gqtNV1aeqvubNm5d/L0yF/WXe6p+SvL8W9evwzDWDLMkbE8FCSfSpQFcR6SgiccBYICWgTgowzv37CmCBqqqINHc7cxGRTkBXYH14QjcVpaqsyN7LI++vYktuftA6O/cfruKojDHhVmbTjdvmfiswD2d45QxVXSkiDwFpqpoCvAi8LCKZQA7OhwHAGcBDIlIAFANTVDWnMnbEhG5zziFSlm5hbkY2a3ccIDZGiK9di/zC4mPqJjVK8CBCY0w4iap6HcNRfD6fpqWleR1G1Mk9dIQPlm/lvYwtfLfR+awd3KExYwYkc2Hf1ixcs/OoNnqAhNgY/nxZX8YMSPYqbGNMiEQkXVV9wdbZN2OjWH5BEQtW72BuRjafrdlBQZHSpUU97hzZnUv6JdG2Sd2f6pYkc/9RN3eO7G5J3pgoYIk+yhQXK4s27Oa9jC18uGIr+/MLaV6/DuOGdWDMgGR6JzUo9durYwYkW2I3JgpZoo8S32/dx9wl2aQs2cLWvfkkxsUwqk9rLh2QzLDOTe3ngY2pwSzRR7AtuXk/daqu3raf2rWEM7s1594LenJuz5Y2/6oxBrBEH3H25hXw8YqtzMnI5tsNOajCwHaNeHh0by48KYkmiXFeh2iMqWYs0UeAw4VFfLZ6J+8tyWb+6h0cKSymU7NEfntuN0b3T6J900SvQzTGVGOW6Kup4mIldWMOc5ds4YNlW9iXX0izenFcM7QdY/onc1KbhvaTwMaYkFiir2Z+2L6fuRnZvLdkC9m5eSTExjCqTytG90/itC7NqG2TahtjyskSfTWwfV8+KUu2MCcjm1Vb9xFTSzi9azPuHNmdEb1akljHDpMx5sRZBvHI/vwCPl6xjblLsvl63W5UoV/bRjxwcS8uOimJ5vXreB2iMSZKWKKvQkcKi/n8h53MWZLNp6u2c7iwmPZN6/Lrs7sypn8SnZrX8zpEY0wUskRfyVSVxZv2MCcjm/eXbSX3UAFNEuO4cnBbxgxIZkDbRtapaoypVJboK0nmjgO8tySbuUuy2ZyTR3xsLUb0asWlA5I4vWtzYq1T1RhTRSzRh9GO/fn8e+lW5mZkszx7L7UETu3SjN+c042RfVpRzzpVjTEesMxTQQcPFzJv5TbmZGTzVeYuihX6Jjfk/gt7ckm/JFo0iPc6RGNMDWeJ/gQUFBXz5dpdzMnI5pNV28krKKJN4wRuHt6FMQOS6NKivtchGmPMTyzRh0hVWbI5l7lup+rug0domBDLZQOTuXRAMoPaN7ZOVWNMtWSJ3jU3IzvopBsbdh10v6mazcbdh4irXYsRPVsyZkAyZ3ZrTlxt61Q1xlRvNpUgTpIPnEYvNkZo3TCeTTl5iMCwTk0ZMyCZUX1a0SA+tkrjM8aYsthUgn6Cnbk/9vHqo5I8QEGRsiU3n3sv6MHF/ZJo3dAmyTbGRKaoSfSlNb34m7M4i6lzlpNfUAxAdm4ev31jCaVd0xQVK5PP6FzJkRtjTOUKKdGLyCjgSSAGeEFVHw1YXweYBQwCdgNXqupGd91UYCJQBNymqvPCFr0rsOklOzePu95ZxqL1u2mSGMePuw+xcfdBVm3Zd0xSV0Dc+0BJjews3hgT+cpM9CISA0wDRgBZQKqIpKjqKr9qE4E9qtpFRMYCjwFXikgvYCzQG0gCPhWRbqp6dDtJBT0+b80xTS9HCouZnbqZ2rWEtk3q0r5p3VLP3BVIiI056jESYmO4c2T3cIZpjDGeCGXIyBAgU1XXq+oRYDYwOqDOaOAl9++3gXPEGWs4GpitqodVdQOQ6T5eWG3JzQtaLsDqh0fx2e+HM/P6ISSXcoae3CiBP1/Wl+RGCYjfcmDTjzHGRKJQmm6Sgc1+y1nA0NLqqGqhiOwFmrrliwK2DXv2TGqUQHaQZJ/UKOGoiTruHNn9mNE1JWfuYwYkW2I3xkSlajEIXEQmi0iaiKTt3Lmz3NvfObI7CbExR5UFa3oZMyDZztyNMTVOKGf02UBbv+U2blmwOlkiUhtoiNMpG8q2qOp0YDo44+hDDb5ESaIua9RNSV1L7MaYmiSURJ8KdBWRjjhJeixwdUCdFGAc8A1wBbBAVVVEUoDXRORvOJ2xXYHvwhW8P0vgxhgTXJmJ3m1zvxWYhzO8coaqrhSRh4A0VU0BXgReFpFMIAfnwwC33pvAKqAQuCXcI26MMcYcn/0EgjHGRIHj/QRCteiMNcYYU3ks0RtjTJSzRG+MMVGu2rXRi8hO4McQqzcDdlViONVVTdzvmrjPYPtd01Rkv9uravNgK6pdoi8PEUkrrfMhmtXE/a6J+wy2317HUdUqa7+t6cYYY6KcJXpjjIlykZ7op3sdgEdq4n7XxH0G2++aplL2O6Lb6I0xxpQt0s/ojTHGlCEiE72IjBKRNSKSKSL3eB1POIlIWxH5TERWichKEbndLW8iIp+IyFr3vrFbLiLyD/e1WCYiA73dg4oRkRgRyRCR993ljiLyrbt/b4hInFtex13OdNd38DTwChCRRiLytoisFpHvRWRYtB9vEfmt+/5eISKvi0h8tB5rEZkhIjtEZIVfWbmPr4iMc+uvFZFx5Ykh4hK939SG5wO9gKvcKQujRSHwO1XtBZwM3OLu3z3AfFXtCsx3l8F5Hbq6t8nAP6s+5LC6Hfjeb/kx4AlV7QLswZm2EvymrwSecOtFqieBj1W1B9APZ/+j9niLSDJwG+BT1T44P5ZYMgVpNB7rmcCogLJyHV8RaQI8gDPp0xDggZIPh5CoakTdgGHAPL/lqcBUr+OqxP19D2e+3jVAa7esNbDG/fs54Cq/+j/Vi7QbznwF84GzgfdxZoPcBdQOPPY4v6Y6zP27tltPvN6HE9jnhsCGwNij+Xjz84x0Tdxj9z4wMpqPNdABWHGixxe4CnjOr/yoemXdIu6MnuBTG0blD9G7l6gDgG+Blqq61V21DWjp/h1Nr8ffgbuAYne5KZCrqoXusv++HTV9JVAyfWWk6QjsBP7lNlm9ICKJRPHxVtVs4K/AJmArzrFLJ/qPtb/yHt8KHfdITPQ1gojUA94BfqOq+/zXqfORHlXDpUTkImCHqqZ7HUsVqw0MBP6pqgOAg/x8GQ9E3/F2mxxG43zIJQGJHNu0UWNUxfGNxEQf0vSEkUxEYnGS/Kuq+q5bvF1EWrvrWwM73PJoeT1OBS4RkY3AbJzmmyeBRu70lHD0vv203wHTV0aaLCBLVb91l9/GSfzRfLzPBTao6k5VLQDexTn+0X6s/ZX3+FbouEdiov9pakO3V34szlSGUUFEBGfGru9V9W9+q0qma8S9f8+v/Fdub/3JwF6/S8KIoapTVbWNqnbAOaYLVPUa4DOc6Snh2P0ueT1+mr6yCkMOC1XdBmwWkZKZ7M/BmZEtmo/3JuBkEanrvt9L9jmqj3WA8h7fecB5ItLYvSI6zy0LjdedFCfYsXEB8AOwDrjP63jCvG+n4VzGLQOWuLcLcNok5wNrgU+BJm59wRmFtA5YjjOSwfP9qOBrMBx43/27E848w5nAW0AdtzzeXc5013fyOu4K7G9/IM095nOBxtF+vIE/AquBFcDLQJ1oPdbA6zh9EQU4V3ATT+T4AhPc1yATuL48Mdg3Y40xJspFYtONMcaYcrBEb4wxUc4SvTHGRDlL9MYYE+Us0RtjTJSzRG+MMVHOEr0xxkQ5S/TGGBPl/h/NNgVWVG70JgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Simulated Annealing Model\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conclusions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 5 (ACO, PSO).ipynb b/Workshop - 5 (ACO, PSO).ipynb new file mode 100644 index 0000000..93e92a3 --- /dev/null +++ b/Workshop - 5 (ACO, PSO).ipynb @@ -0,0 +1,1022 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Append template path to sys path\n", + "sys.path.append(os.getcwd() + \"/template\") " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.load_data import load_data\n", + "from utils.load_data import log\n", + "from utils.visualize_tsp import plotTSP\n", + "from utils.tsp import TSP\n", + "from utils.tsp import TSP_Bench\n", + "from utils.tsp import TSP_Bench_ALL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workshop Starts Here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"TSP\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"solutions\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get familiar with your dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are problems at different levels. **3 simple, 2 medium, 1 hard**." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16 = np.array(load_data(\"./template/data/simple/ulysses16.tsp\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[38.24, 20.42],\n", + " [39.57, 26.15],\n", + " [40.56, 25.32],\n", + " [36.26, 23.12],\n", + " [33.48, 10.54],\n", + " [37.56, 12.19],\n", + " [38.42, 13.11],\n", + " [37.52, 20.44],\n", + " [41.23, 9.1 ],\n", + " [41.17, 13.05],\n", + " [36.08, -5.21],\n", + " [38.47, 15.13],\n", + " [38.15, 15.35],\n", + " [37.51, 15.17],\n", + " [35.49, 14.32],\n", + " [39.36, 19.56]])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ulysses16[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(ulysses16[:, 0], ulysses16[:, 1])\n", + "for i in range(0, 16):\n", + " plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: In Order" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]\n" + ] + } + ], + "source": [ + "simple_sequence = list(range(0, 16))\n", + "print(simple_sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([simple_sequence], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: Random Permutation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[11, 9, 14, 2, 15, 10, 0, 5, 3, 4, 7, 1, 12, 13, 6, 8]\n" + ] + } + ], + "source": [ + "random_permutation = np.random.permutation(16).tolist()\n", + "print(random_permutation)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([random_permutation], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Best Solution" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]\n", + "plotTSP([best_ulysses16], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Fitness (Sum of all Distances)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def dist(node_0, node_1, coords):\n", + " \"\"\"\n", + " Euclidean distance between two nodes.\n", + " \"\"\"\n", + " coord_0, coord_1 = coords[node_0], coords[node_1]\n", + " return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 0: [38.24 20.42]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 0:\", ulysses16[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 1: [39.57 26.15]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 1:\", ulysses16[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance Between 5.882329470541408\n" + ] + } + ], + "source": [ + "print(\"Distance Between\", dist(0, 1, ulysses16))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness(solution, coords):\n", + " N = len(coords)\n", + " cur_fit = 0\n", + " for i in range(len(solution)):\n", + " cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)\n", + " return cur_fit" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Order Fitness:\t 104.42225210207233\n", + "Random Fitness:\t 152.17750148686756\n", + "Best Fitness:\t 74.10873595815309\n" + ] + } + ], + "source": [ + "print (\"Order Fitness:\\t\", fitness(simple_sequence, ulysses16))\n", + "print (\"Random Fitness:\\t\", fitness(random_permutation, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Random Model" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyRandomModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " random_solutions = []\n", + " for i in range(0, max_it):\n", + " solution = np.random.permutation(self.N).tolist()\n", + " random_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 114.07985427845105\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, max_it=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Ant Colony Optimization" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "https://github.com/rochakgupta/aco-tsp" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyACOModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " class Edge:\n", + " def __init__(self, a, b, weight, initial_pheromone):\n", + " self.a = a\n", + " self.b = b\n", + " self.weight = weight\n", + " self.pheromone = initial_pheromone\n", + "\n", + " class Ant:\n", + " def __init__(self, alpha, beta, num_nodes, edges):\n", + " self.alpha = alpha\n", + " self.beta = beta\n", + " self.num_nodes = num_nodes\n", + " self.edges = edges\n", + " self.tour = None\n", + " self.distance = 0.0\n", + "\n", + " def _select_node(self):\n", + " roulette_wheel = 0.0\n", + " unvisited_nodes = [node for node in range(self.num_nodes) if node not in self.tour]\n", + " heuristic_total = 0.0\n", + " for unvisited_node in unvisited_nodes:\n", + " heuristic_total += self.edges[self.tour[-1]][unvisited_node].weight\n", + " for unvisited_node in unvisited_nodes:\n", + " roulette_wheel += pow(self.edges[self.tour[-1]][unvisited_node].pheromone, self.alpha) * \\\n", + " pow((heuristic_total / self.edges[self.tour[-1]][unvisited_node].weight), self.beta)\n", + " random_value = random.uniform(0.0, roulette_wheel)\n", + " wheel_position = 0.0\n", + " for unvisited_node in unvisited_nodes:\n", + " wheel_position += pow(self.edges[self.tour[-1]][unvisited_node].pheromone, self.alpha) * \\\n", + " pow((heuristic_total / self.edges[self.tour[-1]][unvisited_node].weight), self.beta)\n", + " if wheel_position >= random_value:\n", + " return unvisited_node\n", + "\n", + " def find_tour(self):\n", + " self.tour = [random.randint(0, self.num_nodes - 1)]\n", + " while len(self.tour) < self.num_nodes:\n", + " self.tour.append(self._select_node())\n", + " return self.tour\n", + "\n", + " def get_distance(self):\n", + " self.distance = 0.0\n", + " for i in range(self.num_nodes):\n", + " self.distance += self.edges[self.tour[i]][self.tour[(i + 1) % self.num_nodes]].weight\n", + " return self.distance\n", + "\n", + " def init(self, nodes, *args):\n", + " super().init(nodes)\n", + " mode, colony_size, elitist_weight, min_scaling_factor, alpha, beta, rho, pheromone_deposit_weight, initial_pheromone, labels = args\n", + "\n", + " self.mode = mode[0]\n", + " self.colony_size = colony_size\n", + " self.elitist_weight = elitist_weight\n", + " self.min_scaling_factor = min_scaling_factor\n", + " self.rho = rho\n", + " self.pheromone_deposit_weight = pheromone_deposit_weight\n", + " self.num_nodes = len(nodes)\n", + " self.nodes = nodes\n", + "\n", + " if labels is not None:\n", + " self.labels = labels\n", + " else:\n", + " self.labels = range(1, self.num_nodes + 1)\n", + " self.edges = [[None] * self.num_nodes for _ in range(self.num_nodes)]\n", + " for i in range(self.num_nodes):\n", + " for j in range(i + 1, self.num_nodes):\n", + " self.edges[i][j] = self.edges[j][i] = self.Edge(i, j, math.sqrt(\n", + " pow(self.nodes[i][0] - self.nodes[j][0], 2.0) + pow(self.nodes[i][1] - self.nodes[j][1], 2.0)),\n", + " initial_pheromone)\n", + " self.ants = [self.Ant(alpha, beta, self.num_nodes, self.edges) for _ in range(self.colony_size)]\n", + " self.global_best_tour = None\n", + " self.global_best_distance = float(\"inf\")\n", + "\n", + " def _add_pheromone(self, tour, distance, weight=1.0):\n", + " pheromone_to_add = self.pheromone_deposit_weight / distance\n", + " for i in range(self.num_nodes):\n", + " self.edges[tour[i]][tour[(i + 1) % self.num_nodes]].pheromone += weight * pheromone_to_add\n", + "\n", + " def _acs(self, max_it):\n", + " for step in range(0, max_it):\n", + "# print('[step]', step)\n", + " for ant in self.ants:\n", + " self._add_pheromone(ant.find_tour(), ant.get_distance())\n", + " if ant.distance < self.global_best_distance:\n", + " self.global_best_tour = ant.tour\n", + " self.global_best_distance = ant.distance\n", + " self.fitness_list.append(ant.distance)\n", + " for i in range(self.num_nodes):\n", + " for j in range(i + 1, self.num_nodes):\n", + " self.edges[i][j].pheromone *= (1.0 - self.rho)\n", + "\n", + " def _elitist(self, max_it):\n", + " for step in range(0, max_it):\n", + "# print('[step]', step)\n", + " for ant in self.ants:\n", + " self._add_pheromone(ant.find_tour(), ant.get_distance())\n", + " if ant.distance < self.global_best_distance:\n", + " self.global_best_tour = ant.tour\n", + " self.global_best_distance = ant.distance\n", + " self.fitness_list.append(ant.distance)\n", + " self._add_pheromone(self.global_best_tour, self.global_best_distance, weight=self.elitist_weight)\n", + " for i in range(self.num_nodes):\n", + " for j in range(i + 1, self.num_nodes):\n", + " self.edges[i][j].pheromone *= (1.0 - self.rho)\n", + "\n", + " def fit(self, max_it=1000):\n", + " \"\"\"\n", + " Execute simulated annealing algorithm.\n", + " \"\"\"\n", + " # Initialize with the greedy solution.\n", + " if self.mode == 'ACS':\n", + " self._acs(max_it)\n", + " elif self.mode == 'Elitist':\n", + " self._elitist(max_it)\n", + " else:\n", + " print(\"Un supported\")\n", + "# print('Sequence : <- {0} ->'.format(' - '.join(str(self.labels[i]) for i in self.global_best_tour)))\n", + "# print('Total distance travelled to complete the tour : {0}\\n'.format(round(self.global_best_distance, 2)))\n", + "\n", + " return self.global_best_tour, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "# Set hypter-parameters\n", + "mode='ACS', \n", + "colony_size=10\n", + "elitist_weight=1.0\n", + "min_scaling_factor=0.001\n", + "alpha=1.0\n", + "beta=3.0\n", + "rho=0.1\n", + "pheromone_deposit_weight=1.0\n", + "initial_pheromone=1.0\n", + "labels = None" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 74.1087359581531\n", + "[*] Running for: 1.61 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyACOModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, mode, colony_size, elitist_weight, min_scaling_factor, alpha, beta, rho, pheromone_deposit_weight, initial_pheromone, labels, max_it=1000, timeout=300)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your Smart Model" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Naive Random Solution\")\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your Model" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_problem = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[MyModel] Naive Random Solution\n", + "[*] [Node] 16, [Best] 149.95613345077442\n", + "[*] Running for: 0.00 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test All Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_results(best_solutions, times, title):\n", + " fig = plt.figure()\n", + " nodes = [len(s) for s in best_solutions]\n", + " data = np.array([[node, time] for node, time in sorted(zip(nodes, times))])\n", + " plt.plot(data[:, 0], data[:, 1], 'o-')\n", + " fig.suptitle(title, fontsize=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_path = './template/data'" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Random Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 726804.3180499345\n", + "[*] Running for: 0.30 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 30377.079411308096\n", + "[*] Running for: 0.18 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] [Node] 1000, [Best] 532033547.526717\n", + "[*] Running for: 0.71 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 114552.11880841342\n", + "[*] Running for: 0.05 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 107.55064433885224\n", + "[*] Running for: 0.04 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 3006.0125566251013\n", + "[*] Running for: 0.06 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "\n", + "print(\"Random Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Random Model\")" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "# Set hypter-parameters\n", + "mode='ACS', \n", + "colony_size=10\n", + "elitist_weight=1.0\n", + "min_scaling_factor=0.001\n", + "alpha=1.0\n", + "beta=3.0\n", + "rho=0.1\n", + "pheromone_deposit_weight=1.0\n", + "initial_pheromone=1.0\n", + "labels = None" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ant Colony Optimization\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 81773.39944759021\n", + "[*] Running for: 437.55 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 3402.3354165651604\n", + "[*] Running for: 122.83 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "[*] Timeout -3\n", + "[*] Running for: 600.01 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "[*] [Node] 48, [Best] 37903.563183654456\n", + "[*] Running for: 1.60 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "[*] [Node] 16, [Best] 74.61480359572822\n", + "[*] Running for: 0.18 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "[*] [Node] 70, [Best] 758.1364540871836\n", + "[*] Running for: 3.71 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyACOModel()\n", + "\n", + "print(\"Ant Colony Optimization\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model, mode, colony_size, elitist_weight, min_scaling_factor, alpha, beta, rho, pheromone_deposit_weight, initial_pheromone, labels, max_it=100, timeout=600)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAEVCAYAAAAb/KWvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAu4UlEQVR4nO3deZwU9Z3/8deHGWC4h3O4GS6BMR7oeB8gCJ4bTNbcBzG6bDyS7GbXjSYmms1m467728Ssxkg0UbNJ1DVGiTEB5PC+QFRkABluBpgZjuGcYa7P74+qwWboYbqZHmq65/18PPrRXd/6Vtenqro//e1v1bfb3B0REcksHaIOQEREUk/JXUQkAym5i4hkICV3EZEMpOQuIpKBlNxFRDKQkrskzcwmm5mb2V1Rx5IpzCw/3KePtPJ63MwWt+Y6kmFmi81M12O3AiX342Rm3w3fKG5m41L83C16wZtZBzO71sz+YGabzazKzA6Y2Uozm21mF6Qy3nRmZtlmdr2ZzTOzMjOrDu/nm9kNZpadwnW1qcR6IpjZI+F250cdS3uTshdue2JmBtwAOGDA3wH/HGlQITMbCDwFXADsA+YDawniHAt8Dvg7M/u6u98XWaBtgJkNBeYAE4FS4M/ANmAgcAVwKXCTmX3c3be0cjglwARgTyuvZwJwsJXXkYwvA12jDiITKbkfn+lAPvAIcDkw08y+4+7VUQZlZl2BvwKnAY8DN7n77kZ1ehJ8EPU68RG2HeG++gvwMeBRgn11sNH8nwMzgefN7NzY+anm7jXAqtZ6/pj1tPo6kuHum6KOIWO5u25J3ghaxg6cD/xX+PgzTdS9K5w/GbgWeIug5bSLIAEPiambH9aNd1ucQFzfDeu+AnRopm7nRtO9gB8Dq4EqYDcwF7g0zrKTw/XcFWfeWOAxgpZoNbA1nB7bkn0T1n8dqAfym9imfwqf758T2Fd3hHVfbWpfEXRbvhrW+26jeYvD8s7AvwHrgUME35LuBDrF1P3KMY7rXY2O/SON1vNIWD4SuAUoCo/PBuA7gIX1PhXuvwNAGXAf0CXONh3xWoo5lse6TY6pfw3wv8CH4boOAEuBbzTej8d4vg2N92MT+/5rwNvA/nA9bwM3xjteDdsF9ANmE3wDOwSsAK6LOmdEcVPLPUlmlgd8HPjQ3V8zs70ESWUW8MQxFr0pXG4O8CJwDvAZ4DQzO93dDwEVwA8IksGI8HGDDQmENyu8/6G71x+rYri+hm3KJUhiBQRvoJ8SvEk+Dcwzsxvd/cHmVm5mZwEvAD0ItrMIGA98EZhhZpe6+9txFk1k3wA8AJxL0A323TjPM4vgDf1Ic7GGzwHwb03tK3evN7MfEXTXzAJ+FKfak8BZBB/4NcAMgg+twrA7x4F3CY7lncDGRvEtTiBWCBoRk4E/AfMI9tePgE5mtgu4G3gGeBmYBtwMZBEkw2PZwJGvswYdgW8BORzZjXM3wQfsmwQf4L2AKcC9BPvhSzF1f0DwYXBaOL8iLK+geb8BPg9sBh4iSN6fIPg2dSHwhTjL5BK8jqsJjkdngg+9X5lZvbs/msB6M0fUny7pdgNuI3ih3R5TtoTgBT8mTv27wvp7gVMazftdOO/TjcoXE6c100xcw8LnqgFyklz2wXDZBwlbgmH5WII+4EPEtJaJ03In6NNfGZZ/odHzfyYsX0VMqyvZfUOQaHYQtMqyG9VviOm3Se6ro1q3jep2Ces5MLTxMSJowfZuFOPr4bwvNXquJr+B0XzLfQNHfsvLDffFAaAcmBAzrzPBB+shYECiMTSx3p80Kh8dp24Hgq4tB85p4nnym1jPUa91gvNCDrwDdI8p70bwXnPg83G2ywk+CLJiyguAWqAomfdEJtx0tUwSYk6k1hN0NTR4hI9OrDblZ+6+vFHZL8P7s1MQ3qDwfqe7VyW6kJl1ImhZ7yf4wPKGee6+BvgZ0IngxNexnE/QSn/d3X8bO8PdnyDoKhpH0OpqLKF9E27XrwlOeM5oVP/vw/tmv2Fw5L6qPFbFcP7OcHJwnCo/9JjzGmGMt4eTX00glkT90N1LYtZTQfBNpyvwgLuvjJl3iOBbZCeCE6hJMbPvE5xreJbgW+lh7r62cX0PvvncG05eluz64mjYb7e5+/6Y9RwAvh1O3hBnuYPAt9y9LmaZIoLW/AQz656C2NKGkntypgCjgfmxbzSCVmY18BUz69jEskvilG0O73unLsSkjSNIEO+5+6448xeG9xObeZ4zGtVP5nmS2TcPELTQGpI5ZtaP4Cv7Snd/qZk4U+3FOGWvAHU0v8+SEW8fbQ3vl8aZ1/D6HJrMSszsCwTdKUsIWsf1jeb3NbO7zex9M9vfcDlwTAxDkllfE84gaEAtjjPvRZret2vcfW+c8rbwPjvh1OeenIY+7UdiC919l5n9CfhbghblU3GWrYhTVhveZ6Ugtm3hfV8zy0mi9d6r0fJNPW9uKz5PRZyyuPvG3deZ2VzgMjMbHbYkZxJ0RSTSagfYHt73NbMux2q9m1kXoG84uTVOldLGBe5ea2Y7gAEJxpOIeJdI1iYwr6nGxlHMbBLwK4LzAld7o6uDwnMzbxOc3H2L4NvrrnBducA3CY5DS/UCdnmcq8+a2bcVTTxfKt9naUMt9wSZWX+Ck0MAv48ZwNTQcvnbcN6suE/Qytx9M7CJ4AP74iQWbUgMA5uYP6hRvdZ+nkQ8wJHdYLMIriB5rMklYnhw+d1mgn01uZnqk8N6mzz+te55jQvCgU/9CM4lpAUzGw/8EagErnT3oz60CLpCRgI/cPdz3P0md7/D3e/i2BcTJGsP0Cfet+B03LdRUXJP3EyCPsylwMNN3MqBS81sZAvXVQdgZsm2NGaH93eY2TGPrZk1tLBWE/RVnha2zBq7JLx/p5l1LwvvJzcxP9HnScRzBB9k15nZdOAk4ElvdE1/Mx4K778Tnks5SrgPvxNOzo5XB5gUp+xCglbiskbl9bTB1mPYcPkz0B3427CfOp4x4f0f4syLtx8gfC2T3HYvI8hN8RopF4fPlYrXUUZTck9cQyvxJne/Id6N8GoT4p/sSUbDCbzhSS73E+A94CLgsXjJ2sy6m9mdhCNqw6++vyW4fPGHjeqOJrh+uYbg0rRjeZXgg+JCM7u20fNcG8b0IUF/dIuE/cCzCb6a/yos/kWST/PfBFf3XAg8FHa/HBZO/zKc/wHBvo3ne2bWO2a5HILxAhCc/I21k+BKnTYjjHcOMAr4e3dfcIzqG8L7yY2eYyIfnURu7Hheyw3H9MfhYLKG9XQluBQTgsaUHIP63BNgZpMJWofL3f2tY1R9mOD66+vM7E53rz1G3WNZQHB97tNm9jzBV+WN7n7MBOvuB83scoI+/y8Af2NmsT8/MAaYCvQkGBDT4DaC5HtLeK36Ij66zr0HcIu7r29m3W5mMwl+7uAJM3uW4NLHcQTdWfuALzc+QdcCDwHfJziBt9zdX09mYXffH+6rOQRXZ1wZ7uvtBF0tVxJ0Jb0L/E3j/ucYK4EVZhZ7nftogpZw4+O1APhseH7mnbD+SxGcBI71DYKxA+uAERb/x+AecfcNBN1etwI/NbNLgDUEl8teDTxNcMlrYwvCZX5pZn8geB1U+DF++sLdf2dmMwhefyvM7BmCk+jXEHQLPdH4iiyJI+prMdPhRtCydeAbCdSdF9b9RDh9F41G+cXUzSf+tc1ZwL8TvOEarrFenES8HQg/HIAtBP3RBwmS7UPA+XGWyQX+g+AN2zCgaj4wPU7dyTQ9QnUcQVLbFsa+jWBE47g4dZPeN43q/DGsc3MLjm1Hgm9lLxB0q9WE9wvC8o5NLLeY+CNU1xEMVuocZ5kBBFdWlRJ0Vxzeh8d4LTxCE9eJN7P/vhLO+0qj8iNeSzHPcazb5Jj6BQQfiGV8NDr1hmMdL4LBUCvD/eMkPkL1JoKrdg6Gt6UEg7OaHKHaxLFqch9m8q1h6LJIWgn7w4sJWtmDPP4lcK25/sXAJHeP218vEjX1uUu6upbgK/pjJzqxi6QD9blLWjGz24A+BJc/HuCjk5ciEkPJXdLNjwn6xYuAW10/GSsSl/rcRUQykPrcRUQykJK7iEgGUnIXEclASu4iIhlIyV1EJAMpuYuIZCAldxGRDKTkLiKSgdrECNV+/fp5fn5+1GGIiKSVpUuX7nD3/vHmtYnknp+fz5Il8f7/V0REmmJmG5uap24ZEZEMpOQuIpKBlNxFRDKQkruISAZSchcRyUAJJXczyzWzp8xslZmtNLPzzKyPmc03szXhfe+wrpnZz8ys2MzeN7MzWncTRETSzzPLSrjg7oWMvO3PXHD3Qp5ZVpLS50+05X4v8Fd3Hw+cRvBP5rcBC9x9LME/xd8W1r0CGBveZgEPpDRiEZE098yyEm5/ejklFZU4UFJRye1PL09pgm82uZtZL+Bi4GEAd6929wpgBvBoWO1R4Jrw8QyCPy12d38DyDWzQSmLWEQkzd0zdxWVNXVHlFXW1HHP3NUpW0cig5hGAuXAr83sNGAp8E0gz923hXW2A3nh4yHA5pjlt4Rl22LKMLNZBC17hg8ffrzxi4ikhZq6et5ev4t5RaWUVFTFrbO1ojJl60skuWcDZwBfd/c3zexePuqCAcDd3cyS+jNWd58NzAYoLCzUH7mKSMY5cKiWlz4sZ15RKQtXlbGnsobO2R3Iye5AVW39UfUH53ZJ2boTSe5bgC3u/mY4/RRBci81s0Huvi3sdikL55cAw2KWHxqWiYhkvLJ9VSxYWcb8olJeKd5BdW09uV07MnXCAKYXDOTik/oxb0Uptz+9/IiumS4ds7j1snEpi6PZ5O7u281ss5mNc/fVwFSgKLzNBO4O758NF5kD3GJmjwPnAHtium9ERDLO2vL9zFtRyvyi7SzbXIE7DOvThS+eM4LpJ+dROKI32VkfneK8ZuIQAO6Zu5qtFZUMzu3CrZeNO1yeCubefI+ImZ0OPAR0AtYB1xGcjH0SGA5sBD7t7rvMzID7gMuBg8B17n7MXwUrLCx0/XCYiKSL+npn2eYK5hVtZ35RKevKDwBwypBeTCvIY1pBHuMH9iBIh63HzJa6e2G8eQn9KqS7vwvEe4Kpceo6cHMyAYqItHVVNXW8tnYH84tKmV9Uxo79h8juYJw7qi9fOT+fSyfkpbTPvKXaxE/+ioi0RRUHq1m4Kug/f/HDcg5W19G9czaTxvVnekEek8cNoFeXjlGHGZeSu4hIjC27DzK/qJR5K0p5a8Mu6uqdAT0684mJQ5hWkMd5o/vSOTsr6jCbpeQuIu2au7Ni694goReVsnLbXgDGDujO1yaNYlrBQE4d0osOHVq3/zzVlNxFpN2pqavnrfW7wv7zUkoqKjGDwhG9+c6V45lWMJCR/bpFHWaLKLmLSLuwv2FA0YrtLFxVxt6qWjpnd+Cisf355tSxTJkwgH7dO0cdZsoouYtIxirbW8ULK8uYV7Sd14p3Ul1XT++uHZl+8kCmFeRx0dh+dO2UmWkwM7dKRNqt4rL9h68/X7apAoDhfbrypfNGML0gjzMbDSjKVEruIpLW6uqddzfvDkeIlrJuRzCg6NShvfinaScx/eSBnJTXvdUHFLU1Su4iknaqaup4tTgYUPTCylJ27K8mu4Nx3ui+XHdBPpcW5DGoV9sZUBQFJXcRSQu7D3w0oOilNR8NKJo8rj/TTx7I5HH96ZnTNgcURUHJXUTarM27DjKvKPhBrrc37Kau3snr2ZlPnjGEaQUDOXdUn7QYUBQFJXcRaTMaBhTNKypl3ortrNq+D4CT8rpz46TRTCvI45Q0HFAUBSV3EYlUw4CieSuCK1y27qmig0HhiD5898oJTCvIIz/NBxRFQcldRE64/YdqeXF1OfOKtrMoHFCU0zEYUPQP005i6vgB9M2gAUVRUHIXkROibG8V81cGP8j1+tpgQFGfbp247PCAov506aT+81RRcheRVuHurC3fz9zw+vN3N1cAMKJvV7583gimnzyQM0f0Jkv9561CyV1EUqau3lm2aXd4hUsp68MBRacN7cU/Tz+JaQXtc0BRFJTcRaRFqmrqeGXNDuYVbWfByjJ2HqimY5Zx3uh+fPXCkUybkMfAXjlRh9nuKLmLSNJ2H6hmwaoy5hdt56UPd1BZU0ePztlMHj+A6QV5TNKAosgpuYtIQhoGFM1bsZ23N+yi3mFgzxyuPXMo0wryOHdUXzplZ/4PcqULJXcRicvd+aBkL/OLtjOvqPTwgKLxA3tw8yVjDg8oUv9526TkLiKHVdfW8+b6nYf/oWhbw4Ci/D7ccdUEphcMZHjfrlGHKQlQchdp5/ZV1fDih+XMW1HKotVl7AsHFF08tj/fmnYSUyfk0adbp6jDlCQpuYu0Q6V7qw7/IfTra3dQU+f06daJKz42kGkFA7lwTD8NKEpzCSV3M9sA7APqgFp3LzSzPsATQD6wAfi0u++2oAPuXuBK4CDwFXd/J/Whi0ii3J01ZfsPJ/T3wgFF+X27ct0FI5lWkMcZwzWgKJMk03K/xN13xEzfBixw97vN7LZw+tvAFcDY8HYO8EB4LyInUF29886m3Yd/kGvDzoMAnDYsl1svG8f0gjzGDNCAokzVkm6ZGcDk8PGjwGKC5D4DeMzdHXjDzHLNbJC7b2tJoCLSvKqaOl5es4P5jQYUnT+6HzdcNIppBXnk9dSAovYg0eTuwDwzc+BBd58N5MUk7O1AXvh4CLA5ZtktYdkRyd3MZgGzAIYPH3580YsIuw5Us2Bl6eF/KKqqqadHTjZTxg9gWkEek07qTw8NKGp3Ek3uF7p7iZkNAOab2arYme7uYeJPWPgBMRugsLAwqWVF2ruNOw8c7j9fEg4oGtQrh08XDmN6wUDOHtlHA4rauYSSu7uXhPdlZvZH4GygtKG7xcwGAWVh9RJgWMziQ8MyETlO7s7ykj1BQl9RyurSjwYU3XLJGKYVDORjQ3qq/1wOaza5m1k3oIO77wsfTwf+FZgDzATuDu+fDReZA9xiZo8TnEjdo/52keRV19bzxrqPBhRt3xsMKDorvw/fu7qAaRPyNKBImpRIyz0P+GPYIsgGfufufzWzt4Enzex6YCPw6bD+8wSXQRYTXAp5XcqjFslQe6tqWLy6nPlFpSxeVca+Q7V06ZjFxSf149aCcUwZP4DeGlAkCWg2ubv7OuC0OOU7galxyh24OSXRibQD2/c0/EPRdt5Yt5OaOqdvt05cecogphXkceHYfuR01IAiSY5GqIqcYO7Oh6X7mV8UXH/+3pY9AIzs142vhgOKJmpAkbSQkrvICVBX7yzdGA4oWlnKxnBA0enDcvmXy4MBRaP7a0CRpI6Su0grqayu4+U15cwrKmXhqjJ2HaimU1YHzh/Tl1kXj+LSCRpQJK1HyV0khXbuPxT+Q1EpLzcaUDS9YCCTxvWne2e97aT16VUm0kIbdhw4fLniko3BgKLBvXL4TOEwpp8cDCjqmKUBRXJiKbmLJKm+PhhQNC88Ifph6X4AJgzqyS1TxjK9II+TB2tAkURLyV0kAdW19by+bufhK1xK9x4iq4NxVn5vvn91AdMK8hjWRwOKpO1Qchdpwt6qGhaF/ecvri4/PKBo0kn9mX5yHpeM04AiabuU3EVibNtTyQvhD3I1DCjq170TV50aDCi6YIwGFEl6UHKXds3dWV26j/krgoS+vCQYUDSqXze+euFIphfkcfowDSiS9KPkLu1ObV09SzbuPnyFy6ZdwYCiicMbBhQNZMyA7hFHKdIySu7SLlRW1/HSmnLmrShl4apSdh+soVNWBy4Y05evTRrNpRMGMEADiiSDKLlLRnhmWQn3zF3N1opKBud24dbLxnHR2H4sWFnGvHBA0aHaenrmZDN1Qh7TCvK4+CQNKJLMpVe2pL1nlpVw+9PLqaypA6CkopJvPfku9eH/ew3J7cLnzh7O9II8ztKAImknlNwl7d0zd/XhxN6g3qFHTjaPzzqXgkEaUCTtj5K7pL2tFZVxy/dX1XLy4F4nOBqRtkHfTyXtDc7tklS5SHug5C5p74aLRh5V1qVjFrdeNi6CaETaBiV3SXsbdx7EgLyenTGCE6g//uQpXDNxSNShiURGfe6S1sr3HeL3b23iU4VD+c9rj/qrX5F2Sy13SWsPvbKOmrp6bpw8JupQRNoUJXdJWxUHq/nf1zdy9amDGdmvW9ThiLQpSu6Stn796gYOVNdx8yVqtYs0puQuaWlfVQ2/fnU9l52cx7iBPaIOR6TNSTi5m1mWmS0zs+fC6ZFm9qaZFZvZE2bWKSzvHE4Xh/PzWyl2acd+88ZG9lbVcsslY6MORaRNSqbl/k1gZcz0fwA/cfcxwG7g+rD8emB3WP6TsJ5IylRW1/Hwy+uZdFJ/ThmqEagi8SSU3M1sKHAV8FA4bcAU4KmwyqPANeHjGeE04fypph/2kBT6/Vub2Hmgmq9PUV+7SFMSbbn/FPgXoD6c7gtUuHttOL0FaBgxMgTYDBDO3xPWP4KZzTKzJWa2pLy8/Piil3bnUG0dD760lnNH9aEwv0/U4Yi0Wc0mdzO7Gihz96WpXLG7z3b3Qncv7N+/fyqfWjLYU0u3ULr3kPraRZqRyAjVC4CPm9mVQA7QE7gXyDWz7LB1PhQoCeuXAMOALWaWDfQCdqY8cml3aurqeWDxWk4flssFY476MigiMZptubv77e4+1N3zgc8CC939C8Ai4Nqw2kzg2fDxnHCacP5Cd/eURi3t0px3t7JldyVfnzJGv88u0oyWXOf+beBbZlZM0Kf+cFj+MNA3LP8WcFvLQhSBunrn/sXFTBjUkynjB0Qdjkibl9QPh7n7YmBx+HgdcHacOlXAp1IQm8hhf/1gO+vKD3D/589Qq10kARqhKm2eu/M/C9cwun83Lv/YwKjDEUkLSu7S5i1YWcaq7fu4afIYsjqo1S6SCCV3adPcnfsWFTOsTxc+fvrgqMMRSRtK7tKmvVq8k3c3V3DjpDF0zNLLVSRRerdIm/Y/C9cwsGcOf3um/jJPJBlK7tJmvb1hF2+u38Wsi0fROTsr6nBE0oqSu7RZ9y0spm+3Tnzu7OFRhyKSdpTcpU16f0sFL35YzvUXjaRLJ7XaRZKl5C5t0n0Li+mZk82Xzh0RdSgiaUnJXdqc1dv3Ma+olOsuGEmPnI5RhyOSlpTcpc25f1Ex3Tplcd0F+VGHIpK2lNylTVm/4wDPvb+VL543gtyunaIORyRtKblLm/LA4mI6ZnXghgtHRR2KSFpTcpc2Y8vugzz9TgmfO3s4/Xt0jjockbSm5C5txoMvrsMMZl2sVrtISym5S5tQtreKJ5Zs5tozhzI4t0vU4YikPSV3aRN++fI6auvq+dqk0VGHIpIRlNwlcrsOVPO/b2xixulDGNG3W9ThiGQEJXeJ3K9fXU9VbR03TVarXSRVlNwlUnsqa3jk1Q1cfvJAxub1iDockYyh5C6R+s3rG9h3qJabLxkTdSgiGUXJXSJzsLqWh19Zz5TxA/jYkF5RhyOSUZTcJTK/e3MTuw/WqNUu0gqU3CUSVTV1PPjSOs4f3ZczR/SOOhyRjNNscjezHDN7y8zeM7MVZvaDsHykmb1pZsVm9oSZdQrLO4fTxeH8/FbeBklD/7d0C+X7DnHLFLXaRVpDIi33Q8AUdz8NOB243MzOBf4D+Im7jwF2A9eH9a8HdoflPwnriRxWU1fPLxav5cwRvTlvVN+owxHJSM0mdw/sDyc7hjcHpgBPheWPAteEj2eE04Tzp5qZpSpgSX9/XFZCSUUlt1wyBr00RFpHQn3uZpZlZu8CZcB8YC1Q4e61YZUtwJDw8RBgM0A4fw9wVPPMzGaZ2RIzW1JeXt6ijZD0UVfvPLB4LScP7snkcf2jDkckYyWU3N29zt1PB4YCZwPjW7pid5/t7oXuXti/v97k7cWfl29j/Y4DfH2KWu0irSmpq2XcvQJYBJwH5JpZdjhrKFASPi4BhgGE83sBO1MRrKS3+nrn/oXFjB3QnekFA6MORySjJXK1TH8zyw0fdwGmASsJkvy1YbWZwLPh4znhNOH8he7uKYxZ0tT8laWsLt3HzZeMoUMHtdpFWlN281UYBDxqZlkEHwZPuvtzZlYEPG5m/wYsAx4O6z8M/MbMioFdwGdbIW5JM+7O/YuKGdG3K1efOijqcEQyXrPJ3d3fBybGKV9H0P/euLwK+FRKopOM8dKaHby/ZQ93f/IUsrM0dk6kteldJifEfQvXMKhXDp88Y2jUoYi0C0ru0ureXLeTtzfs5muTRtMpWy85kRNB7zRpdfctKqZf98585qxhUYci0m4ouUurendzBS+v2cHfXTSSnI5ZUYcj0m4ouUurum9hMbldO/KFc0dEHYpIu6LkLq2maOteXlhZynXnj6R750SuuhWRVFFyl1Zz/+JiunfO5ivn50cdiki7o+QurWJt+X6eX76NL583gl5dO0Ydjki7o+QureLni9bSObsD1184MupQRNolJXdJuc27DvLMuyV8/uwR9O3eOepwRNolJXdJuQdeXEuWGbMuHhV1KCLtlpK7pNT2PVU8tWQL1xYOZWCvnKjDEWm3lNwlpWa/tI46d26cNDrqUETaNSV3SZkd+w/xu7c2cs3pQxjWp2vU4Yi0a0rukjK/emU9h2rruekStdpFoqbkLimx52ANj72+kStPGcTo/t2jDkek3VNyl5R45LUN7D9Uyy2XjIk6FBFByV1SYP+hWn792nounZDHhEE9ow5HRFBylxT47RsbqThYwy1T1GoXaSuU3KVFqmrq+OXL67lobD9OH5YbdTgiElJylxZ54u3N7Nh/SH3tIm2Mkrsct+raen7x4lrOyu/NOaP6Rh2OiMRQcpfj9vQ7W9i2p4pbpoyNOhQRaUTJXY5LbV09D7y4llOH9uLisf2iDkdEGmk2uZvZMDNbZGZFZrbCzL4Zlvcxs/lmtia87x2Wm5n9zMyKzex9MzujtTdCTrzn3t/Gxp0HufmSMZhZ1OGISCOJtNxrgX9y9wLgXOBmMysAbgMWuPtYYEE4DXAFMDa8zQIeSHnUEqn6eue+RcWMy+vBtAl5UYcjInE0m9zdfZu7vxM+3gesBIYAM4BHw2qPAteEj2cAj3ngDSDXzAalOnCJztwV2yku28/NU8bQoYNa7SJtUVJ97maWD0wE3gTy3H1bOGs70NCEGwJsjllsS1jW+LlmmdkSM1tSXl6ebNwSEfeg1T6yXzeuOkWf2SJtVcLJ3cy6A38A/sHd98bOc3cHPJkVu/tsdy9098L+/fsns6hEaPHqclZs3cuNk0eTpVa7SJuVUHI3s44Eif237v50WFza0N0S3peF5SXAsJjFh4Zlkubcnf9ZuIYhuV34xMSjvoyJSBuSyNUyBjwMrHT3/46ZNQeYGT6eCTwbU/7l8KqZc4E9Md03ksZeX7eTdzZV8LVJo+iYpatoRdqy7ATqXAB8CVhuZu+GZd8B7gaeNLPrgY3Ap8N5zwNXAsXAQeC6VAYs0blvYTH9e3TmU4XDmq8sIpFqNrm7+ytAU52rU+PUd+DmFsYlbczSjbt5be1O7rhqAjkds6IOR0Saoe/WkpD7FxXTu2tHPn/O8KhDEZEEKLlLsz4o2cPCVWVcf+FIunZKpCdPRKKm5C7Nun9RMT1ysvny+flRhyIiCVJyl2NaU7qPv67Yzszz8umZ0zHqcEQkQUruckw/X7yWnOwsvnrhyKhDEZEkKLlLkzbuPMCz75bwxXOH06dbp6jDEZEkKLlLk37x4lqyszrwdxeNijoUEUmSkrvEtbWikqeWbuEzhcMY0DMn6nBEJElK7hLX7JfW4Q5/P0mtdpF0pOQuRynfd4jfv7WJT0wcwtDeXaMOR0SOg5K7HOWhV9ZRU1fPjZNHRx2KiBwnJXc5wu4D1fzv6xu5+tTBjOrfPepwROQ4KbnLEX792gYOVNdx8yVjog5FRFpAyV0O21dVwyOvrmd6QR7jBvaIOhwRaQEldznsN29sZG9VLbdMUatdJN0puQsAldV1PPzyeiad1J9Th+ZGHY6ItJB+v7Wde2ZZCffMXU1JRSUApw3rFXFEIpIKarm3Y88sK+H2p5cfTuwAv3xpPc8s0/+Zi6Q7Jfd27J65q6msqTuirLKmjnvmro4oIhFJFSX3dmxrTIs9kXIRSR9K7u3UgpWldOgQ/3/PB+d2OcHRiEiq6YRqO7N510F+8KcVvLCyjLwendldWUN1bf3h+V06ZnHrZeMijFBEUkHJvZ04VFvH7BfXcd+iYrI6GLdfMZ6vXjiSP7+/jXvmrmZrRSWDc7tw62XjuGbikKjDFZEWUnJvB178sJw7n/2ADTsPctUpg7jj6gkM6hV0vVwzcYiSuUgGaja5m9mvgKuBMnf/WFjWB3gCyAc2AJ92991mZsC9wJXAQeAr7v5O64QuzdlaUckPnyviLx9sZ1S/bjz21bO5+KT+UYclIidAIidUHwEub1R2G7DA3ccCC8JpgCuAseFtFvBAasKUZFTX1vPA4rVM/X8vsmh1GbdeNo6//MNFSuwi7UizLXd3f8nM8hsVzwAmh48fBRYD3w7LH3N3B94ws1wzG+Tu21IWsRzTa2t38P1nV1Bctp/pBXl87+oChvXRH26ItDfH2+eeF5OwtwN54eMhwOaYelvCsqOSu5nNImjdM3z48OMMQxqU7q3iR39eyZz3tjK8T1d+9ZVCpozPa35BEclILT6h6u5uZn4cy80GZgMUFhYmvbwEaurqefS1Dfz0hTVU19XzzaljuXHyaHI6ZkUdmohE6HiTe2lDd4uZDQLKwvISYFhMvaFhmbSCt9bv4vvPfsCq7fuYPK4/P/j4yYzo2y3qsESkDTje5D4HmAncHd4/G1N+i5k9DpwD7FF/e+qV7zvEj/+ykqffKWFIbhce/NKZTC/II7hYSUQksUshf09w8rSfmW0B7iRI6k+a2fXARuDTYfXnCS6DLCa4FPK6Voi53aqrd3775kbumbuaqpo6br5kNDdfMoaunTRcQUSOlMjVMp9rYtbUOHUduLmlQcnR3tm0m+898wErtu7lwjH9+MGMkxmtP7AWkSaoydfG7TpQzX/+dRWPv72ZvJ6due/zE7nqlEHqghGRY1Jyb6Pq653H397Mf85dxf6qWmZdPIpvTB1L9846ZCLSPGWKNmj5lj3c8ewHvLe5gnNG9uGH13yMk/J6RB2WiKQRJfc2ZM/BGu6Zt4rfvrmJvt0689PPnM6M0werC0ZEkqbk3gbU1zt/eGcLd/9lFbsPVjPzvHy+Nf0keuZ0jDo0EUlTSu4RK9q6l+8/+wFLNu7mzBG9+c2McygY3DPqsEQkzSm5R2RvVQ0/mf8hj72+kV5dOvKf157KtWcMbfKv70REkqHkfoK5O8++u5UfPb+SHfsP8YVzhvPP08eR27VT1KGJSAZRcj+B1pTu43vPfsAb63Zx2tBePDyzkFOH5kYdlohkICX3E+DAoVp+tmAND7+ynm6ds/n3T5zCZ84aRpa6YESklSi5tyJ35/nl2/nhc0Vs31vFZwqH8e0rxtOnm7pgRKR1Kbm3krXl+7lrzgpeXrODkwf35OdfPIMzhveOOiwRaSeU3FOssrqO+xatYfZL68jpmMUPPn4yXzx3hLpgROSEUnJPEXdnXlEp//qnIkoqKvnkxCHcfuUE+vfoHHVoItIOKbmnwMadB7hrzgoWrS5nXF4Pnph1LueM6ht1WCLSjim5t0BVTR2/eHEtP1+8lo4djDuumsDM8/PpmNUh6tBEpJ1Tcj9Oi1aVceecFWzadZC/OW0wd1w1gbyeOVGHJSICKLknbcvug/zrn4qYV1TK6P7d+O0N53DBmH5RhyUicgQl9wQdqq3joZfX8z8L12AY3758PNdfOJJO2eqCEZG2R8k9Aa+s2cH3n/2AdTsOcMXHBnLH1QUMye0SdVgiIk1Scj+GbXsq+bfnVvLn5dvI79uVR647i8njBkQdlohIs5Tc46ipq+fXr67npy+soa7e+da0k5h18ShyOmZFHZqISEKU3Bt5Y91OvvfMB6wp28+lEwZw59+czLA+XaMOS0QkKRmf3J9ZVsI9c1eztaKSwblduPWycVwzcchR8/J65jAkN4elmyoY2rsLD325kEsL8iKOXkTk+LRKcjezy4F7gSzgIXe/O9XrOFbSjq1z+9PLqaypA6CkopLbn15+eH7svO17q9i+t4rLCgbw08+eQZdO6oIRkfSV8uRuZlnA/cA0YAvwtpnNcfeiVK2jqaTt7lxxyiAOHKrlYHUd//78ysN1GlTW1HH708upq3eq6+qPeu4Ptu5TYheRtNcaLfezgWJ3XwdgZo8DM4CUJfd75q6Om7T/8cn3+Mcn32t2+cbLxtpaUdni+EREotYayX0IsDlmegtwTuNKZjYLmAUwfPjwpFZwrAT87cvH061zFl07ZfPvfy5i18GaowMMr1EvifM8g3X9uohkgMhOqLr7bGA2QGFhoSez7ODcLnET85DcLtw4efTh6ewOdkT3DUCXjlncetk4gGPOExFJZ60xdr4EGBYzPTQsS5lbLxtHl0bXnMdLzNdMHMKPP3kKQ3K7YATJ/8efPIVrJg455jwRkXRn7kk1mpt/QrNs4ENgKkFSfxv4vLuvaGqZwsJCX7JkSVLrSeRqGRGRTGZmS929MN68lHfLuHutmd0CzCW4FPJXx0rsx6uh9S0iIkdrlT53d38eeL41nltERJqn36sVEclASu4iIhlIyV1EJAMpuYuIZKCUXwp5XEGYlQMbE6jaD9jRyuG0Rdru9kXb3b60ZLtHuHv/eDPaRHJPlJktaeqazkym7W5ftN3tS2ttt7plREQykJK7iEgGSrfkPjvqACKi7W5ftN3tS6tsd1r1uYuISGLSreUuIiIJSJvkbmaXm9lqMys2s9uijieVzGyYmS0ysyIzW2Fm3wzL+5jZfDNbE973DsvNzH4W7ov3zeyMaLfg+JlZlpktM7PnwumRZvZmuG1PmFmnsLxzOF0czs+PNPAWMLNcM3vKzFaZ2UozO6+dHOt/DF/fH5jZ780sJxOPt5n9yszKzOyDmLKkj6+ZzQzrrzGzmcnGkRbJPeZ/Wa8ACoDPmVlBtFGlVC3wT+5eAJwL3Bxu323AAncfCywIpyHYD2PD2yzggRMfcsp8E1gZM/0fwE/cfQywG7g+LL8e2B2W/ySsl67uBf7q7uOB0wi2P6OPtZkNAb4BFLr7xwh+MfazZObxfgS4vFFZUsfXzPoAdxL8i93ZwJ0NHwgJc/c2fwPOA+bGTN8O3B51XK24vc8S/MH4amBQWDYIWB0+fhD4XEz9w/XS6UbwRy4LgCnAc4ARDObIbnzcCX5C+rzwcXZYz6LehuPY5l7A+saxt4Nj3fD3m33C4/cccFmmHm8gH/jgeI8v8DngwZjyI+olckuLljvx/5c1I3/MPfz6ORF4E8hz923hrO1AXvg4U/bHT4F/AerD6b5AhbvXhtOx23V4m8P5e8L66WYkUA78OuyOesjMupHhx9rdS4D/AjYB2wiO31Iy/3g3SPb4tvi4p0tybxfMrDvwB+Af3H1v7DwPPr4z5tImM7saKHP3pVHHcoJlA2cAD7j7ROAAH31FBzLvWAOEXQozCD7cBgPdOLrrol04Ucc3XZJ7q/8va9TMrCNBYv+tuz8dFpea2aBw/iCgLCzPhP1xAfBxM9sAPE7QNXMvkBv+VSMcuV2Htzmc3wvYeSIDTpEtwBZ3fzOcfoog2WfysQa4FFjv7uXuXgM8TfAayPTj3SDZ49vi454uyf1tYGx4Zr0TwYmYORHHlDJmZsDDwEp3/++YWXOAhrPkMwn64hvKvxyeaT8X2BPzlS8tuPvt7j7U3fMJjudCd/8CsAi4NqzWeJsb9sW1Yf20a926+3Zgs5k1/Jv7VKCIDD7WoU3AuWbWNXy9N2x3Rh/vGMke37nAdDPrHX7rmR6WJS7qEw9JnKC4kuCPt9cC3406nhRv24UEX9PeB94Nb1cS9DEuANYALwB9wvpGcPXQWmA5wRUIkW9HC7Z/MvBc+HgU8BZQDPwf0Dkszwmni8P5o6KOuwXbezqwJDzezwC928OxBn4ArAI+AH4DdM7E4w38nuC8Qg3BN7Xrj+f4Al8Nt78YuC7ZODRCVUQkA6VLt4yIiCRByV1EJAMpuYuIZCAldxGRDKTkLiKSgZTcRUQykJK7iEgGUnIXEclA/x+1Y8XFA60PtQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Ant Colony Optimization\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 5 (PSO, ACO).ipynb b/Workshop - 5 (PSO, ACO).ipynb new file mode 100644 index 0000000..e34325f --- /dev/null +++ b/Workshop - 5 (PSO, ACO).ipynb @@ -0,0 +1,2278 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Append template path to sys path\n", + "sys.path.append(os.getcwd() + \"/template\") " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.load_data import load_data\n", + "from utils.load_data import log\n", + "from utils.visualize_tsp import plotTSP\n", + "from utils.tsp import TSP" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workshop Starts Here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"TSP\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"solutions\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get familiar with your dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are problems at different levels. **3 simple, 2 medium, 1 hard**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16 = np.array(load_data(\"./template/data/simple/ulysses16.tsp\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16[:]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "plt.scatter(ulysses16[:, 0], ulysses16[:, 1])\n", + "for i in range(0, 16):\n", + " plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: In Order" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "simple_sequence = list(range(0, 16))\n", + "print(simple_sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plotTSP([simple_sequence], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: Random Permutation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "random_permutation = np.random.permutation(16).tolist()\n", + "print(random_permutation)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plotTSP([random_permutation], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Best Solution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]\n", + "plotTSP([best_ulysses16], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Fitness (Sum of all Distances)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def dist(node_0, node_1, coords):\n", + " \"\"\"\n", + " Euclidean distance between two nodes.\n", + " \"\"\"\n", + " coord_0, coord_1 = coords[node_0], coords[node_1]\n", + " return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Coordinate of City 0:\", ulysses16[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"Coordinate of City 1:\", ulysses16[1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(\"Distance Between\", dist(0, 1, ulysses16))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness(solution, coords):\n", + " N = len(coords)\n", + " cur_fit = 0\n", + " for i in range(len(solution)):\n", + " cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)\n", + " return cur_fit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print (\"Order Fitness:\\t\", fitness(simple_sequence, ulysses16))\n", + "print (\"Random Fitness:\\t\", fitness(random_permutation, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Random Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, coords):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(coords)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it=1000, visualize=False):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Naive Random Solution\")\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "tsp_problem = './template/data/simple/ulysses16.tsp'\n", + "tsp_coords = np.array(load_data(tsp_problem))\n", + "\n", + "import timeit\n", + "start = timeit.default_timer()\n", + "\n", + "# Your Model Running\n", + "\n", + "model = MyModel()\n", + "best_solution, fitness_list = TSP(tsp_problem, model)\n", + "\n", + "# Your Model End\n", + "\n", + "stop = timeit.default_timer()\n", + "print()\n", + "print('[*] Running for: {time:.1f} seconds'.format(time=(stop - start)))\n", + "\n", + "print()\n", + "print (\"Best Fitness:\\t\", fitness(best_solution, tsp_coords))\n", + "print (\"Best Solution:\\t\", best_solution)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Minimum Spanning Tree (Depth First)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, coords):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(coords)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it=1000, visualize=False):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Uniform Cost Search Solution\")\n", + "\n", + " UCS_solutions = []\n", + " UCS_losses = []\n", + " # Depth First: Set one city as starting point, iterate to the end, then select next city as starting point.\n", + " for i in range(0, self.N):\n", + " solution = []\n", + " solution.append(i)\n", + " unvisited_list = list(range(0, self.N))\n", + " cur_city = i\n", + " print(\"[starting]\", i)\n", + " for steps in range(self.N - 1):\n", + " # print(unvisited_list)\n", + " unvisited_list.remove(cur_city)\n", + " closest_neighbour = -1\n", + " shortest_distance = math.inf\n", + " for j in unvisited_list:\n", + " if(self.dist(cur_city, j) < shortest_distance):\n", + " closest_neighbour = j\n", + " shortest_distance = self.dist(cur_city, j)\n", + " solution.append(closest_neighbour)\n", + " cur_city = closest_neighbour\n", + " UCS_solutions.append(solution)\n", + " UCS_losses.append(self.fitness(solution))\n", + "\n", + " self.best_solution = UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[MyModel] Uniform Cost Search Solution\n", + "[starting] 0\n", + "[starting] 1\n", + "[starting] 2\n", + "[starting] 3\n", + "[starting] 4\n", + "[starting] 5\n", + "[starting] 6\n", + "[starting] 7\n", + "[starting] 8\n", + "[starting] 9\n", + "[starting] 10\n", + "[starting] 11\n", + "[starting] 12\n", + "[starting] 13\n", + "[starting] 14\n", + "[starting] 15\n", + "[starting] 16\n", + "[starting] 17\n", + "[starting] 18\n", + "[starting] 19\n", + "[starting] 20\n", + "[starting] 21\n", + "[starting] 22\n", + "[starting] 23\n", + "[starting] 24\n", + "[starting] 25\n", + "[starting] 26\n", + "[starting] 27\n", + "[starting] 28\n", + "[starting] 29\n", + "[starting] 30\n", + "[starting] 31\n", + "[starting] 32\n", + "[starting] 33\n", + "[starting] 34\n", + "[starting] 35\n", + "[starting] 36\n", + "[starting] 37\n", + "[starting] 38\n", + "[starting] 39\n", + "[starting] 40\n", + "[starting] 41\n", + "[starting] 42\n", + "[starting] 43\n", + "[starting] 44\n", + "[starting] 45\n", + "[starting] 46\n", + "[starting] 47\n", + "[starting] 48\n", + "[starting] 49\n", + "[starting] 50\n", + "[starting] 51\n", + "[starting] 52\n", + "[starting] 53\n", + "[starting] 54\n", + "[starting] 55\n", + "[starting] 56\n", + "[starting] 57\n", + "[starting] 58\n", + "[starting] 59\n", + "[starting] 60\n", + "[starting] 61\n", + "[starting] 62\n", + "[starting] 63\n", + "[starting] 64\n", + "[starting] 65\n", + "[starting] 66\n", + "[starting] 67\n", + "[starting] 68\n", + "[starting] 69\n", + "[starting] 70\n", + "[starting] 71\n", + "[starting] 72\n", + "[starting] 73\n", + "[starting] 74\n", + "[starting] 75\n", + "[starting] 76\n", + "[starting] 77\n", + "[starting] 78\n", + "[starting] 79\n", + "[starting] 80\n", + "[starting] 81\n", + "[starting] 82\n", + "[starting] 83\n", + "[starting] 84\n", + "[starting] 85\n", + "[starting] 86\n", + "[starting] 87\n", + "[starting] 88\n", + "[starting] 89\n", + "[starting] 90\n", + "[starting] 91\n", + "[starting] 92\n", + "[starting] 93\n", + "[starting] 94\n", + "[starting] 95\n", + "[starting] 96\n", + "[starting] 97\n", + "[starting] 98\n", + "[starting] 99\n", + "[starting] 100\n", + "[starting] 101\n", + "[starting] 102\n", + "[starting] 103\n", + "[starting] 104\n", + "[starting] 105\n", + "[starting] 106\n", + "[starting] 107\n", + "[starting] 108\n", + "[starting] 109\n", + "[starting] 110\n", + "[starting] 111\n", + "[starting] 112\n", + "[starting] 113\n", + "[starting] 114\n", + "[starting] 115\n", + "[starting] 116\n", + "[starting] 117\n", + "[starting] 118\n", + "[starting] 119\n", + "[starting] 120\n", + "[starting] 121\n", + "[starting] 122\n", + "[starting] 123\n", + "[starting] 124\n", + "[starting] 125\n", + "[starting] 126\n", + "[starting] 127\n", + "[starting] 128\n", + "[starting] 129\n", + "[starting] 130\n", + "[starting] 131\n", + "[starting] 132\n", + "[starting] 133\n", + "[starting] 134\n", + "[starting] 135\n", + "[starting] 136\n", + "[starting] 137\n", + "[starting] 138\n", + "[starting] 139\n", + "[starting] 140\n", + "[starting] 141\n", + "[starting] 142\n", + "[starting] 143\n", + "[starting] 144\n", + "[starting] 145\n", + "[starting] 146\n", + "[starting] 147\n", + "[starting] 148\n", + "[starting] 149\n", + "[starting] 150\n", + "[starting] 151\n", + "[starting] 152\n", + "[starting] 153\n", + "[starting] 154\n", + "[starting] 155\n", + "[starting] 156\n", + "[starting] 157\n", + "[starting] 158\n", + "[starting] 159\n", + "[starting] 160\n", + "[starting] 161\n", + "[starting] 162\n", + "[starting] 163\n", + "[starting] 164\n", + "[starting] 165\n", + "[starting] 166\n", + "[starting] 167\n", + "[starting] 168\n", + "[starting] 169\n", + "[starting] 170\n", + "[starting] 171\n", + "[starting] 172\n", + "[starting] 173\n", + "[starting] 174\n", + "[starting] 175\n", + "[starting] 176\n", + "[starting] 177\n", + "[starting] 178\n", + "[starting] 179\n", + "[starting] 180\n", + "[starting] 181\n", + "[starting] 182\n", + "[starting] 183\n", + "[starting] 184\n", + "[starting] 185\n", + "[starting] 186\n", + "[starting] 187\n", + "[starting] 188\n", + "[starting] 189\n", + "[starting] 190\n", + "[starting] 191\n", + "[starting] 192\n", + "[starting] 193\n", + "[starting] 194\n", + "[starting] 195\n", + "[starting] 196\n", + "[starting] 197\n", + "[starting] 198\n", + "[starting] 199\n", + "[starting] 200\n", + "[starting] 201\n", + "[starting] 202\n", + "[starting] 203\n", + "[starting] 204\n", + "[starting] 205\n", + "[starting] 206\n", + "[starting] 207\n", + "[starting] 208\n", + "[starting] 209\n", + "[starting] 210\n", + "[starting] 211\n", + "[starting] 212\n", + "[starting] 213\n", + "[starting] 214\n", + "[starting] 215\n", + "[starting] 216\n", + "[starting] 217\n", + "[starting] 218\n", + "[starting] 219\n", + "[starting] 220\n", + "[starting] 221\n", + "[starting] 222\n", + "[starting] 223\n", + "[starting] 224\n", + "[starting] 225\n", + "[starting] 226\n", + "[starting] 227\n", + "[starting] 228\n", + "[starting] 229\n", + "[starting] 230\n", + "[starting] 231\n", + "[starting] 232\n", + "[starting] 233\n", + "[starting] 234\n", + "[starting] 235\n", + "[starting] 236\n", + "[starting] 237\n", + "[starting] 238\n", + "[starting] 239\n", + "[starting] 240\n", + "[starting] 241\n", + "[starting] 242\n", + "[starting] 243\n", + "[starting] 244\n", + "[starting] 245\n", + "[starting] 246\n", + "[starting] 247\n", + "[starting] 248\n", + "[starting] 249\n", + "[starting] 250\n", + "[starting] 251\n", + "[starting] 252\n", + "[starting] 253\n", + "[starting] 254\n", + "[starting] 255\n", + "[starting] 256\n", + "[starting] 257\n", + "[starting] 258\n", + "[starting] 259\n", + "[starting] 260\n", + "[starting] 261\n", + "[starting] 262\n", + "[starting] 263\n", + "[starting] 264\n", + "[starting] 265\n", + "[starting] 266\n", + "[starting] 267\n", + "[starting] 268\n", + "[starting] 269\n", + "[starting] 270\n", + "[starting] 271\n", + "[starting] 272\n", + "[starting] 273\n", + "[starting] 274\n", + "[starting] 275\n", + "[starting] 276\n", + "[starting] 277\n", + "[starting] 278\n", + "[starting] 279\n", + "[starting] 280\n", + "[starting] 281\n", + "[starting] 282\n", + "[starting] 283\n", + "[starting] 284\n", + "[starting] 285\n", + "[starting] 286\n", + "[starting] 287\n", + "[starting] 288\n", + "[starting] 289\n", + "[starting] 290\n", + "[starting] 291\n", + "[starting] 292\n", + "[starting] 293\n", + "[starting] 294\n", + "[starting] 295\n", + "[starting] 296\n", + "[starting] 297\n", + "[starting] 298\n", + "[starting] 299\n", + "[starting] 300\n", + "[starting] 301\n", + "[starting] 302\n", + "[starting] 303\n", + "[starting] 304\n", + "[starting] 305\n", + "[starting] 306\n", + "[starting] 307\n", + "[starting] 308\n", + "[starting] 309\n", + "[starting] 310\n", + "[starting] 311\n", + "[starting] 312\n", + "[starting] 313\n", + "[starting] 314\n", + "[starting] 315\n", + "[starting] 316\n", + "[starting] 317\n", + "[starting] 318\n", + "[starting] 319\n", + "[starting] 320\n", + "[starting] 321\n", + "[starting] 322\n", + "[starting] 323\n", + "[starting] 324\n", + "[starting] 325\n", + "[starting] 326\n", + "[starting] 327\n", + "[starting] 328\n", + "[starting] 329\n", + "[starting] 330\n", + "[starting] 331\n", + "[starting] 332\n", + "[starting] 333\n", + "[starting] 334\n", + "[starting] 335\n", + "[starting] 336\n", + "[starting] 337\n", + "[starting] 338\n", + "[starting] 339\n", + "[starting] 340\n", + "[starting] 341\n", + "[starting] 342\n", + "[starting] 343\n", + "[starting] 344\n", + "[starting] 345\n", + "[starting] 346\n", + "[starting] 347\n", + "[starting] 348\n", + "[starting] 349\n", + "[starting] 350\n", + "[starting] 351\n", + "[starting] 352\n", + "[starting] 353\n", + "[starting] 354\n", + "[starting] 355\n", + "[starting] 356\n", + "[starting] 357\n", + "[starting] 358\n", + "[starting] 359\n", + "[starting] 360\n", + "[starting] 361\n", + "[starting] 362\n", + "[starting] 363\n", + "[starting] 364\n", + "[starting] 365\n", + "[starting] 366\n", + "[starting] 367\n", + "[starting] 368\n", + "[starting] 369\n", + "[starting] 370\n", + "[starting] 371\n", + "[starting] 372\n", + "[starting] 373\n", + "[starting] 374\n", + "[starting] 375\n", + "[starting] 376\n", + "[starting] 377\n", + "[starting] 378\n", + "[starting] 379\n", + "[starting] 380\n", + "[starting] 381\n", + "[starting] 382\n", + "[starting] 383\n", + "[starting] 384\n", + "[starting] 385\n", + "[starting] 386\n", + "[starting] 387\n", + "[starting] 388\n", + "[starting] 389\n", + "[starting] 390\n", + "[starting] 391\n", + "[starting] 392\n", + "[starting] 393\n", + "[starting] 394\n", + "[starting] 395\n", + "[starting] 396\n", + "[starting] 397\n", + "[starting] 398\n", + "[starting] 399\n", + "[starting] 400\n", + "[starting] 401\n", + "[starting] 402\n", + "[starting] 403\n", + "[starting] 404\n", + "[starting] 405\n", + "[starting] 406\n", + "[starting] 407\n", + "[starting] 408\n", + "[starting] 409\n", + "[starting] 410\n", + "[starting] 411\n", + "[starting] 412\n", + "[starting] 413\n", + "[starting] 414\n", + "[starting] 415\n", + "[starting] 416\n", + "[starting] 417\n", + "[starting] 418\n", + "[starting] 419\n", + "[starting] 420\n", + "[starting] 421\n", + "[starting] 422\n", + "[starting] 423\n", + "[starting] 424\n", + "[starting] 425\n", + "[starting] 426\n", + "[starting] 427\n", + "[starting] 428\n", + "[starting] 429\n", + "[starting] 430\n", + "[starting] 431\n", + "[starting] 432\n", + "[starting] 433\n", + "[starting] 434\n", + "[starting] 435\n", + "[starting] 436\n", + "[starting] 437\n", + "[starting] 438\n", + "[starting] 439\n", + "[starting] 440\n", + "[starting] 441\n", + "[*] Best: 58952.967129705365\n", + "[*] Writing the best solution to file\n", + "\n", + "[*] Running for: 18.7 seconds\n", + "\n", + "Best Fitness:\t 58952.967129705365\n", + "Best Solution:\t [395, 173, 172, 161, 149, 136, 126, 385, 114, 103, 440, 101, 102, 113, 125, 135, 148, 160, 171, 184, 399, 404, 226, 233, 237, 238, 265, 268, 272, 275, 278, 280, 281, 427, 341, 340, 345, 346, 347, 432, 348, 349, 350, 351, 342, 352, 353, 354, 433, 355, 356, 357, 434, 358, 359, 360, 343, 361, 362, 363, 364, 365, 366, 344, 367, 368, 369, 370, 371, 372, 373, 374, 337, 336, 426, 335, 334, 333, 306, 332, 331, 330, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 279, 425, 439, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 428, 324, 325, 326, 327, 328, 329, 430, 429, 277, 416, 417, 252, 251, 250, 249, 414, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 234, 227, 405, 400, 185, 398, 186, 174, 391, 137, 115, 388, 386, 150, 151, 392, 152, 138, 127, 116, 104, 105, 106, 117, 128, 140, 153, 164, 163, 176, 188, 200, 401, 201, 189, 190, 397, 177, 165, 154, 141, 129, 118, 107, 438, 82, 50, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 441, 98, 99, 83, 51, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 375, 376, 32, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 84, 85, 86, 377, 87, 88, 89, 90, 91, 92, 93, 94, 378, 95, 379, 96, 97, 382, 383, 112, 124, 134, 147, 159, 170, 183, 198, 209, 219, 225, 410, 409, 413, 236, 264, 419, 267, 415, 263, 262, 235, 261, 260, 259, 258, 257, 256, 255, 254, 253, 231, 223, 214, 202, 178, 394, 393, 166, 155, 142, 130, 119, 108, 384, 120, 121, 109, 131, 144, 143, 390, 156, 167, 180, 193, 204, 205, 206, 194, 195, 196, 181, 168, 157, 145, 132, 122, 110, 100, 435, 111, 123, 133, 146, 158, 169, 182, 197, 208, 218, 217, 207, 216, 403, 408, 407, 411, 412, 418, 421, 437, 422, 271, 274, 436, 431, 232, 224, 215, 203, 191, 179, 192, 389, 387, 380, 381, 139, 162, 175, 187, 199, 212, 221, 229, 228, 220, 210, 402, 211, 396, 213, 222, 230, 424, 420, 423, 339, 338, 276, 273, 270, 266, 269, 406]\n" + ] + } + ], + "source": [ + "tsp_problem = './template/data/medium/pcb442.tsp'\n", + "tsp_coords = np.array(load_data(tsp_problem))\n", + "\n", + "import timeit\n", + "start = timeit.default_timer()\n", + "\n", + "# Your Model Running\n", + "\n", + "model = MyModel()\n", + "best_solution, fitness_list = TSP(tsp_problem, model)\n", + "\n", + "# Your Model End\n", + "\n", + "stop = timeit.default_timer()\n", + "print()\n", + "print('[*] Running for: {time:.1f} seconds'.format(time=(stop - start)))\n", + "\n", + "print()\n", + "print (\"Best Fitness:\\t\", fitness(best_solution, tsp_coords))\n", + "print (\"Best Solution:\\t\", best_solution)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Minimum Spanning Tree (Breadth First)" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, coords):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(coords)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it=1000, visualize=False):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Uniform Cost Search Solution\")\n", + "\n", + " UCS_solutions = []\n", + " UCS_losses = []\n", + " \n", + " for i in range(0, self.N):\n", + " solution = [i]\n", + " UCS_solutions.append(solution)\n", + " \n", + " # Breadth First: Set each city as starting point, then go to next city simultaneously\n", + " for step in range(0, self.N - 1):\n", + " print(\"[step]\", step)\n", + " UCS_solutions[i]\n", + " solution = []\n", + " solution.append(i)\n", + " unvisited_list = list(range(0, self.N))\n", + " cur_city = i\n", + " # For each search path\n", + " for i in range(0, self.N):\n", + " cur_city = UCS_solutions[i][step]\n", + " unvisited_list = list( set(range(0, self.N)) - set(UCS_solutions[i]) )\n", + " # print(unvisited_list)\n", + " closest_neighbour = -1\n", + " shortest_distance = math.inf\n", + " for j in unvisited_list:\n", + " if(self.dist(cur_city, j) < shortest_distance):\n", + " closest_neighbour = j\n", + " shortest_distance = self.dist(cur_city, j)\n", + " UCS_solutions[i].append(closest_neighbour)\n", + "\n", + " for i in range(0, self.N):\n", + " UCS_losses.append(self.fitness(UCS_solutions[i]))\n", + " \n", + " self.best_solution = UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[MyModel] Uniform Cost Search Solution\n", + "[step] 0\n", + "[step] 1\n", + "[step] 2\n", + "[step] 3\n", + "[step] 4\n", + "[step] 5\n", + "[step] 6\n", + "[step] 7\n", + "[step] 8\n", + "[step] 9\n", + "[step] 10\n", + "[step] 11\n", + "[step] 12\n", + "[step] 13\n", + "[step] 14\n", + "[step] 15\n", + "[step] 16\n", + "[step] 17\n", + "[step] 18\n", + "[step] 19\n", + "[step] 20\n", + "[step] 21\n", + "[step] 22\n", + "[step] 23\n", + "[step] 24\n", + "[step] 25\n", + "[step] 26\n", + "[step] 27\n", + "[step] 28\n", + "[step] 29\n", + "[step] 30\n", + "[step] 31\n", + "[step] 32\n", + "[step] 33\n", + "[step] 34\n", + "[step] 35\n", + "[step] 36\n", + "[step] 37\n", + "[step] 38\n", + "[step] 39\n", + "[step] 40\n", + "[step] 41\n", + "[step] 42\n", + "[step] 43\n", + "[step] 44\n", + "[step] 45\n", + "[step] 46\n", + "[step] 47\n", + "[step] 48\n", + "[step] 49\n", + "[step] 50\n", + "[step] 51\n", + "[step] 52\n", + "[step] 53\n", + "[step] 54\n", + "[step] 55\n", + "[step] 56\n", + "[step] 57\n", + "[step] 58\n", + "[step] 59\n", + "[step] 60\n", + "[step] 61\n", + "[step] 62\n", + "[step] 63\n", + "[step] 64\n", + "[step] 65\n", + "[step] 66\n", + "[step] 67\n", + "[step] 68\n", + "[step] 69\n", + "[step] 70\n", + "[step] 71\n", + "[step] 72\n", + "[step] 73\n", + "[step] 74\n", + "[step] 75\n", + "[step] 76\n", + "[step] 77\n", + "[step] 78\n", + "[step] 79\n", + "[step] 80\n", + "[step] 81\n", + "[step] 82\n", + "[step] 83\n", + "[step] 84\n", + "[step] 85\n", + "[step] 86\n", + "[step] 87\n", + "[step] 88\n", + "[step] 89\n", + "[step] 90\n", + "[step] 91\n", + "[step] 92\n", + "[step] 93\n", + "[step] 94\n", + "[step] 95\n", + "[step] 96\n", + "[step] 97\n", + "[step] 98\n", + "[step] 99\n", + "[step] 100\n", + "[step] 101\n", + "[step] 102\n", + "[step] 103\n", + "[step] 104\n", + "[step] 105\n", + "[step] 106\n", + "[step] 107\n", + "[step] 108\n", + "[step] 109\n", + "[step] 110\n", + "[step] 111\n", + "[step] 112\n", + "[step] 113\n", + "[step] 114\n", + "[step] 115\n", + "[step] 116\n", + "[step] 117\n", + "[step] 118\n", + "[step] 119\n", + "[step] 120\n", + "[step] 121\n", + "[step] 122\n", + "[step] 123\n", + "[step] 124\n", + "[step] 125\n", + "[step] 126\n", + "[step] 127\n", + "[step] 128\n", + "[step] 129\n", + "[step] 130\n", + "[step] 131\n", + "[step] 132\n", + "[step] 133\n", + "[step] 134\n", + "[step] 135\n", + "[step] 136\n", + "[step] 137\n", + "[step] 138\n", + "[step] 139\n", + "[step] 140\n", + "[step] 141\n", + "[step] 142\n", + "[step] 143\n", + "[step] 144\n", + "[step] 145\n", + "[step] 146\n", + "[step] 147\n", + "[step] 148\n", + "[step] 149\n", + "[step] 150\n", + "[step] 151\n", + "[step] 152\n", + "[step] 153\n", + "[step] 154\n", + "[step] 155\n", + "[step] 156\n", + "[step] 157\n", + "[step] 158\n", + "[step] 159\n", + "[step] 160\n", + "[step] 161\n", + "[step] 162\n", + "[step] 163\n", + "[step] 164\n", + "[step] 165\n", + "[step] 166\n", + "[step] 167\n", + "[step] 168\n", + "[step] 169\n", + "[step] 170\n", + "[step] 171\n", + "[step] 172\n", + "[step] 173\n", + "[step] 174\n", + "[step] 175\n", + "[step] 176\n", + "[step] 177\n", + "[step] 178\n", + "[step] 179\n", + "[step] 180\n", + "[step] 181\n", + "[step] 182\n", + "[step] 183\n", + "[step] 184\n", + "[step] 185\n", + "[step] 186\n", + "[step] 187\n", + "[step] 188\n", + "[step] 189\n", + "[step] 190\n", + "[step] 191\n", + "[step] 192\n", + "[step] 193\n", + "[step] 194\n", + "[step] 195\n", + "[step] 196\n", + "[step] 197\n", + "[step] 198\n", + "[step] 199\n", + "[step] 200\n", + "[step] 201\n", + "[step] 202\n", + "[step] 203\n", + "[step] 204\n", + "[step] 205\n", + "[step] 206\n", + "[step] 207\n", + "[step] 208\n", + "[step] 209\n", + "[step] 210\n", + "[step] 211\n", + "[step] 212\n", + "[step] 213\n", + "[step] 214\n", + "[step] 215\n", + "[step] 216\n", + "[step] 217\n", + "[step] 218\n", + "[step] 219\n", + "[step] 220\n", + "[step] 221\n", + "[step] 222\n", + "[step] 223\n", + "[step] 224\n", + "[step] 225\n", + "[step] 226\n", + "[step] 227\n", + "[step] 228\n", + "[step] 229\n", + "[step] 230\n", + "[step] 231\n", + "[step] 232\n", + "[step] 233\n", + "[step] 234\n", + "[step] 235\n", + "[step] 236\n", + "[step] 237\n", + "[step] 238\n", + "[step] 239\n", + "[step] 240\n", + "[step] 241\n", + "[step] 242\n", + "[step] 243\n", + "[step] 244\n", + "[step] 245\n", + "[step] 246\n", + "[step] 247\n", + "[step] 248\n", + "[step] 249\n", + "[step] 250\n", + "[step] 251\n", + "[step] 252\n", + "[step] 253\n", + "[step] 254\n", + "[step] 255\n", + "[step] 256\n", + "[step] 257\n", + "[step] 258\n", + "[step] 259\n", + "[step] 260\n", + "[step] 261\n", + "[step] 262\n", + "[step] 263\n", + "[step] 264\n", + "[step] 265\n", + "[step] 266\n", + "[step] 267\n", + "[step] 268\n", + "[step] 269\n", + "[step] 270\n", + "[step] 271\n", + "[step] 272\n", + "[step] 273\n", + "[step] 274\n", + "[step] 275\n", + "[step] 276\n", + "[step] 277\n", + "[step] 278\n", + "[step] 279\n", + "[step] 280\n", + "[step] 281\n", + "[step] 282\n", + "[step] 283\n", + "[step] 284\n", + "[step] 285\n", + "[step] 286\n", + "[step] 287\n", + "[step] 288\n", + "[step] 289\n", + "[step] 290\n", + "[step] 291\n", + "[step] 292\n", + "[step] 293\n", + "[step] 294\n", + "[step] 295\n", + "[step] 296\n", + "[step] 297\n", + "[step] 298\n", + "[step] 299\n", + "[step] 300\n", + "[step] 301\n", + "[step] 302\n", + "[step] 303\n", + "[step] 304\n", + "[step] 305\n", + "[step] 306\n", + "[step] 307\n", + "[step] 308\n", + "[step] 309\n", + "[step] 310\n", + "[step] 311\n", + "[step] 312\n", + "[step] 313\n", + "[step] 314\n", + "[step] 315\n", + "[step] 316\n", + "[step] 317\n", + "[step] 318\n", + "[step] 319\n", + "[step] 320\n", + "[step] 321\n", + "[step] 322\n", + "[step] 323\n", + "[step] 324\n", + "[step] 325\n", + "[step] 326\n", + "[step] 327\n", + "[step] 328\n", + "[step] 329\n", + "[step] 330\n", + "[step] 331\n", + "[step] 332\n", + "[step] 333\n", + "[step] 334\n", + "[step] 335\n", + "[step] 336\n", + "[step] 337\n", + "[step] 338\n", + "[step] 339\n", + "[step] 340\n", + "[step] 341\n", + "[step] 342\n", + "[step] 343\n", + "[step] 344\n", + "[step] 345\n", + "[step] 346\n", + "[step] 347\n", + "[step] 348\n", + "[step] 349\n", + "[step] 350\n", + "[step] 351\n", + "[step] 352\n", + "[step] 353\n", + "[step] 354\n", + "[step] 355\n", + "[step] 356\n", + "[step] 357\n", + "[step] 358\n", + "[step] 359\n", + "[step] 360\n", + "[step] 361\n", + "[step] 362\n", + "[step] 363\n", + "[step] 364\n", + "[step] 365\n", + "[step] 366\n", + "[step] 367\n", + "[step] 368\n", + "[step] 369\n", + "[step] 370\n", + "[step] 371\n", + "[step] 372\n", + "[step] 373\n", + "[step] 374\n", + "[step] 375\n", + "[step] 376\n", + "[step] 377\n", + "[step] 378\n", + "[step] 379\n", + "[step] 380\n", + "[step] 381\n", + "[step] 382\n", + "[step] 383\n", + "[step] 384\n", + "[step] 385\n", + "[step] 386\n", + "[step] 387\n", + "[step] 388\n", + "[step] 389\n", + "[step] 390\n", + "[step] 391\n", + "[step] 392\n", + "[step] 393\n", + "[step] 394\n", + "[step] 395\n", + "[step] 396\n", + "[step] 397\n", + "[step] 398\n", + "[step] 399\n", + "[step] 400\n", + "[step] 401\n", + "[step] 402\n", + "[step] 403\n", + "[step] 404\n", + "[step] 405\n", + "[step] 406\n", + "[step] 407\n", + "[step] 408\n", + "[step] 409\n", + "[step] 410\n", + "[step] 411\n", + "[step] 412\n", + "[step] 413\n", + "[step] 414\n", + "[step] 415\n", + "[step] 416\n", + "[step] 417\n", + "[step] 418\n", + "[step] 419\n", + "[step] 420\n", + "[step] 421\n", + "[step] 422\n", + "[step] 423\n", + "[step] 424\n", + "[step] 425\n", + "[step] 426\n", + "[step] 427\n", + "[step] 428\n", + "[step] 429\n", + "[step] 430\n", + "[step] 431\n", + "[step] 432\n", + "[step] 433\n", + "[step] 434\n", + "[step] 435\n", + "[step] 436\n", + "[step] 437\n", + "[step] 438\n", + "[step] 439\n", + "[step] 440\n", + "[*] Best: 58952.967129705365\n", + "[*] Writing the best solution to file\n", + "\n", + "[*] Running for: 21.8 seconds\n", + "\n", + "Best Fitness:\t 58952.967129705365\n", + "Best Solution:\t [395, 173, 172, 161, 149, 136, 126, 385, 114, 103, 440, 101, 102, 113, 125, 135, 148, 160, 171, 184, 399, 404, 226, 233, 237, 238, 265, 268, 272, 275, 278, 280, 281, 427, 341, 340, 345, 346, 347, 432, 348, 349, 350, 351, 342, 352, 353, 354, 433, 355, 356, 357, 434, 358, 359, 360, 343, 361, 362, 363, 364, 365, 366, 344, 367, 368, 369, 370, 371, 372, 373, 374, 337, 336, 426, 335, 334, 333, 306, 332, 331, 330, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 279, 425, 439, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 428, 324, 325, 326, 327, 328, 329, 430, 429, 277, 416, 417, 252, 251, 250, 249, 414, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 234, 227, 405, 400, 185, 398, 186, 174, 391, 137, 115, 388, 386, 150, 151, 392, 152, 138, 127, 116, 104, 105, 106, 117, 128, 140, 153, 164, 163, 176, 188, 200, 401, 201, 189, 190, 397, 177, 165, 154, 141, 129, 118, 107, 438, 82, 50, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 441, 98, 99, 83, 51, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 375, 376, 32, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 84, 85, 86, 377, 87, 88, 89, 90, 91, 92, 93, 94, 378, 95, 379, 96, 97, 382, 383, 112, 124, 134, 147, 159, 170, 183, 198, 209, 219, 225, 410, 409, 413, 236, 264, 419, 267, 415, 263, 262, 235, 261, 260, 259, 258, 257, 256, 255, 254, 253, 231, 223, 214, 202, 178, 394, 393, 166, 155, 142, 130, 119, 108, 384, 120, 121, 109, 131, 144, 143, 390, 156, 167, 180, 193, 204, 205, 206, 194, 195, 196, 181, 168, 157, 145, 132, 122, 110, 100, 435, 111, 123, 133, 146, 158, 169, 182, 197, 208, 218, 217, 207, 216, 403, 408, 407, 411, 412, 418, 421, 437, 422, 271, 274, 436, 431, 232, 224, 215, 203, 191, 179, 192, 389, 387, 380, 381, 139, 162, 175, 187, 199, 212, 221, 229, 228, 220, 210, 402, 211, 396, 213, 222, 230, 424, 420, 423, 339, 338, 276, 273, 270, 266, 269, 406]\n" + ] + } + ], + "source": [ + "tsp_problem = './template/data/medium/pcb442.tsp'\n", + "tsp_coords = np.array(load_data(tsp_problem))\n", + "\n", + "import timeit\n", + "start = timeit.default_timer()\n", + "\n", + "# Your Model Running\n", + "\n", + "model = MyModel()\n", + "best_solution, fitness_list = TSP(tsp_problem, model)\n", + "\n", + "# Your Model End\n", + "\n", + "stop = timeit.default_timer()\n", + "print()\n", + "print('[*] Running for: {time:.1f} seconds'.format(time=(stop - start)))\n", + "\n", + "print()\n", + "print (\"Best Fitness:\\t\", fitness(best_solution, tsp_coords))\n", + "print (\"Best Solution:\\t\", best_solution)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dynamic Programming" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Costs a lot of memory" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, coords):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(coords)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def getMST(self, node):\n", + " MST = []\n", + " distances = []\n", + " for i in range(0, self.N):\n", + " if i != node:\n", + " MST.append(i)\n", + " distances.append(self.dist(node, i))\n", + " return [x for _,x in sorted(zip(distances, MST))]\n", + "\n", + " def fit(self, max_it=1000, visualize=False):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Uniform Cost Search Solution\")\n", + "\n", + " UCS_solutions = []\n", + " UCS_losses = []\n", + "\n", + " # Depth First: Set one city as starting point, iterate to the end, then select next city as starting point.\n", + " MSTs = []\n", + " for i in range(0, self.N):\n", + " MSTs.append([-1] * self.N)\n", + " for i in range(0, self.N):\n", + " solution = []\n", + " solution.append(i)\n", + " unvisited_list = list(range(0, self.N))\n", + " cur_city = i\n", + " print(\"[starting]\", i)\n", + " for steps in range(self.N - 1):\n", + " # print(unvisited_list)\n", + " unvisited_list.remove(cur_city)\n", + " if MSTs[cur_city][0] == -1:\n", + " MST = self.getMST(cur_city)\n", + " MSTs[cur_city] = MST\n", + " \n", + " for j in MSTs[cur_city]:\n", + " if(j in unvisited_list):\n", + " solution.append(j)\n", + " cur_city = j\n", + " break\n", + " # print(solution)\n", + " UCS_solutions.append(solution)\n", + " UCS_losses.append(self.fitness(solution))\n", + "\n", + " self.best_solution = UCS_solutions[ UCS_losses.index(min(UCS_losses)) ]\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[MyModel] Uniform Cost Search Solution\n", + "[starting] 0\n", + "[starting] 1\n", + "[starting] 2\n", + "[starting] 3\n", + "[starting] 4\n", + "[starting] 5\n", + "[starting] 6\n", + "[starting] 7\n", + "[starting] 8\n", + "[starting] 9\n", + "[starting] 10\n", + "[starting] 11\n", + "[starting] 12\n", + "[starting] 13\n", + "[starting] 14\n", + "[starting] 15\n", + "[starting] 16\n", + "[starting] 17\n", + "[starting] 18\n", + "[starting] 19\n", + "[starting] 20\n", + "[starting] 21\n", + "[starting] 22\n", + "[starting] 23\n", + "[starting] 24\n", + "[starting] 25\n", + "[starting] 26\n", + "[starting] 27\n", + "[starting] 28\n", + "[starting] 29\n", + "[starting] 30\n", + "[starting] 31\n", + "[starting] 32\n", + "[starting] 33\n", + "[starting] 34\n", + "[starting] 35\n", + "[starting] 36\n", + "[starting] 37\n", + "[starting] 38\n", + "[starting] 39\n", + "[starting] 40\n", + "[starting] 41\n", + "[starting] 42\n", + "[starting] 43\n", + "[starting] 44\n", + "[starting] 45\n", + "[starting] 46\n", + "[starting] 47\n", + "[starting] 48\n", + "[starting] 49\n", + "[starting] 50\n", + "[starting] 51\n", + "[starting] 52\n", + "[starting] 53\n", + "[starting] 54\n", + "[starting] 55\n", + "[starting] 56\n", + "[starting] 57\n", + "[starting] 58\n", + "[starting] 59\n", + "[starting] 60\n", + "[starting] 61\n", + "[starting] 62\n", + "[starting] 63\n", + "[starting] 64\n", + "[starting] 65\n", + "[starting] 66\n", + "[starting] 67\n", + "[starting] 68\n", + "[starting] 69\n", + "[starting] 70\n", + "[starting] 71\n", + "[starting] 72\n", + "[starting] 73\n", + "[starting] 74\n", + "[starting] 75\n", + "[starting] 76\n", + "[starting] 77\n", + "[starting] 78\n", + "[starting] 79\n", + "[starting] 80\n", + "[starting] 81\n", + "[starting] 82\n", + "[starting] 83\n", + "[starting] 84\n", + "[starting] 85\n", + "[starting] 86\n", + "[starting] 87\n", + "[starting] 88\n", + "[starting] 89\n", + "[starting] 90\n", + "[starting] 91\n", + "[starting] 92\n", + "[starting] 93\n", + "[starting] 94\n", + "[starting] 95\n", + "[starting] 96\n", + "[starting] 97\n", + "[starting] 98\n", + "[starting] 99\n", + "[starting] 100\n", + "[starting] 101\n", + "[starting] 102\n", + "[starting] 103\n", + "[starting] 104\n", + "[starting] 105\n", + "[starting] 106\n", + "[starting] 107\n", + "[starting] 108\n", + "[starting] 109\n", + "[starting] 110\n", + "[starting] 111\n", + "[starting] 112\n", + "[starting] 113\n", + "[starting] 114\n", + "[starting] 115\n", + "[starting] 116\n", + "[starting] 117\n", + "[starting] 118\n", + "[starting] 119\n", + "[starting] 120\n", + "[starting] 121\n", + "[starting] 122\n", + "[starting] 123\n", + "[starting] 124\n", + "[starting] 125\n", + "[starting] 126\n", + "[starting] 127\n", + "[starting] 128\n", + "[starting] 129\n", + "[starting] 130\n", + "[starting] 131\n", + "[starting] 132\n", + "[starting] 133\n", + "[starting] 134\n", + "[starting] 135\n", + "[starting] 136\n", + "[starting] 137\n", + "[starting] 138\n", + "[starting] 139\n", + "[starting] 140\n", + "[starting] 141\n", + "[starting] 142\n", + "[starting] 143\n", + "[starting] 144\n", + "[starting] 145\n", + "[starting] 146\n", + "[starting] 147\n", + "[starting] 148\n", + "[starting] 149\n", + "[starting] 150\n", + "[starting] 151\n", + "[starting] 152\n", + "[starting] 153\n", + "[starting] 154\n", + "[starting] 155\n", + "[starting] 156\n", + "[starting] 157\n", + "[starting] 158\n", + "[starting] 159\n", + "[starting] 160\n", + "[starting] 161\n", + "[starting] 162\n", + "[starting] 163\n", + "[starting] 164\n", + "[starting] 165\n", + "[starting] 166\n", + "[starting] 167\n", + "[starting] 168\n", + "[starting] 169\n", + "[starting] 170\n", + "[starting] 171\n", + "[starting] 172\n", + "[starting] 173\n", + "[starting] 174\n", + "[starting] 175\n", + "[starting] 176\n", + "[starting] 177\n", + "[starting] 178\n", + "[starting] 179\n", + "[starting] 180\n", + "[starting] 181\n", + "[starting] 182\n", + "[starting] 183\n", + "[starting] 184\n", + "[starting] 185\n", + "[starting] 186\n", + "[starting] 187\n", + "[starting] 188\n", + "[starting] 189\n", + "[starting] 190\n", + "[starting] 191\n", + "[starting] 192\n", + "[starting] 193\n", + "[starting] 194\n", + "[starting] 195\n", + "[starting] 196\n", + "[starting] 197\n", + "[starting] 198\n", + "[starting] 199\n", + "[starting] 200\n", + "[starting] 201\n", + "[starting] 202\n", + "[starting] 203\n", + "[starting] 204\n", + "[starting] 205\n", + "[starting] 206\n", + "[starting] 207\n", + "[starting] 208\n", + "[starting] 209\n", + "[starting] 210\n", + "[starting] 211\n", + "[starting] 212\n", + "[starting] 213\n", + "[starting] 214\n", + "[starting] 215\n", + "[starting] 216\n", + "[starting] 217\n", + "[starting] 218\n", + "[starting] 219\n", + "[starting] 220\n", + "[starting] 221\n", + "[starting] 222\n", + "[starting] 223\n", + "[starting] 224\n", + "[starting] 225\n", + "[starting] 226\n", + "[starting] 227\n", + "[starting] 228\n", + "[starting] 229\n", + "[starting] 230\n", + "[starting] 231\n", + "[starting] 232\n", + "[starting] 233\n", + "[starting] 234\n", + "[starting] 235\n", + "[starting] 236\n", + "[starting] 237\n", + "[starting] 238\n", + "[starting] 239\n", + "[starting] 240\n", + "[starting] 241\n", + "[starting] 242\n", + "[starting] 243\n", + "[starting] 244\n", + "[starting] 245\n", + "[starting] 246\n", + "[starting] 247\n", + "[starting] 248\n", + "[starting] 249\n", + "[starting] 250\n", + "[starting] 251\n", + "[starting] 252\n", + "[starting] 253\n", + "[starting] 254\n", + "[starting] 255\n", + "[starting] 256\n", + "[starting] 257\n", + "[starting] 258\n", + "[starting] 259\n", + "[starting] 260\n", + "[starting] 261\n", + "[starting] 262\n", + "[starting] 263\n", + "[starting] 264\n", + "[starting] 265\n", + "[starting] 266\n", + "[starting] 267\n", + "[starting] 268\n", + "[starting] 269\n", + "[starting] 270\n", + "[starting] 271\n", + "[starting] 272\n", + "[starting] 273\n", + "[starting] 274\n", + "[starting] 275\n", + "[starting] 276\n", + "[starting] 277\n", + "[starting] 278\n", + "[starting] 279\n", + "[starting] 280\n", + "[starting] 281\n", + "[starting] 282\n", + "[starting] 283\n", + "[starting] 284\n", + "[starting] 285\n", + "[starting] 286\n", + "[starting] 287\n", + "[starting] 288\n", + "[starting] 289\n", + "[starting] 290\n", + "[starting] 291\n", + "[starting] 292\n", + "[starting] 293\n", + "[starting] 294\n", + "[starting] 295\n", + "[starting] 296\n", + "[starting] 297\n", + "[starting] 298\n", + "[starting] 299\n", + "[starting] 300\n", + "[starting] 301\n", + "[starting] 302\n", + "[starting] 303\n", + "[starting] 304\n", + "[starting] 305\n", + "[starting] 306\n", + "[starting] 307\n", + "[starting] 308\n", + "[starting] 309\n", + "[starting] 310\n", + "[starting] 311\n", + "[starting] 312\n", + "[starting] 313\n", + "[starting] 314\n", + "[starting] 315\n", + "[starting] 316\n", + "[starting] 317\n", + "[starting] 318\n", + "[starting] 319\n", + "[starting] 320\n", + "[starting] 321\n", + "[starting] 322\n", + "[starting] 323\n", + "[starting] 324\n", + "[starting] 325\n", + "[starting] 326\n", + "[starting] 327\n", + "[starting] 328\n", + "[starting] 329\n", + "[starting] 330\n", + "[starting] 331\n", + "[starting] 332\n", + "[starting] 333\n", + "[starting] 334\n", + "[starting] 335\n", + "[starting] 336\n", + "[starting] 337\n", + "[starting] 338\n", + "[starting] 339\n", + "[starting] 340\n", + "[starting] 341\n", + "[starting] 342\n", + "[starting] 343\n", + "[starting] 344\n", + "[starting] 345\n", + "[starting] 346\n", + "[starting] 347\n", + "[starting] 348\n", + "[starting] 349\n", + "[starting] 350\n", + "[starting] 351\n", + "[starting] 352\n", + "[starting] 353\n", + "[starting] 354\n", + "[starting] 355\n", + "[starting] 356\n", + "[starting] 357\n", + "[starting] 358\n", + "[starting] 359\n", + "[starting] 360\n", + "[starting] 361\n", + "[starting] 362\n", + "[starting] 363\n", + "[starting] 364\n", + "[starting] 365\n", + "[starting] 366\n", + "[starting] 367\n", + "[starting] 368\n", + "[starting] 369\n", + "[starting] 370\n", + "[starting] 371\n", + "[starting] 372\n", + "[starting] 373\n", + "[starting] 374\n", + "[starting] 375\n", + "[starting] 376\n", + "[starting] 377\n", + "[starting] 378\n", + "[starting] 379\n", + "[starting] 380\n", + "[starting] 381\n", + "[starting] 382\n", + "[starting] 383\n", + "[starting] 384\n", + "[starting] 385\n", + "[starting] 386\n", + "[starting] 387\n", + "[starting] 388\n", + "[starting] 389\n", + "[starting] 390\n", + "[starting] 391\n", + "[starting] 392\n", + "[starting] 393\n", + "[starting] 394\n", + "[starting] 395\n", + "[starting] 396\n", + "[starting] 397\n", + "[starting] 398\n", + "[starting] 399\n", + "[starting] 400\n", + "[starting] 401\n", + "[starting] 402\n", + "[starting] 403\n", + "[starting] 404\n", + "[starting] 405\n", + "[starting] 406\n", + "[starting] 407\n", + "[starting] 408\n", + "[starting] 409\n", + "[starting] 410\n", + "[starting] 411\n", + "[starting] 412\n", + "[starting] 413\n", + "[starting] 414\n", + "[starting] 415\n", + "[starting] 416\n", + "[starting] 417\n", + "[starting] 418\n", + "[starting] 419\n", + "[starting] 420\n", + "[starting] 421\n", + "[starting] 422\n", + "[starting] 423\n", + "[starting] 424\n", + "[starting] 425\n", + "[starting] 426\n", + "[starting] 427\n", + "[starting] 428\n", + "[starting] 429\n", + "[starting] 430\n", + "[starting] 431\n", + "[starting] 432\n", + "[starting] 433\n", + "[starting] 434\n", + "[starting] 435\n", + "[starting] 436\n", + "[starting] 437\n", + "[starting] 438\n", + "[starting] 439\n", + "[starting] 440\n", + "[starting] 441\n", + "[*] Best: 58952.967129705365\n", + "[*] Writing the best solution to file\n", + "\n", + "[*] Running for: 1.3 seconds\n", + "\n", + "Best Fitness:\t 58952.967129705365\n", + "Best Solution:\t [395, 173, 172, 161, 149, 136, 126, 385, 114, 103, 440, 101, 102, 113, 125, 135, 148, 160, 171, 184, 399, 404, 226, 233, 237, 238, 265, 268, 272, 275, 278, 280, 281, 427, 341, 340, 345, 346, 347, 432, 348, 349, 350, 351, 342, 352, 353, 354, 433, 355, 356, 357, 434, 358, 359, 360, 343, 361, 362, 363, 364, 365, 366, 344, 367, 368, 369, 370, 371, 372, 373, 374, 337, 336, 426, 335, 334, 333, 306, 332, 331, 330, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, 283, 282, 279, 425, 439, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 428, 324, 325, 326, 327, 328, 329, 430, 429, 277, 416, 417, 252, 251, 250, 249, 414, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 234, 227, 405, 400, 185, 398, 186, 174, 391, 137, 115, 388, 386, 150, 151, 392, 152, 138, 127, 116, 104, 105, 106, 117, 128, 140, 153, 164, 163, 176, 188, 200, 401, 201, 189, 190, 397, 177, 165, 154, 141, 129, 118, 107, 438, 82, 50, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 441, 98, 99, 83, 51, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 375, 376, 32, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 84, 85, 86, 377, 87, 88, 89, 90, 91, 92, 93, 94, 378, 95, 379, 96, 97, 382, 383, 112, 124, 134, 147, 159, 170, 183, 198, 209, 219, 225, 410, 409, 413, 236, 264, 419, 267, 415, 263, 262, 235, 261, 260, 259, 258, 257, 256, 255, 254, 253, 231, 223, 214, 202, 178, 394, 393, 166, 155, 142, 130, 119, 108, 384, 120, 121, 109, 131, 144, 143, 390, 156, 167, 180, 193, 204, 205, 206, 194, 195, 196, 181, 168, 157, 145, 132, 122, 110, 100, 435, 111, 123, 133, 146, 158, 169, 182, 197, 208, 218, 217, 207, 216, 403, 408, 407, 411, 412, 418, 421, 437, 422, 271, 274, 436, 431, 232, 224, 215, 203, 191, 179, 192, 389, 387, 380, 381, 139, 162, 175, 187, 199, 212, 221, 229, 228, 220, 210, 402, 211, 396, 213, 222, 230, 424, 420, 423, 339, 338, 276, 273, 270, 266, 269, 406]\n" + ] + } + ], + "source": [ + "tsp_problem = './template/data/medium/pcb442.tsp'\n", + "tsp_coords = np.array(load_data(tsp_problem))\n", + "\n", + "import timeit\n", + "start = timeit.default_timer()\n", + "\n", + "# Your Model Running\n", + "\n", + "model = MyModel()\n", + "best_solution, fitness_list = TSP(tsp_problem, model)\n", + "\n", + "# Your Model End\n", + "\n", + "stop = timeit.default_timer()\n", + "print()\n", + "print('[*] Running for: {time:.1f} seconds'.format(time=(stop - start)))\n", + "\n", + "print()\n", + "print (\"Best Fitness:\\t\", fitness(best_solution, tsp_coords))\n", + "print (\"Best Solution:\\t\", best_solution)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your Smart Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, coords):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(coords)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it=1000, visualize=False):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Naive Random Solution\")\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulated Annealing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self, T=-1, alpha=-1, stopping_T=-1):\n", + " super().__init__()\n", + "\n", + " self.iteration = 0\n", + "\n", + " self.T = T\n", + " self.alpha = 0.995 if alpha == -1 else alpha\n", + " self.stopping_temperature = 1e-8 if stopping_T == -1 else stopping_T\n", + "\n", + " def init(self, coords):\n", + " super().init(coords)\n", + "\n", + " if (self.T == -1):\n", + " self.T = math.sqrt(self.N) \n", + " self.T_save = self.T # save inital T to reset if batch annealing is used\n", + "\n", + " def initial_solution(self):\n", + " \"\"\"\n", + " Greedy algorithm to get an initial solution (closest-neighbour).\n", + " \"\"\"\n", + " cur_node = random.choice(self.nodes) # start from a random node\n", + " solution = [cur_node]\n", + "\n", + " free_nodes = set(self.nodes)\n", + " free_nodes.remove(cur_node)\n", + " while free_nodes:\n", + " next_node = min(free_nodes, key=lambda x: self.dist(cur_node, x)) # nearest neighbour\n", + " free_nodes.remove(next_node)\n", + " solution.append(next_node)\n", + " cur_node = next_node\n", + "\n", + " cur_fit = self.fitness(solution)\n", + " if cur_fit < self.best_fitness: # If best found so far, update best fitness\n", + " self.best_fitness = cur_fit\n", + " self.best_solution = solution\n", + " self.fitness_list.append(cur_fit)\n", + " return solution, cur_fit\n", + "\n", + " def p_accept(self, candidate_fitness):\n", + " \"\"\"\n", + " Probability of accepting if the candidate is worse than current.\n", + " Depends on the current temperature and difference between candidate and current.\n", + " \"\"\"\n", + " return math.exp(-abs(candidate_fitness - self.cur_fitness) / self.T)\n", + "\n", + " def accept(self, candidate):\n", + " \"\"\"\n", + " Accept with probability 1 if candidate is better than current.\n", + " Accept with probabilty p_accept(..) if candidate is worse.\n", + " \"\"\"\n", + " candidate_fitness = self.fitness(candidate)\n", + " if candidate_fitness < self.cur_fitness:\n", + " self.cur_fitness, self.cur_solution = candidate_fitness, candidate\n", + " if candidate_fitness < self.best_fitness:\n", + " self.best_fitness, self.best_solution = candidate_fitness, candidate\n", + " else:\n", + " if random.random() < self.p_accept(candidate_fitness):\n", + " self.cur_fitness, self.cur_solution = candidate_fitness, candidate\n", + "\n", + " def fit(self, max_it=1000):\n", + " \"\"\"\n", + " Execute simulated annealing algorithm.\n", + " \"\"\"\n", + " # Initialize with the greedy solution.\n", + " self.cur_solution, self.cur_fitness = self.initial_solution()\n", + "\n", + " self.log(\"Starting annealing.\")\n", + " while self.T >= self.stopping_temperature and self.iteration < max_it:\n", + " candidate = list(self.cur_solution)\n", + " l = random.randint(1, self.N - 1)\n", + " i = random.randint(0, self.N - l)\n", + " candidate[i : (i + l)] = reversed(candidate[i : (i + l)])\n", + " self.accept(candidate)\n", + " self.T *= self.alpha\n", + " self.iteration += 1\n", + "\n", + " self.fitness_list.append(self.cur_fitness)\n", + "\n", + " self.log(f\"Best fitness obtained: {self.best_fitness}\")\n", + " improvement = 100 * (self.fitness_list[0] - self.best_fitness) / (self.fitness_list[0])\n", + " self.log(f\"Improvement over greedy heuristic: {improvement : .2f}%\")\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_problem = './template/data/simple/ulysses16.tsp'\n", + "tsp_coords = np.array(load_data(tsp_problem))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import timeit\n", + "start = timeit.default_timer()\n", + "\n", + "# Your Model Running\n", + "\n", + "model = MyModel()\n", + "best_solution, fitness_list = TSP(tsp_problem, model)\n", + "\n", + "# Your Model End\n", + "\n", + "stop = timeit.default_timer()\n", + "print()\n", + "print('[*] Running for: {time:.1f} seconds'.format(time=(stop - start)))\n", + "\n", + "print()\n", + "print (\"Best Fitness:\\t\", fitness(best_solution, tsp_coords))\n", + "print (\"Best Solution:\\t\", best_solution)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test All Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " # Get input file name\n", + " tsp_file = str(root) + '/' + str(f)\n", + " log(tsp_file)\n", + "\n", + " # Your Model\n", + " model = MyModel()\n", + "\n", + " # Run TSP\n", + " TSP(tsp_file, model)\n", + "\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Workshop - 6 (GA, SOM).ipynb b/Workshop - 6 (GA, SOM).ipynb new file mode 100644 index 0000000..022f6c2 --- /dev/null +++ b/Workshop - 6 (GA, SOM).ipynb @@ -0,0 +1,1317 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Make sure you run this at the begining**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import math\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Append template path to sys path\n", + "sys.path.append(os.getcwd() + \"/template\") " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from utils.load_data import load_data\n", + "from utils.load_data import log\n", + "from utils.visualize_tsp import plotTSP\n", + "from utils.tsp import TSP\n", + "from utils.tsp import TSP_Bench\n", + "from utils.tsp import TSP_Bench_ALL" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workshop Starts Here" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"TSP\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"solutions\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Get familiar with your dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are problems at different levels. **3 simple, 2 medium, 1 hard**." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ulysses16 = np.array(load_data(\"./template/data/simple/ulysses16.tsp\"))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[38.24, 20.42],\n", + " [39.57, 26.15],\n", + " [40.56, 25.32],\n", + " [36.26, 23.12],\n", + " [33.48, 10.54],\n", + " [37.56, 12.19],\n", + " [38.42, 13.11],\n", + " [37.52, 20.44],\n", + " [41.23, 9.1 ],\n", + " [41.17, 13.05],\n", + " [36.08, -5.21],\n", + " [38.47, 15.13],\n", + " [38.15, 15.35],\n", + " [37.51, 15.17],\n", + " [35.49, 14.32],\n", + " [39.36, 19.56]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ulysses16[:]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.scatter(ulysses16[:, 0], ulysses16[:, 1])\n", + "for i in range(0, 16):\n", + " plt.annotate(i, (ulysses16[i, 0], ulysses16[i, 1]+0.5))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: In Order" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]\n" + ] + } + ], + "source": [ + "simple_sequence = list(range(0, 16))\n", + "print(simple_sequence)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXIAAAD4CAYAAADxeG0DAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAA6j0lEQVR4nO3deVhUZf/H8fcNIgguqCDuIJrmmua+t7j0lKWVltuTWmn5qFlZmVrxU9PMNjRNM0uzXLK0NLVyX0MUNfcdxB1RUZRNYO7fHwOEsijMcmbg+7ourpgzM+d8TPzO4V6V1hohhBDOy8XoAEIIISwjhVwIIZycFHIhhHByUsiFEMLJSSEXQggnV8SIi/r4+OiAgAAjLi2EEE5r165dl7XWvnceN6SQBwQEEBYWZsSlhRDCaSmlIrM7Lk0rQgjh5KSQCyGEk5NCLoQQTk4KuRBCODkp5EII4eSkkAshbGp+VBQBISG4bNxIQEgI86OijI5U4Bgy/FAIUTjMj4pi0NGjxJtMAEQmJTHo6FEA+vj5GRmtQJE7ciGEzYwJD88o4uniTSbGhIcblKhgkjtyIYTNnE5KyvZ4ZGICaqwCoHrp6nQM7EjH6h15OOBhShcrbc+IBYIUciGETZi0iSLJV0l2K5PlOR9XE082HMCa8DWcjDnJyV0nmblrZpbXubm40bF6R3OhD+xIHd86KKXsEd+pKCN2CGrSpImWKfpCFFy7zu+iyTdNwPdR3OuMIYl/i6+niwuzatXKto38VuotdpzbwZqTa1gTvoaQsyG5Xqd+ufp0COxAx8COtPNvh1dRrzzlnB8VxZjwcE4nJVHV3Z0JgYEO3XavlNqltW6S5bgUciGENXVf3J0lh5cAED86nqVXY61WLCOvRbI2fC1rws2F/mrC1RxfW8q9VMbdfIfADlTzrnbb3fydHbGQ+4eMI7C4kCulqgDzAD9AA7O01lOUUv8HDASi0146Wmu9KrdzSSEXouCJiIkgcGogANP+M40hzYbY9frxyfFsPb01425+b9TeXF9ftNVSbrllbY/3d3fnVMuWtoppkZwKeV7ayFOAEVrr3UqpEsAupdSatOe+0Fp/ao2gQgjn8+7ad/l428cARL8djY+nj90zeLp50ql6JzoEdmDwtcEcij5029eBSwdISEnIeP2tIqWyPU9OHbSO7J4Ludb6AnAh7fsbSqnDQCVbBRNCOL6rCVcpO7ksACNajuDTTta/n0tOTebE1RP/FuXL/xbnFFNKns5VsURF6vrWpY5vHX5wSeWqzjoCu6q7u7Wi202+Rq0opQKARkAo0BoYqpR6AQjDfNcek817BgGDAKpWrZrfvEIIBzEzbCaDVw4G4MSwE1QvU/2e3peQnMDRK0dvu1s+GH2QY1eO5TlDYOlA6vjWoY5PHfN/fetwv8/9lHAvcdf3Ns2hjXxCYGCecxgtz52dSqniwCZggtZ6qVLKD7iMud18PFBBa/1ibueQNnIhnFdiSiJeE70waRPdanVjTtc5HLlyJEtTRuT1bPdAyFV6Mc5cmO8rex8eRTxs8CcppKNWlFJuwArgL63159k8HwCs0FrXy+08UsiFcExaay7HX769KF8+xMFLB4mKy9saKUVdi1LHt05GU0b6V2DpQIq4yBSW/LC4s1OZx+18CxzOXMSVUhXS2s8BngYOWBpWCGEdWmvO3TiXpRnjUPQhriVey9O5XJQLJm3C28ObMW3HZBToKqWq4KJktQ8j5eVjsTXwX2C/UuqftGOjgV5KqYaYm1ZOAa9YMZ8QIpNUUyoR1yKyNGMcij5024iMe1HOq1yWZow6vnUo51XutvHWO87toPns5pi0id97/U6Xml2s/ccSFsrLqJWtQHZzY3MdMy6EyNmt1Fscv3L8tjvl9C9N3vqvqpaqmm3HX37XLtFa8/RPT7Ps6DLcXNyIHRVrs7ZqYRlpqBLCiuKT4zly2dzxd/DSwYyhcieunsjzuWqUqZFtYc7rNPT8OHn1JDW+rAHAjCdm8GqTV21+TZF/UsiFyMW1xGvZNmOciT2Tp/O4KJccR2QUdS1qo/T5M+KvEXy+3dwNduWdK5QplnXRK+FYpJCLQkNrzaW4S1k6/Q5FHyI6PvruJ8jE080z28Ic4B2Aq4urjf4EtnU5/jK+n/gCMLL1SCZ1mGRwInGvpJALm7H1GF2tNWdiz/zbjJFp1l9sUmyezlXao/RtHX7pX5VKVCoUy6ZO2zGNYX8MAyBieAQB3gHGBhJ5IoVc2ER+tvhKMaUQHhOebVNGUmre1r8oX7x8tiMyfL18LfuDFTAJyQl4TvQEoEedHizusdjgRCI/pJALm8hpi6/+e7fSN6R7ns8X4B2QbcdfKY/sFz4Sd/fr4V95ZvEzAIQNDKNxxcYGJxL5JYVc2EROK8ilpC0bWqtsrSzNGLXK1qKYWzF7xiyUUk2p1JpWi5MxJ2lYviG7Bu2SCT1OTgq5sAlvkogh6ypy/h7FOBVk/81MhFnImRBafdcKgJW9V/L4fY8bnEhYgxRyYVXJqcmU/rg0cd4tcK39Lqnq3x8xZ11ZriDQWtNlQRdWnVhFsSLFiBkZg3sR51uuVWRPfp8SVrPz3E6KfliUuOQ4Qp76kO/r1Mff3R2FedcVR95CqyA7fuU4LuNcWHViFbOfnE38mHgp4gWM3JELqxj4+0Bm756Nu6s7saNiKepalBbkPEJF2MfwP4czNXQqAFffuZrv6frCsUkhFxa5lniN0h+bi8PkDpN5u/XbBicSAJfiLuH3qflD9P127zPu4XEGJxK2JIVc5NvSw0t5dvGzgEwicSTB24N54683AIh8PZKqpWRHroJOCrnIM601LWa3YMf5HbSo1IK/X/q7UMx+dHRxt+Io/lFxAHrV68WCZxcYnEjYixRykScRMREETjWPPFn63FKerv20wYkEwC+HfqHHzz0A2D1oN40qNDI4kbAnKeTink3eNpmRa0cCEDMyBm8Pb2MDCVJMKVSfWp3T10/TtGJTtr+8XSb3FEJSyMVd3Uq9RfGJxUk2JTPwwYHMenKW0ZEEsPX0VtrOaQvAX33/olP1TgYnEkaRQi5ytf3sdlp+2xKAHS/voGmlpgYnElprOv3YibXhaynpXpLot6Mdbk1zYV9SyEWOBvw2gLl751K8aHGuvnMVN1c3oyMVekcuH6H29NoAzOk6h/4N+xsbSDgEKeQii5iEGMpMNu8K83mnz3mj5RsGJxIA/1v5P2aEzQDg2shrsvKjyCCFXNxm8cHFPP/L8wCcGn4Kf29/gxMZz9YbZNzteu9ULMOQufcDMPahsXzQ/gObXVs4JynkAjC3uzae1Zg9F/fQtmpbNvXfJGPDyd8GGda+3pATEeD7KGf6zqVyycpWv6ZwfjJOSXDy6klcxrmw5+IelvVcxuYBm6WIp8lpg4wx4eF2ux6uHvg3Gi9FXOTonu/IlVJVgHmAH6CBWVrrKUqpMsBPQABwCnhOax1j/ajCFiZumciY9WMAuP7udUq6lzQ4kWPJaYOMnI7b6nqRiQmosQovNy/aB7Snvb/568EKD0ontMhT00oKMEJrvVspVQLYpZRaA/QH1mmtJyml3gXeBUZaP6qwpqSUJDwmeAAwuMlgvnriK4MTOaaq7u5EZlNcdeJFjl4+Si2fWna5XgmdQDW/BuyL2seq46tYdXxVtu93Va48FPCQudAHtKdZpWZ4FPGwakbheJTW+dutRSm1DJiW9vWQ1vqCUqoCsFFrnetPd5MmTXRYWFi+risst+30NtrMaQPArkG7eLDCgwYnclx3tlkDFNEppByeBNHrANj36j7q+9W32fU8XVxyXMv9WuI1tp3exqbITWw8tZGd53fe9Rqtq7TOKPStqrSieNHiVskubE8ptUtr3STL8fwUcqVUALAZqAec1lp7px1XQEz64zveMwgYBFC1atXGkZGReb6usFzfpX2Zv38+pT1Kc+ntSxRxkf7uu8k8isQz9SZxR4M5+vxXXIm/krFtGlhvA2NrjpKJuxVHyNkQNp7ayKbITWw9vfWu72lSsUlG001b/7Z3XYrB3qN6CjOrFXKlVHFgEzBBa71UKXUtc+FWSsVorXNdvV7uyO3vSvwVfD7xAWDqY1MZ1nyYwYmclxpr7ghOfj+ZIi5F2HV+F02++fffVshLIbSo3MKoeHmSmJLIjnM72HRqE5sizV8pppRc31O/XP2MO/porwa8FXnxnn+DEJaxSiFXSrkBK4C/tNafpx07ijStOLSF+xfSe2lvAM68cUZGP1goITkBz4meFCtSjPgx8RnH90ftp8HMBhmPN/bbSPuA9kZEtJrk1GR2X9idUeQ3ndpEXHLcvy9ovhA8ymd5n7+7O6datrRj0sIhp0J+z8MP05pNvgUOpxfxNMuBfmnf9wOWWRJUWI/Wmvoz6tN7aW8eDngY0wcmKeJWUMytGDte3kFCSgKj143OOF7frz46SHN4yGEAHvr+IdRYxeqTqw1Kajk3VzeaV27OO63fYXKHyfSp3+f2F7iXy/Z9thrVI7J3z3fkSqk2wBZgP5D+e9RoIBRYDFQFIjEPP7ya27nkjtz2jl85Ts1pNQFY0WsFT9R8wuBEBc/odaP5aOtHOS4mdvLqSWp8WSPj8bKey3iq1lP2jJhvN5JuMPefuQSHBhMek3XM/JCmQxjWbBidj1/NdpSN3JHbhlU7Oy0lhdy2xm8azwcbzdO4Y9+NpYR7CYMTFVweH3qQlJpE/Oh4irkVy/Y1p6+f5v5p95OQkgDA4u6L6VG3hz1j5kprzcZTG5kSOoVlR7P+Qt3Ovx2vN3+dp2o9hauL623P5XWUjbCMFPJCIDElkWITzMVkWLNhTP3PVIMTFXwpphTcxpsn5Oig3P8tXbhxgXoz6nE1wfwL6/fdvueFB16wecY7nb9xnhk7ZxAcGszNWzdve65MsTK83vx1XmnyCuW8sm82uZOMWrEfKeQF3ObIzbSfa+5Y2/PKHhqWb2hsoELk2JVj1JpWi/4P9GdOtzl3fX10XDSNvm7EuRvnAPi6y9cMajzIJtmSU5NZengpU0KnEHI2JMvzPer0YHjz4bSq0kqWZXACUsgLsOd/fp7FhxZTzqsc5948J2PDDfBl6Je89udredqp52rCVVrMbsHxq8cBCO4czPAWwy3KcfDSQaaETuGb3d9kee5+n/t5vfnr9G3QF6+iXhZdRxhDCnkBdDn+Mr6f+ALw1eNfMbjpYIMTFW61vqzFsavHuPrOVUoXy3UqxW1ik2JpN6cde6P2AvDRox/xbpt37/q+u3VIDm06lGHNh1GzbM17/0MIhyaFvID5Ye8PvPCbuX313JvnqFiiosGJhNYal3HmEb2mD0x5bqqIuxVHh3kd2H5uOwDvt3ufsQ+NRSmV0SEZHBrM8qPLs7y3vX97hjcfnm2HpCg4pJAXECZtovb02hy7coxO1TvxZ58/pW3TgZy/cZ5Kn1fi0WqPsvaFtfk6R0JyAh3ndWTb2W3ZPp+fDklRMORUyKUx1Ylk3q/xjz5/8FiNxwxOJO5UsURFFj67kF5LerHowCJ61ut51/ekd0gGhwaz/ez2HF83uPFgpj0xDRcl2wiI28kduZN4f/37fLjlQwBujropnVUOruMPHVkbvpazb5ylUslKtz134NIBpmyfwuw9s7O8r7ZPbYY3H35bh2RyajJ9lvbh50M/A9D/gf7Mfmq2NKEUQtK04qTS1/UAeLPFm3zW+TODE4l7lb64VnDnYKbumGpxh2SqKZUXl73IvH3zAHi+7vP8+MyPMkqpEJFC7oQ2RGzgkXmPANZd81rYhtaaDac2MCV0SrYdkg8FPMTw5sN5suaTFt1Nm7SJISuHMHPXTACerPkkvzz3C0Vdi+b7nMI5SCF3Ms/+9CxLjyylcsnKnBp+Sn6NdkDnYs/x1c6vmBI65fYVAYGyxcoyvPlwavnU4vlfnmfKY1N4rflrVr2+1pq3Vr/F59vNa9h1qNaB33v/LjsCFWBSyJ3EpbhL+H1qnt48q8ssBjYeaHAiAeZ26iWHlzAldEq2HZLP1X2O4c2H07JyyyyjiAYsG8Dcf+ZydOhRm4zp1lrz/ob3mbBlAgCtKrdizQtr8HTztPq1hLGkkDuBuf/MZcCyAQBcGHGB8sWzrvMs7COvHZJ3c+dmFLagtWbilom8t+E9ABqVb8Sm/ptk0bQCRAq5AzNpEzWm1iDiWgRP3PcEK3qvMDpSoRKbFMucPXOYEjqFiGsRWZ63xgzJ9E5rd1d3Et9LtCTuPfk85HNGrB4BQK2ytQh5KSRPs02FY5JC7qAORR+i7ld1AVjddzUdq3c0OFHBZq8OyeyEnQ+j6TdNGdl6JJM6TLLquXMyY+cM/rfqfwBUKVmF3a/sxsfTxy7XFtYnhdwBjVo7iknbzP+g40bHSZumDeTWIenj6cPw5sMZ1HiQ3WZIjlk3holbJxL6cijNKjWzyzXh9mY7H08f9g/eL013TkgKuQOJT47Ha6K5bfWdVu/wccePDU5UMFjSIWlPnhM8SUhJyHUzClvJvH+rl5sXR4Yeke3/nIgUcgexNnwtHX8wN58cGHyAuuXqGpzIeeXWIVnHt05Gh6Sj/aaTl80obOXXw7/yzOJnAFAoTr52kmqlqxmSRdw7KeQO4KmFT/H7sd8J8A7g5GsnZc2MPLhbh+SwZsMY2myo0yzZmr6n6gsNXuD7p783LMcfx//g8QWPZzy21RBJYR1SyA108eZFKnxWAYDvnvqOAY0GGJzIsWmtWR+xnimhU/j92O9Znn8o4CFeb/46XWp2ceqJUtN3TGfoH0P5s8+fdK7R2dAs6yPW8+i8RzMey2+LjkkKuUFm757NwN/Nk3oujriIX3HZy/BO6R2SwaHBxCfH3/acER2S9lR7Wm2OXDnC1y+eYOLZS4bve7nt9DbazGmT8Xj3oN00qtDI7jlE9qSQ21mqKZWAKQGcjT1Lt1rd+LXnr0ZHcgjJqcn8cugXpoROIfRcaJbnHaVDMp2tNxbWWuMyoyPUegtc/51ab/RO9DvP7aTZ7H9H1YS8FEKLyi0MySL+ZXEhV0p9B3QBLmmt66Ud+z9gIBCd9rLRWutVdztXQS/kBy4doP4M8wJX615YxyPVHjE4kXH2R+1nSugUvt3zbZbn6vjW4fXmr9OnQR+H65AEcxEfdPQo8SZTxjFrFthUUypXEq5Qf/dBLqVm/dDyd3fnVMuWOWazx871ey/upeHXDTMeb+q/iXb+7ax+HXFvrFHI2wE3gXl3FPKbWutP8xKmIBfyt1a/xWch5qVmjRheZqT0Dsng0GBOXTuV5flhzYYxrNkw7it7n/3D5UNASAiRSUlZjpd1SeEd191E3YwiKi7tK+37S3GX8n6hdusgu45vbYLN5nbr+33up2XllrSs3JIrJRoy/mKCzT5gsnM4+jB1vqqT8XjNf9fQIbCDTa4lcmaVphWlVACwQgp5VnG34ij+UXEARrcZzYRHJxicyLacrUNSa82VhCucvHqS8JhwwmPCORlzkpMx5sdnY89mfdM9FNjslPMqh5+XH37F/fDz8qN88fK3PU7/r6+XL0VciuT4gVFSJ9D0zGeEnA25ve+g+ULwyDqZJ7c7eGs5cfUE93357wfx771+p0vNLja9pviXLbd6G6qUegEIA0ZorWOscE6n8teJv3hsvnnbtcNDDnO/z/0GJ7K+c7HnmL5zOlNCpxjaIXkj6Ya5AOdQkPPLVblSvUx1qpeuTmDpQAJLBzIpGaJNWV/r71GMU1Yc/z0hMDDbJpyvaj1In4ez7vvpsnEj2V39dDYfBtZWo0wNdJAm8lokNafV5MmFTwLwc4+f6V6nu82vL7JnaSGfAYwHdNp/PwNezO6FSqlBwCCAqlWrWnhZx6C15rH5j7H65Gpqlq3J4SGHC8TY8PQOyeDQYHac25Hl+efrPs/w5sNpUblFvjokE1MSiYiJuL0gXwvn5FVzQb6Veivf2f1L+VO9THUCvQPN/y0dmFGc87polF8ObeQTAgPznS876c0h6W3eOvEixS/9Tp9287N9fWX3opxJyvr/qKq7u1Vz5cbf25+k95I4F3uOejPq0ePnHgD88PQP9G3Q1245hJlFTSv3+tydCkLTSvpu6QDfd/ueFx54weBEObtbx9i+qH1MDZ2abYdkXd+6DG8+PEuHZIophchrkRl3xLf99+pJbty6ke+85YuXp3rp6rcV5PRiXM6rnF1Hs9irUzGzdeHr6PBDB77o/AWvt3g9y/Pqqw4ON8rlUtwlGs5syIWbFwBZS99WbNVGXkFrfSHt+zeA5lrru24b7uyFfGbYTAavHAzApbcu4evla3CinGU38sINE6Uiv+HyqUVZXl+zbE08inhwLvYcVxKu5Pu6ZYqVybgbTi/C6QW5YomKDtFu7sheWv4S3+35LktTXXpn+uTeu5h+Ocnwced3uhJ/hWazm2U0c335ny8Z2myowakKDmuMWlkIPAT4AFFAUNrjhpibVk4Br6QX9tw4ayFPNaVS6fNKRMVF0aNODxb3WGx0pLvKqSONxIsQ2ivX9xYvWjyjvfjOgly1VFXZI9LG7tyMYl/UPh6Y+QDvtX2P8Y+MNzhd7q4nXqfNnDYcuHQAgI87fMw7rd8xOJXzkwlBFso8nnZjv420D2hvbKB7lFPHmAJutm7mkOO3hVliSiLFJhTDzcWN+DHxhi+0lR83b93kke8fYef5nQAEtQ8iqH2QQ0z2ckY5FXLn75mzg9f/fD2jiCeMSXCaIg45d4BVdXeXIu7gPIp4EDYwjGRTMiU/KgmYf/6cSfGixdkxcAfxo+Np79+esZvG4jLOhZFrRmLETWRBJYU8FzeSbqDGKqaETiGofRA6SDvdDuUTAgPxdLn9r9kWIy+EbTSu2JjOgZ1JSEng6y5fO93PX7pibsXY2H8jiWMS+U+N/zD578m4jHNh2KphUtCtQJpWcrDq+CqeWPAE4PxLexox8kJYx+nrp/EP9qeIKkKKTikwO0klpybT85eeLD2yFIAXG73IN09+UyCG79qStJHfI601HeZ1YP2p9dTxrcP+wfvlh0sYQmuNyzjzz17K+ykUGV8EfB/Fv9H4AvOhnGpKpd9v/Zi/3zxmvle9Xsx7eh5FXKwxV7HgkTbye3A29iwu41xYf2o985+Zz8H/HZQiLgzT6rtWAFx95yquLq582mcP1HqLyKQkNBCZlMSgo0eZHxVlbFALuLq48uMzP5L6QSoDHxzIwgMLcRvvRrdF3UhOTTY6nsXmR0UREBKCy8aNBISE2OzvSqpUmmk7plHliyoAXH77Mr3r9zY4kSjMlhxawvaz21ny3JKMGalfRifcNgkIIN5kYkx4/pcmcBQuyoVZT87C9IGJ4c2Hs+zoMop+WJTOP3QmKcX2Sw/YQvocDnt88Bb6Qp5iSqHs5LIM+2MYvev1RgdpynqWNTqWKMRiEmLo/nN3WlRuQYB3AO+seQf/YH8iE7MfsWKPNVbsRSlF8GPBmD4wMarNKFaHr8Zjggdtv2ubZY0fRzcmPPy2iXhguw/eQt1GvufCHh6c9SAAWwZsoU3VNnd5hxC2ER4TzqIDi1h0YBH7L+3P9jVurZaQ7FYmy3F7rHpoFK01H27+kA82fgBA4wqN2dBvAyXcSxic7O7Uxg2YZ2zccRwwPfRQ/s4pnZ23G7JqCF/t/AqAxDGJuBex34JDovC6FHeJXw79wqIDi9hyekuOrxvcZDCvNH6FBn4NMibP2HqjC0f3ybZPeGeteXZobZ/a/P3S33h7eBsbKhtbIrfQbm47myw3LIU8TWxSLKUmlQLgw4c/ZEy7MYbkEM4lr0M4b966yfKjy1l0YFG267UDlPYoTc96PelZryetq7Tm7zN/025uu1zXJ5GhpP9uWg3m1S53DdrlEM2h0XHRlPv032WcZww4zohT5636wSuFHFh+dDldF3UF4Piw49QoU8PuGYTzye1OuIdPadaGr81oFkk2ZR1poVAZBbtz9c7Z/vaXPh3fx9OH6Lejszwvsvpuz3e8tPwlwLyZx75X9xmyublJm3hywZOsOmHe5XLrgK20rtoaMP/sjAo/yZnERKp4ePBRYHWLPngLdSHXWtN+bnu2nN5Cw/IN2T1ot6z1IO5JUkoSgaE7OJ+cmvXJbBYee/y+x3m+7vN0rdWVUh6l7vk6dy6QJe7dgv0L6LO0D2BeEuDwkMNULlnZLtfO/NtBbguDqbGKsIFhNK7Y2KLr2XKHIIeWPjMOYNGzi3i+3vMGJxL2pLXmasJVIq5FEBETQcS1CMJjwjMeh8eEk6qzKdKZ5bTlm4cf5988T4USFSzK+P769wHY++peKeL50Lt+b3rX782SQ0vo/nN3qnxRBVflyonXThDgHWCTa+46v4sm35jraduqbVnfb/1d/+72XNxjcSHPSYH+qQneHswbf70BwJV3rlCmWNYef+H4UkwpnI09ay7AacU4cyGOirNsXG6lEpWoVroa1byrEVg6kGre1TIeVyxRkeqhO7JdCtjf3cPiIn44+jAfbvmQt1q+RQO/Bhadq7B7ts6z6CDNymMr6bKwC9WmVAPg2NBjVtvw+1riNap+UTVj45Szb5ylUslK9/Tefy7+Y5UM2SmQhTw5NZmyk8ty49YN+j3Qj7nd5hodqdC7kXTjtrviiJgIwq/9W5gtGSPs7uqebSEOLB1IgHeAxSMbctpT09KFx1JNqRk703/S6ROLziX+9UTNJ9BBmrXha+n4Q0dqTjOvk3Rg8AHqlqubr3NqremztA8LDywEYHXf1XSs3jFP55BCngdh58No+k1TAP5+8W9aVimY42vtzaRNXLx5MeMuOPNdccS1CE5fP23R+X09fTOKceZCXM27GlVKVTF0E4s799S01miRwKnmD4K40XEWZxRZdQjsgA7SGcMB680w70K555U9NCzf8J7PM2/vPPr91g+A0W1GM+HRCfnKs+finny9714UqEL+yopXmLVrFkVcihA3Ok52sLlDYkpixj6b2d0VX0u8lu9zK1SOhbha6Wr4evo6dQdzHz8/qw7z+2bXN5y+fpp1L6wrEKsZOrK2/m3RQZrQs6G0+LYFjb5uBEDoy6E0q9Qsx/cdij5E3a/Md/D1y9Vn58Cd+Z5vElg6MGP7O1soEIX8euJ1vD/2BmDSo5MY2WaksYFsJL3j7s7Ousx3x3ftuMtFSfeS2bYTVytdjQDvACk4VnL+xnkGrRjEM7Wf4ZFqjxgdp9BoXrk5OkhnzOhuPrs5AJv7b6atf9uM18XdiuP+6fdzNvYsACdfO0lgacua0RqVbySFPDe/Hv6VZxY/A0D4a+FUK13N4ES5SzGlcOb6mWwLcXhMOJfiLll0/kolKpkLcTZtxhWKV5BNjw2mtabS5+bOsSXPLTE4TeHUqEIjdJDm4KWD1JtRzzwLE3O799IjS5kZNhOApc8t5enaT1vlmg3LN2TJYdv9fTttIdda0+rbVmw/t52mFZsS+nKo3X51j02Kva3TLnMhjoiJICEl/9txubu651iIq3lXy9PYZOF4OszrACCTfhxA3XJ10UGa41eOU3NaTTr92AmAx2s8zoreK6xaT/LSJp8fTlPIM09Nrujmyrm9YyF6O7/0+IVn6zybp3OZtIkLNy7k2DxxJvaMRVkzd9zdOYqiSskquLm6WXR+4Zx+P/o760+tZ8EzC/Dx9DE6jsC8WFn6qJaKJSpy8cZFVp1Yhcs4F5Y8t4Rnaj9jleukF3KttU1uOJ1iZmd2U6RJTeT/KpSgqdv1bO+Kryddz3e+zB13dxbiat7V8PH0ceqOO2F/6Wv8POD3AP+8+o/RcQq9pJQkmnzThAOXDgBw8H8HqeNrHgp6NvYsdabXyRgrPv+Z+RbvT5C+25OlE8iceop+QEhIthMyspsina6Ue6kcR1H4e/tLx52wq/Qp+KYPTHITYLDR60bz0daPAJjXbR7/feC/2b4u6mYUDWY2yOi3+vapb3mx0Yv5vq4aq/ijzx88VuOx/J/D0in6SqnvgC7AJa11vbRjZYCfgADgFPCc1jom3ylzkNPC+cqjPKYg2YFbOLaBvw8EzKMfpIgbZ/XJ1XT+sTMAfer34Yenf8j178OvuB9Rb0VxOf4yTb9pykvLX+Kl5S8x7T/TGNJsSL4y7Lmwx6JCnpO87BA0F7gzwbvAOq31fcC6tMdWV9U9+7GbOR0XwlGEng1l9u7ZTO4w2eIhbCJ/zsWeQ41VdP6xMyXdS3Jt5DV+fObHe/5Q9fH0IWJ4BDEjY6jtU5uhfwxFjVV8+venec5iq0lB91zItdabgat3HO4KfJ/2/fdAN+vEut2EwEA8XW6Pao0p0kLY0q3UW7T4tgWebp683fpto+MUOimmFNp814bKX5hXQgwbGMb1d6/ne+SXt4c3h4YcIvbdWBpXaMzba95GjVWM3zSee22ittU0fUv37PTTWl9I+/4ikOPUN6XUIKVUmFIqLDo6b0Ov+vj5MatWLfzd3VGYd9goLLuiCOflNdELgGsjrxkbpBD6eOvHuI13Y9uZbUx/fDo6SFtt5cES7iUIGxRG3Og42lZtywcbP8BlnAuj1o7KtaC7u7pz/Opxq2S4U546O5VSAcCKTG3k17TW3pmej9Fal77beRxhqzchbGnilomMWT/GKmtQi3u39fRW2s4xz9J84r4nWN5rOS7ZLUFsRYkpiXRd2JXV4asBeK3ZawQ/Fpyl6abF7BaEngtFW9Cvl1Nnp6V/wiilVIW0C1QALJuWKEQBcPzKccasH8P/mv5PiridRMdFo8aqjCJ+6a1LrOi9wuZFHMCjiAd//fcvbr13i261ujF1x1RcxrkwcPlATPrfIdONyjeyWQZL/5TLgX5p3/cDlll4PiGcmkmbMiaYTH98usFpCj6TNtFlQZeMvTK3DNiCDtL4evnaPYubqxu/9vyV5PeT6VWvF7P3zMZ1nCt9l/Yl1ZTKrbLmDZldNm4kICSE+VGWraOf2T0XcqXUQiAEqKWUOquUegmYBHRUSh0HOqQ9FqLQqjvdvFrejVE3DE5S8M3YOQPXca6sPL6Sjx79CB2kaVO1jdGxKOJShAXPLiD1g1RebPQi8/fPp8jMzsxNKAse5dFAZFISg44etVoxd4oJQUI4g/R1qy2d9CFyt/vCbhrPMjdZtanShg39Nzj0Fnlaa0ptWMUNF68sz/m7u3Oq5b3vmVBo9+wUwh6ibkbR77d+PFbjMSniNnI98TpVvqiSr23WjKSU4mY2RRxynuyYV7bvCRCiECj/WXkAVvVeZXCSgkdrTd+lffH+2Jsbt27wZ58/0UHaKYp4OltPapRCLoSFuizoAsCFERdkCr6V/bjvR1zGuTB//3zebf0uOkjTuUZno2Plma0nNUrTihAWWH1yNSuPr2RO1zmUL17e6DgFxuHowxkbU9crV4+wgWH53mbNEdhq39d0UsiFyKebt27S+cfO3FfmPvo37G90nAIh7lYctafXztgT4MSwE1QvU93gVNZh7X1fM5OmFSHyqcRHJQA4MvSIwUmcn9aaIauGUPyj4pyJPcOS55agg3SBKeK2JnfkQuTDa3+8BsDRoUftMnuwIPvtyG88/ZN5b8zBTQYz/fHp0teQR1LIhcij3Rd28+WOLxn30Dhqlq1pdBynFRETQeBUc2df5ZKVOTLkCF5Fsx+mJ3InhVyIPEhOTc6YjPJ++/cNTuOcklKSaPpNU/Zf2g/AgcEHqFuursGpnJv8TihEHvh8Yt40OXFMosFJnNN769/DY4IH+y/t5/tu36ODtBRxK5A7ciHu0echnxObFEvISyFOPRTOCGtOrqHTj50A6F2vd5526BF3J4VciHsQERPBiNUjGNBwAC0qtzA6jtM4f+M8lT43z8AsXrQ4Z944g7eHt7GhCiAp5ELchdY6o1Puu67fGZzGOaSYUnjk+0fYcnoLADsH7qRJxSxrPQkrkTZyIe6iySxzAZIt2+7NJ9s+wW28G1tOb2Haf6ahg7QUcRuTO3IhcvHTgZ/YfXE3vz3/W7437S0s/j7zN62/aw3A4zUe5/fev8sYezuRQi5EDq7EX6Hnkp60929P1/u7Gh3HYV2Ov4zvJ//uyBP1VhTlvMoZmKjwkY9LIXKQPtRwQ78NBidxTCZtouvCrhlFfHP/zeggLUXcAHJHLkQ2nvv5OcC8eYEMk8tqZthMBq8cDMDERyYyqu0ogxMVblLIhbjDhogN/HzoZ2Y8McOpNi+whz0X9vDgrAcBaFW5FRv7b8TN1c3gVEIKuRCZJCQn8Mi8R6hYoiKvNnnV6DgO43ridfyD/bmedB2AM2+coXLJyganEumkjVyITDwnegJw+vXTBidxDFprXvj1Bbw/9uZ60nX+6PMHOkhLEXcwckcuRJqRa0YC5kWcXF1cDU5jvPn75tP3174AjGw9kkkdJhmcSOTEKoVcKXUKuAGkAilaaxn9L5zK/qj9TP57MqPajCr0izgduXyE2tNrA1DHtw67Bu3Co4iHwalEbqx5R/6w1vqyFc8nhF2kmlJpMLMBABMfnWhwGuPEJ8dTZ3odIq9HAgVrm7WCTtrIRaFX+Qtze2/86HiDkxhDa82wP4bhNdGLyOuR/NLjF9lmzclY645cA6uVUhr4Wms9y0rnFcKmpu+YzsWbF9nUfxPF3IoZHcfulh1ZRrefugHwSuNXmPHEDBk374SsVcjbaK3PKaXKAWuUUke01pszv0ApNQgYBFC1alUrXVaI/Dsbe5ahfwylV71etPNvZ3Qcu8q8zVrFEhU5OvQoxYsWNziVyC+ltbbuCZX6P+Cm1vrTnF7TpEkTHRYWZtXrCpEXWmtcxplbFnWQdf8NOLKklCSaz27O3qi9AOwfvJ965eoZnErcK6XUruwGk1jcRq6U8lJKlUj/HugEHLD0vELYUts5bQG48s4Vg5PYzwcbPsBjggd7o/Yyp+scdJCWIl5AWKNpxQ/4Na1drQiwQGv9pxXOK4RN/HbkN7ad2cbi7ospU6yM0XFsbm34Wjr+0BGAnnV7suDZBdIOXsBYXMi11uHAA1bIIoTNXUu8xtM/PU2Tik3oUbeH0XFsKvM2a15uXpx986xss1ZAycxOUaiU/rg0ADte3mFwEttJMaXQYV4HNkVuAmSbtcJAxpGLQqP/b/0BODX8VIFtWvj0709xG+/GpshNTH1sqmyzVkjIHbkoFLad3sb3e78nuHMw/t7+RsexuszbrD1W/TFW9F4h68UUIlLIRYGXlJJEmzlt8PbwZniL4UbHsaor8Vfw/cQXjXkIpWyzVjhJ04oo8DwmmBd8in472uAk1mPSJrot6obPJz5oNJv6b5Jt1goxuSMXBVrQhiAA9ryyhyIuBePH/euwr3l1pXnTiw8f/pAx7cYYnEgYrWD8ZAuRjSOXjzBu8zheb/46Dcs3NDqOxf65+A+Nvm4EQMvKLdnUf5NssyYAKeSigDJpU8aa2l889oXBaSwTmxRLQHAAMYkxgHn3oiqlqhicSjgSaSMXBdJ9X94HwM1RNw1Okn9aa/r/1p9Sk0oRkxjDqt6r0EFairjIQu7IRYHz7e5vCY8JZ81/1+BV1MvoOPmyYP8C+iztA8Dbrd5mcsfJBicSjkwKuShQLty4wMu/v0zXWl3pENjB6Dh5dvTyUe6ffj8AtX1qs/uV3bLNmrgrKeSiwNBaU/HzigD81vM3Y8PkUXxyPPW+qkfEtQgAjg87To0yNQxOJZyFtJGLAqPTj50A86QYZ6G1Zvifw/Ga6EXEtQh+7vEzOkhLERd5InfkokBYdXwVa8PX8sPTPzjNpJjlR5fTdVFXAAY+OJCvu3xdYNeAEbYlhVw4vRtJN3hiwRPU9a1L3wZ9jY5zV5HXIgmYEgBAheIVODbsmGyzJiwihVw4vZKTSgLmbcsc2a3UW7SY3YI9F/cAss2asB5pIxdO7dUV5qnqx4cdd+hmiaANQbh/6M6ei3v47qnvZJs1YVVyRy6c1s5zO/l619d89OhHDts5uC58HR1+MA+DfL7u8yx8dqFDf+AI5ySFXDil5NRkms1uRlHXorzb5l2j42Rx4caFjKGQxYoU49yb5yhdrLTBqURBJYVcOKUSH5UA4MaoGwYnuV2KKYVOP3Riw6kNgHlLuaaVmhqcShR00kYunM6krZNISk1ix8s7KOpa1Og4GT4P+Ry38W5sOLWBKY9NQQdpKeLCLuSOXDiVE1dPMGrdKF5p/IrDFMntZ7fT8tuWAHSu3pmVvVfKNmvCrqSQC6ehtc5Y1XBml5kGpzFvs+b3qR+pOhWAiyMu4lfcz+BUojCyStOKUuoxpdRRpdQJpZTj9TyJAqHBjAYAxL4ba2gOkzbxzE/P4POJD6k6lY39NqKDtBRxYRiL78iVUq7AdKAjcBbYqZRarrU+ZOm5hUj3474fORB9gJW9V1LCvYRhOb7Z9Q2DVgwCYPzD43mv3XuGZREinTWaVpoBJ7TW4QBKqUVAV0AKubCK6Lho/vvrf+kY2JHH73vckAx7L+6l4dcNAWheqTlbBmyRbdaEw7BGIa8EnMn0+CzQ/M4XKaUGAYMAqlataoXLisKi3KfmRbD+6vuX3a8dmxRL4JRAriRcAWSbNeGY7Db8UGs9S2vdRGvdxNfX116XFU4ufXXA82+et+uMSK01A5YNoNSkUlxJuMLK3itlmzXhsKxxR34OyPzTXTntmBAWWRu+luVHlzP7ydlUKFHBbtdddGARvZb0AuCtlm/xSadP7HZtIfLDGoV8J3CfUqoa5gLeE+hthfOKQizuVhwdf+hINe9qvPTgS3a5ZuZt1mqVrcWeV/ZQzK2YXa4thCUsLuRa6xSl1FDgL8AV+E5rfdDiZKJQK/6ReX3uE6+dsPm1EpITqD+jPidjTgJwbOgx7it7n82vK4S1WGVCkNZ6FbDKGucS4o0/3wDg8JDDuCjbdeNorRmxegRfbP8CgMXdF9Ojbg+bXU8IW5GZncKh/HPxH4JDg/mg3Qfc73O/za6z4tgKnlz4JAAvP/gys7rMkuVlhdOSQi4cRoophUZfNwJg7MNjbXKNzNus+Xn5cXzYcUMnGAlhDVLIhcMo94l5vHjimESrn/tW6i1aftuS3Rd2A7Dv1X3U96tv9esIYQRZxlY4hODtwcQkxrDtxW24F3G36rnHbhyL+4fu7L6wm2+f+hYdpKWIiwJF7siF4U5dO8Ubf71Bvwf60apKK6udd0PEBh6Z9wgAPer04KfuP0k7uCiQpJALQ2mtqTalGgBzu821yjkv3rxIhc/ME4g8inhw7s1zlClWxirnFsIRSSEXhmo+27wsT8zIGIvPlWpKpfOPnVkXsQ6A0JdDaVapmcXnFcLRSRu5MMzPB39m5/mdLH1uKd4e3had64uQLygyvgjrItYR3DkYHaSliItCQ+7IhSGuJlzluV+eo02VNjxd++l8nyfzNmsdAzvyR58/ZJs1UehIIReGKDu5LACbB2zO1/uvJlyl/KflSTYlA3BhxAXKFy9vtXxCOBNpWhF21+sX88qCp18/nedRJCZtovvi7pSdXJZkUzIb+m1AB2kp4qJQkztyYVebIzez6OAipv1nWp7X9p69ezYDfx8IwNiHxvJB+w9sEVEIpyOFXNhNQnIC7ee2p5xXOYY0G3LP79sXtY8HZj4AQNOKTdn64laKuha1VUwhnI4UcmE3nhM9AfNuP/fiRtINqk+tTnR8NACRr0dStZRsEyjEnaSNXNjFqLWjAPMaJ3cbVaK15sVlL1JyUkmi46NZ0WsFOkhLERciB3JHLmzu4KWDTNo2ibdbvX3XNU5+OvATPZf0BODNFm/yWefP7BFRCKcmhVzYVKoplXoz6gEwuePkHF937Moxak2rBUDNsjX555V/ZJs1Ie6RFHJhU/7B/gDEjY7L9vmE5AQemPkAx68eB2SbNSHyQ9rIhc3MDJvJuRvnWP/CejzdPLM8P+KvEXhO9OT41eMsenYROkhLERciH+SOXNjE2dizDF45mO51uvNwtYdvey7zNmsvNnqR2U/OluVlhbCAFHJhdVprqnxhnuzzc4+fM46fvn46o6mlnFc5Tgw7IdusCWEFUsiF1T009yEALr99GTBvs9b6u9aEnQ8DYO+re2ng18CoeEIUOBa1kSul/k8pdU4p9U/a1+PWCiac07Ijy9h8ejMLn11IWc+yjNs0DvcP3Qk7H8bsJ2ejg7QUcSGszBp35F9orT+1wnmEk7ueeJ1uP3WjUflG+Hn5ocaa27271+7OTz1+wkVJ37oQtiBNK8Ii86OiGBMezumkJHTiRfB9lD0X1/HIvEco6lqUCyMuyDZrQtiYNQr5UKXUC0AYMEJrbfmeXcIpzI+KYtDRo8SbTOYDHuWh1lsAbH9qAs0rNzcwnRCFh9Ja5/4CpdYC2S32PAbYDlwGNDAeqKC1fjGH8wwCBgFUrVq1cWRkpAWxhSMICAkhMikpy3F/d3dOtWxpQCIhCjal1C6tdZM7j9/1jlxr3eEeL/ANsCKX88wCZgE0adIk908P4RROZ1PEczsuhLANS0etVMj08GnggGVxhDOp6u6ep+NCCNuwdBjBZKXUfqXUPuBh4A0rZBJOYkJgIJ4ut/8Iebq4MCEw0KBEQhROFnV2aq3/a60gwvn08fMDyBi1UtXdnQmBgRnHhRD2IcMPhUX6+PlJ4RbCYDJDQwghnJwUciGEcHJSyIUQwslJIRdCCCcnhVwIIZzcXafo2+SiSkUDjjRH3wfzUgOOSLLljyNnA8fOJ9nyxx7Z/LXWvnceNKSQOxqlVFh26xc4AsmWP46cDRw7n2TLHyOzSdOKEEI4OSnkQgjh5KSQm80yOkAuJFv+OHI2cOx8ki1/DMsmbeRCCOHk5I5cCCGcnBRyIYRwcoWqkCulPJRSO5RSe5VSB5VSY+94fqpS6qYjZVNKzVVKRSil/kn7auhg+ZRSaoJS6phS6rBS6jUHyrYl0/+380qp3xwo26NKqd1p2bYqpWo4ULZH0rIdUEp9r5QybJVUpZSrUmqPUmpF2uNqSqlQpdQJpdRPSqmiRmXLId/QtGxaKeVjtyBa60LzBSigeNr3bkAo0CLtcRPgB+CmI2UD5gLdHfX/HTAAmAe4pD1XzlGy3fGaJcALjpINOAbUTjv+P2Cug2RrBZwBaqYdHwe8ZODP3ZvAAmBF2uPFQM+072cCg43KlkO+RkAAcArwsVeOQnVHrs3S77jd0r60UsoV+AR4x9GyGZXnTrnkGwyM01qb0l53yYGyAaCUKgk8AvzmQNk0UDLteCngvINkSwVuaa2PpR1fAzxr72wASqnKwBPA7LTHCvPf4y9pL/ke6GZEtrQ8t+UD0Frv0VqfsneWQlXIIeNXoX+AS8AarXUoMBRYrrW+4IDZACYopfYppb5QShm2IWYO+aoDzyulwpRSfyil7nOgbOm6Aeu01rEOlO1lYJVS6izwX2CSI2QDdgBFlFLpMxS7A1WMyAYEY765MqU9Lgtc01qnpD0+C1QyIFe6YG7PZ5hCV8i11qla64ZAZaCZUqod0AP40tBgZJutHjAKuB9oCpQBRjpYPncgUZunJn8DfOdA2dL1AhYakQtyzPYG8LjWujIwB/jcEbIBdYGewBdKqR3ADcx36XallOoCXNJa77L3te+Fo+UrdIU8ndb6GrAB86bRNYATSqlTgKdS6oSB0TJne0xrfSHtV+AkzP/gmxmZDW7Ph/muaGnaU78CDQyKBWTJRlqHUzNgpYGxgNuy/Qd4INNvDT9hbps2zB0/cyFa67Za62bAZszt+fbWGngq7d/kIsxNKlMA70ydr5WBcwZkg2zyKaV+NChL4SrkSilfpZR32vfFgI7ALq11ea11gNY6AIjXWhsxgiC7bEeUUhXSjinMTQQH7J0tt3yY250fTntZewz4R59LNjA3DazQWifaO1cu2Q4DpZRSNdNeln7MEbIdUUqVSzvmjvk3wJn2zqa1HqW1rpz2b7InsF5r3Qfzh033tJf1A5bZO1su+foakQUK3+bLFYDv0zo3XYDFWusVBmdKl202pdR6pZQv5hEG/wCvOli+rcB8pdQbwE3Mbb8OkS3tuZ4Y1P6cJqf/bwOBJUopExADvOhA2T5JazpwAWZordcbkC0nI4FFSqkPgT3AtwbnuY0yD799BygP7FNKrdJa2/zfhEzRF0IIJ1eomlaEEKIgkkIuhBBOTgq5EEI4OSnkQgjh5KSQCyGEk5NCLoQQTk4KuRBCOLn/B14KGtJzkpaXAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([simple_sequence], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Solution: Random Permutation" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 8, 9, 12, 3, 2, 6, 11, 0, 14, 15, 7, 4, 5, 13, 10]\n" + ] + } + ], + "source": [ + "random_permutation = np.random.permutation(16).tolist()\n", + "print(random_permutation)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([random_permutation], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Best Solution" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "best_ulysses16 = [0, 13, 12, 11, 6, 5, 14, 4, 10, 8, 9, 15, 2, 1, 3, 7]\n", + "plotTSP([best_ulysses16], ulysses16, num_iters=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Fitness (Sum of all Distances)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def dist(node_0, node_1, coords):\n", + " \"\"\"\n", + " Euclidean distance between two nodes.\n", + " \"\"\"\n", + " coord_0, coord_1 = coords[node_0], coords[node_1]\n", + " return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 0: [38.24 20.42]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 0:\", ulysses16[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Coordinate of City 1: [39.57 26.15]\n" + ] + } + ], + "source": [ + "print(\"Coordinate of City 1:\", ulysses16[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Distance Between 5.882329470541408\n" + ] + } + ], + "source": [ + "print(\"Distance Between\", dist(0, 1, ulysses16))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def fitness(solution, coords):\n", + " N = len(coords)\n", + " cur_fit = 0\n", + " for i in range(len(solution)):\n", + " cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords)\n", + " return cur_fit" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Order Fitness:\t 104.42225210207233\n", + "Random Fitness:\t 142.71833065004333\n", + "Best Fitness:\t 74.10873595815309\n" + ] + } + ], + "source": [ + "print (\"Order Fitness:\\t\", fitness(simple_sequence, ulysses16))\n", + "print (\"Random Fitness:\\t\", fitness(random_permutation, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Naive Random Model" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyRandomModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " random_solutions = []\n", + " for i in range(0, max_it):\n", + " solution = np.random.permutation(self.N).tolist()\n", + " random_solutions.append(solution)\n", + " self.fitness_list.append(self.fitness(solution))\n", + "\n", + " self.best_solution = random_solutions[self.fitness_list.index(min(self.fitness_list))]\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_file = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[*] [Node] 16, [Best] 108.63032651658955\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model, max_it=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Genetic Algorithm" + ] + }, + { + "cell_type": "code", + "execution_count": 244, + "metadata": {}, + "outputs": [], + "source": [ + "class Gene: # City\n", + " def __init__(self, name, lat, lng):\n", + " self.name = name\n", + " self.lat = lat\n", + " self.lng = lng\n", + "\n", + " def get_distance_to(self, dest):\n", + " return math.sqrt( (self.lng - dest.lng) ** 2 + (self.lat - dest.lat) ** 2 )\n", + "\n", + "class Individual: # Route: possible solution to TSP\n", + " def __init__(self, genes):\n", + " assert(len(genes) > 3)\n", + " self.genes = genes\n", + " self.__reset_params()\n", + "\n", + " def swap(self, gene_1, gene_2):\n", + " self.genes[0]\n", + " a, b = self.genes.index(gene_1), self.genes.index(gene_2)\n", + " self.genes[b], self.genes[a] = self.genes[a], self.genes[b]\n", + " self.__reset_params()\n", + "\n", + " def add(self, gene):\n", + " self.genes.append(gene)\n", + " self.__reset_params()\n", + "\n", + " @property\n", + " def fitness(self):\n", + " if self.__fitness == 0:\n", + " self.__fitness = 1 / self.travel_cost # Normalize travel cost\n", + " return self.__fitness\n", + "\n", + " @property\n", + " def travel_cost(self): # Get total travelling cost\n", + " if self.__travel_cost == 0:\n", + " for i in range(len(self.genes)):\n", + " origin = self.genes[i]\n", + " if i == len(self.genes) - 1:\n", + " dest = self.genes[0]\n", + " else:\n", + " dest = self.genes[i+1]\n", + "\n", + " self.__travel_cost += origin.get_distance_to(dest)\n", + "\n", + " return self.__travel_cost\n", + "\n", + " def __reset_params(self):\n", + " self.__travel_cost = 0\n", + " self.__fitness = 0\n", + "\n", + "class Population: # Population of individuals\n", + " def __init__(self, individuals):\n", + " self.individuals = individuals\n", + "\n", + " @staticmethod\n", + " def gen_individuals(sz, genes):\n", + " individuals = []\n", + " for _ in range(sz):\n", + " individuals.append(Individual(sample(genes, len(genes))))\n", + " return Population(individuals)\n", + "\n", + " def add(self, route):\n", + " self.individuals.append(route)\n", + "\n", + " def rmv(self, route):\n", + " self.individuals.remove(route)\n", + "\n", + " def get_fittest(self):\n", + " fittest = self.individuals[0]\n", + " for route in self.individuals:\n", + " if route.fitness > fittest.fitness:\n", + " fittest = route\n", + "\n", + " return fittest" + ] + }, + { + "cell_type": "code", + "execution_count": 380, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "from random import randint, sample\n", + "\n", + "class MyGAModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.iteration = 0\n", + "\n", + " def init(self, nodes):\n", + " super().init(nodes)\n", + "\n", + " def evolve(self, pop, tourn_size, mut_rate):\n", + " new_generation = Population([])\n", + " pop_size = len(pop.individuals)\n", + " elitism_num = pop_size // 4\n", + "\n", + " # Elitism\n", + " for _ in range(elitism_num):\n", + " fittest = pop.get_fittest()\n", + " new_generation.add(fittest)\n", + " pop.rmv(fittest)\n", + "\n", + " # Crossover\n", + " for _ in range(elitism_num, pop_size):\n", + " parent_1 = self.selection(new_generation, tourn_size)\n", + " parent_2 = self.selection(new_generation, tourn_size)\n", + " child = self.crossover(parent_1, parent_2)\n", + " new_generation.add(child)\n", + "\n", + " # Mutation\n", + " for i in range(elitism_num, pop_size):\n", + " self.mutate(new_generation.individuals[i], mut_rate)\n", + "\n", + " return new_generation\n", + "\n", + " def crossover(self, parent_1, parent_2):\n", + " def fill_with_parent1_genes(child, parent, genes_n):\n", + " start_at = randint(0, len(parent.genes)-genes_n-1)\n", + " finish_at = start_at + genes_n\n", + " for i in range(start_at, finish_at):\n", + " child.genes[i] = parent_1.genes[i]\n", + "\n", + " def fill_with_parent2_genes(child, parent):\n", + " j = 0\n", + " for i in range(0, len(parent.genes)):\n", + " if child.genes[i] == None:\n", + " while parent.genes[j] in child.genes:\n", + " j += 1\n", + " child.genes[i] = parent.genes[j]\n", + " j += 1\n", + "\n", + " genes_n = len(parent_1.genes)\n", + " child = Individual([None for _ in range(genes_n)])\n", + " fill_with_parent1_genes(child, parent_1, genes_n // 2)\n", + " fill_with_parent2_genes(child, parent_2)\n", + "\n", + " return child\n", + "\n", + " def mutate(self, individual, rate):\n", + " for _ in range(len(individual.genes)):\n", + " if random.random() < rate:\n", + " sel_genes = sample(individual.genes, 2)\n", + " individual.swap(sel_genes[0], sel_genes[1])\n", + "\n", + " def selection(self, population, competitors_n):\n", + " return Population(sample(population.individuals, competitors_n)).get_fittest()\n", + "\n", + " def fit(self, max_it=20):\n", + " \"\"\"\n", + " Execute simulated annealing algorithm.\n", + " \"\"\"\n", + " pop_size = 1000\n", + " mut_rate = 0.9\n", + " tourn_size = 100\n", + "\n", + " genes = [Gene(num, city[0], city[1]) for num, city in enumerate(self.coords)]\n", + " self.genes = genes\n", + "\n", + " population = Population.gen_individuals(pop_size, genes)\n", + " \n", + "\n", + " for it in range(0, max_it):\n", + " mut_rate = mut_rate * 0.95\n", + " if mut_rate < 0.05:\n", + " mut_rate = 0.05\n", + " population = self.evolve(population, tourn_size, mut_rate)\n", + " cost = population.get_fittest().travel_cost\n", + "\n", + " it += 1\n", + " self.fitness_list.append(cost)\n", + " print(\"[step] \", it, \" [mut] \", mut_rate, \" [best] \", self.fitness_list[self.fitness_list.index(min(self.fitness_list))])\n", + "\n", + " self.best_solution = [gene.name for gene in population.get_fittest().genes]\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "code", + "execution_count": 381, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_problem = \"./template/data/simple/ulysses16.tsp\"" + ] + }, + { + "cell_type": "code", + "execution_count": 382, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Genetic Algorithm\n", + "[step] 1 [mut] 0.855 [best] 96.11229392543888\n", + "[step] 2 [mut] 0.8122499999999999 [best] 93.76996122899693\n", + "[step] 3 [mut] 0.7716374999999999 [best] 93.76996122899693\n", + "[step] 4 [mut] 0.7330556249999999 [best] 93.36477102051143\n", + "[step] 5 [mut] 0.6964028437499998 [best] 93.36477102051143\n", + "[step] 6 [mut] 0.6615827015624998 [best] 93.36477102051143\n", + "[step] 7 [mut] 0.6285035664843748 [best] 90.01149831972343\n", + "[step] 8 [mut] 0.597078388160156 [best] 90.01149831972343\n", + "[step] 9 [mut] 0.5672244687521482 [best] 89.10668237027161\n", + "[step] 10 [mut] 0.5388632453145408 [best] 89.10668237027161\n", + "[step] 11 [mut] 0.5119200830488138 [best] 89.10668237027161\n", + "[step] 12 [mut] 0.486324078896373 [best] 75.20103046245312\n", + "[step] 13 [mut] 0.4620078749515544 [best] 75.20103046245312\n", + "[step] 14 [mut] 0.43890748120397666 [best] 75.20103046245312\n", + "[step] 15 [mut] 0.4169621071437778 [best] 75.10440611823527\n", + "[step] 16 [mut] 0.3961140017865889 [best] 75.10440611823527\n", + "[step] 17 [mut] 0.37630830169725943 [best] 74.94828839659989\n", + "[step] 18 [mut] 0.3574928866123964 [best] 74.94828839659989\n", + "[step] 19 [mut] 0.33961824228177656 [best] 74.94828839659989\n", + "[step] 20 [mut] 0.3226373301676877 [best] 74.94828839659989\n", + "[step] 21 [mut] 0.3065054636593033 [best] 74.94828839659989\n", + "[step] 22 [mut] 0.29118019047633814 [best] 74.23355449180846\n", + "[step] 23 [mut] 0.2766211809525212 [best] 74.21961177789215\n", + "[step] 24 [mut] 0.26279012190489515 [best] 74.21961177789215\n", + "[step] 25 [mut] 0.24965061580965037 [best] 74.21961177789215\n", + "[step] 26 [mut] 0.23716808501916783 [best] 73.987618045175\n", + "[step] 27 [mut] 0.22530968076820942 [best] 73.987618045175\n", + "[step] 28 [mut] 0.21404419672979894 [best] 73.987618045175\n", + "[step] 29 [mut] 0.20334198689330898 [best] 73.987618045175\n", + "[step] 30 [mut] 0.19317488754864354 [best] 73.987618045175\n", + "[step] 31 [mut] 0.18351614317121134 [best] 73.987618045175\n", + "[step] 32 [mut] 0.17434033601265078 [best] 73.987618045175\n", + "[step] 33 [mut] 0.16562331921201823 [best] 73.987618045175\n", + "[step] 34 [mut] 0.15734215325141732 [best] 73.987618045175\n", + "[step] 35 [mut] 0.14947504558884644 [best] 73.987618045175\n", + "[step] 36 [mut] 0.14200129330940411 [best] 73.987618045175\n", + "[step] 37 [mut] 0.1349012286439339 [best] 73.987618045175\n", + "[step] 38 [mut] 0.1281561672117372 [best] 73.987618045175\n", + "[step] 39 [mut] 0.12174835885115033 [best] 73.987618045175\n", + "[step] 40 [mut] 0.11566094090859282 [best] 73.987618045175\n", + "[step] 41 [mut] 0.10987789386316317 [best] 73.987618045175\n", + "[step] 42 [mut] 0.104383999170005 [best] 73.987618045175\n", + "[step] 43 [mut] 0.09916479921150474 [best] 73.987618045175\n", + "[step] 44 [mut] 0.0942065592509295 [best] 73.987618045175\n", + "[step] 45 [mut] 0.08949623128838302 [best] 73.987618045175\n", + "[step] 46 [mut] 0.08502141972396386 [best] 73.987618045175\n", + "[step] 47 [mut] 0.08077034873776566 [best] 73.987618045175\n", + "[step] 48 [mut] 0.07673183130087738 [best] 73.987618045175\n", + "[step] 49 [mut] 0.0728952397358335 [best] 73.987618045175\n", + "[step] 50 [mut] 0.06925047774904183 [best] 73.987618045175\n", + "[step] 51 [mut] 0.06578795386158974 [best] 73.987618045175\n", + "[step] 52 [mut] 0.06249855616851025 [best] 73.987618045175\n", + "[step] 53 [mut] 0.05937362836008474 [best] 73.987618045175\n", + "[step] 54 [mut] 0.0564049469420805 [best] 73.987618045175\n", + "[step] 55 [mut] 0.05358469959497647 [best] 73.987618045175\n", + "[step] 56 [mut] 0.050905464615227644 [best] 73.987618045175\n", + "[step] 57 [mut] 0.05 [best] 73.987618045175\n", + "[step] 58 [mut] 0.05 [best] 73.987618045175\n", + "[step] 59 [mut] 0.05 [best] 73.987618045175\n", + "[step] 60 [mut] 0.05 [best] 73.987618045175\n", + "[step] 61 [mut] 0.05 [best] 73.987618045175\n", + "[step] 62 [mut] 0.05 [best] 73.987618045175\n", + "[step] 63 [mut] 0.05 [best] 73.987618045175\n", + "[step] 64 [mut] 0.05 [best] 73.987618045175\n", + "[step] 65 [mut] 0.05 [best] 73.987618045175\n", + "[step] 66 [mut] 0.05 [best] 73.987618045175\n", + "[step] 67 [mut] 0.05 [best] 73.987618045175\n", + "[step] 68 [mut] 0.05 [best] 73.987618045175\n", + "[step] 69 [mut] 0.05 [best] 73.987618045175\n", + "[step] 70 [mut] 0.05 [best] 73.987618045175\n", + "[step] 71 [mut] 0.05 [best] 73.987618045175\n", + "[step] 72 [mut] 0.05 [best] 73.987618045175\n", + "[step] 73 [mut] 0.05 [best] 73.987618045175\n", + "[step] 74 [mut] 0.05 [best] 73.987618045175\n", + "[step] 75 [mut] 0.05 [best] 73.987618045175\n", + "[step] 76 [mut] 0.05 [best] 73.987618045175\n", + "[step] 77 [mut] 0.05 [best] 73.987618045175\n", + "[step] 78 [mut] 0.05 [best] 73.987618045175\n", + "[step] 79 [mut] 0.05 [best] 73.987618045175\n", + "[step] 80 [mut] 0.05 [best] 73.987618045175\n", + "[step] 81 [mut] 0.05 [best] 73.987618045175\n", + "[step] 82 [mut] 0.05 [best] 73.987618045175\n", + "[step] 83 [mut] 0.05 [best] 73.987618045175\n", + "[step] 84 [mut] 0.05 [best] 73.987618045175\n", + "[step] 85 [mut] 0.05 [best] 73.987618045175\n", + "[step] 86 [mut] 0.05 [best] 73.987618045175\n", + "[step] 87 [mut] 0.05 [best] 73.987618045175\n", + "[step] 88 [mut] 0.05 [best] 73.987618045175\n", + "[step] 89 [mut] 0.05 [best] 73.987618045175\n", + "[step] 90 [mut] 0.05 [best] 73.987618045175\n", + "[step] 91 [mut] 0.05 [best] 73.987618045175\n", + "[step] 92 [mut] 0.05 [best] 73.987618045175\n", + "[step] 93 [mut] 0.05 [best] 73.987618045175\n", + "[step] 94 [mut] 0.05 [best] 73.987618045175\n", + "[step] 95 [mut] 0.05 [best] 73.987618045175\n", + "[step] 96 [mut] 0.05 [best] 73.987618045175\n", + "[step] 97 [mut] 0.05 [best] 73.987618045175\n", + "[step] 98 [mut] 0.05 [best] 73.987618045175\n", + "[step] 99 [mut] 0.05 [best] 73.987618045175\n", + "[step] 100 [mut] 0.05 [best] 73.987618045175\n", + "[step] 101 [mut] 0.05 [best] 73.987618045175\n", + "[step] 102 [mut] 0.05 [best] 73.987618045175\n", + "[step] 103 [mut] 0.05 [best] 73.987618045175\n", + "[step] 104 [mut] 0.05 [best] 73.987618045175\n", + "[step] 105 [mut] 0.05 [best] 73.987618045175\n", + "[step] 106 [mut] 0.05 [best] 73.987618045175\n", + "[step] 107 [mut] 0.05 [best] 73.987618045175\n", + "[step] 108 [mut] 0.05 [best] 73.987618045175\n", + "[step] 109 [mut] 0.05 [best] 73.987618045175\n", + "[step] 110 [mut] 0.05 [best] 73.987618045175\n", + "[step] 111 [mut] 0.05 [best] 73.987618045175\n", + "[step] 112 [mut] 0.05 [best] 73.987618045175\n", + "[step] 113 [mut] 0.05 [best] 73.987618045175\n", + "[step] 114 [mut] 0.05 [best] 73.987618045175\n", + "[step] 115 [mut] 0.05 [best] 73.987618045175\n", + "[step] 116 [mut] 0.05 [best] 73.987618045175\n", + "[step] 117 [mut] 0.05 [best] 73.987618045175\n", + "[step] 118 [mut] 0.05 [best] 73.987618045175\n", + "[step] 119 [mut] 0.05 [best] 73.987618045175\n", + "[step] 120 [mut] 0.05 [best] 73.987618045175\n", + "[step] 121 [mut] 0.05 [best] 73.987618045175\n", + "[step] 122 [mut] 0.05 [best] 73.987618045175\n", + "[step] 123 [mut] 0.05 [best] 73.987618045175\n", + "[step] 124 [mut] 0.05 [best] 73.987618045175\n", + "[step] 125 [mut] 0.05 [best] 73.987618045175\n", + "[step] 126 [mut] 0.05 [best] 73.987618045175\n", + "[step] 127 [mut] 0.05 [best] 73.987618045175\n", + "[step] 128 [mut] 0.05 [best] 73.987618045175\n", + "[step] 129 [mut] 0.05 [best] 73.987618045175\n", + "[step] 130 [mut] 0.05 [best] 73.987618045175\n", + "[step] 131 [mut] 0.05 [best] 73.987618045175\n", + "[step] 132 [mut] 0.05 [best] 73.987618045175\n", + "[step] 133 [mut] 0.05 [best] 73.987618045175\n", + "[step] 134 [mut] 0.05 [best] 73.987618045175\n", + "[step] 135 [mut] 0.05 [best] 73.987618045175\n", + "[step] 136 [mut] 0.05 [best] 73.987618045175\n", + "[step] 137 [mut] 0.05 [best] 73.987618045175\n", + "[step] 138 [mut] 0.05 [best] 73.987618045175\n", + "[step] 139 [mut] 0.05 [best] 73.987618045175\n", + "[step] 140 [mut] 0.05 [best] 73.987618045175\n", + "[step] 141 [mut] 0.05 [best] 73.987618045175\n", + "[step] 142 [mut] 0.05 [best] 73.987618045175\n", + "[step] 143 [mut] 0.05 [best] 73.987618045175\n", + "[step] 144 [mut] 0.05 [best] 73.987618045175\n", + "[step] 145 [mut] 0.05 [best] 73.987618045175\n", + "[step] 146 [mut] 0.05 [best] 73.987618045175\n", + "[step] 147 [mut] 0.05 [best] 73.987618045175\n", + "[step] 148 [mut] 0.05 [best] 73.987618045175\n", + "[step] 149 [mut] 0.05 [best] 73.987618045175\n", + "[step] 150 [mut] 0.05 [best] 73.987618045175\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[step] 151 [mut] 0.05 [best] 73.987618045175\n", + "[step] 152 [mut] 0.05 [best] 73.987618045175\n", + "[step] 153 [mut] 0.05 [best] 73.987618045175\n", + "[step] 154 [mut] 0.05 [best] 73.987618045175\n", + "[step] 155 [mut] 0.05 [best] 73.987618045175\n", + "[step] 156 [mut] 0.05 [best] 73.987618045175\n", + "[step] 157 [mut] 0.05 [best] 73.987618045175\n", + "[step] 158 [mut] 0.05 [best] 73.987618045175\n", + "[step] 159 [mut] 0.05 [best] 73.987618045175\n", + "[step] 160 [mut] 0.05 [best] 73.987618045175\n", + "[step] 161 [mut] 0.05 [best] 73.987618045175\n", + "[step] 162 [mut] 0.05 [best] 73.987618045175\n", + "[step] 163 [mut] 0.05 [best] 73.987618045175\n", + "[step] 164 [mut] 0.05 [best] 73.987618045175\n", + "[step] 165 [mut] 0.05 [best] 73.987618045175\n", + "[step] 166 [mut] 0.05 [best] 73.987618045175\n", + "[step] 167 [mut] 0.05 [best] 73.987618045175\n", + "[step] 168 [mut] 0.05 [best] 73.987618045175\n", + "[step] 169 [mut] 0.05 [best] 73.987618045175\n", + "[step] 170 [mut] 0.05 [best] 73.987618045175\n", + "[step] 171 [mut] 0.05 [best] 73.987618045175\n", + "[step] 172 [mut] 0.05 [best] 73.987618045175\n", + "[step] 173 [mut] 0.05 [best] 73.987618045175\n", + "[step] 174 [mut] 0.05 [best] 73.987618045175\n", + "[step] 175 [mut] 0.05 [best] 73.987618045175\n", + "[step] 176 [mut] 0.05 [best] 73.987618045175\n", + "[step] 177 [mut] 0.05 [best] 73.987618045175\n", + "[step] 178 [mut] 0.05 [best] 73.987618045175\n", + "[step] 179 [mut] 0.05 [best] 73.987618045175\n", + "[step] 180 [mut] 0.05 [best] 73.987618045175\n", + "[step] 181 [mut] 0.05 [best] 73.987618045175\n", + "[step] 182 [mut] 0.05 [best] 73.987618045175\n", + "[step] 183 [mut] 0.05 [best] 73.987618045175\n", + "[step] 184 [mut] 0.05 [best] 73.987618045175\n", + "[step] 185 [mut] 0.05 [best] 73.987618045175\n", + "[step] 186 [mut] 0.05 [best] 73.987618045175\n", + "[step] 187 [mut] 0.05 [best] 73.987618045175\n", + "[step] 188 [mut] 0.05 [best] 73.987618045175\n", + "[step] 189 [mut] 0.05 [best] 73.987618045175\n", + "[step] 190 [mut] 0.05 [best] 73.987618045175\n", + "[step] 191 [mut] 0.05 [best] 73.987618045175\n", + "[step] 192 [mut] 0.05 [best] 73.987618045175\n", + "[step] 193 [mut] 0.05 [best] 73.987618045175\n", + "[step] 194 [mut] 0.05 [best] 73.987618045175\n", + "[step] 195 [mut] 0.05 [best] 73.987618045175\n", + "[step] 196 [mut] 0.05 [best] 73.987618045175\n", + "[step] 197 [mut] 0.05 [best] 73.987618045175\n", + "[step] 198 [mut] 0.05 [best] 73.987618045175\n", + "[step] 199 [mut] 0.05 [best] 73.987618045175\n", + "[step] 200 [mut] 0.05 [best] 73.987618045175\n", + "[*] [Node] 16, [Best] 73.987618045175\n", + "[*] Running for: 32.92 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyGAModel()\n", + "\n", + "print(\"Genetic Algorithm\")\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_problem, model, max_it=200)" + ] + }, + { + "cell_type": "code", + "execution_count": 383, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 383, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(fitness_list, 'o-')" + ] + }, + { + "cell_type": "code", + "execution_count": 384, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotTSP([best_solution], load_data(tsp_problem), num_iters=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 386, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Best Fitness:\t 73.987618045175\n", + "Best Fitness:\t 74.10873595815309\n" + ] + } + ], + "source": [ + "print (\"Best Fitness:\\t\", fitness(best_solution, ulysses16))\n", + "print (\"Best Fitness:\\t\", fitness(best_ulysses16, ulysses16))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Your Smart Model" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import random\n", + "from model.base_model import Model\n", + "\n", + "class MyModel(Model):\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def init(self, nodes):\n", + " \"\"\"\n", + " Put your initialization here.\n", + " \"\"\"\n", + " super().init(nodes)\n", + " self.log(\"Nothing to initialize in your model now\")\n", + "\n", + " def fit(self, max_it):\n", + " \"\"\"\n", + " Put your iteration process here.\n", + " \"\"\"\n", + " self.log(\"Naive Random Solution\")\n", + " self.best_solution = np.random.permutation(self.N).tolist()\n", + " self.fitness_list.append(self.fitness(self.best_solution))\n", + "\n", + " return self.best_solution, self.fitness_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test your Model" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_problem = './template/data/simple/ulysses16.tsp'" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[MyModel] Nothing to initialize in your model now\n", + "[MyModel] Naive Random Solution\n", + "[*] [Node] 16, [Best] 147.19356281214667\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyModel()\n", + "best_solution, fitness_list, time = TSP_Bench(tsp_file, model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test All Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "./template/data/medium/pcb442.tsp\n", + "./template/data/medium/a280.tsp\n", + "./template/data/hard/dsj1000.tsp\n", + "./template/data/simple/att48.tsp\n", + "./template/data/simple/ulysses16.tsp\n", + "./template/data/simple/st70.tsp\n" + ] + } + ], + "source": [ + "for root, _, files in os.walk('./template/data'):\n", + " if(files):\n", + " for f in files:\n", + " print(str(root) + \"/\" + f)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_results(best_solutions, times, title):\n", + " fig = plt.figure()\n", + " nodes = [len(s) for s in best_solutions]\n", + " data = np.array([[node, time] for node, time in sorted(zip(nodes, times))])\n", + " plt.plot(data[:, 0], data[:, 1], 'o-')\n", + " fig.suptitle(title, fontsize=20)" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [], + "source": [ + "tsp_path = './template/data/medium'" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Random Search\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "[*] [Node] 442, [Best] 722875.708265324\n", + "[*] Running for: 0.26 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "[*] [Node] 280, [Best] 31126.512432333657\n", + "[*] Running for: 0.16 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyRandomModel()\n", + "\n", + "print(\"Random Search\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model)" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Random Model\")" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Genetic Algorithm\n", + "[*] ./template/data/medium/pcb442.tsp\n", + "'module' object is not callable\n", + "[*] Unkown -4\n", + "[*] No Answer -1\n", + "[*] Running for: 0.12 seconds\n", + "\n", + "[*] ./template/data/medium/a280.tsp\n", + "'module' object is not callable\n", + "[*] Unkown -4\n", + "[*] No Answer -1\n", + "[*] Running for: 0.05 seconds\n", + "\n", + "[*] ./template/data/hard/dsj1000.tsp\n", + "'module' object is not callable\n", + "[*] Unkown -4\n", + "[*] No Answer -1\n", + "[*] Running for: 0.38 seconds\n", + "\n", + "[*] ./template/data/simple/att48.tsp\n", + "'module' object is not callable\n", + "[*] Unkown -4\n", + "[*] No Answer -1\n", + "[*] Running for: 0.01 seconds\n", + "\n", + "[*] ./template/data/simple/ulysses16.tsp\n", + "'module' object is not callable\n", + "[*] Unkown -4\n", + "[*] No Answer -1\n", + "[*] Running for: 0.00 seconds\n", + "\n", + "[*] ./template/data/simple/st70.tsp\n", + "'module' object is not callable\n", + "[*] Unkown -4\n", + "[*] No Answer -1\n", + "[*] Running for: 0.01 seconds\n", + "\n" + ] + } + ], + "source": [ + "model = MyGAModel()\n", + "\n", + "print(\"Genetic Algorithm\")\n", + "best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, model, max_it=100, timeout=600)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_results(best_solutions, times, \"Genetic Algorithm\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/images/ab-pruning.png b/images/ab-pruning.png new file mode 100644 index 0000000000000000000000000000000000000000..6d60996aef0420e93884d169ef0aa44bd204afb1 GIT binary patch literal 41494 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 NUv$91D({m&{sTN}R44!d literal 0 HcmV?d00001 diff --git a/images/minimax.png b/images/minimax.png new file mode 100644 index 0000000000000000000000000000000000000000..cae1c807de9fb020aa7f5f84e9592de03d8a0856 GIT binary patch literal 42780 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

7REQ!- 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 R08z2EM+ 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 literal 0 HcmV?d00001 diff --git a/images/solutions.png b/images/solutions.png new file mode 100644 index 0000000000000000000000000000000000000000..4e2e934c30797fa8b48a1cb201fd799419aee30c GIT binary patch literal 44087 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 SO_Ri*9%t`tcgEH&^nU<2z}3+J literal 0 HcmV?d00001 diff --git a/images/terminal.png b/images/terminal.png new file mode 100644 index 0000000000000000000000000000000000000000..8e15da3af41c3471d7b15670feb9f9eb856b8ef0 GIT binary patch literal 56215 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 literal 0 HcmV?d00001 diff --git a/.dockerignore b/template/.dockerignore similarity index 100% rename from .dockerignore rename to template/.dockerignore diff --git a/.gitignore b/template/.gitignore similarity index 100% rename from .gitignore rename to template/.gitignore diff --git a/Dockerfile b/template/Dockerfile similarity index 100% rename from Dockerfile rename to template/Dockerfile diff --git a/README.md b/template/README.md similarity index 83% rename from README.md rename to template/README.md index 02cadaf..487f313 100644 --- a/README.md +++ b/template/README.md @@ -1,3 +1,6 @@ +## Build Image + +docker build -t com2014-tsp . ## Windows diff --git a/data/hard/dsj1000.tsp b/template/data/hard/dsj1000.tsp similarity index 100% rename from data/hard/dsj1000.tsp rename to template/data/hard/dsj1000.tsp diff --git a/data/medium/a280.tsp b/template/data/medium/a280.tsp similarity index 100% rename from data/medium/a280.tsp rename to template/data/medium/a280.tsp diff --git a/data/medium/pcb442.tsp b/template/data/medium/pcb442.tsp similarity index 100% rename from data/medium/pcb442.tsp rename to template/data/medium/pcb442.tsp diff --git a/data/simple/att48.tsp b/template/data/simple/att48.tsp similarity index 100% rename from data/simple/att48.tsp rename to template/data/simple/att48.tsp diff --git a/data/simple/st70.tsp b/template/data/simple/st70.tsp similarity index 100% rename from data/simple/st70.tsp rename to template/data/simple/st70.tsp diff --git a/data/simple/ulysses16.tsp b/template/data/simple/ulysses16.tsp similarity index 100% rename from data/simple/ulysses16.tsp rename to template/data/simple/ulysses16.tsp diff --git a/main.py b/template/main.py similarity index 96% rename from main.py rename to template/main.py index dc0054b..048f30b 100644 --- a/main.py +++ b/template/main.py @@ -35,13 +35,13 @@ def TSP(tsp_file, model): coords = load_data(tsp_file) # Set timeout - signal.signal(signal.SIGALRM, timeout_handler) - signal.alarm(60) + # signal.signal(signal.SIGALRM, timeout_handler) + # signal.alarm(60) # Try your algorithm try: model.init(coords) - best_solution, fitness_list = model.fit(max_it=100000) + best_solution, fitness_list = model.fit(max_it=10000) except Exception as exc: if(str(exc) == "Timeout"): log("Timeout -3") diff --git a/model/anneal_model.py b/template/model/anneal_model.py similarity index 98% rename from model/anneal_model.py rename to template/model/anneal_model.py index 621d16b..bcb1a9d 100644 --- a/model/anneal_model.py +++ b/template/model/anneal_model.py @@ -72,7 +72,7 @@ class SimAnneal(Model): self.log("Starting annealing.") while self.T >= self.stopping_temperature and self.iteration < max_it: candidate = list(self.cur_solution) - l = random.randint(2, self.N - 1) + l = random.randint(1, self.N - 1) i = random.randint(0, self.N - l) candidate[i : (i + l)] = reversed(candidate[i : (i + l)]) self.accept(candidate) diff --git a/model/base_model.py b/template/model/base_model.py similarity index 100% rename from model/base_model.py rename to template/model/base_model.py diff --git a/model/my_model.py b/template/model/my_model.py similarity index 100% rename from model/my_model.py rename to template/model/my_model.py diff --git a/template/output/.gitignore b/template/output/.gitignore new file mode 100644 index 0000000..1c471ba --- /dev/null +++ b/template/output/.gitignore @@ -0,0 +1,8 @@ +# .gitignore sample +################### + +# Ignore all files in this dir... +* + +# ... except for this one. +!.gitignore \ No newline at end of file diff --git a/requirements.txt b/template/requirements.txt similarity index 100% rename from requirements.txt rename to template/requirements.txt diff --git a/template/utils/load_data.py b/template/utils/load_data.py new file mode 100644 index 0000000..592fb6a --- /dev/null +++ b/template/utils/load_data.py @@ -0,0 +1,21 @@ +def log(msg): + print('[*] {msg}'.format(msg=msg)) + +def load_data(file): + coords = [] + with open(file, "r") as infile: + line = infile.readline() + # Skip instance header + while "NODE_COORD_SECTION" not in line: + line = infile.readline() + + for line in infile.readlines(): + line = line.replace("\n", "") + if line and 'EOF' not in line: + line = [float(x) for x in line.lstrip().split(" ", 1)[1].split(" ") if x] + coords.append(line) + return coords + +def timeout_handler(signum, frame): + print("Timeout") + raise Exception("Timeout") diff --git a/template/utils/tsp.py b/template/utils/tsp.py new file mode 100644 index 0000000..d21722b --- /dev/null +++ b/template/utils/tsp.py @@ -0,0 +1,139 @@ +import os +import signal +import json +import math +import timeit + +from utils.load_data import load_data +from utils.load_data import log + +def timeout_handler(signum, frame): + raise Exception("Timeout") + +def dist(node_0, node_1, coords): + """ + Euclidean distance between two nodes. + """ + coord_0, coord_1 = coords[node_0], coords[node_1] + return math.sqrt((coord_0[0] - coord_1[0]) ** 2 + (coord_0[1] - coord_1[1]) ** 2) + +def fitness(solution, coords): + N = len(coords) + cur_fit = 0 + for i in range(len(solution)): + cur_fit += dist(solution[i % N], solution[(i + 1) % N], coords) + return cur_fit + +def TSP_Bench(tsp_file, model, *args, max_it=1000, timeout=60): + + start = timeit.default_timer() + + # Model Running + best_solution, fitness_list = TSP(tsp_file, model, *args, max_it=max_it,timeout=timeout) + # Model End + + stop = timeit.default_timer() + print('[*] Running for: {time:.2f} seconds'.format(time=(stop - start))) + + print() + return best_solution, fitness_list, (stop - start) + +def TSP_Bench_ALL(tsp_file_path, model, *args, max_it=1000, timeout=60): + best_solutions = [] + fitness_lists = [] + times = [] + for root, _, files in os.walk(tsp_file_path): + if(files): + for f in files: + # Get input file name + tsp_file = str(root) + '/' + str(f) + log(tsp_file) + + # Run TSP + best_solution, fitness_list, time = TSP_Bench(tsp_file, model, *args, max_it=max_it,timeout=timeout) + best_solutions.append(best_solution) + fitness_lists.append(fitness_lists) + times.append(time) + + return best_solutions, fitness_lists, times + +def TSP(tsp_file, model, *args, max_it=1000, timeout=60): + + best_solution = [] + fitness_list = [] + + nodes = load_data(tsp_file) + + # Set timeout + signal.signal(signal.SIGALRM, timeout_handler) + signal.alarm(timeout) + + if not os.path.exists('output'): + os.makedirs('output') + + # Try your algorithm + try: + model.init(nodes, *args) + best_solution, fitness_list = model.fit(max_it) + except Exception as exc: + if(str(exc) == "Timeout"): + log("Timeout -3") + with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile: + outfile.write("-3") + best_solution = [-1] * len(nodes) + else: + print(exc) + log("Unkown -4") + with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile: + outfile.write("-4") + + signal.alarm(0) + + # Collect results + if(len(fitness_list) > 0): + log("[Node] " + str(len(best_solution)) + ", [Best] " + str(fitness_list[fitness_list.index(min(fitness_list))])) + + if (len(best_solution) == 0): + log("No Answer -1") + with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile: + outfile.write("-1") + elif (len(best_solution) != len(nodes)): + log("Invalid -2") + with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile: + outfile.write("-2") + else: + # log("Writing the best solution to file" ) + with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.txt', "w") as outfile: + outfile.write(str(model.fitness(best_solution))) + outfile.write("\n") + outfile.write(", ".join(str(item) for item in best_solution)) + + # Write to JSON + data = {} + + data['nodes'] = [] + for i in range(len(nodes)): + data['nodes'].append({ + 'title': str(i), + 'id': i, + 'x': int(nodes[i][0]), + 'y': int(nodes[i][1]) + }) + + data['edges'] = [] + for i in range(len(best_solution)): + if i == len(best_solution)-1: + data['edges'].append({ + 'source': best_solution[i], + 'target': best_solution[0] + }) + else: + data['edges'].append({ + 'source': best_solution[i], + 'target': best_solution[i+1] + }) + + with open('output/' + os.path.splitext(os.path.basename(tsp_file))[0] + '.json', 'w') as outfile: + json.dump(data, outfile) + + return best_solution, fitness_list \ No newline at end of file diff --git a/utils/visualize_tsp.py b/template/utils/visualize_tsp.py similarity index 100% rename from utils/visualize_tsp.py rename to template/utils/visualize_tsp.py