Skip to content

Commit

Permalink
Added hypercube on a string example
Browse files Browse the repository at this point in the history
  • Loading branch information
tBuLi committed Jul 5, 2024
1 parent 93944df commit 4563639
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 0 deletions.
207 changes: 207 additions & 0 deletions content/2DPGA/ex_2dpga_hypercube_on_string.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "169aa061-abb7-4888-83cb-088b0ad87af9",
"metadata": {},
"source": [
"# Hypercube on a string\n",
"\n",
"A demo of the famous tesseract on a string! More info can be found here: https://enki.ws/ganja.js/examples/pga_dyn.html"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "2dc7b21b-034b-42e9-ad83-05d9605de074",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Note: you may need to restart the kernel to use updated packages.\n"
]
}
],
"source": [
"%pip install -q kingdon anywidget==0.9.9"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ebb1e69c-7bb1-4eeb-a6a0-dbf06c76c4d4",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from kingdon import Algebra\n",
"from sympy import cos, sin, Symbol\n",
"import ipywidgets"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "6dd82824-271e-4b23-a547-993d9c771149",
"metadata": {},
"outputs": [],
"source": [
"def euler(f,y,h):\n",
" return [yi + h*fi for yi, fi in zip(y, f(*y))]\n",
"\n",
"def RK4(f,y,h):\n",
" k1 = f(*y)\n",
" k2 = f(*[yi + 0.5*h*k1i for yi, k1i in zip(y, k1)])\n",
" k3 = f(*[yi + 0.5*h*k2i for yi, k2i in zip(y, k2)])\n",
" k4 = f(*[yi + h*k3i for yi, k3i in zip(y, k3)])\n",
" return [yi + (h/3)*(k2i + k3i + (k1i + k4i)*0.5) \n",
" for yi, k1i, k2i, k3i, k4i in zip(y, k1, k2, k3, k4)]"
]
},
{
"cell_type": "markdown",
"id": "a48fa9e9-b26b-4d5a-b2e7-4c2d12e5a8ca",
"metadata": {},
"source": [
"Hint: try increasing $d$!"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0d34bcef-2f02-49ff-955a-87fd3d694147",
"metadata": {},
"outputs": [],
"source": [
"d = 2\n",
"alg = Algebra(d, 0, 1)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "0ffd82d4-cfba-41e5-879e-f9ad4e284f20",
"metadata": {},
"outputs": [],
"source": [
"points = [\n",
" alg.vector([1.0, *(float(x)-0.5 for x in bin(i)[2:].zfill(d))]).dual()\n",
" for i in range(2**d)\n",
"]\n",
"edges = [\n",
" [a, b]\n",
" for i, a in enumerate(points)\n",
" for j, b in enumerate(points)\n",
" if not (i<=j or (i ^ j) & ((i ^ j) - 1))\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "be300f39-b86d-4121-997b-a647a37e0348",
"metadata": {},
"outputs": [],
"source": [
"# Gravitational force and spring constant\n",
"fg = alg.multivector(e02=-9.81)\n",
"spring_constant = 12\n",
"# attach = alg.evenmv(e=1, e02=-0.25) >> points[2**d-1]\n",
"attach = alg.evenmv(e=1, e02=-1) * points[2**d-1]\n",
"\n",
"def force(M, B):\n",
" gravitational = (M.reverse() >> fg).dual()\n",
" hooke = -spring_constant*((M.reverse() >> attach) & points[2**d-1])\n",
" damping = (-0.25 * B).dual()\n",
" return hooke + gravitational + damping\n",
"\n",
"state = [\n",
" alg.evenmv(e=1, e01=0.0, e02=0.0, e12=0.0), # The starting position and orientation in space. (identity) \n",
" alg.multivector(e01=0.0, e02=0.0, e12=-0.2) # The starting linear and rotational velocity in body.\n",
"]\n",
"\n",
"dState = lambda M, B: [ # Change in M and B\n",
" -0.5 * M * B,\n",
" (force(M, B) + B.cp(B.dual())).undual()\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "9a395761-71f5-4854-aaf0-b675d922f3d0",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cd4171369bfa4943be2358538a1971ad",
"version_major": 2,
"version_minor": 1
},
"text/plain": [
"GraphWidget(cayley=[['1', 'e0', 'e1', 'e2', 'e01', 'e02', 'e12', 'e012'], ['e0', '0', 'e01', 'e02', '0', '0', …"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def graph_func():\n",
" global state\n",
" \n",
" for _ in range(10):\n",
" state = euler(dState, state, 1/600)\n",
" # state = RK4(dState, state, 1/60)\n",
" new_edges = [[state[0] >> p for p in edge] for edge in edges]\n",
"\n",
" return [\n",
" *new_edges,\n",
" 0x007799,\n",
" attach, \n",
" [attach, state[0] >> points[2**d-1]],\n",
" ]\n",
"\n",
"alg.graph(\n",
" graph_func,\n",
" animate=True,\n",
" scale=0.5,\n",
" lineWidth=6,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bfac1ff2-0180-40b4-ac7e-2b63834811ca",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.10.14"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
3 changes: 3 additions & 0 deletions images/pga2d_hypercube_on_string.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions jp_app_launcher_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
type: notebook
catalog: 2DPGA

- title: Tesseract on a string
source: content/2DPGA/ex_2dpga_hypercube_on_string.ipynb
icon: images/pga2d_hypercube_on_string.svg
type: notebook
catalog: 2DPGA

- title: Pointcloud Fitting
source: content/ex_pointcloud.ipynb
type: notebook
Expand Down

0 comments on commit 4563639

Please sign in to comment.