Skip to content

Instantly share code, notes, and snippets.

@mirrornerror
Last active April 20, 2023 14:38
Show Gist options
  • Save mirrornerror/79442d72b7003be1d31ae930c550ac21 to your computer and use it in GitHub Desktop.
Save mirrornerror/79442d72b7003be1d31ae930c550ac21 to your computer and use it in GitHub Desktop.
TSP bit DP
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {},
"cell_type": "markdown",
"source": "# TSP BIT DP\n### Travelling Salesman Problem by Dynamic Programming (bit DP)"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Import Libraries"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:33.992801Z",
"end_time": "2019-05-23T08:32:34.002606Z"
},
"trusted": true
},
"cell_type": "code",
"source": "import matplotlib.pyplot as plt\nimport numpy as np\nseed = 42\nnp.random.seed(seed=seed)\n%matplotlib inline",
"execution_count": 88,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Generate Parameters"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:34.005356Z",
"end_time": "2019-05-23T08:32:34.042335Z"
},
"trusted": true
},
"cell_type": "code",
"source": "def gen_param(num):\n path = list(range(num)) + [0]\n X, Y= np.random.random([2, num])\n XY = X + Y * 1j\n return num, X, Y, XY, path\n\ndef dist_mx(num):\n mx = []\n for i in range(num):\n mx.append([])\n for j in range(num):\n mx[i].append(abs(XY[i] - XY[j]))\n return mx\n\n# Generate new parameters\nnum, X, Y, XY, path = gen_param(10) # input the number of nodes\ndist = dist_mx(num)\nall_visited = (1 << num) - 1\nprint('num =', num)\nprint('dist size =', num, 'x', num)\nprint('all_visited =', bin(all_visited))\nprint('path =', path)",
"execution_count": 89,
"outputs": [
{
"output_type": "stream",
"text": "num = 10\ndist size = 10 x 10\nall_visited = 0b1111111111\npath = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Plot Path"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:34.048364Z",
"end_time": "2019-05-23T08:32:34.302694Z"
},
"trusted": true
},
"cell_type": "code",
"source": "def plot_path(path, size=6):\n plt.figure(figsize=(size, size))\n cmap = plt.get_cmap(\"tab10\")\n plt.axis('equal')\n plt.plot(X[path], Y[path], alpha=0.0)\n plt.scatter(X[0], Y[0], s=80, c='r', marker='o')\n for i in range(len(path)-1):\n plt.arrow(X[path[i]], Y[path[i]], \n X[path[i+1]]-X[path[i]], Y[path[i+1]]-Y[path[i]], \n head_width=0.02, head_length=0.02, length_includes_head=True, \n fc=cmap(0), ec=cmap(0))\n \n for i in range(num):\n plt.text(X[i], Y[i]+0.01, s=i, fontsize=10, color='gray')\n\nprint('Initial Plot Path:')\nplot_path(path)",
"execution_count": 90,
"outputs": [
{
"output_type": "stream",
"text": "Initial Plot Path:\n",
"name": "stdout"
},
{
"output_type": "display_data",
"data": {
"text/plain": "<matplotlib.figure.Figure at 0x110985940>",
"image/png": "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\n"
},
"metadata": {}
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## TSP with functools.lru_cache"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:34.306577Z",
"end_time": "2019-05-23T08:32:34.358664Z"
},
"trusted": true
},
"cell_type": "code",
"source": "from functools import lru_cache\n\n@lru_cache(maxsize=None)\ndef TSP_lru(S, pos): \n if S == all_visited:\n return dist[pos][0]\n return min([dist[pos][i] + TSP_lru(S | (1 << i), i) for i in range(num) if S & (1 << i) == 0])\n\n# @lru_cache(maxsize=None)\n# def TSP_lru(S, pos): # same as the above\n# if S == all_visited:\n# return dist[pos][0]\n#\n# d_min = float('inf')\n# for i in range(num):\n# if S & (1 << i) == 0: # if not visited \n# d = dist[pos][i] + TSP_lru(S | (1 << i), i)\n# if d < d_min:\n# d_min = d\n# return d_min\n\n# Solve by TSP with functools.lru_cache\n%time print('Total Distance:', TSP_lru(1, 0))\nprint(TSP_lru.cache_info()) # show cache info\nTSP_lru.cache_clear() # clear cache otherwise same outputs as before",
"execution_count": 91,
"outputs": [
{
"output_type": "stream",
"text": "Total Distance: 2.8311616245285047\nCPU times: user 14.9 ms, sys: 2.6 ms, total: 17.5 ms\nWall time: 17.8 ms\nCacheInfo(hits=6921, misses=2305, maxsize=None, currsize=2305)\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## TSP with memoization decorator"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:34.365036Z",
"end_time": "2019-05-23T08:32:34.410654Z"
},
"trusted": true
},
"cell_type": "code",
"source": "def memoize(f):\n cache = {}\n def func(*args):\n if not args in cache:\n cache[args] = f(*args)\n return cache[args]\n return func\n\n@memoize\ndef TSP_memo(S, pos): # re-run this function to clear cache otherwise same outputs as before\n if S == all_visited:\n return dist[pos][0]\n return min([dist[pos][i] + TSP_memo(S | (1 << i), i) for i in range(num) if S & (1 << i) == 0])\n\n# Solve by TSP with memoization decorator\n%time print('Total Distance:', TSP_memo(1, 0))",
"execution_count": 92,
"outputs": [
{
"output_type": "stream",
"text": "Total Distance: 2.8311616245285047\nCPU times: user 16.8 ms, sys: 1.94 ms, total: 18.8 ms\nWall time: 19 ms\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## TSP bit DP"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:34.415330Z",
"end_time": "2019-05-23T08:32:34.473153Z"
},
"trusted": true
},
"cell_type": "code",
"source": "def TSP_BDP(S, pos):\n # if visited before\n if dp[S][pos] >= 0:\n return dp[S][pos]\n \n # if all visited \n if S == all_visited: \n dp[S][pos] = dist[pos][0]\n return dp[S][pos]\n \n # if not visited yet\n dp[S][pos] = min([dist[pos][i] + TSP_BDP(S | (1 << i), i) for i in range(num) if S & (1 << i) == 0])\n \n return dp[S][pos]\n\n# Solve TSP by bit DP (15 nodes: 0.75 sec, 18 nodes: 8.42 sec, 20 nodes: 44 sec)\ndp = [[-1] * num for _ in range(1 << num)] # initialize memoization\n%time print('Total Distance:', TSP_BDP(1, 0))",
"execution_count": 93,
"outputs": [
{
"output_type": "stream",
"text": "Total Distance: 2.8311616245285047\nCPU times: user 18.7 ms, sys: 2.43 ms, total: 21.2 ms\nWall time: 23.1 ms\n",
"name": "stdout"
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Generate Tour from TSP_BDP"
},
{
"metadata": {
"ExecuteTime": {
"start_time": "2019-05-23T08:32:34.476402Z",
"end_time": "2019-05-23T08:32:34.750629Z"
},
"code_folding": [],
"trusted": true
},
"cell_type": "code",
"source": "def gen_dp_tour():\n tour = [0]\n S = 1\n while len(tour) < num:\n d_min = np.inf\n pos = None\n for i in range(num):\n if S & (1 << i) == 0:\n d = dist[tour[-1]][i] + dp[S | (1 << i)][i]\n if d < d_min:\n d_min = d\n pos = i\n S |= (1 << pos)\n tour.append(pos)\n return tour + [0]\n\n# Generate Tour\nTour = gen_dp_tour()\nprint('Tour:', Tour)\nplot_path(Tour)",
"execution_count": 94,
"outputs": [
{
"output_type": "stream",
"text": "Tour: [0, 3, 9, 7, 1, 2, 8, 6, 5, 4, 0]\n",
"name": "stdout"
},
{
"output_type": "display_data",
"data": {
"text/plain": "<matplotlib.figure.Figure at 0x118713e48>",
"image/png": "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\n"
},
"metadata": {}
}
]
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "",
"execution_count": null,
"outputs": []
}
],
"metadata": {
"kernelspec": {
"name": "py36",
"display_name": "py36",
"language": "python"
},
"language_info": {
"name": "python",
"version": "3.6.7",
"mimetype": "text/x-python",
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"pygments_lexer": "ipython3",
"nbconvert_exporter": "python",
"file_extension": ".py"
},
"gist": {
"id": "79442d72b7003be1d31ae930c550ac21",
"data": {
"description": "Jupyters/TSP/Untitled.ipynb",
"public": true
}
},
"_draft": {
"nbviewer_url": "https://gist.github.com/79442d72b7003be1d31ae930c550ac21"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment