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": "iVBORw0KGgoAAAANSUhEUgAAAXcAAAD4CAYAAAAXUaZHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAA2Y0lEQVR4nO3deXjc5XXo8e+Z0UgzkkerNbIlW5JjG3kDbJAdCCEhYDCBBDu+SQNJU9rkNm2SNmlD3UBzn6S397bQuklv27S55WajTxICAccmhcTYkISs4BW8yMYmWJttWdZiyRqtM+/9Y2ZkWdY2muU38/udz/P4sTQzmjkg6fid93fec8QYg1JKKXtxWR2AUkqp5NPkrpRSNqTJXSmlbEiTu1JK2ZAmd6WUsqEcqwMAmDt3rqmtrbU6DKWUyir79u07b4wpn+i+jEjutbW17N271+owlFIqq4hI42T36baMUkrZkCZ3pZSyIU3uSillQ9MmdxH5hoicE5HDY24rFZFdInIi+ndJ9PZbROSCiByM/vlCKoNXSik1sZms3L8F3DnutgeBF4wxS4EXop/H/NwYszr652+SE6ZSSql4TFstY4x5SURqx928Ebgl+vFjwE+BzyUzsOlsP9DK1p3HOd3dT2Wxjy0b6ti0piqdISilVMaa7Z57hTHmTPTjs0DFmPtuFJFXReRHIrJysicQkY+LyF4R2dve3h7Xi28/0MpD2w7R2t2PAVq7+3lo2yG2H2iN+z9EKaXsKOELqibSMzjWN3g/UGOMuRb4V2D7FF/3qDGm3hhTX14+YQ3+pLbuPE7/cOiy2/qHQ2zdeTyu51FKKbuabXJvE5H5ANG/zwEYY3qMMRejHz8HeERkblIiHeN0d39ctyullNPMNrk/A9wf/fh+YAeAiMwTEYl+vC76/B2JBjleZbEvrtuVUsppZlIK+Tjwa6BORFpE5GPAI8DtInICWB/9HOD9wGEReRX4F+Bek4JRT1s21OHzuC+7zedxs2VDXbJfSmWZ7QdauemRF1n04LPc9MiLeh1GOdZMqmXum+Su2yZ47FeAryQa1HRiVTFbdx6ntbsfn8fNw5uv1moZh4tdaI9dj4ldaAf0Z0M5TtaeUN20popfPngr6xaVsqqqUH95lV5oV2qMrE3uMTWl+TR2BK0OQ2UAvdCu1CVZn9xr5xZwrneQ4NCI1aEoi+mFdqUuyfrkXl2aD0BTp67ene7P1i+94ja90K6cKuuTe01ZJLnr1owqm5N72edVxT690K4cKyMmMSWiprQAgCZN7o636+g5CnLdrKwsYjgc5gefvMnqkJSyTNav3IvyPRTnezjV0Wd1KMpC4bDhhYY23llXzoISH+d6Bq0OSSlLZX1yh0jFjO65O9uh1guc6x1k/fIKygvzaO8dJAXn55TKGrZI7tVlBbrn7nC7G9pwCbyrLkDA72UoFKY7OGx1WEpZxhbJvbYsn9bufoZDYatDURbZdbSN+tpSSgpyqSjMA+Bcr27NKOeyRXKvLs0nFDa0dulhFSdq7gxy7Gwvty+PjBUI+L0AtPUMWBmWUpayRXKvKYtUzDTqvrsjvdDQBsD6FbHkrit3pWyR3GtHa921YsaJdjecY3F5AYvmRv6RD4xuy+jKXTmXLZJ7uT8Pn8etF1UdqGdgmN/8toPbV8wbvS0/Nwd/Xo6WQypHs0VyFxGqtYGYI/3seDsjYcPtKwKX3V5emKcrd+VotkjuEGlD0NSp2zJOs7uhjbKCXFYvLLns9oA/T1fuytFsldwbO4KEw3pwxSmGQ2F+cuwcty4L4HbJZfcF/F69oKoczTbJvbqsgMGRsP5CO8ieNzvpGRgZrZIZqyK6LaOnVJVT2Sa515RqxYzT7GpoIzfHxc1L515xX8DvZWA4TO+g9vlXzmSb5F4bq3XXi6qOYIxhd0Mbb18yl/zcK5ubjpZD6kEm5VC2Se6VxV5yXEKjXlR1hNfbLtLc2c/65VduyUCkPBbQi6rKsWyT3HPcLqpKfLpyd4jd0VOpty0PTHh/rAWBXoNRTmWb5A6RNgSa3J1h19E2rl1QREWhd8L7K/SUqnI4eyX30ny9oOoA53oHONjcPemWDMCcvBx8Hjdtui2jHMpeyb0sn56BEbqDQ1aHolLoxYZzABOWQMaICIHCPN2WUY5ls+SuFTNOsLuhjQUlPpbN80/5uMgpVd2WUc5ks+QeqXXXear21T8U4ucnzrN+eQUiMuVjA4Ve2nXlrhxq2uQuIt8QkXMicnjMbaUisktETkT/LoneLiLyLyJyUkReE5HrUhn8eNXRg0xNunK3rV+cPM/gSJjbp9iSiQn483Rgh3KsmazcvwXcOe62B4EXjDFLgReinwO8G1ga/fNx4KvJCXNmvB43FYV5OrTDxnYdPYvfm8O6RaXTPjbg99I3FKJPT6kqB5o2uRtjXgI6x928EXgs+vFjwKYxt/+nifgNUCwi85MU64xEyiF1W8aOQmHDCw3nuKUugMc9/bpEJzIpJ5vtnnuFMeZM9OOzQOw9chXQPOZxLdHbriAiHxeRvSKyt729fZZhXKlG+7rb1sHmbjr6hlg/ycGl8WI18HpRVTlRwhdUTaTtXtyt94wxjxpj6o0x9eXl5YmGMaqmLJ9zvYMEh/StuN3sbmgjxyXcctXMknusv0ybrtyVA802ubfFtluif5+L3t4KLBzzuAXR29ImVg7ZpPvutrP7aBvrFpVSlO+Z0eNHt2V05a4caLbJ/Rng/ujH9wM7xtz+e9GqmRuAC2O2b9KiZnRYtiZ3Ozl1vo8T5y5OeSp1vCKfh9wcl5ZDKke6slfqOCLyOHALMFdEWoAvAo8AT4rIx4BG4HeiD38OuAs4CQSBP0hBzFOqKY2u3DW520qsUVg8yV1EIgeZNLkrB5o2uRtj7pvkrtsmeKwBPpVoUIkoyvdQnO/R1r82s7uhjboKP9XRd2YzpbXuyqlsdUI1Ritm7KU7OMSeU10zOrg0ns5SVU5ly+Rera1/beWnx9sJhc2UjcImEyjU/jLKmWyZ3GtK82nt7mc4FLY6FJUEuxraKPfncU1VUdxfW1HopWdghIHhUAoiUypz2TO5l+UTChtau/qtDkUlaGgkzM+Ot7N+eQCXa+pGYROJjdvTihnlNDZN7tHWv1rrnvV+89sOLg6OxFUlM1as1l0vqiqnsWlyj3WH1IqZbLe7oQ2vx8VNS+bO6ut1lqpyKlsm94A/D6/HxSm9qJrVjDHsPtrGzUvL8Xrcs3qO0VmqunJXDmPL5C4i1JRqxUy2O3qmh9MXBrh9llsyACX5ueS4RFfuynFsmdwBqsvyadKDTFlt99FziMC7ls2sUdhEXC6h3J+ng7KV49g2uccOMoXDcTesVBlid0MbaxYWj1a8zFakBYFuyyhnsW9yn1vA4EhY345nqTMX+jnUemFWB5fG01mqyomm7S2TrWpKY90h+5hX5LU4GhWvFxoiXaTvSEZy9+exr7Er4edRU9t+oJWtO49zurufymIfWzbUsWnNhLN6VBrYd+Uea/2rte5ZaXdDG7Vl+Swun5PwcwX8Xjr7hhga0RPLqbL9QCsPbTtEa3c/Bmjt7uehbYfYfiCt4xzUGLZN7lXFPnJcovNUs1Df4Ai/OtnB+uUViMR/KnW82ESm9ou6NZMKw6Ewf/dcA/3jWjz0D4fYuvO4RVEp227L5LhdVJX4tBwyC/38RDtDoXBS9tvh8olMVcW+pDynU7X3DnLsbA/HzvTScKaHhrO9nDzXy3Bo4sKF093aAsQqtk3uANWl+TpuLwvtOnqOIp+H+pqSpDzf6KBsvah6hcn2yQdHQpw8d5FjZ3ojyfxsJJmfvzg0+rUVhXksm1fIO66ay5N7mukKDl/x/JX6j6llbJ3ca8sK2HFQ9/yyyUgozIvH2rh1WYAcd3J2DXWW6sRi++Sx7ZTW7n4eePJVHvlRA+cvDjESLSPOzXFRV+HnXXUBls0vZPk8P8vmF1JakDv6XMvnFV72XAA+j4stG+rS+x+lRtk6udeU5dMzMEJ3cIji/Nzpv0BZbn9TN13B4Vk3CptI2Zw8XKIr9/G27jx+xT55yBi6g8P80TvfwrJ5hSyf76e2rGDaf2hjVTFbdx6nNboV8/7rF2i1jIVsndyrSy8Ny9bknh12N7ThcQvvuGp2jcIm4nYJZXPyOKenVC8z2X744EiYLRuWxf18m9ZUsWlNFeGw4T3/+gt+crydwZEQeTmz6wukEmPbahm41Pr3lFbMZI3dR9u44S1l+L2epD5vRaGeUh1vsv3wRPfJXS7hobuW0dLVz7d/05TQc6nZs3Vyj63cm7RiJiu80X6R357vm9Ws1OnoLNUrbdlQR864ASg+jzsp++Q3Ly3n5qVz+dcXT3Ch/8oLrSr1bJ3cfbluKgrz9CBTlth9tA2A25K43x4T0OZhV9i0porrqotxCQiRsyEPb746afvkD757GRf6h/nqT99IyvPN1vYDrdz0yIssevBZbnrkRcccrLL1njtATWmBrtyzxO6GNlZWFqakFj3gz6Ojb5CRUDhpVTh2ICJcV13CU594W9Kfe2VlEe9bU8U3fvkmH7mxxpIzBhNVBD207RCA7S/22v6nvKYsX/fcs0DHxUH2NXYltUpmrEChF2Ogo29o+gc7SFNnkOpoq45UeOCOyBbPl59/PWWvMZWJKoKccnLWEcn9XO8g/UOh6R+sLLH9QCu3fflnhA1895WmlLxtvlTrrlszMQPDIc72DIxem0qFqmIff/C2WrYdaOHo6Z6Uvc5kJqsIcsLJWdsn9+poxYyeVM1MsbfN3dHTje29gylpOBWInlLVQdmXtHT1Y8ylJnup8slbllDo9fD3Pz6W0teZyGSzAJxwctb2yb02+oOrWzOZKV1vm0dX7loxMyo2qay6tCClr1OU7+FPb13Cz15v5xcnzqf0tcbqGRgmHL6yE2iyKoIyXULJXUQ+IyKHReSIiPxZ9La/FpFWETkY/XNXUiKdpZroD65eVM1M6XrbXD6a3HXlHhNrqpfKbZmYj9xYw4ISHw//qCEt09GMMfzl91+jq3+ET9+2hLJoq4S5c3KTWhGUyWad3EVkFfCHwDrgWuA9IrIkevc/GWNWR/88l4Q4Z60o30ORz0OjzlPNSKk6SDOex+2irCBXV+5jNHYEyc91M3dO6k9v5+W4+Ys76jhyuodnXj2d8tf72s/f5MdHzvLQu5fx2dvrePEvbkEEfu/GWkckdkhs5b4ceNkYEzTGjAA/AzYnJ6zkqinL19a/Gepjb6+94rZUvW0u9+dp87AxmjuDVJfmJ6Vn/kzcc20lKysL2brzOAPDqStweOXNTh758THuXDmPj719EQBFPg91FX72nOpM2etmmkSS+2HgZhEpE5F84C5gYfS+PxGR10TkGyIyYd9WEfm4iOwVkb3t7e0JhDG9mrICTe4Z6kL/CBBpD5CKgzRjBQr1lOpYjZ3BlF9MHcvlEv7qruW0dvfz7d80puQ1zvUO8Cff3c/CEh//8IFrLvuHa21tKfsbuxgJOWMi16yTuzGmAfh74Hngx8BBIAR8FVgMrAbOAF+a5OsfNcbUG2Pqy8vLZxvGjNSU5tPa3c+wQ76p2SIUNnx/bzPvuKqcl/9qPW8+cje/fPDWlL1trvBr87CYcNhEatzTsN8+1k1L5vLOq8r51xdPcmGC/u+JGAmF+fTjB+gZGOarv3s9heP6E9XXltA3FOLY2d6kvm6mSuiCqjHm68aY640x7wC6gNeNMW3GmJAxJgz8PyJ78paqLssnFDaOqG3NJi+daOf0hQHuXbtw+gcnQaAwj/aLg2m5oJfpzvUOMjQSHi0VTqcH372MnoFh/v2nJ5P6vF/a9Tq/+W0n/3vT1SyfX3jF/fW1pQCOGZaeaLVMIPp3NZH99u+KyPwxD3kfke0bS9WOdofUrZlM8sQrzZQV5KbsVOp4Ab+XUNjoKVUYnS1ck+aVO8Dy+YVsXrOAb/7qFC1dyfmd3H20ja/+9A3uW7eQ91+/YMLHVBX7qCzyOmbfPdE696dF5CjwQ+BTxphu4B9E5JCIvAa8C/jzBF8jYbF9xSatdc8Y7b2D7G5o479dv4DcnPQctwhoOeSoWDO9dO65j/XAHVcByWlL0NQR5LNPHmRVVSFffO/KKR9bX1vKnlOdGGP/d2+JbsvcbIxZYYy51hjzQvS2jxhjrjbGXGOMuccYcyY5oc5ewJ+H1+PSi6oZ5On9LYyEDb9Tn54tGbh0SlUvqkYSotsllp3UrCz28dGbFvGDg60cOX1h1s8zMBzik9/dB8BXP3w9Xs/Ug0HW1pbQ1jNIS5f9t2htf0IVIp3vakoLdFsmQxhjeGJPM2trS1gSmJO2142t3Nv1oipNnUEqi714LOyQ+YlbFlPk8/DIj2bfluB//vAIh1t7+PLvrGbhDLaYYvvuexvtvzXjiOQOkYuqTXqQKSO8/GYnb57v49611Wl9XT2lekljZ3D09LZVinwe/vTWpfz8xHleej3+cuin9rXw+CvNfOKWxayf4YCXqyr8+L057Dll/4uqjknuNaX5NHUGtVIiAzyxpxl/Xg53XT1/+gcnkdfjpsjn0aEdRK4/zWSlm2q/e0N1tC3Bsbh+NxvO9PD5HxzixreU8cDtV83469wu4fqaEvY64KKqc5J7WT4Dw2Hdb7XYheAwzx06w8Y1lfhy0z84OeDXWao9A8N0BYctu5g6Vl5O5DRyw5keth+cWSfQnoFhPvHtfRT5PPzLfWviHr6ytraU19su0h20d9WUg5J75C1oo1bMWGr7wVYGR8Jp35KJqdBTqqNN9Kwog5zIe6+p5OqqIr70/OvTtiWINQRr7urnKx+6btKWvlOpr4kcmrd7vbuDknvkB1nnqVrHGMPjrzSxqqqQVVVFlsQQ0FOqo7MNUjmBKR4ul/DQXcto7e7nP399asrHfv0XkYZgD965jHWLSmf1etcuLMbjFtvvuzsmuVcW+3C7RFv/WuhQ6wWOne3lgxat2gHKC/No7x10RJ3zZNLZ6nem3rZ4Lu+qK+crL56cdLtkz6lOHv5RpCHYf7950axfy+txs6qqiH02r5hxTHL3uF0sKPHp0A4LPf5KM16Pi42rKy2LIeD3MhQKj05+cqKmziClBbn4x/Vesdrn3r2M3sER/u0nV7YlaO8d5FPfmbgh2GysrS3l1eYLKe1OaTXHJHeIrFR03J41+gZHeOZgK3dfXXlFQ6d0qijUiUxNnX0ZtWqPWTavkPdft4DHftVI85jf0+kags1GfU0JQ6Ewh1tnf4Aq0zkquWtfd+s8e+gMfUMh7l2XvhOpEwn4Y6dUnVsx09iR/m6QM/XZO65CBL70/KUxi1/e9Tq//m3HpA3BZuP66EVVO++751gdQDrVlhVwoX+Y7uAQxfmpnz6jLvneK00sLi8YrVSwSuyUqlNr3YdDYU539/O+DJ1GNL/Ix8fevoh//+kb/PKNDtqj77BuWFQ6aUOw2Sibk8fi8oJovfvipD1vJnHUyj22WtHVe3q93tbL/qZu7l1bnbapP5MJFDr7lGprVz9hk1kXU8dbWBrpd9M+ZuvsYEs32w/MrA5+ptbWlrK3scu2BxsdldxHa9113z2tntjTjMctbL7O+tVifm4O/rwcx5ZDXuoGaW3rgal85cU3rrhtYDjM1p3HJ3j07NXXlnKhf5iT7ReT+ryZwlHJfXTlfl4rZtJlcCTEtv0t3LFiHmVz4j9wkgqxckgnirW9zuSV+2RDdZI9bGdtbWzf3Z4lkY5K7r5cNxWFebpyT6Pnj7TRFRzmg2matjQTAX8ebQ4dlN3UGSQvxzV67SETTdaGONntiatL85k7J4+9Nr2o6qjkDlBTWqAHmdLoiT3NVBX7ePuSuVaHMirgd24LgliljMtl7bWPqWzZUIdvXF92nyfSgyaZRIS1tSW6creL6rJ8GrX1b1o0dQT5xcnzfHDtwoxKJhWFkeZhTjyl2tQZzIiGYVPZtKaKhzdfTVWxDyEyHu/hzVenZHB6fW0pLV39nL1gv3dyjiqFBKgty+epfYP0D4Us6UroJE/ubcYlJLWELRkCfi8Dw2F6B0csPVCVbsYYmjqD3Li4zOpQprVpTVVKkvl4sX33vY2dvOca605Op4IDV+6RKgE9qZpaI6Ew39/XzDuvKrdslNtkRsshHbbvfv7iEMGhUMZ0g8wEK+YXkp/rtuW+u+OSe81orbtuzaTST4+309YzyL3rrGsSNpnRiUwOK4eMTSLL5DLIdMtxu1hTXWzLfXfHJffa0b7uunJPpe/taWbunDxuXRawOpQrVDh0UHbsZz4TJjBlkvqaUhrO9NA7YK9mco5L7kX5Hop8Hr2omkJtPQP85Pg53n/9AksHME8m4NBZqk2dQUQunQBVEWtrSwkbONDUbXUoSZV5v3lpoA3EUuupfS2EwiajatvHmpOXg8/jdt62TEeQ+YVe8nK0kGCs1dXFuF1iu7mqjkzu1aWa3FMlHDY8saeZG95SyqK5mbm3KyIECvNoc9q2TGcwY6YvZZI5eTksn++3XYdIRyb32rICWrv7GQ6FrQ7Fdn792w6aOoPcl4EXUseq8HsdVy3T1Jm5rX6tVl9TyoHmLlvlBEcm9+qyfEJhk/ReFSpyIbXI52HDynlWhzIlp/WXCQ6N0N47qJUyk1hbW8rAcJgjp3usDiVpHJncY+WQp3RrJqm6+obYefgs71tThdeT2fu6AX+eo6plRodi68p9QvWxw0w22ndPKLmLyGdE5LCIHBGRP4veVioiu0TkRPRva6czTKA2uhfcpLXuSbXtQCtDoXDGXkgdK+D3cnFwhL7BEatDSYtMHIqdSSoKvVSX5tvqMNOsk7uIrAL+EFgHXAu8R0SWAA8CLxhjlgIvRD/PKAF/Hl6PSy+qJpExhif2NHHtwuKkjUJLpUvlkM5YvTeP9nHX5D6Z+toS9jZ22qbnUCIr9+XAy8aYoDFmBPgZsBnYCDwWfcxjwKaEIkwBEYlUzGgLgqQ50NzN620XuTcLVu0w5iCTQy6qNnYEKfTm6HjJKaytLeX8xSHbbNcmktwPAzeLSJmI5AN3AQuBCmPMmehjzgIVE32xiHxcRPaKyN729vYEwpid6tICbUGQRN97pYn8XDfvvTY7mi9dGrfnjJV7Y2dQL6ZOw27DO2ad3I0xDcDfA88DPwYOAqFxjzHAhO9xjDGPGmPqjTH15eXlsw1j1mrL8mnqDNrmLZiVegeG+eGrZ3jvNZXMycuORqOXBmU7Y+XerGWQ01pcPoeSfI9tLqomdEHVGPN1Y8z1xph3AF3A60CbiMwHiP59LvEwk6+mLJ+B4bBjVm6p9F+vnaF/OMQH12XHlgxAkc9Dbo7LEeWQobChpUsPME1HRLi+psQ2F1UTrZYJRP+uJrLf/l3gGeD+6EPuB3Yk8hqpEmv9e0rnqSbse680UVfhZ83CYqtDmTERcUw55OnufoZDRlv9zkB9bSm/Pd/H+YvZ/3ORaJ370yJyFPgh8CljTDfwCHC7iJwA1kc/zzi10VWMXlRNzNHTPbzacoEPrl2ISOZMW5qJSHK3/7bMaI27rtynNTq8wwar94Q2SI0xN09wWwdwWyLPmw6VxT7cLtF5qgl6cm8zuW4X70vD1JxkC/i9nGy/aHUYKacHmGZuVVURuTku9p7q5M5VmX3KejqOPKEK4HG7qCr2cUorZmZtYDjEtv0t3LlqHiUF2VdiFyjMc0QpZGNHEI9bmF+krX6nk5fjZvWCYvY0Zv/K3bHJHSIXVXXc3uxsP9DKjQ+/QM/ACL964zzbD7RaHVLcKgq99AyMMDAcmv7BWayps4+FJfm4M2hIeSarry3hSOsF+oey++fC8cldT6nGb/uBVh7adoiuYGRyzfmLQzy07VDWJfjYuD27V8w0dQZ1+lIc1taWMhI2HGzutjqUhDg7uZcWcKF/mO7gkNWhZJWtO4/RP2612z8cYuvO4xZFNDtOmMhkjKGxI6htB+JwXXUJItnfRMzRyT1WPaCr95lr7x2ktXviZJhtLZQD/kgLgjYbT2TqDg7TOzCiF1PjUJTvoa7Cn/X77o5O7qPDsnXffUaeO3SGDf/npUnvryzOrgt2FbEWBDa+qNo42jBMWw/E4/qaEvY3dhEKZ+8Jdkcn99hqRlv/Tq07OMSnHz/AJ7+znwUlPh68sw7fuH7tPo+bLRvqLIpwdkryc8lxia0PMmkZ5OysrS3l4uAIx85m7/CO7GgEkiK+XDcBf55tusClwovH2njw6UN09g3x2duv4hO3LMbjdjGvyMfWncc53d1PZbGPLRvq2JRlte4ul1Bu81OqsYWLJvf41I85zLSyssjiaGbH0ckdIlszepDpSr0Dw/yv/zrKk3tbWDbPzzd+fy2rqi79kG9aU5V1yXwiAX+erZuHNXYECfjz8OVm9mSsTFNV7GN+kZc9pzq5/221VoczK45P7tVl+fz8RPpbDmeyX548z18+9RpnLvTzyVsW85n1S8nLsWdyCBR6RwdZ2JEOxZ4dEaG+tpRX3uzAGJN1rTXA4XvuEJmn2tYzmPUHFpIhODTCF3Yc5sNfe5m8HBdPf+Jt/OWdy2yb2MH+s1SbOrUb5GytrS2hrWeQlq7sqgKLcfzKvSY2T7UzSN08v8XRWGfvqU4e+P6rNHUG+ehNi9iyoc4Rb+UDfi+dfUMMjYTJzbHXWmdgOMTZngFqSrVSZjbqa0oB2NfYlZWHwOz10zwLsTaoTp3KNDAc4uHnGvjAf/yasDE8/oc38IX3rnBEYodLE5nabdDidbyWriDG6NzU2aqb58efl5O1k5l05R79wXdij5nXWrp54MlXOXHuIh96azV/ddfyrJmklCxja92rsqxOfzqxn+lsXHVmArdLuC6Lh3c46zd5AsX5uRR6cxzRHXL7gdbR8sU5eTlcHByhotDLYx9dxzuvSv+ow0wQO6Vqx3332MlrXbnPXn1NCV/a9ToXgsMU5XusDicujt+WAaidW2D7FgSxZl+t3f0YoHdwBJcIn16/xLGJHcb2l7Fnci/IdVOWhe2YM0V9bXTfvSn7tmY0uRM54GH3bZmtO49f0ewrZAz/9uIbFkWUGcrm5OESe7YgaI52g8zGMr5MsXphMTkuYU8Wbs1ocifytrWlq5/hUNjqUFLCGEPrJE29sq3ZV7K5XULZnDzO2bB5WGOndoNMlC/XzaqqoqzsEKnJnUhTpVDY2DLRhcKGLz5zZNL7s63ZVypUFNpvlmo4bGjqDGrDsCRYW1vCq80Xsm6oiyZ3xpZD2mtrZmA4xCe/s4///HUjt9aV4/Nc/u3OxmZfqRDwe223597WO8DQSFhPpyZBfW0pQ6Ewh1svWB1KXDS5c6kdqp1q3bv6hvjw117m+aNt/PV7V/CNP1jHw5uvoarYhxDpnfHw5qtt0R8mUZH+MvZK7rF+SZrcE1dfE2kilm377o4vhYTIL7fX47LNyr25M8j933yFlq5+/v1D1/Huq+cD9mn2lWwBfx4dfYOMhMLkuO2x3rnUx12Te6LK5uTxlvKC6L77YqvDmTF7/CQnyOUSqkvzbTG043DrBTZ/9Vd0XBziO//9raOJXU0uUOjFGOjos8+4xaaOIG6X6DWVJFlbU8q+pi7CWTS8Q5M7kRrwpo4gu462cdMjL2bdoOeYl15v54P/8Wty3S6e/sSNrI3W6Kqpjda622hrpqkzSFWxD49N3olY7fraErqDw7zRftHqUGbM8d/52OGegZFIGWRrdz8PbTuUdQn+6X0tfPRbe6guK2DbJ9/GkoBzm6DFK1AYO6Vqn4qZRm31m1SxhVI27bs7PrlPdLinfzjE1p3HLYooPsYY/u0nJ3ng+6/y1reU8uQf3UBFNFmpmYmt3O10UbWpo09b/SZRbVk+c+fkZlW9e0LJXUT+XESOiMhhEXlcRLwi8i0ReVNEDkb/rE5SrCkxWW17a3c/PQPDaY4mPqGw4X9sP8zWncd535oqvvn76/B7s6v/RSYoH21BYI+Ve8/AMF3B4dESX5U4EaG+ppQ9jQ5I7iJSBXwaqDfGrALcwL3Ru7cYY1ZH/xxMPMzUmeqC07q/3c0DT77KnlOdGJNZF1L6h0L88bf38Z2Xm/jELYv58u9ca7t+5OnicbsoK8i1Ta27lkGmRn1tCc2d/Zy9kB2LgESzQQ7gE5EcIB84nXhI6bVlQx0+z+W9y30eF5+9fSmbr1vAziNn+cD//TW3fflnPPrSG5zPgL7fnX1DfOhrv2F3Qxt/s3Eln7tzmfYPSVC53z4tCGJ9knRbJrli++57s2T1Pus6d2NMq4j8I9AE9APPG2OeF5EPAX8rIl8AXgAeNMZk7G9NrO471gq3stjHlg11o7f/j7uX8+xrZ3hiTzN/99wxtu48zu0rKvjg2mrevmQubld6k2pTR6SG/XR3P1/98PXcuWpeWl/frgKF3pRuy4xttzz+ZyzZLrX61dYDybSishCfx83eU12855pKq8OZ1qyTu4iUABuBRUA38H0R+V3gIeAskAs8CnwO+JsJvv7jwMcBqqurZxtGUkx1uCc/N4cP1C/kA/ULOXmulyf2NPP0/laeO3SWqmIfH6hfwAfqF6Zl0MOhlgv8wbdeYSRs+O4fvpXra7TUMVkq/Hm8frY3Jc8dq8iKXbiPVWQBKUnwTZ1BygpyHTd4JdU8bhdrqouzZjJTIt/99cCbxph2ABHZBrzNGPPt6P2DIvJN4C8m+mJjzKNEkj/19fWZtaE9iSUBP5+/ewVbNixj19E2vreniX9+4QT//MIJ3rG0nPvWLeTiwAj/tPtEUlZoY1d7pQW59AwME/B7+d5H17EkMCfJ/3XOFijM4/zFQcJhgyvJ78amqshKTXLv0+lLKeLPy+FXb3Sw6MFnU/4OLFGJJPcm4AYRySeyLXMbsFdE5htjzkhkE3gTcDjxMDNLbo6Lu6+Zz93XzKe5M8j397Xw/b3N/PG391/2uNbufh58+jW6+4e4c2V8J0V/fOQMjzx3bLT+vqNvCBH4o3cs0sSeAgG/l5GwoTM4xNw5eUl97skqslLVhbSxI8j10X4oKnm2H2jlJ8fbATCk/h1YohLZc39ZRJ4C9gMjwAEiK/EfiUg5IMBB4I+TEGfGWliaz2dvv4rP3LaUdX+7+4oj7AMjYf76maP89TNHE34tY+A/XnqT33vbooSfS13uUq37QNKTe2Wxb8J++qloDTA0EuZ0dz+bMzDZZLutO48zNG7mQyrfgSUqoU05Y8wXgS+Ou/nWRJ4zW7ldQucUvUke3nx1XM8XWxGMZ8ee85ng0inVQVYm+bk/ectiPr/98jewqWq3fLq7n7DRodipkO53YInSKy5JNNkKrarYx33r4rto/JUXT6ZttacurdzbU1AOGStTLZ+TR/vFQXwed8raLV/qBqmVMsmWzndgyaCnXpJo4pr52a3QkvlcanqpPKW6/WAri8sLeOXzt3HfuoWIwB0rK5L+OhBpOwDa6jcVsu13UpN7Em1aU8XDm69OykCMZD6Xmp7X46bI50l6f5nT3f288mYnG1dXISJsXF1FcCjE7oZzSX2dmKbOIHk5rtF3Iip5xv5OQuSi4t9sXJmxv5O6LZNkyRyIocM10isVs1R/+Grk0PbG1ZFDL+tqS5lX6GXHgVbuuTb5B2EaOyLdIPXEcmrEfid/efI8H/7ay3jHreQzia7clYpKxSzV7QdPs3ph8egeuMsl3LO6kp+93k5XCoaDRIZi65ZMqt3wljLmFXr5QQa3BtfkrlRUIMn9ZV5v66XhTA+bVl++Qt+4upKRsOG5w2eS9loQaf/c1BmkulQvpqaa2yVsXBP5RzoT+k1NRJO7UlHlhXm09w4mrQPojoOtuATuHteHZMX8QpYE5rDjQHL77J2/OERwKKQr9zTZvGYBobAZ3XrLNJrclYoK+L0MhcJ0BxPv42+MYcfB09y0ZO5oJU6MiLDx2kpeOdU5YWndbDV1RipltNVvetTN87OysjBjt2Y0uSsVVVEYK4dM/G32/qZuWrr62bR64gviG6O3P3Mweau+WDdIbfWbPu9bU8VrLRc4eS7zZqtqclcqKuBP3izVHQdbyctxTVrPXl2Wz5rqYnYcTN6qr6kziAgsKMnMQzV2dM/qSlwCPzjQYnUoV9DkrlRUrDY80Yuqw6Ewz752hvXLK6Yce7hpdRXHzvZyPEmthps6gswv9JKXk7nleXYT8Hu5eWk52w+cJhzOrOa2mtyVigpEt2XaEly5//LkeTr6hkZr2ydz19Xzcbskaav3xs6gbslYYPN1VbR29/Pym5nV512Tu1JR+bk5+PNyEl657zh4mkJvDu+sK5/yceX+PG5aMpcdB08npUKnsSNIjZZBpt0dK+ZRkOvOuK0ZTe5KjRErh5yt/qEQO4+c5a6r589oe2TT6kpau/vZ19g169cECA6NcP7ioK7cLeDLdXPnqvn86NBZBsYNZbGSJnelxgj4E2tBsKuhjeBQaLQaZjp3rJyH1+NiR4JVM6NDsbUM0hKbr6uid3CEXUfbrA5llCZ3pcYI+L0JNQ975mAr8wq9vHXRzObbzsnLYf3yCp49dIbhcYMg4nFpKLYmdytkYjsCTe5KjRFrHjabPfCuviF+erw9Uh4XxxzWjaur6Owb4hcnzsf9mjHNsT7uuuduiUxsR6DJXakxAn4vA8NhegdH4v7a5w6fYSRs4u72+M6ryinyeRKqmmnsCFLozaEof/LSS5VamdaOQJO7UmPEyiFnUzGz4+BpFpcXsLKyMK6vy81xcdfV83n+aBvBofj/UYFIGaROX7JW3Tw/K+ZnTjsCTe5KjTE6kaknvouqsaEcm6JDOeK1cXUlwaHQrC/INXX0aaVMBth8Xea0I9DkrtQYFWMGZcfjmehb8XumObg0mXW1pcwv8s6q10wobGjp6qdGK2Usl0ntCDS5KzVGYJazVHeMG8oRL5dLuOfayAW5zjiHeJzu7mckbLQMMgNkUjsCTe5KjTEnLwefxx3XnvtkQznidU9siMeh+IZ4jNa467ZMRoi1I3jllLXtCDS5KzWGiBAozItrW2ayoRzxWjG/kKWBOXFXzcSSu15QzQyj7Qj2W3thVZO7UuNU+L20zfCC6lRDOeIlImxcXcmeU120dAVn/HWNHUE8bmFe9HqBslasHcFzh85Y2o5Ak7tS48TTX2Z/U9eUQznidc+1kef54asz35pp6uxjYUk+7jgOTqnUyoR2BJrclRon0l9mZsl9x8HTUw7liFd1WT7XxTnEo7FDW/1mmkxoR5BQcheRPxeRIyJyWEQeFxGviCwSkZdF5KSIPCEiuckKVql0CPi9XBwcoW+aU6qjQzlWTD2UI14bo0M8jp3tmfaxxhiaOoJaBplhMqEdwayTu4hUAZ8G6o0xqwA3cC/w98A/GWOWAF3Ax5IRqFLpMtNZqr+IDeWIs93AdO6+JjbEY/qa9+7gML2DIyzU5J5xrG5HkOi2TA7gE5EcIB84A9wKPBW9/zFgU4KvoVRajc5Sneai6jMzHMoRr7lz8nj7krk8c3D6WulGrZTJWFa3I5h1cjfGtAL/CDQRSeoXgH1AtzEm9n62BZjwSpOIfFxE9orI3vb29tmGoVTSBWawco8N5bj7mpkN5YjXxugQj/1NUw/xuFQGqSv3TGRlO4JEtmVKgI3AIqASKADunOnXG2MeNcbUG2Pqy8uTu/JRKhGXTqlOntxjQzli1S3JFhvisX2aC6tNHX0ALCzR5J6J7rnWunYEiWzLrAfeNMa0G2OGgW3ATUBxdJsGYAGQGS3SlJqhIp+H3BzXlNsy8Q7liNfoEI/Xph7i0dgRJODPw5eb/HcPKnGBQi9vt6gdQSLJvQm4QUTyJdIG7zbgKPAT4P3Rx9wP7EgsRKXSS0SmLIec7VCOeG1cXUVXcJifn5h82zLS6ldX7Zls8xpr2hEksuf+MpELp/uBQ9HnehT4HPBZETkJlAFfT0KcSqXVVLNUZzuUI16XhnhMXm3R3BmkWqcvZbQ7VlZY0o4goWoZY8wXjTHLjDGrjDEfMcYMGmN+a4xZZ4xZYoz5gDEmM2ZOKRWHgN87afOw2Q7liNfoEI8jEw/xGBgOcbZnQLtBZrj83BxL2hHoCVWlJhAozJuwv0xrgkM54rVpdSX9wxMP8WjpCmKMVspkAyvaEWhyV2oCFYVeegZGrlhp/TDBoRzxWhsd4jHR1oy2+s0eVrQj0OSu1ARiHR7HNxDbcfA0a6pnP5QjXrEhHi9NMMSjsSNa467bMhnPinYEmtyVmsBEE5liQzmS3W5gOhtXVzESNjw7bohHY0eQglw3pQXavikbpLsdgSZ3pSYQa0HQNuai6o6DrbhdkvBQjngtn+9naWAOz4w70NTUGaS6rCAte/8qceluR6DJXakJjDYPi15UTeZQjnhNNsSjqVO7QWabdLYj0OSu1ARK8nPJccnoQabYUI50b8nEbIwOA3km+pY+HDbRlbsm92ySznYEmtyVmoDLJZSPOaWa7KEc8VpYGh3icSCS3Nt6BxgaCWuNe5ZJZzsCTe5KTSLWgmA4FOa/UjCUI16b1lRxvC0yxKOpQ7tBZqt0tSPQ5K7UJAKFXs71DPCLk+fpTMFQjnjddfWlIR6jfdy19UDWuWNlBflpaEegyV2pScRW7s8cPE2Rz8MtdQFL4xk7xKOxow+3S5hf7LU0JhW/SDuCeSlvR6DJXalJBPxeOvuG2HnkLHddPY/cHOt/XTatiQzx2HHwNFXFPjxu62NS8du8ZgG9gyPsbkhdOwL9yVBqEq3dka2P4FCkt8t2CyfZx9y+Yh45Lmjp6qepM8hNj7yYEXGp+Ny4uIxCbw5/8eSrLHrw2ZR8H3Omf4hSzrP9QCvbD1w6SXj+4hAPbTsERC5sWmX30TaMESBSadHa3Z8Rcan4/PDV0wSHQoyEU/d91JW7UhPYuvM4Q+MmIPUPh9i687hFEUVs3XmckLm8hC4T4lLx2brz+Ghij0n291GTu1ITON3dH9ft6ZKpcan4pOP7qMldqQlUFvviuj1dMjUuFZ90fB81uSs1gS0b6vB5Lh867fO42bKhzqKIIjI1LhWfdHwf9YKqUhOIXdTauvM4p7v7qSz2sWVDneUXLTM1LhWfdHwfxZjU9jeYifr6erN3716rw1BKqawiIvuMMfUT3afbMkopZUOa3JVSyoY0uSullA1pcldKKRvS5K6UUjaUEdUyItIONM7yy+cC55MYTrJkalyQubFpXPHRuOJjx7hqjDHlE92REck9ESKyd7JSICtlalyQubFpXPHRuOLjtLh0W0YppWxIk7tSStmQHZL7o1YHMIlMjQsyNzaNKz4aV3wcFVfW77krpZS6kh1W7koppcbR5K6UUjaU1cldRO4UkeMiclJEHrQ6HgARWSgiPxGRoyJyREQ+Y3VMY4mIW0QOiMh/WR1LjIgUi8hTInJMRBpE5EarYwIQkT+Pfg8Pi8jjIuK1KI5viMg5ETk85rZSEdklIieif5dkSFxbo9/H10TkByJSnO64JottzH0PiIgRkbmZEpeI/Gn0/9sREfmHZLxW1iZ3EXED/wa8G1gB3CciK6yNCoAR4AFjzArgBuBTGRJXzGeABquDGOefgR8bY5YB15IB8YlIFfBpoN4YswpwA/daFM63gDvH3fYg8IIxZinwQvTzdPsWV8a1C1hljLkGeB14KN1BRX2LK2NDRBYCdwBN6Q4o6luMi0tE3gVsBK41xqwE/jEZL5S1yR1YB5w0xvzWGDMEfI/I/yBLGWPOGGP2Rz/uJZKoMmKSgogsAO4GvmZ1LDEiUgS8A/g6gDFmyBjTbWlQl+QAPhHJAfKB01YEYYx5Cegcd/NG4LHox48Bm9IZE0wclzHmeWPMSPTT3wAL0h1XNI6J/p8B/BPwl4AllSSTxPUJ4BFjzGD0MeeS8VrZnNyrgOYxn7eQIUk0RkRqgTXAyxaHEvN/iPxghy2OY6xFQDvwzeh20ddEpMDqoIwxrURWUE3AGeCCMeZ5a6O6TIUx5kz047NAhZXBTOKjwI+sDiJGRDYCrcaYV62OZZyrgJtF5GUR+ZmIrE3Gk2Zzcs9oIjIHeBr4M2NMTwbE8x7gnDFmn9WxjJMDXAd81RizBujDmi2Gy0T3sDcS+cenEigQkd+1NqqJmUg9c0bVNIvI54lsUX7H6lgARCQf+CvgC1bHMoEcoJTINu4W4EkRkUSfNJuTeyuwcMznC6K3WU5EPEQS+3eMMdusjifqJuAeETlFZAvrVhH5trUhAZF3XC3GmNi7m6eIJHurrQfeNMa0G2OGgW3A2yyOaaw2EZkPEP07KW/lk0FEfh94D/BhkzkHaRYT+Yf61ejvwAJgv4jMszSqiBZgm4l4hcg764Qv9mZzct8DLBWRRSKSS+Ri1zMWx0T0X9yvAw3GmC9bHU+MMeYhY8wCY0wtkf9XLxpjLF+JGmPOAs0iEhv7fhtw1MKQYpqAG0QkP/o9vY0MuNA7xjPA/dGP7wd2WBjLKBG5k8jW3z3GmKDV8cQYYw4ZYwLGmNro70ALcF30589q24F3AYjIVUAuSehembXJPXrR5k+AnUR+6Z40xhyxNiogskL+CJGV8cHon7usDirD/SnwHRF5DVgN/J214UD0ncRTwH7gEJHfFUuOr4vI48CvgToRaRGRjwGPALeLyAki7zIeyZC4vgL4gV3Rn/3/m+64pojNcpPE9Q3gLdHyyO8B9yfjHY+2H1BKKRvK2pW7UkqpyWlyV0opG9LkrpRSNqTJXSmlbEiTu1JK2ZAmd6WUsiFN7kopZUP/H+WNZzrJiwwoAAAAAElFTkSuQmCC\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": "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\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": "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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": [ + "[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": "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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": [ + "[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": "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\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": "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\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": "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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": [ + "[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": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEVCAYAAADwyx6sAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/Il7ecAAAACXBIWXMAAAsTAAALEwEAmpwYAAAqDklEQVR4nO3dd3wUdf7H8deHECD0jhAIRSAQbEBo6tkRFBXLzxNQT+70sJ7t9NRTzxPsnHh4x6moWFDEeoiAomDvdIWEhNAJvYWWkPb9/bEDt8YNBEgyW97Px2MfyXxndvczO/DeyWdnZ8w5h4iIRL4qfhcgIiLlQ4EuIhIlFOgiIlFCgS4iEiUU6CIiUUKBLiISJRToElbMbKiZOTMb6nctkcrMPjezIz4e2cxWmNmKcihJKokCPYp5wRh8KzKzrd5/+KFmZn7XGOnM7O9Br++rB1ju1KDlVlRiiRJDqvpdgFSKB72f8UB74CLgVCAVuMmvoqJMIfB/Znazc257iPl/9JbR/zmpMNpDjwHOub97t3udc5cBpwPFwA1m1tbn8qLFFCABuLzkDDNrAFwCfFDZRUlsUaDHIOfcN8BiwIDuwfPMrLuZjTazBV57Js/MlpjZk14wUWL5/T1vMzvda+fsNLMdZjbVzDqHqsHM2pvZ22a2zcx2m9m3ZjbgQHV7tb1rZhvNbK+ZrTSz/5hZ8xDLvuzV1dbMbjKzNG9dVpjZX/e1m8zsUjP70atho5n928wSDuHl3OcjYA1wTYh5VwI1gOcPsG5VzOw6M5tlZru8emaZ2fVmFvL/qZkNMrM5Zpbr1T7ezFocqEgz62dm08xss/caLjWzkWZWv+yrKuFKf/5JQYnpPxJoyXwBzCDwpt8duB04x8x6Oed2hnic84CBwIfAs0AKcC7Qw8xSnHOb9y1oZh2A74BG3vLzCbSCJnnTv2Jm5wHvEngTegdY6dV1PTDQzE52zi0Pcdd/AKcR2Dv+GLgAeBioZmZbgce85/0K6AvcCMR5j3soioBxwN/MLNU5Nzto3h+B5QRez9KMB4YAq4EXAEdgO/wHOJkSe/5mdhswCtgOvOr97Ad8C+SEegIzewD4O7CVwF8UG4HjgDuAc82sj3NuRxnXV8KRc063KL0RCAUXYvwUAgG0F2heYl5rIC7Efa72Hu+uEuNDvfFC4MwS8x715v2lxPjH3vgtJcYH7qsZGBo0XhvY4tX8mxL3uctb/uMS4y974yuAxKDx+sBmYDewCegcNK86kOa9Lk3L+Br/3Xuea7zXrgh4Lmh+b2/+vQR2oBywosRjDPbG5wK1g8ZrAbO9eUOCxtsA+QSCuU3QeBUCb3q/2u4E2myOQODXL2UbPlVifEXJWnUL75vvBehWgRv3f+H4d+/2MPCmFwbFwJ8O4bGMwJ7fpyXG94XBayHu09ab907QWEtvbBmh3zg+DxHol3tjE0IsX5XA3q8DkoLG9wX61SHuM86bNzzEvAe8eaeW8XXZH+je9IfADqCWN/0igTe7FgcI9E+88bNDPP6Z3rxPg8bu9cYeDLF8OwJvKq7E+H+9+3QpZT3mARtLjCnQI+ymlktseKDE9L6ge6nkgmYWD1wLDCLQNqnHLz9rSSzlOWaHGFvt/QzuvXf1fn7tnCsKcZ/PCRyBE6yb9/PTkgs75wrN7EsCe61dgVVlqGut93NOiHnZ3s+WIeaVxfNAf2CQmb0NXAZMdc6tNbPS/r91I/AG+3mIeV8QCOiuJZbfN+8XnHPLzGw1gb8WgvUh0F671MwuDfE81YAmZtbIObellDolzCnQY4Bzbt8HgLUI/Md+EXjWzFY650qG5JsEerfLgPeB9QRaEAC3EmhLhLI9xPMWep89xgUN1/N+bijlcdaHGNt3n3Wl3GffeP0Q80L1kwvLMC++lOc6mA8IrNs13mPU4gAfhnrqAVudc/klZ3iv4WagaYnl4cCvYclAb0Tg/3vJN/eS9rW3JAIp0GOIc243MMPMzifQr33FzJKdc3sAzCyVQJjPAM5xzu0LN7wjLf5SDmXsC9Fmpcw/6gD3CTUPoHmJ5XzjnCsws5eAuwns5a+hlA96g+QADc0s3jn3iw+pvb36xgTaOMHLQ+A1XBTi8Up7Das45xoefC0kUumwxRjknPuJwF5jS+C2oFntvZ+Tg8Pc05PAcdZHap7382Qziwsx/7QD3OdX87zA+403OfdIiysn+45SaQmMK6W1FGwegf+Lp4SYdwqBv3CC123f7yVbU5hZO6BViMf5HmhgZl0OUotEMAV67HqIQCvljqDjy1d4P08LXtDMmgJjyuNJnXNrCHwI2JYS31I1s4GECCkChxVuBQabWe8S8271HmuGc65k/9wXzrmlBProFwFPl+Eu47yfj5pZzX2D3u+PeZMvBi3/OoF++J/MrE3Q8lWAkYT+f/2U9/P5UMeqm1mtEK+tRBi1XGKUcy7bzJ4FbiHQSrkHmAV8A1xsZt8CXxP4s/4cIIP/fZh4pG4kcBz6P83sbGAB/zslwQfA+SVq3WVmfwDeBr7wPmxcReA49LMJ9IyvLafayoVz7uNDWHaC92b2W2CRmU0isId/IYE3qzedc68HLb/CzO4GngTmmdmbBFoq/Qh8jvATgePLg59jpnefR4ElZjaNwNFBtQn0208lsL37H876SnjQHnpsexTYA9xsZs281sAFwDMEDrO7mcCXWl4gEBYlv4R0WJxzSwgcn/0ucBKBN5VWBALsvVLu87637DSvljuAzgS+xNTdObesPGrz0WACb3RbCLw5XQdsI/BXzJCSCzvnRnnjywkcOvoHYCFwone/X3HOPU6ghTOVwGt5K3ApgSOXxgL3ld/qiB/MuSM+y6aIiIQB7aGLiEQJBbqISJRQoIuIRAkFuohIlFCgi4hECQW6iEiUUKCLiEQJBbqISJRQoIuIRAkFuohIlFCgi4hECQW6iEiU8O30uY0bN3Zt2rTx6+lFRCLSnDlzNjvnmoSa51ugt2nThtmzQ12/V0RESmNmK0ubp5aLiEiUUKCLiEQJBbqISJRQoIuIRAkFuohIlPDtKBcRkVgzaV42I6dnsHZ7Li3qJ3Bnv2Qu7JpYbo+vQBcRqQST5mVzz3s/k1tQBED29lzuee9ngHILdbVcREQqwcjpGfvDfJ/cgiJGTs8ot+dQoIuIVLCiYkf29tyQ89aWMn44yhToZtbfzDLMLMvM7g4xf6iZbTKz+d7tmnKrUEQkgn27dDMDnv6q1Pkt6ieU23MdNNDNLA4YA5wDpACDzSwlxKJvOudO8G4vlFuFIiIRaMXm3Qx7dTZDnv+BnXmFXNWnNQnxv4zchPg47uyXXG7PWZYPRXsCWc65ZQBmNhEYCKSVWxUiIlFiR14B//40i5e+WU61uCrc2S+Zq09uS434OLomNfD9KJdEYHXQ9BqgV4jlLjGzU4BM4Dbn3OoQy4iIRKXComLenL2aUR9nsnVPPpd2b8kdZyfTtG6N/ctc2DWxXAO8pPI6bPED4A3n3F4zuxZ4BTij5EJmNgwYBpCUlFROTy0i4q9vsjYzYkoai9fvpGfbhrxyXgrHJNar9DrKEujZQKug6Zbe2H7OuS1Bky8AT4R6IOfcWGAsQGpqqjukSkVEwszyzbt5eGo6M9I30KphAs9c3o3+xxyFmflST1kCfRbQwczaEgjyQcCQ4AXMrLlzbp03eQGQXq5VioiEkZw9BTz96RJe/W4F1avGcVf/Tvz+pDbUiI/zta6DBrpzrtDMbgKmA3HAOOfcIjMbDsx2zk0GbjazC4BCYCswtAJrFhHxRWFRMW/8uIpRn2SyPbeAy1JbcfvZHWlap8bB71wJzDl/Oh+pqalOVywSkUjxZeYmRkxJY8nGXfRu15D7z0uhS4vK75Ob2RznXGqoeTqXi4jIAWRt3MUj09L5dPFGWjeqyXNXdufslGa+9ckPRIEuIhLC9j35jJ65hPHfrSQhPo6/ntuJq05sQ/Wq/vbJD0SBLiISpKComAk/rOKpGZnsyC1gUM8kbu/bkca1q/td2kEp0EVEPJ9nbOShqelkbdzFiUc34v7zUujcvK7fZZWZAl1EYl7Wxp08NDWdzzM20aZRTZ7/XSpndW4aln3yA1Ggi0jM2rbb65N/v5Ka1eK4b0BnftenDdWqRuaZxRXoIhJzCoqKGf/dSkbPXMLOvAKG9EritrM60igC+uQHokAXkZjhnOMzr0++bNNuTm7fmPvPSyH5qDp+l1YuFOgiEhMyN+xkxJQ0vlqymXaNa/HiVamc0Sny+uQHokAXkai2dXc+T32SyYQfV1GrWhz3n5fClb1bR2yf/EAU6CISlfILi3n1uxWMnrmEPflFXN4riVvP6kjDWtX8Lq3CKNBFJKo455iZvpGHp6WzfPNuftMh0Cfv2Cw6+uQHokAXkaixeP0OHpqSztdZm2nXpBYvDe3BaclNoqpPfiAKdBGJeFt27WXUJ5m88eMq6tSI54HzU7iid2vi46KvT34gCnQRiVj5hcW88u0Knp65hD0FRfyuTxtuPasD9WtGb5/8QBToIhJxnHN8kraBR6als2LLHk5PbsK9AzrTvmn098kPRIEuIhElfd0ORkxJ49ulW2jftDYv/74HpyU39bussKBAF5GIsHnXXp78OJM3Z62ibkI8wwd2YXDPpJjrkx+IAl1EwtrewiJe/mYF//o0i7yCIoae2JZbzuxAvZrxfpcWdhToIhKWnHNMXxTok6/auoczOzXlrwM6c3ST2n6XFrYU6CISdhZm5zBiSho/LN9Kx2a1GX91T37ToYnfZYU9BbqIhI2NO/N4cnomb81ZTYOa1XjowmMY1KMVVdUnLxMFuoj4Lq+giHHfLGfMp1nkFxVzzcltuemMDtRLUJ/8UCjQRcQ3zjk+XLieR6als2ZbLn1TmvHXczvTtnEtv0uLSAp0EfHFwuwchn+Qxo8rttLpqDq8fk0vTmrf2O+yIpoCXUQq1cYdeYycnsE7c9fQsGY1HrnoWC7r0Yq4KrFxAq2KpEAXkUqRV1DEi18vZ8xnWRQUFTPsN+248Yz21K2hPnl5UaCLSIVyzjH153U8Om0x2dtz6delGfec05k26pOXOwW6iFSYn9ZsZ/gHacxeuY3Ozesy8tLjOPFo9ckrigJdRMrdhh15PPFRBu/OXUPj2tV47OJjuTRVffKKpkAXkXKTV1DE818u4z+fL6Wo2HHdqUdz4+lHU0d98kpRpkA3s/7AaCAOeME591gpy10CvAP0cM7NLrcqRSSsOef44Kd1PDYtnbU5eZxzzFHcc05nkhrV9Lu0mHLQQDezOGAM0BdYA8wys8nOubQSy9UBbgF+qIhCRSQ8zV+9neEfLGLuqu10aVGXUZedQO92jfwuKyaVZQ+9J5DlnFsGYGYTgYFAWonlRgCPA3eWa4UiEpbW5eTyxEcZ/HdeNo1rV+eJS47jku4t1Sf3UVkCPRFYHTS9BugVvICZdQNaOeemmlmpgW5mw4BhAElJSYderYj4Lje/iOe+XMqzXyyl2MENpx3NDae3p3Z1fSTntyPeAmZWBRgFDD3Yss65scBYgNTUVHekzy0ilae42DF5wVoe/2gx63LyGHBcc+7u34lWDdUnDxdlCfRsoFXQdEtvbJ86wDHA52YGcBQw2cwu0AejItFh7qptDP8gjfmrt3NsYj1GD+pKz7YN/S5LSihLoM8COphZWwJBPggYsm+mcy4H2P9NATP7HLhDYS4S+dZuz+Xxjxbz/vy1NK1TnX9cejwXd02kivrkYemgge6cKzSzm4DpBA5bHOecW2Rmw4HZzrnJFV2kiFSuPfmFPPvFMsZ+uRTn4E9ntOe6U4+mlvrkYa1MW8c5Nw2YVmLsb6Use9qRlyUifigudkyan83jHy1mw469nH98C+7qn0zLBuqTRwK93YoIAHNWbmX4B2ksWJPD8S3rMWZIN1LbqE8eSRToIjFuzbY9PPbhYqb8tI5mdasz6rfHc+EJ6pNHIgW6SIzavbeQZz5fyvNfLQPg5jM7cN2p7ahZTbEQqbTlRGJMcbHj3blrGDk9g4079zLwhBb8pX8nEusn+F2aHCEFukgM+XH5VkZMSePn7BxOaFWfZ6/sTrekBn6XJeVEgS4SA1ZvDfTJp/68jub1ajB60Amcf1wL9cmjjAJdJIrt2lvIfz7L4oWvlxNnxm1ndWTYKe1IqBbnd2lSARToIlGoqNjx7pw1PDE9g8279nJx10Tu7J9M83rqk0czBbpIlPl+2RZGTElj0doddEuqzwtXpXJCq/p+lyWVQIEuEiVWbdnDox+m8+HC9bSoV4OnB3fl/OOa4500T2KAAl0kwu3MK2DMZ0sZ9/Vy4qoYf+7bkT+e0o4a8eqTxxoFukiEKip2vD17Nf/4OIPNu/K5pFtL/tI/mWZ1a/hdmvhEgS4Sgb5dupkRU9JJX7eD1NYNGDe0B8e1rO93WeIzBbpIBFm5ZTePTEtn+qINJNZP4N9DujLgWPXJJUCBLhIBduQVMObTLMZ9s5z4uCrc2S+Zq09uqz65/IICXSSMFRU7Js5axaiPM9m6J59Lu7fkjrOTaao+uYSgQBcJU99kbWbElDQWr99JzzYNeeX8FI5JrOd3WRLGFOgiYWb55t08PDWdGekbaNkggWcu70b/Y45Sn1wOSoEuEiZycgv418wlvPLdCqrFVeGu/p34/Ult1CeXMlOgi/issKiYN2at5qlPMtm2J5/LUltx+9kdaVpHfXI5NAp0ER99tWQTI6akkblhF73aNuRv56fQpYX65HJ4FOgiPli6aRePTE1n5uKNJDWsybNXdKdfl2bqk8sRUaCLVKKcPQWMnrmEV79bQY34OO45pxNDT2pD9arqk8uRU6CLVILComIm/LiKUZ9ksiO3gMt6JHF73440qVPd79IkiijQRSrYF5mbeGhKGks27qJPu0bcf14KKS3q+l2WRCEFukgFydq4i4enpvFZxiZaN6rJ2Cu70zdFfXKpOAp0kXK2fU8+/5yxhPHfr6RmfBz3ntuZ353YWn1yqXAKdJFyUlBUzOvfr+SpGUvYmVfA4J6BPnmj2uqTS+VQoIuUg88yNvLQlDSWbtrNye0bc995nel0lPrkUrkU6CJHIHPDTh6ams6XmZto17gWL16VyhmdmqpPLr4oU6CbWX9gNBAHvOCce6zE/OuAG4EiYBcwzDmXVs61ioSNrbvz+eeMTF7/YRW1qsVx/3kpXNm7NdWqVvG7NIlhBw10M4sDxgB9gTXALDObXCKwJzjnnvWWvwAYBfSvgHpFfJVfWMz471cyekYmu/OLuLxXEree1ZGGtar5XZpImfbQewJZzrllAGY2ERgI7A9059yOoOVrAa48ixTxm3OOTxdv5OGp6SzbvJvfdGjM/eel0LFZHb9LE9mvLIGeCKwOml4D9Cq5kJndCNwOVAPOKJfqRMJAxvqdPDQ1ja+WbKZdk1q8NLQHpyU3UZ9cwk65fSjqnBsDjDGzIcB9wFUllzGzYcAwgKSkpPJ6apEKsWXXXp6akcmEH1ZRp0Y8D5yfwhW9WxMfpz65hKeyBHo20CpouqU3VpqJwDOhZjjnxgJjAVJTU9WWkbCUX1jMK9+u4OlPl7Anv4jf9WnDrWd1oH5N9cklvJUl0GcBHcysLYEgHwQMCV7AzDo455Z4kwOAJYhEGOccn6Rt4JFp6azYsofTk5tw74DOtG+qPrlEhoMGunOu0MxuAqYTOGxxnHNukZkNB2Y75yYDN5nZWUABsI0Q7RaRcJa+bgcjpqTx7dIttG9am5d/34PTkpv6XZbIISlTD905Nw2YVmLsb0G/31LOdYlUis279vLkx5m8OWsVdRPiGT6wC4N7JqlPLhFJ3xSVmLS3sIiXv1nBvz/NIregiKEntuWWMztQr2a836WJHDYFusQU5xzTFwX65Ku27uHMTk3564DOHN2ktt+liRwxBbrEjEVrcxgxJY3vl22lY7PavPqHnpzSsYnfZYmUGwW6RL1NO/fy5McZvDl7NfUT4hlx4TEM7tGKquqTS5RRoEvUyiso4qVvVjDmsyzyCoq4+qS2/OnMDtRLUJ9copMCXaKOc46PFq7nkQ/TWb01l7M6N+Ov53ainfrkEuUU6BJVFmbnMHxKGj8u30pyszq8dnUvTu7Q2O+yRCqFAl0i1qR52YycnsHa7bk0q1uD1o0S+HHFNhrUrMbDFx3DZanqk0tsUaBLRJo0L5t73vuZ3IIiANbvyGP9jjxOT27C6MFdqVtDfXKJPdp9kYg0cnrG/jAPlrlhl8JcYpYCXSJS9vbckONrSxkXiQVquUhEKS52jJ5Z+sk8W9RPqMRqRMKL9tAlYuTkFvDHV2czeuYSerRuQI34X/7zTYiP485+yT5VJ+I/7aFLRMjcsJNrx89h9dY9DB/YhSt7t+b9+Wv3H+XSon4Cd/ZL5sKuiX6XKuIbBbqEvak/rePOdxZQq3pV3hjWmx5tGgJwYddEBbhIEAW6hK3ComJGfpzBc18so1tSfZ65ojvN6tbwuyyRsKVAl7C0dXc+N78xj6+zNnN5ryQeOL8L1arqIx+RA1GgS9hZmJ3DtePnsGnXXp645Dh+26PVwe8kIgp0CS/vzlnDX//7M41qVePta/twfKv6fpckEjEU6BIWCoqKeWhKGq98t5Le7Rry7yHdaFy7ut9liUQUBbr4buPOPG58fS6zVmzjmpPbcvc5nXRSLZHDoEAXX81ZuY0bXp9DTm4BowedwMATdBiiyOFSoIsvnHNM+HEVf5+8iOb1EvjvDT3p3Lyu32WJRDQFulS6vIIiHnh/EW/OXs2pHZswetAJ1K9Zze+yRCKeAl0q1drtuVz/2hwWrMnhptPbc1vfjsRVMb/LEokKCnSpNN8t3cJNE+ayt7CY567sTr8uR/ldkkhUUaBLhXPO8eLXy3n0w8W0aVST565MpX1TXbBZpLwp0KVC5eYXcfd7P/H+/LX069KMf1x6PHV0RSGRCqFAlwqzasseho2fTcaGndzZL5nrTz2aKuqXi1QYBbpUiM8zNnLLxPkAvDS0B6clN/W3IJEYoECXcuWc4z+fL+UfH2eQ3KwOY69MJalRTb/LEokJZfp+tZn1N7MMM8sys7tDzL/dzNLM7Cczm2lmrcu/VAl3O/MKuO61OYycnsH5x7XgvRtOVJiLVKKD7qGbWRwwBugLrAFmmdlk51xa0GLzgFTn3B4zux54ArisIgqW8JS1cRfXjp/Nii17uP+8FP5wUhvM1C8XqUxlabn0BLKcc8sAzGwiMBDYH+jOuc+Clv8euKI8i5TwNn3Rev781gKqV63Ca1f3os/RjfwuSSQmlSXQE4HVQdNrgF4HWP5q4MNQM8xsGDAMICkpqYwlSrgqKnY89Ukm//4si+Nb1uOZK7rTon6C32WJxKxy/VDUzK4AUoFTQ813zo0FxgKkpqa68nxuqVw5ewq4eeI8vsjcxGWprXhwYBdqxMf5XZZITCtLoGcDwdcAa+mN/YKZnQXcC5zqnNtbPuVJOEpft4Nrx89hXU4uD190DEN6JqlfLhIGyhLos4AOZtaWQJAPAoYEL2BmXYHngP7OuY3lXqWEjckL1nLXOz9RN6EqE4f1oXvrBn6XJCKegwa6c67QzG4CpgNxwDjn3CIzGw7Mds5NBkYCtYG3vT21Vc65CyqwbqlkhUXFPPbhYl74ejk92jRgzOXdaFqnht9liUiQMvXQnXPTgGklxv4W9PtZ5VyXhJEtu/Zy04R5fLdsC1f1ac29A1KoVlWXiBMJN/qmqBzQgtXbuf61OWzZnc+Tlx7PJd1b+l2SiJRCgS6lemvWau57fyFNalfn3etP5JjEen6XJCIHoECXX8kvLObBDxbx+g+rOLl9Y54e3JWGtXSJOJFwp0CXX9iwI4/rX5vD3FXbufbUdtx5djJV49QvF4kECnTZb9aKrdzw+lx27y1kzJBuDDiuud8licghUKALzjnGf7+S4R+k0bJBAq9d3Yvko+r4XZaIHCIFegyaNC+bkdMzWLs9l+b1apBYP4FZK7dxZqemjLrsBOol6BJxIpFIgR5jJs3L5p73fia3oAiAtTl5rM3Jo19KM565orsuEScSwfRpV4wZOT1jf5gHW7h2h8JcJMIp0GPM2u25hzQuIpFDgR5DVm/dQ9W40HvhOo+5SORToMeI9+dnc+7or6hiEF8i1BPi47izX7JPlYlIedGHolFu995CHpi8iHfmrKFbUn1GD+rKnJXb9h/l0qJ+Anf2S+bCrol+lyoiR0iBHsUWZufwpzfmsWLLbm4+oz03n9mBqnFVaNWwpgJcJAop0KNQcbFj3DfLefyjxTSqVZ0J1/TWhZtFYoACPcps2rmXO95ewBeZmzg7pRmPX3IcDXRiLZGYoECPIl9mbuL2txawM6+AERcewxW9dK1PkViiQI8C+YXFjJy+mOe/Wk7HZrV5/Rqdi0UkFinQI9zyzbu5+Y15/JydwxW9k7hvQAo14uP8LktEfKBAj1DOOd6dm83f3l9ItapVeO7K7vTrcpTfZYmIjxToEWhnXgH3TVrI+/PX0qttQ/456ASa19M3PUVinQI9wsxbtY2bJ85j7fY8/ty3Izec3p44nVRLRFCgR4ziYsezXy5l1MeZNKtbg7eu7U331g39LktEwogCPQJs2JHHbW/O59ulWxhwXHMeuehYXYRCRH5FgR7mZqZv4I63F5BXUMwTlxzHpaktdWy5iISkQA9TeQVFPPbhYl7+dgUpzevy9OCutG9a2++yRCSMKdDDUNbGndw0YR6L1+/kDye15a5zkqleVceWi8iBKdDDiHOOibNW8+AHi6hZrSrjhqZyRqdmfpclIhFCgR4mcvYUcM9/f2Laz+s5uX1jRv32eJrWreF3WSISQRToYWD2iq3cMnE+G3bkcfc5nRj2m3a6YLOIHLIyXYLOzPqbWYaZZZnZ3SHmn2Jmc82s0Mz+r/zLjE5FxY7RM5bw2+e+o2qc8c71J3LdqUcrzEXksBx0D93M4oAxQF9gDTDLzCY759KCFlsFDAXuqIgio9Ha7bnc+uZ8fly+lYu6JjJ8YBfq1NCx5SJy+MrScukJZDnnlgGY2URgILA/0J1zK7x5xRVQY9T5aOE67nr3ZwqLihn12+O5uFtLv0sSkShQlkBPBFYHTa8Beh3Ok5nZMGAYQFJS0uE8RETLzS9ixNQ0JvywiuNa1uPpQV1p07iW32WJSJSo1A9FnXNjgbEAqamprjKf22+L1+/gTxPmsWTjLq49tR1/7ptMtapl+ghDRKRMyhLo2UCroOmW3piUgXOO8d+v5KGp6dStEc+rf+jJKR2b+F2WiEShsgT6LKCDmbUlEOSDgCEVWlWU2Lo7n7+88xMz0jdwWnIT/nHp8TSuXd3vskQkSh000J1zhWZ2EzAdiAPGOecWmdlwYLZzbrKZ9QD+CzQAzjezB51zXSq08jD37dLN3PbmfLbuzuf+81L4/YltdDiiiFSoMvXQnXPTgGklxv4W9PssAq2YmFdQVMw/Z2Tyn8+X0rZxLV68qgfHJNbzuywRiQH6pmg5Wr11DzdPnMe8Vdu5LLUVD1yQQs1qeolFpHIobcrJ5AVrufe9nwH41+CunH98C58rEpFYo0A/Qrv3FvL3yYt4e84auiXVZ/SgrrRqWNPvskQkBinQj8DC7BxufmMey7fs5k9ntOeWMztQNU7HlouIPxToh6G42DHum+U8/tFiGtWqzoRretPn6EZ+lyUiMU6Bfog279rLHW8v4POMTfRNacYTlxxHg1rV/C5LRESBfii+zNzE7W8tYEdeASMGduGK3q11wWYRCRsK9DLILyzmyY8zeO7LZXRsVpvXrulJp6Pq+l2WiMgvKNAPYvnm3dwycR4/rcnh8l5J3DcghYRqumCziIQfBfoBvDd3DfdPWkjVuCo8e0V3+h9zlN8liYiUSoEews68Au6ftJBJ89fSs21D/nnZCbSon+B3WSIiB6RAL2H+6u3c/MY81mzbw+19O3Lj6e2J00m1RCQCKNA9xcWOZ79cyqiPM2lWtwZvXduH1DYN/S5LRKTMojLQJ83LZuT0DNZuz6VF/QTu7JfMhV0TS11+w448bn9rPt9kbWHAsc155KJjqVdTF2wWkcgSdYE+aV4297z3M7kFRQBkb8/lHu+kWRd2TfxV2J9z7FG8NzebPfmFPHbxsVzWo5WOLReRiBR1gT5yesb+MN8nt6CI4VPSyCso4sEP0n4R9i98tZwW9Wrw1rUn075pHT9KFhEpF1EX6Gu354Yc37o7n7u9PfVQFOYiEumi7tSATeuGvmZn49qln29lXU5eRZUjIlJpoirQi4sdtUNcISghPo77BqSQWMqx5DrGXESiQVQF+rhvlrN0824G9WxFYv0EDEisn8CjFx/LhV0TubNfMgnxv/zafkJ8HHf2S/anYBGRchQ1PfTMDTt5YnoGZ3VuxqMXHRvySJV9hy4eyiGNIiKRIioCPb+wmNvenE+d6lV57JLQYb7PhV0TFeAiEpWiItD/9ekSFq3dwbNXdKdx7dAfioqIRLuI76HPXbWNMZ9lcUm3ljoboojEtIgO9Nz8Iv781gKa10vggQtS/C5HRMRXEd1yefTDdJZv3s2EP/aibg2de0VEYlvE7qF/mbmJV79bydUnt+XEoxv7XY6IiO8iag89+MRaZtC0TnUdQy4i4omYPfR9Z1HM3p6LA4od5OQW8NHC9X6XJiISFiIm0EOdRXFvYTEjp2f4VJGISHgpU6CbWX8zyzCzLDO7O8T86mb2pjf/BzNrU96FlnYWxdLGRURizUED3czigDHAOUAKMNjMSh4jeDWwzTnXHngKeLy8Cy3tBFo6sZaISEBZ9tB7AlnOuWXOuXxgIjCwxDIDgVe8398BzrRyvuyPTqwlInJgZQn0RGB10PQabyzkMs65QiAHaFQeBe5zYddEHr342JBnURQRkUo+bNHMhgHDAJKSkg75/jqxlohI6cqyh54NtAqabumNhVzGzKoC9YAtJR/IOTfWOZfqnEtt0qTJ4VUsIiIhlSXQZwEdzKytmVUDBgGTSywzGbjK+/3/gE+dc678yhQRkYM5aMvFOVdoZjcB04E4YJxzbpGZDQdmO+cmAy8C480sC9hKIPRFRKQSlamH7pybBkwrMfa3oN/zgEvLtzQRETkUEfNNUREROTDzq9VtZpuAlWVYtDGwuYLLCUda79ii9Y4tR7LerZ1zIY8q8S3Qy8rMZjvnUv2uo7JpvWOL1ju2VNR6q+UiIhIlFOgiIlEiEgJ9rN8F+ETrHVu03rGlQtY77HvoIiJSNpGwhy4iImUQ1oF+sAtrRDIza2Vmn5lZmpktMrNbvPGGZvaJmS3xfjbwxs3MnvZei5/MrJu/a3D4zCzOzOaZ2RRvuq13YZQs70Ip1bzxCr9wSmUxs/pm9o6ZLTazdDPrEyPb+jbv3/dCM3vDzGpE4/Y2s3FmttHMFgaNHfL2NbOrvOWXmNlVoZ7rQMI20Mt4YY1IVgj82TmXAvQGbvTW725gpnOuAzDTm4bA69DBuw0Dnqn8ksvNLUB60PTjwFPeBVK2EbhgClTChVMq0WjgI+dcJ+B4Ausf1dvazBKBm4FU59wxBE4dMojo3N4vA/1LjB3S9jWzhsADQC8C16F4YN+bQJk558LyBvQBpgdN3wPc43ddFbi+7wN9gQyguTfWHMjwfn8OGBy0/P7lIulG4GydM4EzgCmAEfiCRdWS253A+YP6eL9X9ZYzv9fhMNa5HrC8ZO0xsK33XSehobf9pgD9onV7A22AhYe7fYHBwHNB479Yriy3sN1Dp2wX1ogK3p+WXYEfgGbOuXXerPVAM+/3aHk9/gn8BSj2phsB213gwijwy/Wq8AunVJK2wCbgJa/V9IKZ1SLKt7VzLhv4B7AKWEdg+80h+rf3Poe6fY94u4dzoMcEM6sNvAvc6pzbETzPBd6mo+YwJDM7D9jonJvjdy2VrCrQDXjGOdcV2M3//vwGom9bA3jtgoEE3tBaALX4dVsiJlTW9g3nQC/LhTUimpnFEwjz151z73nDG8ysuTe/ObDRG4+G1+Mk4AIzW0Hg2rRnEOgt1/cujAK/XK8yXTglAqwB1jjnfvCm3yEQ8NG8rQHOApY75zY55wqA9wj8G4j27b3PoW7fI97u4RzoZbmwRsQyMyNwHvl059yooFnBFwu5ikBvfd/477xPyHsDOUF/zkUE59w9zrmWzrk2BLbnp865y4HPCFwYBX69zhF/4RTn3HpgtZntu6L5mUAaUbytPauA3mZW0/v3vm+9o3p7BznU7TsdONvMGnh/3ZztjZWd3x8kHORDhnOBTGApcK/f9ZTzup1M4E+wn4D53u1cAj3DmcASYAbQ0FveCBz1sxT4mcCRA76vxxGs/2nAFO/3dsCPQBbwNlDdG6/hTWd589v5XfcRrO8JwGxve08CGsTCtgYeBBYDC4HxQPVo3N7AGwQ+Jygg8BfZ1YezfYE/eOufBfz+UOvQN0VFRKJEOLdcRETkECjQRUSihAJdRCRKKNBFRKKEAl1EJEoo0EVEooQCXUQkSijQRUSixP8DVlFuCUl2miIAAAAASUVORK5CYII=\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 0000000..6d60996 Binary files /dev/null and b/images/ab-pruning.png differ diff --git a/images/minimax.png b/images/minimax.png new file mode 100644 index 0000000..cae1c80 Binary files /dev/null and b/images/minimax.png differ diff --git a/images/pwd.png b/images/pwd.png new file mode 100644 index 0000000..bdc8256 Binary files /dev/null and b/images/pwd.png differ diff --git a/images/solutions.png b/images/solutions.png new file mode 100644 index 0000000..4e2e934 Binary files /dev/null and b/images/solutions.png differ diff --git a/images/terminal.png b/images/terminal.png new file mode 100644 index 0000000..8e15da3 Binary files /dev/null and b/images/terminal.png differ diff --git a/images/tsp.jpg b/images/tsp.jpg new file mode 100644 index 0000000..cf8fedc Binary files /dev/null and b/images/tsp.jpg differ 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