{ "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 }