Solve the general multivector equation A X = B with expressions¶
Keywords: expressions · solve · A X = B · multivector equation
Builds the linear map forward = A * X once, then recovers the unknown
X in two ways:
Expression.inv— inverts the square, invertible map, returning a new expression that mapsBback toX.Expression.lstsq— solvesM · vec(X) = vec(B)numerically with an explicit right-hand side.
Run¶
Source¶
Code¶
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
# Copyright 2021 Christian Perwass
r"""Solve the general multivector equation ``A X = B`` with expressions.
Builds the linear map ``forward = A * X`` once, then recovers the unknown
``X`` in two ways:
- :meth:`Expression.inv` — inverts the square, invertible map, returning a new
expression that maps ``B`` back to ``X``.
- :meth:`Expression.lstsq` — solves ``M · vec(X) = vec(B)`` numerically with an
explicit right-hand side.
Run
---
.. code-block:: bash
uv run python py/examples/ga/expression/solve_ax_b.py
Keywords: expressions, solve, A X = B, multivector equation
"""
from __future__ import annotations
from pytanga import BladeMask, MV, Variable
from pytanga.basis import BasisP3
def main() -> None:
P3 = BasisP3()
full = BladeMask(P3)
# A concrete invertible multivector and its "true" solution.
A = P3("1 + 2 e1 - e2 + 0.5 e3")
X_true = P3("3 - 2 e1 + e2 + 0.25 e3 + 1.5 e123")
B = A * X_true
# The linear map X -> A * X (full-mask variable).
X = Variable("X", full)
forward = A * X
# Fit 1 — exact inverse.
X_inv = forward.inv("X")(X=B)
assert isinstance(X_inv, MV)
print("Solve A X = B via Expression.inv:")
print(" A =", {k: round(v, 4) for k, v in A.to_dict().items()})
print(" B =", {k: round(v, 4) for k, v in B.to_dict().items()})
print(" X recovered =", {k: round(v, 4) for k, v in X_inv.to_dict().items()})
print(" |A·X - B| =", (A * X_inv - B).mag)
# Fit 2 — least squares with an explicit right-hand side.
X_lstsq = forward.lstsq(rhs=B)
print("\nSolve A X = B via Expression.lstsq (explicit rhs):")
print(" X recovered =", {k: round(v, 4) for k, v in X_lstsq.to_dict().items()})
print(" |A·X - B| =", (A * X_lstsq - B).mag)
if __name__ == "__main__":
main()