948 lines
25 KiB
Plaintext
948 lines
25 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"**Make sure you run this at the begining**"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from utils.load_data import load_data\n",
|
|
"from utils.visualize_tsp import plotTSP\n",
|
|
"\n",
|
|
"from tsp import TSP_Bench_ONE\n",
|
|
"from tsp import TSP_Bench_PATH\n",
|
|
"from tsp import TSP_Bench_ALL"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Workshop Starts Here"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"<img src=\"images/tsp.jpg\" alt=\"TSP\" style=\"width: 900px;\"/>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"<img src=\"images/solutions.png\" alt=\"solutions\" style=\"width: 900px;\"/>"
|
|
]
|
|
},
|
|
{
|
|
"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": null,
|
|
"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": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def fitness(solution, coords):\n",
|
|
" N = len(coords)\n",
|
|
" cur_fit = 0\n",
|
|
" if(len(solution) != N):\n",
|
|
" return math.inf\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": {
|
|
"scrolled": true
|
|
},
|
|
"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",
|
|
"import numpy as np\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=1000):\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": null,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"tsp_file = './template/data/simple/ulysses16.tsp'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"best_solution, fitness_list, time = TSP_Bench_ONE(tsp_file, MyRandomModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.plot(fitness_list, 'o-')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Uniform Cost Search"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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=1000):\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": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tsp_file = './template/data/simple/ulysses16.tsp'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"best_solution, fitness_list, time = TSP_Bench_ONE(tsp_file, MyUCSModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## A star"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Heuristic"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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=1000):\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\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tsp_file = './template/data/simple/ulysses16.tsp'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"best_solution, fitness_list, time = TSP_Bench_ONE(tsp_file, MyASModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": true
|
|
},
|
|
"outputs": [],
|
|
"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": null,
|
|
"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": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tsp_file = './template/data/simple/ulysses16.tsp'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"best_solution, fitness_list, time = TSP_Bench_ONE(tsp_file, MyHillClimbModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.plot(fitness_list)"
|
|
]
|
|
},
|
|
{
|
|
"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, 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=1000):\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": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tsp_problem = './template/data/simple/ulysses16.tsp'"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"best_solution, fitness_list, time = TSP_Bench_ONE(tsp_file, MyModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Test All Dataset"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tsp_path = './template'\n",
|
|
"for root, _, files in os.walk(tsp_path + '/data'):\n",
|
|
" if(files):\n",
|
|
" for f in files:\n",
|
|
" print(str(root) + \"/\" + f)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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": null,
|
|
"metadata": {
|
|
"scrolled": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(\"Random Search\")\n",
|
|
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyRandomModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_results(best_solutions, times, \"Random Model\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(\"Uniform Cost Search\")\n",
|
|
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyUCSModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_results(best_solutions, times, \"Uniform Cost Search\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(\"A Star Search\")\n",
|
|
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyASModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_results(best_solutions, times, \"A Star Search\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(\"Hill-Climbing Search\")\n",
|
|
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyHillClimbModel)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"scrolled": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"plot_results(best_solutions, times, \"Hill-Climbing Search\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Conclusions"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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": [
|
|
"<p style=\"font-size: 18px\"> 1. UCS is the slowest one, and gets the same result as BFS, DFS, DP </p>\n",
|
|
"<p style=\"font-size: 18px\"> 1. A-Star can only solve problems with number of cities < 50. </p>\n",
|
|
"<p style=\"font-size: 18px\"> 2. Hill-Climbing gets different results every time (Heuristic). </p>\n",
|
|
"<p style=\"font-size: 18px\"> 3. Hill-Climbing is the fastest one till now. (faster than Dynamic Programming, but worse results). </p>"
|
|
]
|
|
},
|
|
{
|
|
"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
|
|
}
|