[fix] error handling

This commit is contained in:
2021-01-07 22:52:00 +00:00
parent 0a10febfd7
commit ff8de454a6
18 changed files with 4581 additions and 4939 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,954 @@
{
"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.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": [
"<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",
"import numpy as np\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",
" 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(tsp_file, MyRandomModel, max_it=100)"
]
},
{
"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):\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(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):\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": 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(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(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",
"import numpy as np\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": 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(tsp_file, MyModel)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Test All Dataset"
]
},
{
"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",
" print(str(root) + \"/\" + f)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tsp_path = './template/data'"
]
},
{
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@@ -0,0 +1,679 @@
{
"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.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": [
"<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",
" 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",
"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):\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": {},
"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(tsp_file, MyRandomModel, max_it=100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.plot(fitness_list, 'o-')"
]
},
{
"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 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": null,
"metadata": {},
"outputs": [],
"source": [
"tsp_file = './template/data/simple/ulysses16.tsp'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Set hyper-parameters\n",
"T = -1\n",
"stopping_T = -1\n",
"alpha = 0.99"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"best_solution, fitness_list, time = TSP_Bench(tsp_file, MySAModel, T, stopping_T, alpha, max_it=1000)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"plt.plot(fitness_list, 'o-')"
]
},
{
"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",
" 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": 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(tsp_file, MyModel)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Test All Dataset"
]
},
{
"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",
" 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": {},
"outputs": [],
"source": [
"tsp_path = './template/data'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {},
"outputs": [],
"source": [
"# Set hyper-parameters\n",
"T = -1\n",
"stopping_T = -1\n",
"alpha = 0.8"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"print(\"Simulated Annealing\")\n",
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MySAModel, T, stopping_T, alpha, max_it=1000)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@@ -0,0 +1,717 @@
{
"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.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": [
"<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",
" 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",
"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):\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": true
},
"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(tsp_file, MyRandomModel, max_it=100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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": null,
"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": null,
"metadata": {},
"outputs": [],
"source": [
"tsp_file = './template/data/simple/ulysses16.tsp'"
]
},
{
"cell_type": "code",
"execution_count": null,
"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": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"best_solution, fitness_list, time = TSP_Bench(tsp_file, MyACOModel, 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": 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",
" 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": null,
"metadata": {},
"outputs": [],
"source": [
"tsp_problem = './template/data/simple/ulysses16.tsp'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"best_solution, fitness_list, time = TSP_Bench(tsp_file, MyModel)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Test All Dataset"
]
},
{
"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",
" 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": {},
"outputs": [],
"source": [
"tsp_path = './template/data'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"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": {},
"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": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Ant Colony Optimization\")\n",
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyACOModel, 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": null,
"metadata": {},
"outputs": [],
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@@ -0,0 +1,763 @@
{
"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.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": [
"<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",
" 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",
"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):\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": {},
"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(tsp_file, MyRandomModel, max_it=100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.plot(fitness_list, 'o-')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Genetic Algorithm"
]
},
{
"cell_type": "code",
"execution_count": null,
"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": null,
"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": null,
"metadata": {},
"outputs": [],
"source": [
"tsp_problem = \"./template/data/simple/ulysses16.tsp\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"print(\"Genetic Algorithm\")\n",
"best_solution, fitness_list, time = TSP_Bench(tsp_problem, MyGAModel, max_it=200)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"plt.plot(fitness_list, 'o-')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plotTSP([best_solution], load_data(tsp_problem), num_iters=1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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": 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",
" 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": null,
"metadata": {},
"outputs": [],
"source": [
"tsp_problem = './template/data/simple/ulysses16.tsp'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"best_solution, fitness_list, time = TSP_Bench(tsp_file, MyModel)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Test All Dataset"
]
},
{
"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",
" 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": {},
"outputs": [],
"source": [
"tsp_path = './template/data/medium'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Random Search\")\n",
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyRandomModel)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"plot_results(best_solutions, times, \"Random Model\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"Genetic Algorithm\")\n",
"best_solutions, fitness_lists, times = TSP_Bench_ALL(tsp_path, MyGAModel, max_it=100, timeout=600)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}