From bacca0c9e1233d9307063a095eddf38a59990280 Mon Sep 17 00:00:00 2001 From: utensil Date: Sun, 31 Mar 2024 17:23:12 +0800 Subject: [PATCH] A workaround for the broken MatrixFunction --- examples/ipython/gsym-printing.ipynb | 238 +++++++++++++++++++++++---- galgebra/atoms.py | 13 +- 2 files changed, 217 insertions(+), 34 deletions(-) diff --git a/examples/ipython/gsym-printing.ipynb b/examples/ipython/gsym-printing.ipynb index 06d96a34..ee96dd7f 100644 --- a/examples/ipython/gsym-printing.ipynb +++ b/examples/ipython/gsym-printing.ipynb @@ -30,27 +30,7 @@ "cell_type": "code", "execution_count": 2, "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "argument of type 'int' is not iterable", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[2], line 4\u001b[0m\n\u001b[1;32m 2\u001b[0m f \u001b[38;5;241m=\u001b[39m Ga(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124me*u|v\u001b[39m\u001b[38;5;124m'\u001b[39m, gsym\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 3\u001b[0m g \u001b[38;5;241m=\u001b[39m Ga(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124me*u|v\u001b[39m\u001b[38;5;124m'\u001b[39m, gsym\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mg\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m----> 4\u001b[0m fc \u001b[38;5;241m=\u001b[39m \u001b[43mGa\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43me*u|v\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcoords\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcoords\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mgsym\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mf\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 5\u001b[0m gc \u001b[38;5;241m=\u001b[39m Ga(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124me*u|v\u001b[39m\u001b[38;5;124m'\u001b[39m, coords\u001b[38;5;241m=\u001b[39mcoords, gsym\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mg\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/ga.py:685\u001b[0m, in \u001b[0;36mGa.__init__\u001b[0;34m(self, bases, wedge, **kwargs)\u001b[0m\n\u001b[1;32m 683\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcoords \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 684\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_update_de_from_rbasis()\n\u001b[0;32m--> 685\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_build_grads\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 687\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnect_flg:\n\u001b[1;32m 688\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_build_connection()\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/ga.py:942\u001b[0m, in \u001b[0;36mGa._build_grads\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 940\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_build_grads\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 941\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mis_ortho:\n\u001b[0;32m--> 942\u001b[0m r_basis \u001b[38;5;241m=\u001b[39m \u001b[43m[\u001b[49m\u001b[43mx\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43me_sq\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mx\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mr_basis_mv\u001b[49m\u001b[43m]\u001b[49m\n\u001b[1;32m 943\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 944\u001b[0m r_basis \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mr_basis_mv\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/ga.py:942\u001b[0m, in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 940\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_build_grads\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 941\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mis_ortho:\n\u001b[0;32m--> 942\u001b[0m r_basis \u001b[38;5;241m=\u001b[39m [x \u001b[38;5;241m/\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43me_sq\u001b[49m \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mr_basis_mv]\n\u001b[1;32m 943\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 944\u001b[0m r_basis \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mr_basis_mv\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/_utils/cached_property.py:25\u001b[0m, in \u001b[0;36mcached_property.__get__\u001b[0;34m(self, obj, cls)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m obj \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\n\u001b[0;32m---> 25\u001b[0m val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mobj\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;66;03m# this entry hides the _cached_property\u001b[39;00m\n\u001b[1;32m 27\u001b[0m \u001b[38;5;28msetattr\u001b[39m(obj, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m, val)\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/ga.py:1844\u001b[0m, in \u001b[0;36mGa.e_sq\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 1840\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgsym \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 1841\u001b[0m \u001b[38;5;66;03m# Define square of pseudo-scalar in terms of metric tensor\u001b[39;00m\n\u001b[1;32m 1842\u001b[0m \u001b[38;5;66;03m# determinant\u001b[39;00m\n\u001b[1;32m 1843\u001b[0m n \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn\n\u001b[0;32m-> 1844\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m (\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m) \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m (n\u001b[38;5;241m*\u001b[39m(n \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m1\u001b[39m)\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m2\u001b[39m) \u001b[38;5;241m*\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdetg\u001b[49m\n\u001b[1;32m 1845\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1846\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m simplify(expand((\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39me\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39me)\u001b[38;5;241m.\u001b[39mscalar()))\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/_utils/cached_property.py:25\u001b[0m, in \u001b[0;36mcached_property.__get__\u001b[0;34m(self, obj, cls)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m obj \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\n\u001b[0;32m---> 25\u001b[0m val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mobj\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;66;03m# this entry hides the _cached_property\u001b[39;00m\n\u001b[1;32m 27\u001b[0m \u001b[38;5;28msetattr\u001b[39m(obj, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m, val)\n", - "File \u001b[0;32m~/projects/galgebra/galgebra/metric.py:642\u001b[0m, in \u001b[0;36mMetric.detg\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 640\u001b[0m g \u001b[38;5;241m=\u001b[39m MatrixSymbol(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgsym, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn)\n\u001b[1;32m 641\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 642\u001b[0m g \u001b[38;5;241m=\u001b[39m \u001b[43mMatrixFunction\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgsym\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mn\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mn\u001b[49m\u001b[43m)\u001b[49m(\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcoords)\n\u001b[1;32m 643\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m Determinant(g)\n", - "File \u001b[0;32m~/.pyenv/versions/3.11.8/lib/python3.11/site-packages/sympy/core/function.py:194\u001b[0m, in \u001b[0;36mFunctionClass.__init__\u001b[0;34m(cls, *args, **kwargs)\u001b[0m\n\u001b[1;32m 192\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m3\u001b[39m:\n\u001b[1;32m 193\u001b[0m namespace \u001b[38;5;241m=\u001b[39m args[\u001b[38;5;241m2\u001b[39m]\n\u001b[0;32m--> 194\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43meval\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mnamespace\u001b[49m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(namespace[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124meval\u001b[39m\u001b[38;5;124m'\u001b[39m], \u001b[38;5;28mclassmethod\u001b[39m):\n\u001b[1;32m 195\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124meval on Function subclasses should be a class method (defined with @classmethod)\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[0;31mTypeError\u001b[0m: argument of type 'int' is not iterable" - ] - } - ], + "outputs": [], "source": [ "coords = symbols('u v', real=True)\n", "f = Ga('e*u|v', gsym='f')\n", @@ -68,9 +48,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{f}\\right|$" + ], + "text/plain": [ + "-│f│" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{g}\\right|$" + ], + "text/plain": [ + "-│g│" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{f{\\left(u,v \\right)}}\\right|$" + ], + "text/plain": [ + "-│f(u, v)│" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{g{\\left(u,v \\right)}}\\right|$" + ], + "text/plain": [ + "-│g(u, v)│" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "display(f.e_sq)\n", "display(g.e_sq)\n", @@ -87,9 +116,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{f}\\right|$" + ], + "text/plain": [ + "-Determinant(f)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{g}\\right|$" + ], + "text/plain": [ + "-Determinant(g)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{f{\\left(u,v \\right)}}\\right|$" + ], + "text/plain": [ + "-Determinant(f)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "$\\displaystyle - \\left|{g{\\left(u,v \\right)}}\\right|$" + ], + "text/plain": [ + "-Determinant(g)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "display(f.mv(f.e_sq))\n", "display(g.mv(g.e_sq))\n", @@ -106,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -116,7 +194,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -136,9 +214,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( f\\right )\\end{equation*}" + ], + "text/plain": [ + "-│f│" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( g\\right )\\end{equation*}" + ], + "text/plain": [ + "-│g│" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( f \\right )\\end{equation*}" + ], + "text/plain": [ + "-│f(u, v)│" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( g \\right )\\end{equation*}" + ], + "text/plain": [ + "-│g(u, v)│" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "display(fp.e_sq)\n", "display(gp.e_sq)\n", @@ -155,9 +282,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( f\\right )\\end{equation*}" + ], + "text/plain": [ + "-Determinant(f)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( g\\right )\\end{equation*}" + ], + "text/plain": [ + "-Determinant(g)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( f \\right )\\end{equation*}" + ], + "text/plain": [ + "-Determinant(f)" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/latex": [ + "\\begin{equation*}- \\det\\left ( g \\right )\\end{equation*}" + ], + "text/plain": [ + "-Determinant(g)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "display(fp.mv(fp.e_sq))\n", "display(gp.mv(gp.e_sq))\n", diff --git a/galgebra/atoms.py b/galgebra/atoms.py index dc26e7e8..56fa7213 100644 --- a/galgebra/atoms.py +++ b/galgebra/atoms.py @@ -9,6 +9,7 @@ from sympy.printing.pretty.stringpict import prettyForm, stringPict from sympy.printing.pretty.pretty_symbology import U + __all__ = [ 'BasisVectorSymbol', 'BasisBladeSymbol', @@ -146,14 +147,20 @@ def _pretty(self, printer): return prettyForm(*pform.parens()) -class MatrixFunction(UndefinedFunction): +class MatrixFunctionClass(UndefinedFunction): """ Like a MatrixSymbol, but for functions. """ - def __new__(mcl, name, m, n, **kwargs): + def __new__(mcl, name, shape, **kwargs): cls = super().__new__(mcl, name, (AppliedUndef, MatrixExpr), {}, **kwargs) - cls.shape = sympify(n, strict=True), sympify(n, strict=True) + m, n = shape + cls.shape = sympify(m, strict=True), sympify(n, strict=True) return cls +# workaround until pygae/galgebra#495 is truely fixed +def MatrixFunction(name, m, n): + return MatrixFunctionClass(name, (m, n)) + + # workaround until sympy/sympy#19354 is merged if _Determinant.is_commutative is not True: class Determinant(_Determinant):