Skip to content

Instantly share code, notes, and snippets.

@7shi
Last active June 25, 2024 14:33
Show Gist options
  • Save 7shi/912ad67f3edd07278b61ecb2fb0acf26 to your computer and use it in GitHub Desktop.
Save 7shi/912ad67f3edd07278b61ecb2fb0acf26 to your computer and use it in GitHub Desktop.
[py] calculate quaternions and octonions
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import importlib\n",
"importlib.reload(importlib.import_module('symmath'))\n",
"from symmath import *\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import re\n",
"from IPython.display import display, Math\n",
"\n",
"def to_tex(n):\n",
" if isinstance(n, str):\n",
" return n\n",
" s = repr(n)\n",
" s = re.sub(r\"\\b([a-z])(\\d)\", r\"\\1_\\2\", s)\n",
" s = re.sub(r\"\\bcos\", r\"\\\\cos\", s)\n",
" s = re.sub(r\"\\bsin\", r\"\\\\sin\", s)\n",
" return s.replace(\"*\", \"\")\n",
"\n",
"def tex(*args):\n",
" display(Math(\"\".join(to_tex(arg) for arg in args)))\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def f1(expr):\n",
" expr = arrange_o(flatten(expand(expr)))\n",
" expr = flatten(collect(expr, *xs))\n",
" expr = flatten(collect(expr, -1))\n",
" expr = forward(expr)\n",
" expr = replace_sc(expr)\n",
" expr = replace(expr, 0*x1 + 1*x1*e1, x1*e1)\n",
" expr = forward(forward(expr, *xs))\n",
" return expr\n",
"\n",
"def rm1(expr):\n",
" one = N(1)\n",
" def f(expr):\n",
" if isinstance(expr, Product):\n",
" while len(expr.values) and eq_expr(expr.values[0], one):\n",
" expr = Product(*expr.values[1:])\n",
" if hasattr(expr, \"values\"):\n",
" values = [f(x) for x in expr.values]\n",
" return type(expr)(*values) if len(values) != 1 else values[0]\n",
" return expr\n",
" return f(flatten(replace(forward(expr), N(-1) * -1, one)))\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle o=\\cosθ + \\sinθ e_1$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle o^*=\\cosθ - \\sinθ e_1$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle v=x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle ov=-x_1 \\sinθ + x_1 \\cosθ e_1 + (x_2 \\cosθ - x_3 \\sinθ) e_2 + (x_3 \\cosθ + x_2 \\sinθ) e_3 + (x_4 \\cosθ - x_5 \\sinθ) e_4 + (x_5 \\cosθ + x_4 \\sinθ) e_5 + (x_6 \\cosθ + x_7 \\sinθ) e_6 + (x_7 \\cosθ - x_6 \\sinθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle (ov)o^*=x_1 e_1 + (x_2 \\cos2θ - x_3 \\sin2θ) e_2 + (x_2 \\sin2θ + x_3 \\cos2θ) e_3 + (x_4 \\cos2θ - x_5 \\sin2θ) e_4 + (x_4 \\sin2θ + x_5 \\cos2θ) e_5 + (x_6 \\cos2θ + x_7 \\sin2θ) e_6 + (-x_6 \\sin2θ + x_7 \\cos2θ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle vo^*=x_1 \\sinθ + x_1 \\cosθ e_1 + (x_2 \\cosθ - x_3 \\sinθ) e_2 + (x_2 \\sinθ + x_3 \\cosθ) e_3 + (x_4 \\cosθ - x_5 \\sinθ) e_4 + (x_4 \\sinθ + x_5 \\cosθ) e_5 + (x_6 \\cosθ + x_7 \\sinθ) e_6 + (-x_6 \\sinθ + x_7 \\cosθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle o(vo^*)=x_1 e_1 + (x_2 \\cos2θ - x_3 \\sin2θ) e_2 + (x_2 \\sin2θ + x_3 \\cos2θ) e_3 + (x_4 \\cos2θ - x_5 \\sin2θ) e_4 + (x_4 \\sin2θ + x_5 \\cos2θ) e_5 + (x_6 \\cos2θ + x_7 \\sin2θ) e_6 + (-x_6 \\sin2θ + x_7 \\cos2θ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"tex(\"o=\", O := C + S*e1)\n",
"tex(\"o^*=\", O_ := forward(conj_o(O)))\n",
"tex(\"v=\", V := x1*e1 + x2*e2 + x3*e3 + x4*e4 + x5*e5 + x6*e6 + x7*e7)\n",
"\n",
"tex(\"ov=\", ov := flatten(arrange_o(ov_ := replace_o(expand(O * V)))))\n",
"tex(\"(ov)o^*=\", ov_o := f1(ov_ * O_))\n",
"\n",
"tex(\"vo^*=\", vo := flatten(rm1(arrange_o(vo_ := replace_o(expand(V * O_))))))\n",
"tex(\"o(vo^*)=\", o_vo := f1(O * vo_))\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle ov=(\\cosθ + \\sinθ e_1) (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7)\\\\=x_1 \\cosθ e_1 + x_2 \\cosθ e_2 + x_3 \\cosθ e_3 + x_4 \\cosθ e_4 + x_5 \\cosθ e_5 + x_6 \\cosθ e_6 + x_7 \\cosθ e_7 + x_1 \\sinθ e_1 e_1 + x_2 \\sinθ e_1 e_2 + x_3 \\sinθ e_1 e_3 + x_4 \\sinθ e_1 e_4 + x_5 \\sinθ e_1 e_5 + x_6 \\sinθ e_1 e_6 + x_7 \\sinθ e_1 e_7\\\\=x_1 \\cosθ e_1 + x_2 \\cosθ e_2 + x_3 \\cosθ e_3 + x_4 \\cosθ e_4 + x_5 \\cosθ e_5 + x_6 \\cosθ e_6 + x_7 \\cosθ e_7 - x_1 \\sinθ + x_2 \\sinθ e_3 - x_3 \\sinθ e_2 + x_4 \\sinθ e_5 - x_5 \\sinθ e_4 - x_6 \\sinθ e_7 + x_7 \\sinθ e_6\\\\=-x_1 \\sinθ + x_1 \\cosθ e_1 + (x_2 \\cosθ - x_3 \\sinθ) e_2 + (x_3 \\cosθ + x_2 \\sinθ) e_3 + (x_4 \\cosθ - x_5 \\sinθ) e_4 + (x_5 \\cosθ + x_4 \\sinθ) e_5 + (x_6 \\cosθ + x_7 \\sinθ) e_6 + (x_7 \\cosθ - x_6 \\sinθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle vo^*=(x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7) (\\cosθ - \\sinθ e_1)\\\\=x_1 \\cosθ e_1 - x_1 \\sinθ e_1 e_1 + x_2 \\cosθ e_2 - x_2 \\sinθ e_2 e_1 + x_3 \\cosθ e_3 - x_3 \\sinθ e_3 e_1 + x_4 \\cosθ e_4 - x_4 \\sinθ e_4 e_1 + x_5 \\cosθ e_5 - x_5 \\sinθ e_5 e_1 + x_6 \\cosθ e_6 - x_6 \\sinθ e_6 e_1 + x_7 \\cosθ e_7 - x_7 \\sinθ e_7 e_1\\\\=x_1 \\cosθ e_1 + x_1 \\sinθ + x_2 \\cosθ e_2 + x_2 \\sinθ e_3 + x_3 \\cosθ e_3 - x_3 \\sinθ e_2 + x_4 \\cosθ e_4 + x_4 \\sinθ e_5 + x_5 \\cosθ e_5 - x_5 \\sinθ e_4 + x_6 \\cosθ e_6 - x_6 \\sinθ e_7 + x_7 \\cosθ e_7 + x_7 \\sinθ e_6\\\\=x_1 \\sinθ + x_1 \\cosθ e_1 + (x_2 \\cosθ - x_3 \\sinθ) e_2 + (x_2 \\sinθ + x_3 \\cosθ) e_3 + (x_4 \\cosθ - x_5 \\sinθ) e_4 + (x_4 \\sinθ + x_5 \\cosθ) e_5 + (x_6 \\cosθ + x_7 \\sinθ) e_6 + (-x_6 \\sinθ + x_7 \\cosθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"tex(\"ov=\", x := O*V,\n",
" r\"\\\\=\", x := backward(forward(expand(x), *xs), *octonions),\n",
" r\"\\\\=\", x := replace_o(x),\n",
" r\"\\\\=\", x := flatten(arrange_o(x)))\n",
"tex(\"vo^*=\", x := V*O_,\n",
" r\"\\\\=\", x := backward(forward(forward(expand(x), *xs)), *octonions),\n",
" r\"\\\\=\", x := rm1(replace_o(x)),\n",
" r\"\\\\=\", x := flatten(arrange_o(x)))\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle ov=(\\cosθ + \\sinθ e_1) (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7)\\\\=\\cosθ (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7) + \\sinθ e_1 (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7)\\\\=-x_1 \\sinθ + x_1 \\cosθ e_1 + (x_2 \\cosθ - x_3 \\sinθ) e_2 + (x_2 \\sinθ + x_3 \\cosθ) e_3 + (x_4 \\cosθ - x_5 \\sinθ) e_4 + (x_4 \\sinθ + x_5 \\cosθ) e_5 + (x_6 \\cosθ + x_7 \\sinθ) e_6 + (-x_6 \\sinθ + x_7 \\cosθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle vo^*=(x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7) (\\cosθ - \\sinθ e_1)\\\\=\\cosθ (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7) + \\sinθ e_1 (-x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7)\\\\=x_1 \\sinθ + x_1 \\cosθ e_1 + (x_2 \\cosθ - x_3 \\sinθ) e_2 + (x_2 \\sinθ + x_3 \\cosθ) e_3 + (x_4 \\cosθ - x_5 \\sinθ) e_4 + (x_4 \\sinθ + x_5 \\cosθ) e_5 + (x_6 \\cosθ + x_7 \\sinθ) e_6 + (-x_6 \\sinθ + x_7 \\cosθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"def f2(expr):\n",
" expr = forward(flatten(expand(collect(flatten(expand(expr)), *xs))), *xs)\n",
" return rm1(flatten(arrange_o(forward(replace_o(expr)))))\n",
"\n",
"tex(\"ov=\", x := O*V,\n",
" r\"\\\\=\", x := C*V + S*e1*V,\n",
" r\"\\\\=\", x := f2(x))\n",
"tex(\"vo^*=\", x := V*O_,\n",
" r\"\\\\=\", x := C*V + S*e1*(-1*x1*e1 + x2*e2 + x3*e3 + x4*e4 + x5*e5 + x6*e6 + x7*e7),\n",
" r\"\\\\=\", x := f2(x))\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle n=n_1 e_1 + n_2 e_2 + n_3 e_3 + n_4 e_4 + n_5 e_5 + n_6 e_6 + n_7 e_7\\quad (n_1^2+n_2^2+n_3^2+n_4^2+n_5^2+n_6^2+n_7^2=1,\\ n^2=-1)$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle r=\\exp(θn)=\\cosθ + \\sinθ n\\quad (|r|=1)\\\\r^*=\\cosθ - \\sinθ n\\quad (rr^*=1)$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle rv=(\\cosθ + \\sinθ n) (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7)\\\\=x_1 \\sinθ (n e_1) + x_2 \\sinθ (n e_2) + x_3 \\sinθ (n e_3) + x_4 \\sinθ (n e_4) + x_5 \\sinθ (n e_5) + x_6 \\sinθ (n e_6) + x_7 \\sinθ (n e_7) + x_1 \\cosθ e_1 + x_2 \\cosθ e_2 + x_3 \\cosθ e_3 + x_4 \\cosθ e_4 + x_5 \\cosθ e_5 + x_6 \\cosθ e_6 + x_7 \\cosθ e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle vr^*=(x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7) (\\cosθ - \\sinθ n)\\\\=-x_1 \\sinθ (e_1 n) - x_2 \\sinθ (e_2 n) - x_3 \\sinθ (e_3 n) - x_4 \\sinθ (e_4 n) - x_5 \\sinθ (e_5 n) - x_6 \\sinθ (e_6 n) - x_7 \\sinθ (e_7 n) + x_1 \\cosθ e_1 + x_2 \\cosθ e_2 + x_3 \\cosθ e_3 + x_4 \\cosθ e_4 + x_5 \\cosθ e_5 + x_6 \\cosθ e_6 + x_7 \\cosθ e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n1, n2, n3, n4, n5, n6, n7 = syms(\"n1,n2,n3,n4,n5,n6,n7\")\n",
"ns = [n1, n2, n3, n4, n5, n6, n7]\n",
"ne1, ne2, ne3, ne4, ne5, ne6, ne7 = syms(\"(n e1),(n e2),(n e3),(n e4),(n e5),(n e6),(n e7)\")\n",
"ne = [ne1, ne2, ne3, ne4, ne5, ne6, ne7]\n",
"e1n, e2n, e3n, e4n, e5n, e6n, e7n = syms(\"(e1 n),(e2 n),(e3 n),(e4 n),(e5 n),(e6 n),(e7 n)\")\n",
"en = [e1n, e2n, e3n, e4n, e5n, e6n, e7n]\n",
"\n",
"def combine_n(expr):\n",
" expr = forward(backward(expr, *octonions, n))\n",
" for i in range(7):\n",
" expr = replace(expr, n*octonions[i], ne[i])\n",
" expr = replace(expr, octonions[i]*n, en[i])\n",
" return flatten(collect(expr, *octonions, *ne, *en))\n",
"\n",
"tex(\"n=\", N_ := n1*e1 + n2*e2 + n3*e3 + n4*e4 + n5*e5 + n6*e6 + n7*e7,\n",
" \"\\quad (n_1^2+n_2^2+n_3^2+n_4^2+n_5^2+n_6^2+n_7^2=1,\\ n^2=-1)\")\n",
"tex(\"r=\\exp(θn)=\", R1 := C + S*n, r\"\\quad (|r|=1)\\\\r^*=\", R1_ := C - S*n, \"\\quad (rr^*=1)\")\n",
"tex(\"rv=\", rv1 := R1*V,\n",
" r\"\\\\=\", rv1 := combine_n(forward(expand(rv1), *xs)))\n",
"tex(\"vr^*=\", vr1 := V*R1_,\n",
" r\"\\\\=\", vr1 := combine_n(forward(expand(vr1), *xs)))\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle (rv)r^*=x_1 \\cosθ \\sinθ (n e_1) - x_1 \\sin^2θ (n e_1) n + x_2 \\cosθ \\sinθ (n e_2) - x_2 \\sin^2θ (n e_2) n + x_3 \\cosθ \\sinθ (n e_3) - x_3 \\sin^2θ (n e_3) n + x_4 \\cosθ \\sinθ (n e_4) - x_4 \\sin^2θ (n e_4) n + x_5 \\cosθ \\sinθ (n e_5) - x_5 \\sin^2θ (n e_5) n + x_6 \\cosθ \\sinθ (n e_6) - x_6 \\sin^2θ (n e_6) n + x_7 \\cosθ \\sinθ (n e_7) - x_7 \\sin^2θ (n e_7) n + x_1 \\cos^2θ e_1 - x_1 \\cosθ \\sinθ e_1 n + x_2 \\cos^2θ e_2 - x_2 \\cosθ \\sinθ e_2 n + x_3 \\cos^2θ e_3 - x_3 \\cosθ \\sinθ e_3 n + x_4 \\cos^2θ e_4 - x_4 \\cosθ \\sinθ e_4 n + x_5 \\cos^2θ e_5 - x_5 \\cosθ \\sinθ e_5 n + x_6 \\cos^2θ e_6 - x_6 \\cosθ \\sinθ e_6 n + x_7 \\cos^2θ e_7 - x_7 \\cosθ \\sinθ e_7 n$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle r(vr^*)=-x_1 \\cosθ \\sinθ (e_1 n) - x_2 \\cosθ \\sinθ (e_2 n) - x_3 \\cosθ \\sinθ (e_3 n) - x_4 \\cosθ \\sinθ (e_4 n) - x_5 \\cosθ \\sinθ (e_5 n) - x_6 \\cosθ \\sinθ (e_6 n) - x_7 \\cosθ \\sinθ (e_7 n) + x_1 \\cos^2θ e_1 + x_2 \\cos^2θ e_2 + x_3 \\cos^2θ e_3 + x_4 \\cos^2θ e_4 + x_5 \\cos^2θ e_5 + x_6 \\cos^2θ e_6 + x_7 \\cos^2θ e_7 - x_1 \\sin^2θ n (e_1 n) - x_2 \\sin^2θ n (e_2 n) - x_3 \\sin^2θ n (e_3 n) - x_4 \\sin^2θ n (e_4 n) - x_5 \\sin^2θ n (e_5 n) - x_6 \\sin^2θ n (e_6 n) - x_7 \\sin^2θ n (e_7 n) + x_1 \\cosθ \\sinθ n e_1 + x_2 \\cosθ \\sinθ n e_2 + x_3 \\cosθ \\sinθ n e_3 + x_4 \\cosθ \\sinθ n e_4 + x_5 \\cosθ \\sinθ n e_5 + x_6 \\cosθ \\sinθ n e_6 + x_7 \\cosθ \\sinθ n e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"C_2 = N(\"cos^2θ\")\n",
"S_2 = N(\"sin^2θ\")\n",
"\n",
"def replace_sc2(expr):\n",
" expr = replace(expr, S*C, C*S)\n",
" expr = replace(expr, S*S, S_2)\n",
" expr = replace(expr, C*C, C_2)\n",
" return expr\n",
"\n",
"def f3(expr):\n",
" expr = flatten(collect(forward(forward(expand(expr), *xs)), *octonions, n, *ne, *en))\n",
" return replace_sc2(expr)\n",
"\n",
"tex(\"(rv)r^*=\", x := f3(rv1*R1_))\n",
"tex(\"r(vr^*)=\", x := f3(R1*vr1))\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle r=\\cosθ + \\sinθ (n_1 e_1 + n_2 e_2 + n_3 e_3 + n_4 e_4 + n_5 e_5 + n_6 e_6 + n_7 e_7)$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle r^*=\\cosθ - \\sinθ (n_1 e_1 + n_2 e_2 + n_3 e_3 + n_4 e_4 + n_5 e_5 + n_6 e_6 + n_7 e_7)$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle rv=-x_1 n_1 \\sinθ - x_2 n_2 \\sinθ - x_3 n_3 \\sinθ - x_4 n_4 \\sinθ - x_5 n_5 \\sinθ - x_6 n_6 \\sinθ - x_7 n_7 \\sinθ + (x_1 \\cosθ - x_2 n_3 \\sinθ + x_3 n_2 \\sinθ - x_4 n_5 \\sinθ + x_5 n_4 \\sinθ + x_6 n_7 \\sinθ - x_7 n_6 \\sinθ) e_1 + (x_1 n_3 \\sinθ + x_2 \\cosθ - x_3 n_1 \\sinθ - x_4 n_6 \\sinθ - x_5 n_7 \\sinθ + x_6 n_4 \\sinθ + x_7 n_5 \\sinθ) e_2 + (-x_1 n_2 \\sinθ + x_2 n_1 \\sinθ + x_3 \\cosθ - x_4 n_7 \\sinθ + x_5 n_6 \\sinθ - x_6 n_5 \\sinθ + x_7 n_4 \\sinθ) e_3 + (x_1 n_5 \\sinθ + x_2 n_6 \\sinθ + x_3 n_7 \\sinθ + x_4 \\cosθ - x_5 n_1 \\sinθ - x_6 n_2 \\sinθ - x_7 n_3 \\sinθ) e_4 + (-x_1 n_4 \\sinθ + x_2 n_7 \\sinθ - x_3 n_6 \\sinθ + x_4 n_1 \\sinθ + x_5 \\cosθ + x_6 n_3 \\sinθ - x_7 n_2 \\sinθ) e_5 + (-x_1 n_7 \\sinθ - x_2 n_4 \\sinθ + x_3 n_5 \\sinθ + x_4 n_2 \\sinθ - x_5 n_3 \\sinθ + x_6 \\cosθ + x_7 n_1 \\sinθ) e_6 + (x_1 n_6 \\sinθ - x_2 n_5 \\sinθ - x_3 n_4 \\sinθ + x_4 n_3 \\sinθ + x_5 n_2 \\sinθ - x_6 n_1 \\sinθ + x_7 \\cosθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle vr^*=x_1 n_1 \\sinθ + x_2 n_2 \\sinθ + x_3 n_3 \\sinθ + x_4 n_4 \\sinθ + x_5 n_5 \\sinθ + x_6 n_6 \\sinθ + x_7 n_7 \\sinθ + (x_1 \\cosθ - x_2 n_3 \\sinθ + x_3 n_2 \\sinθ - x_4 n_5 \\sinθ + x_5 n_4 \\sinθ + x_6 n_7 \\sinθ - x_7 n_6 \\sinθ) e_1 + (x_1 n_3 \\sinθ + x_2 \\cosθ - x_3 n_1 \\sinθ - x_4 n_6 \\sinθ - x_5 n_7 \\sinθ + x_6 n_4 \\sinθ + x_7 n_5 \\sinθ) e_2 + (-x_1 n_2 \\sinθ + x_2 n_1 \\sinθ + x_3 \\cosθ - x_4 n_7 \\sinθ + x_5 n_6 \\sinθ - x_6 n_5 \\sinθ + x_7 n_4 \\sinθ) e_3 + (x_1 n_5 \\sinθ + x_2 n_6 \\sinθ + x_3 n_7 \\sinθ + x_4 \\cosθ - x_5 n_1 \\sinθ - x_6 n_2 \\sinθ - x_7 n_3 \\sinθ) e_4 + (-x_1 n_4 \\sinθ + x_2 n_7 \\sinθ - x_3 n_6 \\sinθ + x_4 n_1 \\sinθ + x_5 \\cosθ + x_6 n_3 \\sinθ - x_7 n_2 \\sinθ) e_5 + (-x_1 n_7 \\sinθ - x_2 n_4 \\sinθ + x_3 n_5 \\sinθ + x_4 n_2 \\sinθ - x_5 n_3 \\sinθ + x_6 \\cosθ + x_7 n_1 \\sinθ) e_6 + (x_1 n_6 \\sinθ - x_2 n_5 \\sinθ - x_3 n_4 \\sinθ + x_4 n_3 \\sinθ + x_5 n_2 \\sinθ - x_6 n_1 \\sinθ + x_7 \\cosθ) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle rv-vr^*=-2 \\sinθ (x_1 n_1 + x_2 n_2 + x_3 n_3 + x_4 n_4 + x_5 n_5 + x_6 n_6 + x_7 n_7)$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"def f4(expr):\n",
" expr = replace_o(flatten(expand(flatten(expand(expr)))))\n",
" expr = forward(forward(flatten(expand(expr)), *ns), *xs)\n",
" expr = flatten(collect(expr, *xs, *ns, forward=True))\n",
" return rm1(collect(expr, *octonions, forward_other=True))\n",
"\n",
"tex(\"r=\", R := C + S*N_)\n",
"tex(\"r^*=\", R_ := C - S*N_)\n",
"tex(\"rv=\" , rv := f4(R*V))\n",
"tex(\"vr^*=\", vr := f4(V*R_))\n",
"tex(\"rv-vr^*=\", collect(simplify(rv - vr), -2, S, forward=True))\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle (rv)r^*=((\\cosθ + \\sinθ n) (x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7)) (\\cosθ - \\sinθ n)\\\\=(\\cos^2θ x_1 + \\sin2θ (-x_2 n_3 + x_3 n_2 - x_4 n_5 + x_5 n_4 + x_6 n_7 - x_7 n_6) + \\sin^2θ (x_1 n_1 n_1 - x_1 n_2 n_2 - x_1 n_3 n_3 - x_1 n_4 n_4 - x_1 n_5 n_5 - x_1 n_6 n_6 - x_1 n_7 n_7 + 2 x_2 n_1 n_2 + 2 x_3 n_1 n_3 + 2 x_4 n_1 n_4 + 2 x_5 n_1 n_5 + 2 x_6 n_1 n_6 + 2 x_7 n_1 n_7)) e_1 + (\\cos^2θ x_2 + \\sin2θ (x_1 n_3 - x_3 n_1 - x_4 n_6 - x_5 n_7 + x_6 n_4 + x_7 n_5) + \\sin^2θ (2 x_1 n_1 n_2 - x_2 n_1 n_1 + x_2 n_2 n_2 - x_2 n_3 n_3 - x_2 n_4 n_4 - x_2 n_5 n_5 - x_2 n_6 n_6 - x_2 n_7 n_7 + 2 x_3 n_2 n_3 + 2 x_4 n_2 n_4 + 2 x_5 n_2 n_5 + 2 x_6 n_2 n_6 + 2 x_7 n_2 n_7)) e_2 + (\\cos^2θ x_3 + \\sin2θ (-x_1 n_2 + x_2 n_1 - x_4 n_7 + x_5 n_6 - x_6 n_5 + x_7 n_4) + \\sin^2θ (2 x_1 n_1 n_3 + 2 x_2 n_2 n_3 - x_3 n_1 n_1 - x_3 n_2 n_2 + x_3 n_3 n_3 - x_3 n_4 n_4 - x_3 n_5 n_5 - x_3 n_6 n_6 - x_3 n_7 n_7 + 2 x_4 n_3 n_4 + 2 x_5 n_3 n_5 + 2 x_6 n_3 n_6 + 2 x_7 n_3 n_7)) e_3 + (\\cos^2θ x_4 + \\sin2θ (x_1 n_5 + x_2 n_6 + x_3 n_7 - x_5 n_1 - x_6 n_2 - x_7 n_3) + \\sin^2θ (2 x_1 n_1 n_4 + 2 x_2 n_2 n_4 + 2 x_3 n_3 n_4 - x_4 n_1 n_1 - x_4 n_2 n_2 - x_4 n_3 n_3 + x_4 n_4 n_4 - x_4 n_5 n_5 - x_4 n_6 n_6 - x_4 n_7 n_7 + 2 x_5 n_4 n_5 + 2 x_6 n_4 n_6 + 2 x_7 n_4 n_7)) e_4 + (\\cos^2θ x_5 + \\sin2θ (-x_1 n_4 + x_2 n_7 - x_3 n_6 + x_4 n_1 + x_6 n_3 - x_7 n_2) + \\sin^2θ (2 x_1 n_1 n_5 + 2 x_2 n_2 n_5 + 2 x_3 n_3 n_5 + 2 x_4 n_4 n_5 - x_5 n_1 n_1 - x_5 n_2 n_2 - x_5 n_3 n_3 - x_5 n_4 n_4 + x_5 n_5 n_5 - x_5 n_6 n_6 - x_5 n_7 n_7 + 2 x_6 n_5 n_6 + 2 x_7 n_5 n_7)) e_5 + (\\cos^2θ x_6 + \\sin2θ (-x_1 n_7 - x_2 n_4 + x_3 n_5 + x_4 n_2 - x_5 n_3 + x_7 n_1) + \\sin^2θ (2 x_1 n_1 n_6 + 2 x_2 n_2 n_6 + 2 x_3 n_3 n_6 + 2 x_4 n_4 n_6 + 2 x_5 n_5 n_6 - x_6 n_1 n_1 - x_6 n_2 n_2 - x_6 n_3 n_3 - x_6 n_4 n_4 - x_6 n_5 n_5 + x_6 n_6 n_6 - x_6 n_7 n_7 + 2 x_7 n_6 n_7)) e_6 + (\\cos^2θ x_7 + \\sin2θ (x_1 n_6 - x_2 n_5 - x_3 n_4 + x_4 n_3 + x_5 n_2 - x_6 n_1) + \\sin^2θ (2 x_1 n_1 n_7 + 2 x_2 n_2 n_7 + 2 x_3 n_3 n_7 + 2 x_4 n_4 n_7 + 2 x_5 n_5 n_7 + 2 x_6 n_6 n_7 - x_7 n_1 n_1 - x_7 n_2 n_2 - x_7 n_3 n_3 - x_7 n_4 n_4 - x_7 n_5 n_5 - x_7 n_6 n_6 + x_7 n_7 n_7)) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle r(vr^*)=(\\cosθ + \\sinθ n) ((x_1 e_1 + x_2 e_2 + x_3 e_3 + x_4 e_4 + x_5 e_5 + x_6 e_6 + x_7 e_7) (\\cosθ - \\sinθ n))\\\\=(\\cos^2θ x_1 + \\sin2θ (-x_2 n_3 + x_3 n_2 - x_4 n_5 + x_5 n_4 + x_6 n_7 - x_7 n_6) + \\sin^2θ (x_1 n_1 n_1 - x_1 n_2 n_2 - x_1 n_3 n_3 - x_1 n_4 n_4 - x_1 n_5 n_5 - x_1 n_6 n_6 - x_1 n_7 n_7 + 2 x_2 n_1 n_2 + 2 x_3 n_1 n_3 + 2 x_4 n_1 n_4 + 2 x_5 n_1 n_5 + 2 x_6 n_1 n_6 + 2 x_7 n_1 n_7)) e_1 + (\\cos^2θ x_2 + \\sin2θ (x_1 n_3 - x_3 n_1 - x_4 n_6 - x_5 n_7 + x_6 n_4 + x_7 n_5) + \\sin^2θ (2 x_1 n_1 n_2 - x_2 n_1 n_1 + x_2 n_2 n_2 - x_2 n_3 n_3 - x_2 n_4 n_4 - x_2 n_5 n_5 - x_2 n_6 n_6 - x_2 n_7 n_7 + 2 x_3 n_2 n_3 + 2 x_4 n_2 n_4 + 2 x_5 n_2 n_5 + 2 x_6 n_2 n_6 + 2 x_7 n_2 n_7)) e_2 + (\\cos^2θ x_3 + \\sin2θ (-x_1 n_2 + x_2 n_1 - x_4 n_7 + x_5 n_6 - x_6 n_5 + x_7 n_4) + \\sin^2θ (2 x_1 n_1 n_3 + 2 x_2 n_2 n_3 - x_3 n_1 n_1 - x_3 n_2 n_2 + x_3 n_3 n_3 - x_3 n_4 n_4 - x_3 n_5 n_5 - x_3 n_6 n_6 - x_3 n_7 n_7 + 2 x_4 n_3 n_4 + 2 x_5 n_3 n_5 + 2 x_6 n_3 n_6 + 2 x_7 n_3 n_7)) e_3 + (\\cos^2θ x_4 + \\sin2θ (x_1 n_5 + x_2 n_6 + x_3 n_7 - x_5 n_1 - x_6 n_2 - x_7 n_3) + \\sin^2θ (2 x_1 n_1 n_4 + 2 x_2 n_2 n_4 + 2 x_3 n_3 n_4 - x_4 n_1 n_1 - x_4 n_2 n_2 - x_4 n_3 n_3 + x_4 n_4 n_4 - x_4 n_5 n_5 - x_4 n_6 n_6 - x_4 n_7 n_7 + 2 x_5 n_4 n_5 + 2 x_6 n_4 n_6 + 2 x_7 n_4 n_7)) e_4 + (\\cos^2θ x_5 + \\sin2θ (-x_1 n_4 + x_2 n_7 - x_3 n_6 + x_4 n_1 + x_6 n_3 - x_7 n_2) + \\sin^2θ (2 x_1 n_1 n_5 + 2 x_2 n_2 n_5 + 2 x_3 n_3 n_5 + 2 x_4 n_4 n_5 - x_5 n_1 n_1 - x_5 n_2 n_2 - x_5 n_3 n_3 - x_5 n_4 n_4 + x_5 n_5 n_5 - x_5 n_6 n_6 - x_5 n_7 n_7 + 2 x_6 n_5 n_6 + 2 x_7 n_5 n_7)) e_5 + (\\cos^2θ x_6 + \\sin2θ (-x_1 n_7 - x_2 n_4 + x_3 n_5 + x_4 n_2 - x_5 n_3 + x_7 n_1) + \\sin^2θ (2 x_1 n_1 n_6 + 2 x_2 n_2 n_6 + 2 x_3 n_3 n_6 + 2 x_4 n_4 n_6 + 2 x_5 n_5 n_6 - x_6 n_1 n_1 - x_6 n_2 n_2 - x_6 n_3 n_3 - x_6 n_4 n_4 - x_6 n_5 n_5 + x_6 n_6 n_6 - x_6 n_7 n_7 + 2 x_7 n_6 n_7)) e_6 + (\\cos^2θ x_7 + \\sin2θ (x_1 n_6 - x_2 n_5 - x_3 n_4 + x_4 n_3 + x_5 n_2 - x_6 n_1) + \\sin^2θ (2 x_1 n_1 n_7 + 2 x_2 n_2 n_7 + 2 x_3 n_3 n_7 + 2 x_4 n_4 n_7 + 2 x_5 n_5 n_7 + 2 x_6 n_6 n_7 - x_7 n_1 n_1 - x_7 n_2 n_2 - x_7 n_3 n_3 - x_7 n_4 n_4 - x_7 n_5 n_5 - x_7 n_6 n_6 + x_7 n_7 n_7)) e_7$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/latex": [
"$\\displaystyle (rv)r^*-r(vr^*)=0$"
],
"text/plain": [
"<IPython.core.display.Math object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"R2 = flatten(expand(R))\n",
"R2_ = flatten(expand(R_))\n",
"\n",
"def f5(expr):\n",
" expr = replace_o(flatten(expand(flatten(expand(expr)))))\n",
" expr = rm1(flatten(expand(expr)))\n",
" for n in reversed(ns):\n",
" expr = forward(expr, n)\n",
" expr = forward(forward(expr, *xs))\n",
" expr = replace_sc2(expr)\n",
" expr = simplify(expr)\n",
" expr = forward(flatten(expand(collect(expr, *xs, *ns))))\n",
" expr = collect(expr, *octonions)\n",
" expr = replace(expr, 2 * C * S, S2)\n",
" expr = replace(expr, -2 * C * S, -S2)\n",
" return expr\n",
"\n",
"def f6(expr):\n",
" expr = collect(expr, C2, S2, C_2, S_2, forward=True)\n",
" return expr\n",
"\n",
"tex(\"(rv)r^*=\", Product(R1*V, R1_),\n",
" r\"\\\\=\", f6(rv_r := f5(f4(R2*V)*R2_)))\n",
"tex(\"r(vr^*)=\", Product(R1, V*R1_),\n",
" r\"\\\\=\", f6(r_vr := f5(R2*f4(V*R2_))))\n",
"tex(\"(rv)r^*-r(vr^*)=\", simplify(rv_r - r_vr))\n"
]
}
],
"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.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
import sys
def is_number(n):
return isinstance(n, (int, float))
def conv_n(n):
return N(n) if is_number(n) else n
def conv_ns(ns):
return [conv_n(n) for n in ns]
class N:
def __init__(self, value):
self.value = value
def __str__(self):
return f"N({repr(self.value)})"
def __repr__(self):
return to_string(self)
def __add__(self, other):
return Sum(self, conv_n(other))
def __radd__(self, other):
return Sum(conv_n(other), self)
def __neg__(self):
return -1 * self
def __sub__(self, other):
return self + (-conv_n(other))
def __rsub__(self, other):
return conv_n(other) + (-self)
def __mul__(self, other):
return Product(self, conv_n(other))
def __rmul__(self, other):
return Product(conv_n(other), self)
class Sum:
def __init__(self, *values):
if len(values) == 1 and hasattr(values[0], '__iter__'):
self.values = list(values[0])
else:
self.values = list(values)
def __str__(self):
return f"Sum({', '.join(map(str, self.values))})"
def __repr__(self):
return to_string(self)
def __add__(self, other):
if isinstance(other, Sum):
return Sum(*self.values, *other.values)
return Sum(*self.values, conv_n(other))
def __radd__(self, other):
if isinstance(other, Sum):
return Sum(*other.values, *self.values)
return Sum(conv_n(other), *self.values)
def __neg__(self):
return -1 * self
def __sub__(self, other):
return self + (-conv_n(other))
def __rsub__(self, other):
return conv_n(other) + (-self)
def __mul__(self, other):
return Product(self, conv_n(other))
def __rmul__(self, other):
return Product(conv_n(other), self)
class Product:
def __init__(self, *values):
if len(values) == 1 and hasattr(values[0], '__iter__'):
self.values = list(values[0])
else:
self.values = list(values)
def __str__(self):
return f"Product({', '.join(map(str, self.values))})"
def __repr__(self):
return to_string(self)
def __add__(self, other):
return Sum(self, conv_n(other))
def __radd__(self, other):
return Sum(conv_n(other), self)
def __neg__(self):
if len(self.values) and eq_expr(self.values[0], N(-1)):
return Product(*self.values[1:])
return -1 * self
def __sub__(self, other):
return self + (-conv_n(other))
def __rsub__(self, other):
return conv_n(other) + (-self)
def __mul__(self, other):
if isinstance(other, Product):
return Product(*self.values, *other.values)
return Product(*self.values, conv_n(other))
def __rmul__(self, other):
if isinstance(other, Product):
return Product(*other.values, *self.values)
return Product(conv_n(other), *self.values)
def syms(symbols_str):
symbols = symbols_str.split(',')
return tuple(N(sym) for sym in symbols)
# a~zをN("a"),...N("z")として定義
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z = syms("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z")
def to_string(expr):
if isinstance(expr, N):
return str(expr.value)
elif isinstance(expr, Sum):
ret = ""
for term in expr.values:
s = to_string(term)
if isinstance(term, Sum):
if ret:
ret += " + "
ret += f"({s})"
elif ret and s.startswith("-"):
ret += f" - {s[1:]}"
else:
if ret:
ret += " + "
ret += s
return ret
elif isinstance(expr, Product):
factors = expr.values
ret = ""
if len(factors) > 1 and eq_expr(factors[0], N(-1)):
ret += "-"
factors = factors[1:]
for i, factor in enumerate(factors):
if i:
ret += " * "
f = to_string(factor)
if isinstance(factor, (Sum, Product)) or (ret and f.startswith("-")):
ret += f"({f})"
else:
ret += f
return ret
return str(expr)
# テスト関数
def test_to_string():
print("Testing improved to_string function:")
# 基本的な数値
n = N(5)
assert to_string(n) == "5", "Basic number test failed"
# 単純な積
p = Product(N(2), N('x'))
assert to_string(p) == "2 * x", "Simple product test failed"
# ネストされた積
np = Product(N(2), Product(N('x'), N('y')))
assert to_string(np) == "2 * (x * y)", "Nested product test failed"
# 複数のネストされた積
nnp = Product(N(2), Product(N('x'), N('y')), Product(N('a'), N('b')))
assert to_string(nnp) == "2 * (x * y) * (a * b)", "Multiple nested products test failed"
# 和
s = Sum(N(1), N(2))
assert to_string(s) == "1 + 2", "Simple sum test failed"
# 積を含む和
sp = Sum(N(1), Product(N(2), N('x')))
assert to_string(sp) == "1 + 2 * x", "Sum with product test failed"
# 和を含む積
ps = Product(N(2), Sum(N('x'), N('y')))
assert to_string(ps) == "2 * (x + y)", "Product with sum test failed"
print("All to_string tests passed!")
def product_to_sum(xs, ys):
from itertools import product
result = []
for x, y in product(xs, ys):
fs = []
if isinstance(x, Product):
fs += x.values
else:
fs.append(x)
if isinstance(y, Product):
fs += y.values
else:
fs.append(y)
result.append(Product(*fs))
return result
def expand(expr):
if isinstance(expr, Sum):
return Sum(expand(term) for term in expr.values)
elif isinstance(expr, Product):
sums = []
for factor in expr.values:
factor = expand(factor)
if isinstance(factor, Sum):
if not sums:
sums = factor.values
else:
sums = product_to_sum(sums, factor.values)
elif not sums:
sums.append(factor)
else:
sums = product_to_sum(sums, [factor])
return Sum(*sums) if len(sums) != 1 else sums[0]
return expr
def run_tests1():
test_cases = [
('N(2) * (N(3) + N(4))', '2 * 3 + 2 * 4'),
('(N(1) + N(2)) * (N(3) + N(4))', '1 * 3 + 1 * 4 + 2 * 3 + 2 * 4'),
('N(2) * N(3) * (N(4) + N(5))', '2 * 3 * 4 + 2 * 3 * 5'),
('N(1) + N(2) * (N(3) + N(4))', '1 + 2 * 3 + 2 * 4'),
('(a + b) * (c + d)', 'a * c + a * d + b * c + b * d'),
('x * (N(1) + N(2))', 'x * 1 + x * 2'),
('a + b * (c + d)', 'a + b * c + b * d'),
('f * (g + h)', 'f * g + f * h'),
('N(1) * 2 + 3', '1 * 2 + 3'),
('2 * N(3) + 4', '2 * 3 + 4'),
('(N(1) + 2) * (3 + N(4))', '1 * 3 + 1 * 4 + 2 * 3 + 2 * 4'),
]
for input_expr, expected in test_cases:
expr = eval(input_expr)
expanded = flatten(expand(expr))
result = to_string(expanded)
passed = result == expected
print(f"{'✅' if passed else '❌'} {input_expr} => {result}")
def flatten(expr):
if isinstance(expr, (Sum, Product)):
result = []
for x in expr.values:
x = flatten(x)
if isinstance(x, type(expr)):
result += x.values
else:
result.append(x)
return type(expr)(*result) if len(result) != 1 else result[0]
return expr
def eq_expr(expr1, expr2):
if type(expr1) != type(expr2):
return False
if isinstance(expr1, N):
return expr1.value == expr2.value
elif isinstance(expr1, Sum):
if len(expr1.values) != len(expr2.values):
return False
return all(eq_expr(t1, t2) for t1, t2 in zip(sorted(expr1.values, key=lambda x: str(x)), sorted(expr2.values, key=lambda x: str(x))))
elif isinstance(expr1, Product):
if len(expr1.values) != len(expr2.values):
return False
return all(eq_expr(f1, f2) for f1, f2 in zip(expr1.values, expr2.values))
else:
return expr1 == expr2
def forward(expr, *values):
values = conv_ns(values)
def rec(expr):
if isinstance(expr, Sum):
return Sum(rec(term) for term in expr.values)
if isinstance(expr, Product):
nums = []
others = []
for factor in expr.values:
if values and any(eq_expr(factor, value) for value in values):
nums.append(factor)
elif not values and isinstance(factor, N) and is_number(factor.value):
nums.append(factor)
else:
others.append(rec(factor))
return Product(*nums, *others)
return expr
return rec(expr)
def backward(expr, *values):
values = conv_ns(values)
def rec(expr):
if isinstance(expr, Sum):
return Sum(rec(term) for term in expr.values)
if isinstance(expr, Product):
others = []
backs = []
for factor in expr.values:
if any(eq_expr(factor, value) for value in values):
backs.append(factor)
else:
others.append(rec(factor))
return Product(*others, *backs)
return expr
return rec(expr)
def find(nodes1, nodes2):
for i in range(len(nodes1) - len(nodes2) + 1):
if all(eq_expr(nodes1[i + j], nodes2[j]) for j in range(len(nodes2))):
return i
return -1
def replace(expr, pattern, replacement):
replacement = conv_n(replacement)
def rec(expr):
if eq_expr(expr, pattern):
return replacement
if isinstance(expr, (Sum, Product)):
vs1 = expr.values
if isinstance(expr, type(pattern)):
same = isinstance(pattern, type(replacement))
vs2 = pattern.values
result = []
i = 0
last = len(vs1) - len(vs2)
while i < len(vs1):
if i <= last and all(eq_expr(vs1[i + j], v) for j, v in enumerate(vs2)):
if same:
result += replacement.values
else:
result.append(replacement)
i += len(vs2)
else:
result.append(rec(vs1[i]))
i += 1
else:
result = [rec(e) for e in vs1]
return type(expr)(*result) if len(result) != 1 else result[0]
return expr
return rec(expr)
# テスト関数
def test_replace():
I, J, K = syms("I,J,K")
# テストケース1: 単純な置換
expr1 = Product(I, J)
result1 = replace(expr1, Product(I, J), K)
print(f"IJ replaced: {to_string(result1)}")
assert to_string(result1) == "K", "Simple replacement failed"
# テストケース2: ネストされたProductのフラット化1
expr2 = Product(I, Product(J, K), I)
result2 = replace(expr2, Product(J, K), I)
print(f"I(JK)I replaced: {to_string(result2)}")
assert to_string(result2) == "I * I * I", "Nested Product flattening failed"
# テストケース3: ネストされたProductのフラット化2
expr3 = Product(K, J, I)
result3 = replace(expr3, Product(J, I), Product(N(-1), K))
print(f"KJI double replaced: {to_string(result3)}")
assert to_string(result3) == "K * (-1) * K", "Nested Product flattening failed"
print("All replace tests passed!")
def run_tests2():
print("Running tests...")
# flatten のテスト
print("\nTesting flatten:")
a, b, c = syms("a,b,c")
expr1 = Product(a, Product(b, c))
flattened1 = flatten(expr1)
print(f"Original: {to_string(expr1)}")
print(f"Flattened: {to_string(flattened1)}")
assert to_string(flattened1) == "a * b * c", "flatten test 1 failed"
expr2 = Sum(Product(a, Product(b, c)), Product(Product(a, b), c))
flattened2 = flatten(expr2)
print(f"Original: {to_string(expr2)}")
print(f"Flattened: {to_string(flattened2)}")
assert to_string(flattened2) == "a * b * c + a * b * c", "flatten test 2 failed"
# back のテスト
print("\nTesting back:")
x, y, z = syms("x,y,z")
expr3 = Sum(Product(x, y, z), Product(y, x, z))
backed3 = backward(expr3, x)
print(f"Original: {to_string(expr3)}")
print(f"Backed: {to_string(backed3)}")
assert to_string(backed3) == "y * z * x + y * z * x", "back test failed"
# replace のテスト
print("\nTesting replace:")
i, x1, x2, y1, y2 = syms("i,x1,x2,y1,y2")
expr4 = (x1 + y1 * i) * (x2 + y2 * i)
expr4 = expand(expr4)
expr4 = backward(expr4, i)
replaced4 = replace(expr4, Product(i, i), N(-1))
print(f"Original: {to_string(expr4)}")
print(f"Replaced: {to_string(replaced4)}")
assert to_string(replaced4) == "x1 * x2 + x1 * y2 * i + y1 * x2 * i + y1 * y2 * (-1)", "replace test failed"
print("\nAll tests passed!")
def collect(expr, *symbols, forward=False, forward_other=False):
symbols = conv_ns(symbols)
def rec(expr):
if isinstance(expr, Product):
return Product(rec(factor) for factor in expr.values)
if isinstance(expr, Sum):
collected = {}
collected_syms = {}
other_terms = []
for term in expr.values:
term = rec(term)
if isinstance(term, Product):
others = []
syms = []
for factor in term.values:
if any(eq_expr(factor, sym) for sym in symbols):
syms.append(factor)
else:
others.append(factor)
if syms:
s = to_string(Product(*syms))
if s not in collected:
collected[s] = []
collected_syms[s] = syms
collected[s].append(Product(*others) if len(others) != 1 else others[0])
else:
other_terms.append(term)
else:
other_terms.append(term)
result = []
if forward_other:
result += other_terms
for s in sorted(collected):
vs = collected[s]
ks = Sum(*vs) if len(vs) != 1 else vs[0]
if forward:
result.append(Product(*collected_syms[s], ks))
else:
result.append(Product(ks, *collected_syms[s]))
if not forward_other:
result += other_terms
return Sum(*result) if len(result) != 1 else result[0]
return expr
return rec(expr)
def test_collect():
x1, x2, y1, y2, i = syms("x1,x2,y1,y2,i")
# テストケース1
expr = Sum(
Product(x1, x2),
Product(x1, y2, i),
Product(y1, x2, i),
Product(y1, y2, N(-1))
)
print("Test case 1:")
print("Original expression:")
print(to_string(expr))
collected = collect(expr, i)
print("\nAfter collecting terms with respect to i:")
print(to_string(collected))
expected = Sum(
Product(Sum(Product(x1, y2), Product(y1, x2)), i),
Product(x1, x2),
Product(y1, y2, N(-1))
)
assert to_string(collected) == to_string(expected), f"Test case 1 failed. Expected {to_string(expected)}, but got {to_string(collected)}"
print("Test case 1 passed.")
# テストケース2
expr2 = Sum(
Product(N(2), x1, i),
Product(N(3), x2, i),
Product(N(4), x1),
Product(N(5), x2)
)
print("\nTest case 2:")
print("Original expression:")
print(to_string(expr2))
collected2 = collect(expr2, i)
print("\nAfter collecting terms with respect to i:")
print(to_string(collected2))
expected2 = Sum(
Product(Sum(Product(N(2), x1), Product(N(3), x2)), i),
Product(N(4), x1),
Product(N(5), x2)
)
assert to_string(collected2) == to_string(expected2), f"Test case 2 failed. Expected {to_string(expected2)}, but got {to_string(collected2)}"
print("Test case 2 passed.")
print("\nAll test cases passed successfully!")
def simplify(expr):
expr = forward(flatten(expand(flatten(expand(expr)))))
terms = None
if isinstance(expr, Sum):
nterms = []
for term in expr.values:
n = 1
if isinstance(term, Product):
while len(term.values) and isinstance(n0 := term.values[0], N) and is_number(n0.value):
n *= n0.value
term = Product(*term.values[1:])
found = False
for t in nterms:
if eq_expr(t[1], term):
t[0] += n
found = True
break
if not found:
nterms.append([n, term])
terms = [t if n == 1 else n * t for n, t in nterms if n]
elif hasattr(expr, "values"):
terms = [simplify(x) for x in expr.values]
if terms is not None:
l = len(terms)
return N(0) if l == 0 else terms[0] if l == 1 else type(expr)(*terms)
return expr
commons = [
(N(1) * 1, N(1)),
(N(1) * -1, N(-1)),
(N(-1) * -1, N(1)),
]
# 四元数の基本単位を定義
I, J, K = syms("I,J,K")
quaternions = [I, J, K]
qreps = [*commons]
def init_q():
for q in quaternions:
qreps.append((N(1) * q, q))
qreps.append((q * q, N(-1)))
qreps.extend([
(I * J, K),
(J * I, N(-1) * K),
(J * K, I),
(K * J, N(-1) * I),
(K * I, J),
(I * K, N(-1) * J),
])
init_q()
def replace_q(expr):
while True:
new_expr = backward(forward(expr), *quaternions)
for pattern, replacement in qreps:
new_expr = replace(new_expr, pattern, replacement)
if eq_expr(new_expr, expr):
break
expr = new_expr
return expr
def conj_q(expr):
for q in quaternions:
expr = replace(expr, q, N(-1) * q)
return expr
# テスト関数
def test_replace_q():
print("Testing quaternion replacements:")
# テストケース1: IJ
expr1 = Product(I, J)
result1 = replace_q(expr1)
print(f"IJ = {to_string(result1)}")
assert to_string(result1) == "K", "IJ should be K"
# テストケース2: JI
expr2 = Product(J, I)
result2 = replace_q(expr2)
print(f"JI = {to_string(result2)}")
assert to_string(result2) == "-K", "JI should be -K"
# テストケース3: (I + J)K
expr3 = Product(Sum(I, J), K)
expanded3 = expand(expr3)
result3 = replace_q(expanded3)
print(f"(I + J)K = {to_string(result3)}")
assert to_string(result3) == "-J + I", "(I + J)K should be -J + I"
# テストケース4: I(J + K)
expr4 = Product(I, Sum(J, K))
expanded4 = expand(expr4)
result4 = replace_q(expanded4)
print(f"I(J + K) = {to_string(result4)}")
assert to_string(result4) == "K - J", "I(J + K) should be K - J"
# テストケース5: IJK
expr5 = Product(I, J, K)
result5 = replace_q(expr5)
print(f"IJK = {to_string(result5)}")
assert to_string(result5) == "-1", "IJK should be -1"
# テストケース6: IJKJI
expr6 = Product(I, J, K, J, I)
result6 = replace_q(expr6)
print(f"IJKJI = {to_string(result6)}")
assert to_string(result6) == "K", "IJKJI should be K"
# テストケース7: IIJJKK
expr7 = Product(I, I, J, J, K, K)
result7 = replace_q(expr7)
print(f"IIJJKK = {to_string(result7)}")
assert to_string(result7) == "-1", "IIJJKK should be -1"
print("All quaternion tests passed!")
# 八元数の基本単位を定義
e1, e2, e3, e4, e5, e6, e7 = syms("e1,e2,e3,e4,e5,e6,e7")
octonions = [e1, e2, e3, e4, e5, e6, e7]
triads = [
[1, 2, 3],
[1, 4, 5],
[1, 7, 6],
[2, 4, 6],
[2, 5, 7],
[3, 4, 7],
[3, 6, 5]
]
def mulo(a, b):
if a == 0:
return [1, b]
if b == 0:
return [1, a]
if a == b:
return [-1, 0]
for triad in triads:
if a in triad and b in triad:
c = next(x for x in triad if x != a and x != b)
s = 1 if (triad.index(b) - triad.index(a) + 3) % 3 == 1 else -1
return [s, c]
return [0, 0] # エラーケース
oreps = [*commons]
def init_o():
for i in range(1, 8):
o1 = octonions[i - 1]
oreps.append((N(1) * o1, o1))
for j in range(1, 8):
o2 = octonions[j - 1]
result = mulo(i, j)
if result[1] == 0:
oreps.append((o1 * o2, N(result[0])))
else:
o3 = octonions[result[1] - 1]
if result[0] == 1:
oreps.append((o1 * o2, o3))
else:
oreps.append((o1 * o2, N(result[0]) * o3))
init_o()
def replace_o(expr):
while True:
new_expr = backward(forward(expr), *octonions)
for pattern, replacement in oreps:
new_expr = replace(new_expr, pattern, replacement)
if eq_expr(new_expr, expr):
break
expr = new_expr
return expr
def conj_o(expr):
for o in octonions:
expr = replace(expr, Product(o), N(-1) * o)
return expr
def arrange_o(expr):
expr = replace_o(expr)
expr = collect(expr, *octonions, forward_other=True)
expr = forward(expr, *xs)
expr = forward(expr)
return expr
# テスト関数
def test_replace_o():
print("Testing octonion replacements:")
# テストケース1: e1 * e2
expr1 = Product(e1, e2)
result1 = replace_o(expr1)
print(f"e1 * e2 = {to_string(result1)}")
assert to_string(result1) == "e3", "e1 * e2 should be e3"
# テストケース2: e2 * e1
expr2 = Product(e2, e1)
result2 = replace_o(expr2)
print(f"e2 * e1 = {to_string(result2)}")
assert to_string(result2) == "-e3", "e2 * e1 should be -e3"
# テストケース3: (e1 + e2) * e4
expr3 = Product(Sum(e1, e2), e4)
expanded3 = expand(expr3)
result3 = replace_o(expanded3)
print(f"(e1 + e2) * e4 = {to_string(result3)}")
assert to_string(result3) == "e5 + e6", "(e1 + e2) * e4 should be e5 + e6"
# テストケース4: e1 * (e2 + e3)
expr4 = Product(e1, Sum(e2, e3))
expanded4 = expand(expr4)
result4 = replace_o(expanded4)
print(f"e1 * (e2 + e3) = {to_string(result4)}")
assert to_string(result4) == "e3 - e2", "e1 * (e2 + e3) should be e3 - e2"
# テストケース5: e1 * e2 * e4
expr5 = Product(e1, e2, e4)
result5 = replace_o(expr5)
print(f"e1 * e2 * e4 = {to_string(result5)}")
assert to_string(result5) == "e7", "e1 * e2 * e4 should be e7"
print("All octonion tests passed!")
S=N("sinθ")
C=N("cosθ")
S2=N("sin2θ")
C2=N("cos2θ")
def replace_sc(expr):
expr = replace(expr, 1*S, S)
expr = replace(expr, 1*C, C)
expr = replace(expr, S*C, C*S)
expr = replace(expr, C*C+S*S, 1)
expr = replace(expr, -1*C*S+C*S, 0)
expr = replace(expr, C*S+C*S, S2)
expr = replace(expr, -1*S*S+C*C, C2)
return expr
x1, x2, x3, x4, x5, x6, x7 = syms("x1,x2,x3,x4,x5,x6,x7")
xs = [x1, x2, x3, x4, x5, x6, x7]
def set_ov():
def f(expr):
expr = arrange_o(expand(expr))
expr = flatten(collect(expr, *xs))
expr = flatten(collect(expr, -1))
expr = forward(expr)
expr = replace_sc(expr)
expr = replace(expr, 0*x1 + 1*x1*e1, x1*e1)
expr = forward(forward(expr, *xs))
return expr
global O, O_, V, ov, ov_o, vo, o_vo
O = C + S*e1
O_ = forward(conj_o(O))
V = x1*e1 + x2*e2 + x3*e3 + x4*e4 + x5*e5 + x6*e6 + x7*e7
ov = replace_o(expand(O * V))
ov_o = f(ov * O_)
ov = arrange_o(ov)
vo = replace_o(expand(V * O_))
o_vo = f(O * vo)
vo = arrange_o(vo)
print("O =", repr(O))
print("O_ =", repr(O_))
print("V =", repr(V))
print("ov =", repr(ov))
print("ov_o =", repr(ov_o))
print("vo =", repr(vo))
print("o_vo =", repr(o_vo))
def run_all_tests():
test_to_string()
test_replace()
run_tests1()
run_tests2()
test_collect()
test_replace_q()
test_replace_o()
def main():
print("シンボル計算ライブラリデモ")
print("N(...)で単一の要素を表現し、+ と * で加算と乗算を表現します。")
print("例: N(2) * (N(3) + N(4)) または (a + b) * (c + d)")
print("\nテストケース結果:")
run_all_tests()
repl()
def repl():
print("\n数式を入力してください(終了するには [Ctrl]+[D]):")
for line in sys.stdin:
try:
expr = eval(line.strip())
result = to_string(expr)
print(f"結果: {result}")
expanded = expand(expr)
expanded_result = to_string(expanded)
print(f"展開結果: {expanded_result}")
except Exception as e:
print(f"エラー: {str(e)}")
print("\n数式を入力してください(終了するには [Ctrl]+[D]):")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment