Symbolic differential geometry and general relativity in SymPy, with a Lean 4 formal-verification bridge.
Project description
LeviPy
A pure-Python, SymPy-backed library for symbolic differential geometry and general relativity computations — the Levi-Civita connection, curvature tensors, geodesics, and more, all computed exactly as closed-form symbolic expressions.
What sets LeviPy apart is its Lean 4 bridge: it doesn't just compute geometric quantities, it can export them as machine-checkable proof obligations in Lean 4 against Mathlib — turning a symbolic curvature calculation into a formal theorem a proof assistant can verify. See Lean 4 formal verification.
Features
- Metric tensor
g_{ij}with automatic inverseg^{ij} - Christoffel symbols
Γ^k_{ij}of the Levi-Civita connection - Riemann curvature tensor
R^l_{ijk} - Ricci tensor
R_{ij}and Ricci scalarR - Einstein tensor
G_{ij} - Geodesic equations for an affinely parametrised curve
- Parallel transport of a vector field along a curve
- Covariant derivatives of vectors, covectors, and (1,1)-tensors
- Lie bracket
[X, Y]of two vector fields - Lean 4 bridge — translate SymPy expressions to Lean 4 terms, emit theorem stubs, and link to relevant Mathlib lemmas for formal verification
All tensors derived from the metric are computed lazily and cached.
Requirements
- Python ≥ 3.12
- SymPy ≥ 1.14
This project uses uv for environment and dependency management.
Installation
# Clone, then sync the environment
uv sync
# Build a wheel / sdist into dist/
uv build
Quick start
import sympy as sp
from levipy import Manifold
# Coordinates for the 2-sphere
theta, phi = sp.symbols('theta phi', real=True)
r = sp.Symbol('r', positive=True)
# Build a manifold and attach a metric g_{ij}
M = Manifold('S2', coords=[theta, phi])
g = M.metric([[r**2, 0],
[0, r**2 * sp.sin(theta)**2]])
# Derived geometric quantities
g.christoffel() # Christoffel symbols Γ^k_ij
g.riemann() # Riemann tensor R^l_ijk
g.ricci_tensor() # Ricci tensor R_ij
g.ricci_scalar() # Ricci scalar R
g.einstein_tensor() # Einstein tensor G_ij
Most objects provide a .display() method for pretty-printed / LaTeX output.
Geodesics
geo = g.geodesic_equations()
geo.display()
Parallel transport
from levipy import ParallelTransport
pt = ParallelTransport(g)
pt.equations(curve=[sp.cos(pt.lam), sp.sin(pt.lam)])
Lie bracket
from levipy import lie_bracket
X = [theta, 0]
Y = [0, phi]
lie_bracket(X, Y, coords=[theta, phi])
Lean 4 formal verification bridge
Symbolic computation tells you what the curvature of a space is. It does not tell you the result is correct — a typo in a metric or a SymPy simplification quirk can silently produce a wrong tensor. LeviPy's Lean 4 bridge closes that gap by translating your computed geometry into formal statements that the Lean 4 proof assistant can check against Mathlib.
This is a proof-obligation layer, not an automated prover. Given a fully
computed metric (with its Christoffel symbols, Riemann/Ricci tensors, etc.),
TheoremBuilder emits a .lean source file containing:
- The necessary Mathlib imports
- Coordinate symbols declared as
(x : ℝ) - The metric as a
noncomputable def - One theorem per nonzero Christoffel symbol
- Riemann flatness / curvature theorems
- The Ricci scalar theorem
- Geodesic equation statements
Each theorem comes with a sorry-based proof skeleton and tactic hints that
point at real Mathlib lemmas — so a human (or Lean's automation) can fill in
the proofs. The output is a set of checkable obligations: if the geometry is
wrong, the Lean statements won't close.
Three components make up the bridge:
| Component | Role |
|---|---|
SymPyToLean4 |
Translates a SymPy expression into a Lean 4 term string |
TheoremBuilder |
Emits a full .lean file of proof obligations from a metric |
MathlibLinker |
Suggests relevant Mathlib 4 lemmas/tactics for an expression |
import sympy as sp
from levipy import Manifold, TheoremBuilder
# Name the symbols in Greek so the generated Lean uses θ, φ identifiers
theta, phi = sp.symbols('θ φ', real=True)
M = Manifold('S2', coords=[theta, phi])
g = M.metric([[1, 0], [0, sp.sin(theta)**2]])
builder = TheoremBuilder(
g,
manifold_name='Sphere2',
extra_hypotheses=['(hth : 0 < θ)', '(hth2 : θ < π)'], # must match the symbol names
)
builder.save('Sphere2.lean') # writes a Lean 4 source file
The companion Lean project lives in lean/ (a Lake project pinned to
a Mathlib toolchain). Lower-level pieces are also available:
from levipy import SymPyToLean4, MathlibLinker
SymPyToLean4().translate(sp.sin(theta)**2) # SymPy expr → Lean 4 term string
MathlibLinker() # map expressions to Mathlib lemmas
Package layout
levipy/
├── geometry/ Manifold, covariant derivative, Lie bracket
├── tensors/ Metric, Christoffel, Riemann, Ricci, Einstein
├── gr/ General-relativity tools (geodesics, parallel transport)
└── lean4/ Lean 4 bridge (translator, theorem builder, Mathlib linker)
lean/ Companion Lean 4 / Lake project (Mathlib-backed proofs)
Development
# Run the test suite (pytest is a dev dependency)
uv run pytest
# Verbose
uv run pytest -v
License
Released under the MIT License. © 2026 Miraj Samarakkody.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file levipy-0.1.0.tar.gz.
File metadata
- Download URL: levipy-0.1.0.tar.gz
- Upload date:
- Size: 30.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84166a197ed1f54bfc3f29c7a1beb23e05d347d90b28509f72ea3432965049f7
|
|
| MD5 |
a9012076fc68aaed0ec0d7b976a9c159
|
|
| BLAKE2b-256 |
eeda94123822c426e38cfd6b55a1be707358263d7c75fbb4d1d7fc1df2cdab06
|
File details
Details for the file levipy-0.1.0-py3-none-any.whl.
File metadata
- Download URL: levipy-0.1.0-py3-none-any.whl
- Upload date:
- Size: 30.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd1404baa3b0343a67c329e681aafc508bb2cb254728d5f3e89b5ac14438ca72
|
|
| MD5 |
091340d68ffd9620e1fe09972e623aed
|
|
| BLAKE2b-256 |
37ddf01113d55768729cfda7e732881f6f68651fe255757151bdc5b7ab173b64
|