Skip to content

Commit

Permalink
A workaround for the broken MatrixFunction
Browse files Browse the repository at this point in the history
  • Loading branch information
utensil committed Mar 31, 2024
1 parent 252fed4 commit bacca0c
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 34 deletions.
238 changes: 207 additions & 31 deletions examples/ipython/gsym-printing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -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<listcomp>\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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -106,7 +184,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -116,7 +194,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -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",
Expand All @@ -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",
Expand Down
13 changes: 10 additions & 3 deletions galgebra/atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from sympy.printing.pretty.stringpict import prettyForm, stringPict
from sympy.printing.pretty.pretty_symbology import U


__all__ = [
'BasisVectorSymbol',
'BasisBladeSymbol',
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit bacca0c

Please sign in to comment.