Skip to content

ericceg/cuspian

Repository files navigation

Cuspian: Lattice Flows Visualization

Visualize flows on the space of lattices $SL_2(\mathbb{R})/SL_2(\mathbb{Z})$.

  • Horocycle flow: Demonstrates quantitative non-divergence
  • Geodesic flow: Visualizes Diophantine approximation via the Dani correspondence

Installation

Prerequisites

Python 3.8+ is required. Install if needed:

  • macOS: brew install python (or download from python.org)
  • Windows: Download from python.org
  • Linux: Usually pre-installed, or sudo apt install python3

uv (recommended) — fast Python package installer:

curl -LsSf https://astral.sh/uv/install.sh | sh

Or see uv installation docs.

Quick Install (recommended)

uv tool install git+https://github.com/ericceg/cuspian.git

Then run from anywhere:

cuspian

With pip

pip install git+https://github.com/ericceg/cuspian.git

From Source

git clone https://github.com/ericceg/cuspian.git
cd cuspian
uv tool install .
# or: pip install .

Quick Examples

# Horocycle flow (default)
cuspian --flow horocycle

# Save as GIF
cuspian --alpha "sqrt(2)" --save output.gif

# Analysis mode
cuspian --alpha "pi" --analyze

# Geodesic analysis with continued-fraction convergents
cuspian --flow geodesic --alpha pi --analyze --cf-terms 10

# Fading trail in moduli space (fades after 6 seconds)
cuspian --flow horocycle --slope pi --trail 6

# Infinite trail (never fades)
cuspian --flow horocycle --slope pi --trail inf

Gallery

Geodesic Flow: Approximating π

cuspian --flow geodesic --alpha pi --theme light --speed 5

Deep excursions into the cusp correspond to good rational approximations of π.

geodesic_pi

Horocycle Flow: Slope 1/3

cuspian --flow horocycle --slope "1/3" --theme light --speed 5

Rational slope creates a periodic orbit that eventually closes.

horocycle_slope_1_3

Horocycle Flow: Slope π

cuspian --flow horocycle --slope pi --theme light --speed 5

Irrational slope creates a dense orbit that fills the fundamental domain.

horocycle_slope_pi

Interactive Controls

The visualization window supports keyboard shortcuts:

Key Action
Space Pause/Resume animation
Increase speed (1.5x)
Decrease speed (1.5x)
R Reset animation and trail
Q Quit

Key Options

Option Description Default
--flow horocycle or geodesic horocycle
--slope Slope to tilt standard lattice (e.g., "1/2", "sqrt(2)") 1/√2
--alpha Number to approximate (e.g., "pi", "3/7", "sqrt(2)") None
--duration Animation duration (seconds) 10
--speed Speed multiplier 1.0
--theme dark, light, or system system
--save Save to file (.mp4 or .gif) None
--analyze Generate statistics and plots False
--cf-terms Continued-fraction terms/convergents to show in geodesic analysis 8
--div-limit Divergence threshold (shortest vector) 1e-3
--trail Trail in moduli space: inf=infinite, number=fade after N seconds, 0=off inf

What You'll See

  • Left: Physical lattice points evolving under the flow
  • Right: Trajectory in the moduli space fundamental domain
  • Bottom: Cusp height (inverse shortest vector length) over time

For rational α, the geodesic diverges into the cusp (visualization freezes when shortest vector < div-limit).

Mathematical Background

The Space $SL_2(\mathbb{R})/SL_2(\mathbb{Z})$

A lattice in $\mathbb{R}^2$ is a discrete subgroup generated by two linearly independent vectors. The space of all lattices (up to similarity) can be identified with $SL_2(\mathbb{R})/SL_2(\mathbb{Z})$, which parametrizes lattice shapes.

We visualize lattices in two ways:

  1. Physical Space: The actual lattice points $\Lambda_t = g_t \Lambda_0$ in $\mathbb{R}^2$
  2. Moduli Space: Each lattice shape corresponds to a point $\tau \in \mathbb{H}$ in the upper half-plane, reduced to the fundamental domain $\mathcal{F} = {z \in \mathbb{H} : |z| \ge 1, |\text{Re}(z)| \le 1/2}$

The Flows

Horocycle Flow:

$$ u_t = \begin{pmatrix} 1 & t \newline 0 & 1 \end{pmatrix} $$

Shears the lattice horizontally. The slope parameter determines the initial lattice orientation:

  • Rational slope (e.g., --slope 1/3): Creates a periodic orbit
  • Irrational slope (e.g., --slope pi): Creates a dense orbit that fills the fundamental domain (quantitative non-divergence)

Geodesic Flow:

$$ g_t = \begin{pmatrix} e^{t/2} & 0 \newline 0 & e^{-t/2} \end{pmatrix} $$

Expands one direction and contracts the other. The alpha parameter determines which number to approximate.

Starting lattice:

$$ \Lambda_\alpha = \begin{pmatrix} 1 & -\alpha \newline 0 & 1 \end{pmatrix} \mathbb{Z}^2 $$

  • Rational α (e.g., --alpha 3/7): Trajectory diverges into the cusp
  • Badly approximable α (e.g., --alpha sqrt(2)): Trajectory stays bounded
  • Well approximable α (e.g., --alpha pi): Deep cusp excursions at continued fraction convergents

Connection to Diophantine Approximation

The cusp height (inverse shortest vector length $1/\lambda_1$) measures how close the lattice is to degenerating. For geodesic flow with parameter α:

  • Large cusp height ⟺ Good rational approximation $p/q \approx \alpha$
  • Cusp excursion depth ⟺ Quality of approximation (Dani correspondence)

This visualizes why rational numbers have infinitely good approximations (diverge to infinity) while algebraic irrationals like $\sqrt{2}$ are "badly approximable" (bounded trajectories).

When using --analyze with geodesic flow, Cuspian now also prints the continued-fraction expansion of α and a table of convergents (p/q), including approximation error $|\alpha - p/q|$. This helps connect visible cusp excursions to classical best rational approximations.

Development

# Run tests
uv run pytest

# Type checking
uv run mypy cuspian/

# Format code
uv run ruff format cuspian/

Documentation

See AGENTS.md for:

  • Detailed mathematical background
  • Architecture and code structure
  • Development workflows
  • Advanced usage examples

About

Visualize flows on the space of lattices SL2(R)/SL2(Z).

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages