# E-Graph Geometric Algebra (EGGA)
[![PyPI](https://badge.fury.io/py/egga.svg)](https://badge.fury.io/py/egga)
Symbolic [Geometric Algebra](https://en.wikipedia.org/wiki/Geometric_algebra) with [E-Graphs](https://egraphs-good.github.io/)
Things you can do with this library
- Simplify expressions
- Prove equalities
- Solve for variables
Things that are supported
- Any signature
- Arbitrary number of basis vectors
- Symplectic Geometric Algebra (aka Weyl Algebras)
- Derivatives
- Add your own expression types and rules (with egglog)
Based on the [Python bindings](https://github.com/metadsl/egglog-python) for [egglog](https://github.com/egraphs-good/egglog)
## Setup
Supports Python 3.8 and higher.
`pip install egga`
## Usage
The first step is to create a `GeometricAlgebra` object with a given signature.
You can then use its basis vectors as well as functions exposed by it. Use the utility methods provided to do things like simplification and
equation solving. In some cases you might need to interface with egglog directly. Below are
some examples for common use-cases.
Simplification
```python
from egga.geometric_algebra import GeometricAlgebra
from egga.utils import simplify
ga = GeometricAlgebra(signature=[1.0, 1.0])
e_0, e_1 = ga.basis_vectors
e_01 = e_0 * e_1
# Build an expression to simplify
expr = e_01 * e_0 * ~e_01
# Prints Simplified: -e("0")
print("Simplified:", simplify(ga, expr))
```
Equation solving
```python
from egglog import union
from egga.geometric_algebra import GeometricAlgebra
from egga.utils import simplify
# Pass eq_solve=True to enable the equation solving rules.
# Add a cost to variable to it gets rewritten to something else.
ga = GeometricAlgebra(signature=[1.0, 1.0], eq_solve=True, costs={"variable": 1_000})
e_0, e_1 = ga.basis_vectors
e_01 = e_0 * e_1
# Solve e_01 * x * ~e_01 = e_0 for x
x = ga.expr_cls.variable("x")
lhs = e_01 * x * ~e_01
rhs = -e_0
# Make LHS equal to RHS
ga.egraph.register(union(lhs).with_(rhs))
assert str(simplify(ga, x)) == str(ga.expr_cls.e("0"))
```
Equality check
```python
from egga.geometric_algebra import GeometricAlgebra
from egga.utils import check_equality
ga = GeometricAlgebra(signature=[1.0, 1.0])
e_0, e_1 = ga.basis_vectors
e_01 = e_0 * e_1
# Build an lhs to check for equality to an rhs
lhs = e_01 * e_01
rhs = ga.expr_cls.scalar_literal(-1.0)
assert check_equality(ga, lhs, rhs)
```
The [/examples](examples) as well as the [/tests](tests) directories contain more examples.
## List of expressions
### Operators
| Code | Description |
| ------------ | ------------------------------------------------------------------------------- |
| `x_1 + x_2` | Addition of x_1 and x_2 |
| `x_1 - x_2` | Subtraction of x_1 and x_2 |
| `x_1 * x_2` | Multiplication of x_1 and x_2 (aka the Geometric Product) |
| `x_1 ^ x_2` | Wedge / exterior / outer product of x_1 and x_2 |
| `x_1 \| x_2` | Inner ("fat dot") product of x_1 and x_2 |
| `-x_1` | Negation of x_1 |
| `~x_1` | Reversion of x_1 |
| `x_1 ** x_2` | x_1 to the power of x_2 |
| `x_1 / x_2` | x_1 divided by x_2 (more generally, x_1 right-multiplied by the inverse of x_2) |
### Functions
| Code | Description |
| ------------------------- | ---------------------------------------------------------------------------------------------------- |
| `inverse(x)` | Multiplicative inverse of x |
| `grade_involution(x)` | [Grade involution](https://en.wikipedia.org/wiki/Paravector#Grade_automorphism) of x |
| `clifford_conjugation(x)` | [Clifford conjugate](https://en.wikipedia.org/wiki/Paravector#Clifford_conjugation) of x |
| `scalar(x)` | Mark x as a scalar |
| `scalar_literal(f)` | Create a scalar constant |
| `scalar_variable(s)` | Create a scalar variable |
| `e(s)` | Basis vector |
| `e2(s_1, s_2)` | Basis bivector |
| `e3(s_1, s_2, s_3)` | Basis trivector |
| `variable(s)` | Create a variable |
| `cos(x)` | Cos of x |
| `sin(x)` | Sin of x |
| `cosh(x)` | Cosh of x |
| `sinh(x)` | Sinh of x |
| `exp(x)` | Exponential function of x |
| `grade(x)` | Grade of x |
| `mix_grades(x_1, x_2)` | Represents the mixture of two grades. If x_1 and x_2 are the same, this will be simplified to `x_1`. |
| `select_grade(x_1, x_2)` | Selects the grade x_2 part of x_1 |
| `abs(x)` | Absolute value of x |
| `rotor(x_1, x_2)` | Shorthand for `exp(scalar_literal(-0.5) * scalar(x_2) * x_1)` |
| `sandwich(x_1, x_2)` | Shorthand for `x_1 * x_2 * ~x_1` |
| `diff(x_1, x_2)` | Derivative of x_1 with respect to x_2 |
### Unsupported but exists, might or might not work
| Code | Description |
| -------------------- | ------------------------------ |
| `boolean(x)` | Mark x as a boolean |
| `x_1.equal(x_2)` | Whether x_1 equals x_2 |
| `x_1.not_equal(x_2)` | Whether x_1 does not equal x_2 |
## Caveats
- Egraphs are bad with associativity (combined with commutativity?) so things can blow up
- Most operations aren't "fully" implemented (eg. `pow` only supports powers of two right now)
## Contributing
Code contributions as well as suggestions and comments about things that don't work yet are appreciated.
You can reach me by email at `tora@warlock.ai` or in the [Bivector Discord](https://discord.gg/vGY6pPk).
Raw data
{
"_id": null,
"home_page": "https://github.com/RobinKa/egga",
"name": "egga",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "geometric-algebra,clifford-algebra,simplification,equations,egraph,egglog,multi-vector,para-vector,mathematics",
"author": "Robin Kahlow",
"author_email": "tora@warlock.ai",
"download_url": "https://files.pythonhosted.org/packages/35/3c/60565727d0865a459a654c93c03e1afd7fba2cb48e1f3fe597bbeaca14b1/egga-0.1.9.tar.gz",
"platform": null,
"description": "# E-Graph Geometric Algebra (EGGA)\n\n[![PyPI](https://badge.fury.io/py/egga.svg)](https://badge.fury.io/py/egga)\n\nSymbolic [Geometric Algebra](https://en.wikipedia.org/wiki/Geometric_algebra) with [E-Graphs](https://egraphs-good.github.io/)\n\nThings you can do with this library\n\n- Simplify expressions\n- Prove equalities\n- Solve for variables\n\nThings that are supported\n\n- Any signature\n- Arbitrary number of basis vectors\n- Symplectic Geometric Algebra (aka Weyl Algebras)\n- Derivatives\n- Add your own expression types and rules (with egglog)\n\nBased on the [Python bindings](https://github.com/metadsl/egglog-python) for [egglog](https://github.com/egraphs-good/egglog)\n\n## Setup\n\nSupports Python 3.8 and higher.\n\n`pip install egga`\n\n## Usage\n\nThe first step is to create a `GeometricAlgebra` object with a given signature.\nYou can then use its basis vectors as well as functions exposed by it. Use the utility methods provided to do things like simplification and\nequation solving. In some cases you might need to interface with egglog directly. Below are\nsome examples for common use-cases.\n\nSimplification\n\n```python\nfrom egga.geometric_algebra import GeometricAlgebra\nfrom egga.utils import simplify\n\nga = GeometricAlgebra(signature=[1.0, 1.0])\ne_0, e_1 = ga.basis_vectors\ne_01 = e_0 * e_1\n\n# Build an expression to simplify\nexpr = e_01 * e_0 * ~e_01\n\n# Prints Simplified: -e(\"0\")\nprint(\"Simplified:\", simplify(ga, expr))\n```\n\nEquation solving\n\n```python\nfrom egglog import union\n\nfrom egga.geometric_algebra import GeometricAlgebra\nfrom egga.utils import simplify\n\n# Pass eq_solve=True to enable the equation solving rules.\n# Add a cost to variable to it gets rewritten to something else.\nga = GeometricAlgebra(signature=[1.0, 1.0], eq_solve=True, costs={\"variable\": 1_000})\n\ne_0, e_1 = ga.basis_vectors\ne_01 = e_0 * e_1\n\n# Solve e_01 * x * ~e_01 = e_0 for x\nx = ga.expr_cls.variable(\"x\")\nlhs = e_01 * x * ~e_01\nrhs = -e_0\n\n# Make LHS equal to RHS\nga.egraph.register(union(lhs).with_(rhs))\n\nassert str(simplify(ga, x)) == str(ga.expr_cls.e(\"0\"))\n```\n\nEquality check\n\n```python\nfrom egga.geometric_algebra import GeometricAlgebra\nfrom egga.utils import check_equality\n\nga = GeometricAlgebra(signature=[1.0, 1.0])\ne_0, e_1 = ga.basis_vectors\ne_01 = e_0 * e_1\n\n# Build an lhs to check for equality to an rhs\nlhs = e_01 * e_01\nrhs = ga.expr_cls.scalar_literal(-1.0)\n\nassert check_equality(ga, lhs, rhs)\n```\n\nThe [/examples](examples) as well as the [/tests](tests) directories contain more examples.\n\n## List of expressions\n\n### Operators\n\n| Code | Description |\n| ------------ | ------------------------------------------------------------------------------- |\n| `x_1 + x_2` | Addition of x_1 and x_2 |\n| `x_1 - x_2` | Subtraction of x_1 and x_2 |\n| `x_1 * x_2` | Multiplication of x_1 and x_2 (aka the Geometric Product) |\n| `x_1 ^ x_2` | Wedge / exterior / outer product of x_1 and x_2 |\n| `x_1 \\| x_2` | Inner (\"fat dot\") product of x_1 and x_2 |\n| `-x_1` | Negation of x_1 |\n| `~x_1` | Reversion of x_1 |\n| `x_1 ** x_2` | x_1 to the power of x_2 |\n| `x_1 / x_2` | x_1 divided by x_2 (more generally, x_1 right-multiplied by the inverse of x_2) |\n\n### Functions\n\n| Code | Description |\n| ------------------------- | ---------------------------------------------------------------------------------------------------- |\n| `inverse(x)` | Multiplicative inverse of x |\n| `grade_involution(x)` | [Grade involution](https://en.wikipedia.org/wiki/Paravector#Grade_automorphism) of x |\n| `clifford_conjugation(x)` | [Clifford conjugate](https://en.wikipedia.org/wiki/Paravector#Clifford_conjugation) of x |\n| `scalar(x)` | Mark x as a scalar |\n| `scalar_literal(f)` | Create a scalar constant |\n| `scalar_variable(s)` | Create a scalar variable |\n| `e(s)` | Basis vector |\n| `e2(s_1, s_2)` | Basis bivector |\n| `e3(s_1, s_2, s_3)` | Basis trivector |\n| `variable(s)` | Create a variable |\n| `cos(x)` | Cos of x |\n| `sin(x)` | Sin of x |\n| `cosh(x)` | Cosh of x |\n| `sinh(x)` | Sinh of x |\n| `exp(x)` | Exponential function of x |\n| `grade(x)` | Grade of x |\n| `mix_grades(x_1, x_2)` | Represents the mixture of two grades. If x_1 and x_2 are the same, this will be simplified to `x_1`. |\n| `select_grade(x_1, x_2)` | Selects the grade x_2 part of x_1 |\n| `abs(x)` | Absolute value of x |\n| `rotor(x_1, x_2)` | Shorthand for `exp(scalar_literal(-0.5) * scalar(x_2) * x_1)` |\n| `sandwich(x_1, x_2)` | Shorthand for `x_1 * x_2 * ~x_1` |\n| `diff(x_1, x_2)` | Derivative of x_1 with respect to x_2 |\n\n### Unsupported but exists, might or might not work\n\n| Code | Description |\n| -------------------- | ------------------------------ |\n| `boolean(x)` | Mark x as a boolean |\n| `x_1.equal(x_2)` | Whether x_1 equals x_2 |\n| `x_1.not_equal(x_2)` | Whether x_1 does not equal x_2 |\n\n## Caveats\n\n- Egraphs are bad with associativity (combined with commutativity?) so things can blow up\n- Most operations aren't \"fully\" implemented (eg. `pow` only supports powers of two right now)\n\n## Contributing\n\nCode contributions as well as suggestions and comments about things that don't work yet are appreciated.\nYou can reach me by email at `tora@warlock.ai` or in the [Bivector Discord](https://discord.gg/vGY6pPk).\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Symbolic Geometric Algebra with E-Graphs ",
"version": "0.1.9",
"project_urls": {
"Homepage": "https://github.com/RobinKa/egga",
"Repository": "https://github.com/RobinKa/egga"
},
"split_keywords": [
"geometric-algebra",
"clifford-algebra",
"simplification",
"equations",
"egraph",
"egglog",
"multi-vector",
"para-vector",
"mathematics"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "fa8702e8c6818f9de7e3c7ea32e1935c4b29194f6508631694390532ed7f0cc0",
"md5": "e2e9b3066bde2b1df895a9b520249148",
"sha256": "6bb21a485f3a8142a60b46e35fb1c80b500ab8eb6121043a160c799b34cdb6af"
},
"downloads": -1,
"filename": "egga-0.1.9-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e2e9b3066bde2b1df895a9b520249148",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 11123,
"upload_time": "2023-10-11T22:33:21",
"upload_time_iso_8601": "2023-10-11T22:33:21.134984Z",
"url": "https://files.pythonhosted.org/packages/fa/87/02e8c6818f9de7e3c7ea32e1935c4b29194f6508631694390532ed7f0cc0/egga-0.1.9-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "353c60565727d0865a459a654c93c03e1afd7fba2cb48e1f3fe597bbeaca14b1",
"md5": "3ce1dca6f7148a7d9ed680e742fb3f31",
"sha256": "944603a330f7afdc44184f941bc7a0e6661dc6939163992c66fc3d5633cad8d7"
},
"downloads": -1,
"filename": "egga-0.1.9.tar.gz",
"has_sig": false,
"md5_digest": "3ce1dca6f7148a7d9ed680e742fb3f31",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 12299,
"upload_time": "2023-10-11T22:33:22",
"upload_time_iso_8601": "2023-10-11T22:33:22.793072Z",
"url": "https://files.pythonhosted.org/packages/35/3c/60565727d0865a459a654c93c03e1afd7fba2cb48e1f3fe597bbeaca14b1/egga-0.1.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-11 22:33:22",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "RobinKa",
"github_project": "egga",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "egga"
}