Skip to content

Instantly share code, notes, and snippets.

@Hasenpfote
Last active October 10, 2021 13:27
Show Gist options
  • Save Hasenpfote/f9e71ceecf7a185422fe22000ce3cd2f to your computer and use it in GitHub Desktop.
Save Hasenpfote/f9e71ceecf7a185422fe22000ce3cd2f to your computer and use it in GitHub Desktop.
A note on the use of szudzik's pairing function in N dimensions.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "b6a92909-f487-4710-b2eb-006fa3026013",
"metadata": {},
"source": [
"# Pairing function\n",
"- [Pairing_function](https://en.wikipedia.org/wiki/Pairing_function)\n",
"- [ElegantPairing](http://szudzik.com/ElegantPairing.pdf)"
]
},
{
"cell_type": "code",
"execution_count": 466,
"id": "a0b2809e-7705-4961-8f58-1c53b7f23180",
"metadata": {},
"outputs": [],
"source": [
"import itertools\n",
"import math\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.patches as patches\n",
"import matplotlib.ticker as ticker"
]
},
{
"cell_type": "markdown",
"id": "b877d17f-4e5a-4f8d-8eb5-5d7a7e05336a",
"metadata": {},
"source": [
"## Paring function"
]
},
{
"cell_type": "code",
"execution_count": 458,
"id": "c0d73135-1199-47b1-951c-540db8445e58",
"metadata": {},
"outputs": [],
"source": [
"# http://szudzik.com/ElegantPairing.pdf\n",
"# Due to the specification of the function, overflow occurs,\n",
"# but there is no problem in terms of calculation intention.\n",
"def pair(x, y):\n",
" #assert x.dtype.kind == 'u' and y.dtype.kind == 'u',\\\n",
" # 'x and y must be unsigned.'\n",
" \n",
" return np.where(x < y, y * y + x, x * x + x + y)\n",
"\n",
"def unpair(z):\n",
" #assert z.dtype.kind == 'u',\\\n",
" # 'z must be unsigned.'\n",
" '''\n",
" For large integers, the square root will be an unintended value.\n",
" sqrtz = np.floor(np.sqrt(z)).astype(z.dtype)\n",
" '''\n",
" sqrtz = np.vectorize(math.isqrt, otypes=[z.dtype,])(z)\n",
" sqz = sqrtz * sqrtz\n",
" z_sqz = z - sqz\n",
"\n",
" return np.where(z_sqz < sqrtz, (z_sqz, sqrtz), (sqrtz, z_sqz - sqrtz))"
]
},
{
"cell_type": "markdown",
"id": "e758adc1-c516-4d4d-bf62-6ccde3fa16e9",
"metadata": {},
"source": [
"### A simple example."
]
},
{
"cell_type": "code",
"execution_count": 459,
"id": "95a5dff8-ae69-4ac6-8069-8f81c3b9ce6b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"pair: (4, 2) => 22\n",
"unpair: 22 => (4, 2)\n"
]
}
],
"source": [
"x = np.uint32(4)\n",
"y = np.uint32(2)\n",
"z = pair(x, y)\n",
"print('pair: ({}, {}) => {}'.format(x, y, z))\n",
"print('unpair: {} => ({}, {})'.format(z, *unpair(z)))"
]
},
{
"cell_type": "markdown",
"id": "15673476-38c6-49e5-9c33-77faf14103df",
"metadata": {},
"source": [
"## Limits for n-dimensional coordinates"
]
},
{
"cell_type": "code",
"execution_count": 470,
"id": "6de429c9-694d-42d0-841a-711dc4513dbd",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dim:2 dtype:int32 lim:46340\n",
"dim:2 dtype:int64 lim:3037000499\n",
"dim:2 dtype:uint32 lim:65535\n",
"dim:2 dtype:uint64 lim:4294967295\n",
"dim:3 dtype:int32 lim:215\n",
"dim:3 dtype:int64 lim:55108\n",
"dim:3 dtype:uint32 lim:255\n",
"dim:3 dtype:uint64 lim:65535\n",
"dim:4 dtype:int32 lim:14\n",
"dim:4 dtype:int64 lim:234\n",
"dim:4 dtype:uint32 lim:15\n",
"dim:4 dtype:uint64 lim:255\n"
]
}
],
"source": [
"dims = (2, 3, 4)\n",
"kinds = ('i', 'u')\n",
"sizes = (4, 8)\n",
"\n",
"data = []\n",
"\n",
"for d, k, s in itertools.product(dims, kinds, sizes):\n",
" dtype = np.dtype(k + str(s))\n",
" ii = np.iinfo(dtype)\n",
" nth = 2 ** (d - 1)\n",
" lim = int(ii.max ** (1 / nth))\n",
" if int(lim ** nth) >= ii.max:\n",
" lim -= 1\n",
" data.append({'dim': d, 'dtype': dtype, 'lim': lim})\n",
" print('dim:{} dtype:{:6s} lim:{}'.format(d, dtype.name, lim))"
]
},
{
"cell_type": "code",
"execution_count": 477,
"id": "92c8ca3d-6952-4cb9-820d-ad953ef82e14",
"metadata": {},
"outputs": [],
"source": [
"def check_validity(*coord):\n",
" h = pair(*coord[0:2])\n",
" for i in range(2, len(coord)):\n",
" h = pair(h, coord[i])\n",
"\n",
" res = []\n",
" p = unpair(h)\n",
" res.append(p[1])\n",
" for i in range(2, len(coord)):\n",
" p = unpair(p[0])\n",
" res.append(p[1])\n",
"\n",
" res.append(p[0])\n",
" res.reverse()\n",
"\n",
" cond = np.all(coord == np.asarray(res))\n",
"\n",
" print('{} => {} => {} ({})'.format(coord, h, res, cond))"
]
},
{
"cell_type": "code",
"execution_count": 484,
"id": "4826d64b-c140-46ee-aab3-6a3718c58bce",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"----------\n",
"dim:2 dtype:int32 lim:46340\n",
"(46340, 46340) => 2147488280 => [46340, 46340] (True)\n",
"(46339, 46340) => 2147441939 => [46339, 46340] (True)\n",
"----------\n",
"dim:2 dtype:int64 lim:3037000499\n",
"(3037000499, 3037000499) => 9223372037000249999 => [3037000499, 3037000499] (True)\n",
"(3037000498, 3037000499) => 9223372033963249499 => [3037000498, 3037000499] (True)\n",
"----------\n",
"dim:2 dtype:uint32 lim:65535\n",
"(65535, 65535) => 4294967295 => [65535, 65535] (True)\n",
"(65534, 65535) => 4294901759 => [65534, 65535] (True)\n",
"----------\n",
"dim:2 dtype:uint64 lim:4294967295\n",
"(4294967295, 4294967295) => 18446744073709551615 => [4294967295, 4294967295] (True)\n",
"(4294967294, 4294967295) => 18446744069414584319 => [4294967294, 4294967295] (True)\n",
"----------\n",
"dim:3 dtype:int32 lim:215\n",
"(215, 215, 215) => 2176735895 => [215, 215, 215] (True)\n",
"(213, 214, 215) => 2116874305 => [213, 214, 215] (True)\n",
"----------\n",
"dim:3 dtype:int64 lim:55108\n",
"(55108, 55108, 55108) => 9223380422160591388 => [55108, 55108, 55108] (True)\n",
"(55106, 55107, 55108) => 9222376264821159688 => [55106, 55107, 55108] (True)\n",
"----------\n",
"dim:3 dtype:uint32 lim:255\n",
"(255, 255, 255) => 4294902015 => [255, 255, 255] (True)\n",
"(253, 254, 255) => 4195088385 => [253, 254, 255] (True)\n",
"----------\n",
"dim:3 dtype:uint64 lim:65535\n",
"(65535, 65535, 65535) => 18446744069414649855 => [65535, 65535, 65535] (True)\n",
"(65533, 65534, 65535) => 18445055275388370945 => [65533, 65534, 65535] (True)\n",
"----------\n",
"dim:4 dtype:int32 lim:14\n",
"(14, 14, 14, 14) => 2541621824 => [14, 14, 14, 14] (True)\n",
"(11, 12, 13, 14) => 585325456 => [11, 12, 13, 14] (True)\n",
"----------\n",
"dim:4 dtype:int64 lim:234\n",
"(234, 234, 234, 234) => 9300948435151807824 => [234, 234, 234, 234] (True)\n",
"(231, 232, 233, 234) => 8538068300101217516 => [231, 232, 233, 234] (True)\n",
"----------\n",
"dim:4 dtype:uint32 lim:15\n",
"(15, 15, 15, 15) => 4263502335 => [15, 15, 15, 15] (True)\n",
"(12, 13, 14, 15) => 1086130907 => [12, 13, 14, 15] (True)\n",
"----------\n",
"dim:4 dtype:uint64 lim:255\n",
"(255, 255, 255, 255) => 18446183322745962495 => [255, 255, 255, 255] (True)\n",
"(252, 253, 254, 255) => 17053105868504825387 => [252, 253, 254, 255] (True)\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/tmp/ipykernel_7221/3045957758.py:23: RuntimeWarning: overflow encountered in uint_scalars\n",
" return np.where(z_sqz < sqrtz, (z_sqz, sqrtz), (sqrtz, z_sqz - sqrtz))\n",
"/tmp/ipykernel_7221/3045957758.py:23: RuntimeWarning: overflow encountered in ulong_scalars\n",
" return np.where(z_sqz < sqrtz, (z_sqz, sqrtz), (sqrtz, z_sqz - sqrtz))\n"
]
}
],
"source": [
"for datum in data:\n",
" dim = datum['dim']\n",
" dtype = datum['dtype']\n",
" lim = datum['lim']\n",
" print('-'*10)\n",
" print('dim:{} dtype:{} lim:{}'.format(dim, dtype.name, lim))\n",
" # Case A\n",
" arr = np.array([lim,]*dim,\n",
" dtype='u' + str(dtype.itemsize))\n",
" check_validity(*arr)\n",
" # Case B\n",
" arr = np.array([lim - i for i in reversed(range(dim))],\n",
" dtype='u' + str(dtype.itemsize))\n",
" check_validity(*arr) "
]
},
{
"cell_type": "markdown",
"id": "dada1a1e-3854-4018-9633-f4dad2c3d4f7",
"metadata": {},
"source": [
"## Plotting z value"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "19e97d14-0323-4f9f-9b56-5244a21e0565",
"metadata": {},
"outputs": [],
"source": [
"# https://stackoverflow.com/questions/8247973/how-do-i-specify-an-arrow-like-linestyle-in-matplotlib\n",
"def arrowplot(axes, x, y, nArrs=30, mutateSize=10, color='gray', markerStyle='o'):\n",
" '''arrowplot : plots arrows along a path on a set of axes\n",
" axes : the axes the path will be plotted on\n",
" x : list of x coordinates of points defining path\n",
" y : list of y coordinates of points defining path\n",
" nArrs : Number of arrows that will be drawn along the path\n",
" mutateSize : Size parameter for arrows\n",
" color : color of the edge and face of the arrow head\n",
" markerStyle : Symbol\n",
" \n",
" Bugs: If a path is straight vertical, the matplotlab FanceArrowPatch bombs out.\n",
" My kludge is to test for a vertical path, and perturb the second x value\n",
" by 0.1 pixel. The original x & y arrays are not changed\n",
" \n",
" MHuster 2016, based on code by \n",
" '''\n",
" # recast the data into numpy arrays\n",
" x = np.array(x, dtype='f')\n",
" y = np.array(y, dtype='f')\n",
" nPts = len(x)\n",
"\n",
" # Plot the points first to set up the display coordinates\n",
" axes.plot(x,y, markerStyle, ms=5, color=color)\n",
"\n",
" # get inverse coord transform\n",
" inv = axes.transData.inverted()\n",
"\n",
" # transform x & y into display coordinates\n",
" # Variable with a 'D' at the end are in display coordinates\n",
" xyDisp = np.array(axes.transData.transform(list(zip(x,y))))\n",
" xD = xyDisp[:,0]\n",
" yD = xyDisp[:,1]\n",
"\n",
" # drD is the distance spanned between pairs of points\n",
" # in display coordinates\n",
" dxD = xD[1:] - xD[:-1]\n",
" dyD = yD[1:] - yD[:-1]\n",
" drD = np.sqrt(dxD**2 + dyD**2)\n",
"\n",
" # Compensating for matplotlib bug\n",
" dxD[np.where(dxD==0.0)] = 0.1\n",
"\n",
"\n",
" # rtotS is the total path length\n",
" rtotD = np.sum(drD)\n",
"\n",
" # based on nArrs, set the nominal arrow spacing\n",
" arrSpaceD = rtotD / nArrs\n",
"\n",
" # Loop over the path segments\n",
" iSeg = 0\n",
" while iSeg < nPts - 1:\n",
" # Figure out how many arrows in this segment.\n",
" # Plot at least one.\n",
" nArrSeg = max(1, int(drD[iSeg] / arrSpaceD + 0.5))\n",
" xArr = (dxD[iSeg]) / nArrSeg # x size of each arrow\n",
" segSlope = dyD[iSeg] / dxD[iSeg]\n",
" # Get display coordinates of first arrow in segment\n",
" xBeg = xD[iSeg]\n",
" xEnd = xBeg + xArr\n",
" yBeg = yD[iSeg]\n",
" yEnd = yBeg + segSlope * xArr\n",
" # Now loop over the arrows in this segment\n",
" for iArr in range(nArrSeg):\n",
" # Transform the oints back to data coordinates\n",
" xyData = inv.transform(((xBeg, yBeg),(xEnd,yEnd)))\n",
" # Use a patch to draw the arrow\n",
" # I draw the arrows with an alpha of 0.5\n",
" p = patches.FancyArrowPatch( \n",
" xyData[0], xyData[1], \n",
" arrowstyle='simple',\n",
" mutation_scale=mutateSize,\n",
" color=color, alpha=0.5)\n",
" axes.add_patch(p)\n",
" # Increment to the next arrow\n",
" xBeg = xEnd\n",
" xEnd += xArr\n",
" yBeg = yEnd\n",
" yEnd += segSlope * xArr\n",
" # Increment segment number\n",
" iSeg += 1"
]
},
{
"cell_type": "code",
"execution_count": 460,
"id": "3be19305-3b81-4423-acdb-25265e46a1cb",
"metadata": {},
"outputs": [],
"source": [
"def plot_z(z):\n",
" fig, ax = plt.subplots(figsize=(4, 4))\n",
" x, y = unpair(z)\n",
" ax.grid()\n",
" ax.set_aspect('equal')\n",
" ax.get_xaxis().get_major_formatter().set_useOffset(False)\n",
" ax.get_xaxis().set_major_locator(ticker.MaxNLocator(integer=True)) \n",
" ax.get_yaxis().get_major_formatter().set_useOffset(False)\n",
" ax.get_yaxis().set_major_locator(ticker.MaxNLocator(integer=True)) \n",
" arrowplot(ax, x, y, nArrs=4*(len(x)-1), mutateSize=10, color='red')\n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 461,
"id": "f427d769-f2e9-4855-9762-585456b83ed2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23\n",
" 24]\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 288x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"z = np.arange(25, dtype='u4')\n",
"print(z)\n",
"plot_z(z)"
]
},
{
"cell_type": "code",
"execution_count": 462,
"id": "0255deea-75fc-40de-973e-c8ae9e7c126a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[ 0 1 4 2 3 5 6 7 8 12 13 14 20 21 22]\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 288x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"arr_x = np.arange(5, dtype='u4')\n",
"arr_y = np.arange(3, dtype='u4')\n",
"coords = np.array(np.meshgrid(arr_x, arr_y)).T.reshape(-1, 2)\n",
"z = pair(coords[..., 0], coords[..., 1])\n",
"print(z)\n",
"plot_z(z)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment