Skip to main content

Constraint Theory Python

Your floating-point drift ends here. Snap vectors to exact Pythagorean triples.

GitHub stars PyPI version Python Versions License: MIT CI

📦 pip install constraint-theory | 🌐 Live Demo | 📚 Full Docs


💥 The Problem You Know

>>> import numpy as np
>>> v = np.array([3, 4]) / 5
>>> v[0] ** 2 + v[1] ** 2
0.9999999999999999  # "Close enough" for science?

Your physics simulation gives different results on laptop vs. cluster. Your tests flake. Your Monte Carlo won't reproduce.


✨ The Solution

>>> from constraint_theory import PythagoreanManifold
>>> manifold = PythagoreanManifold(200)
>>> manifold.snap(0.6, 0.8)
(0.6, 0.8, 0.0)  # Exact. 3/5, 4/5. Zero noise.
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   Input:      (0.577, 0.816)  ← noisy float                │
│                    ↓                                        │
│   KD-Tree:    O(log n) lookup in Rust                      │
│                    ↓                                        │
│   Output:     (0.6, 0.8)      ← exact Pythagorean triple   │
│                = (3/5, 4/5)   ← stored as exact rationals  │
│                                                             │
│   Same result on EVERY machine. Cross-platform guaranteed. │
│                                                             │
└─────────────────────────────────────────────────────────────┘

🚀 Install Now

Prerequisites: Python 3.8+

pip install constraint-theory

Try it now (30 seconds):

pip install constraint-theory
python -c "from constraint_theory import PythagoreanManifold; m = PythagoreanManifold(200); x, y, _ = m.snap(0.577, 0.816); print(f'Exact: ({x}, {y})')"
# Output: Exact: (0.6, 0.8)

⚡ Quick Start (30 Seconds)

from constraint_theory import PythagoreanManifold, generate_triples

# Create manifold (~1000 exact states)
manifold = PythagoreanManifold(density=200)

print(f"Manifold has {manifold.state_count} exact states")
# Output: Manifold has 1013 exact states

# Snap to nearest Pythagorean triple
x, y, noise = manifold.snap(0.577, 0.816)
print(f"Snapped: ({x:.4f}, {y:.4f}), noise: {noise:.6f}")
# Output: Snapped: (0.6000, 0.8000), noise: 0.0236

📊 Code Reduction: 63% Less Code

Approach Code Reproducible Speed
NumPy (normalize) 156 chars Platform-dependent Fast
Constraint Theory 58 chars Exact everywhere ~100ns

NumPy Approach

# 156 characters - manual normalization
import numpy as np

def normalize(v):
    mag = np.linalg.norm(v)
    return v / mag

v = np.array([0.6, 0.8])
normalized = normalize(v)  # Still floats, still drifts

Constraint Theory Approach

# 58 characters - exact by construction
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(200)
x, y, noise = manifold.snap(0.577, 0.816)  # (0.6, 0.8, 0.0236)

🔢 NumPy Integration — Drop-In Replacement for Normalization

Works seamlessly with your existing NumPy code. Replace v / np.linalg.norm(v) with exact snapping:

import numpy as np
from constraint_theory import PythagoreanManifold

manifold = PythagoreanManifold(200)

# Your old way: v / np.linalg.norm(v) → floating-point drift
# Your new way: manifold.snap(x, y) → exact everywhere

vector = np.array([0.577, 0.816])
sx, sy, noise = manifold.snap(vector[0], vector[1])

# Batch snap 10,000 vectors (SIMD optimized in Rust)
angles = np.random.uniform(0, 2 * np.pi, 10000)
vectors = np.column_stack([np.cos(angles), np.sin(angles)])
results = manifold.snap_batch(vectors)

# Convert results to NumPy arrays for analysis
snapped = np.array([[sx, sy] for sx, sy, _ in results])
noises = np.array([noise for _, _, noise in results])

print(f"Mean snapping noise: {noises.mean():.6f}")
print(f"Max snapping noise:  {noises.max():.6f}")

# Verify exact unit norm
norms = np.linalg.norm(snapped, axis=1)
print(f"Max norm deviation from 1.0: {np.max(np.abs(norms - 1.0)):.2e}")
# Output: 0.00e+00 (exact!)

📈 Performance Comparison

Operation Constraint Theory scipy.spatial.KDTree Speedup
Single snap ~100 ns ~2 μs 20x
Batch 1,000 ~74 μs ~1.5 ms 20x
Batch 10,000 ~740 μs ~15 ms 20x
Metric NumPy Normalize Constraint Theory
Precision Platform-dependent Exact everywhere
Reproducibility Requires seeding Deterministic
Memory per vector 16 bytes (2 floats) 16 bytes (2 floats)
Cross-platform May vary Identical

🎯 Use Cases

🧭 Decision Tree: Is This For You?

                    ┌─────────────────────────────────┐
                    │   Do you use NumPy vectors?     │
                    └─────────────┬───────────────────┘
                                  │
                    ┌─────────────▼─────────────┐
                    │         YES               │
                    └─────────────┬─────────────┘
                                  │
              ┌───────────────────▼───────────────────┐
              │   Need reproducible results across    │
              │   laptop / server / cluster?          │
              └─────────────┬─────────────────────────┘
                            │
         ┌──────────────────┼──────────────────┐
         │                  │                  │
    ┌────▼────┐        ┌────▼────┐       ┌────▼────┐
    │   YES   │        │   NO    │       │ MAYBE   │
    └────┬────┘        └────┬────┘       └────┬────┘
         │                  │                  │
         ▼                  ▼                  ▼
    ┌─────────┐       ┌──────────┐       ┌──────────┐
    │ ✓ USE   │       │ ✗ Maybe  │       │ ? Try    │
    │ THIS!   │       │ overkill │       │ demos    │
    └─────────┘       └──────────┘       └──────────┘

Machine Learning — Reproducible Training

from constraint_theory import PythagoreanManifold
import numpy as np

manifold = PythagoreanManifold(500)

def augment_direction(dx, dy):
    """Deterministic data augmentation."""
    sx, sy, _ = manifold.snap(dx, dy)
    return sx, sy  # Same augmentation, any machine, any run

# Paper reviewers can reproduce your exact training runs

Game Development — Networked Physics

manifold = PythagoreanManifold(150)

def process_player_input(vx, vy):
    dx, dy, _ = manifold.snap(vx, vy)
    return dx, dy  # All clients see identical physics

# No "rubber banding" from FP reconciliation

Scientific Computing — Monte Carlo

import numpy as np
from constraint_theory import PythagoreanManifold

manifold = PythagoreanManifold(300)

# Snap 10,000 random directions to exact states
np.random.seed(42)  # Seed for reproducibility
angles = np.random.uniform(0, 2 * np.pi, 10000)
directions = np.column_stack([np.cos(angles), np.sin(angles)])
results = manifold.snap_batch(directions)
snapped = np.array([[sx, sy] for sx, sy, _ in results])

# Reproducible on any HPC cluster
# Identical results on laptop, server, or cloud

📚 API Reference

PythagoreanManifold(density: int)

Create a manifold with specified density. Higher density = more exact states = finer resolution.

Density Approx States Resolution
50 ~250 0.02
100 ~500 0.01
200 ~1000 0.005
500 ~2500 0.002
1000 ~5000 0.001
Method Returns Description
snap(x, y) (float, float, float) Snap single vector, returns (x, y, noise)
snap_batch(vectors) List[(float, float, float)] Batch snap (SIMD optimized)
state_count int Number of valid Pythagorean states

generate_triples(max_c: int)

from constraint_theory import generate_triples

triples = generate_triples(50)
for a, b, c in triples[:5]:
    print(f"{a}² + {b}² = {c}²")
# 3² + 4² = 5²
# 5² + 12² = 13²
# 8² + 15² = 17²

❓ FAQ

What density should I use?

Use Case Recommended Density Reasoning
Game physics 100-200 Fast lookups, sufficient precision
ML augmentation 200-500 Balance precision and speed
Scientific computing 500-1000 Maximum precision needed

How accurate is the snapping?

Exact. The result is always a perfect Pythagorean triple where x² + y² = 1 exactly.

x, y, noise = manifold.snap(0.577, 0.816)
# x, y are EXACT - x² + y² = 1.0 perfectly
# noise = distance from input to snapped point

Is it thread-safe?

Yes! The Rust core uses immutable data structures.

from concurrent.futures import ThreadPoolExecutor

manifold = PythagoreanManifold(200)

def snap_many(vectors):
    return [manifold.snap(x, y) for x, y in vectors]

# Safe for parallel use
with ThreadPoolExecutor(max_workers=8) as executor:
    results = list(executor.map(snap_many, chunks))

🔧 Troubleshooting

Common Issues

ImportError: cannot import name 'PythagoreanManifold'

The Rust extension wasn't built or loaded correctly.

# Solution 1: Reinstall from PyPI
pip install --upgrade constraint-theory

# Solution 2: Build from source
git clone https://github.com/SuperInstance/constraint-theory-python
cd constraint-theory-python
pip install maturin
maturin develop --release

TypeError: PythagoreanManifold() takes no keyword arguments

You're using the wrong parameter name.

# WRONG - 'dimensions' doesn't exist
manifold = PythagoreanManifold(dimensions=2)

# CORRECT - use 'density' parameter
manifold = PythagoreanManifold(density=200)

ValueError: density must be positive

Density must be a positive integer.

# WRONG
manifold = PythagoreanManifold(0)
manifold = PythagoreanManifold(-100)

# CORRECT
manifold = PythagoreanManifold(200)

snap_batch() returns unexpected results

Ensure your input is the correct shape.

# WRONG - 1D array
vectors = np.array([0.6, 0.8, 0.707, 0.707])
results = manifold.snap_batch(vectors)  # Error!

# CORRECT - Nx2 array
vectors = np.array([[0.6, 0.8], [0.707, 0.707]])
results = manifold.snap_batch(vectors)  # Works!

Slow performance on first call

The first manifold creation is slower due to KD-tree construction.

# Solution: Create manifold once and reuse
manifold = PythagoreanManifold(200)  # ~10-50ms

# Subsequent calls are fast
for _ in range(100000):
    manifold.snap(0.577, 0.816)  # ~100ns each

Getting Help


🌟 Ecosystem

Repo What It Does Key Features
constraint-theory-core 🦀 Rust crate ~100ns snap, SIMD batch, 82 tests
constraint-theory-python 🐍 This repo NumPy integration, PyTorch compatible
constraint-theory-web 🌐 Interactive demos 50 visualizations, zero setup
constraint-theory-research 📚 Mathematical foundations arXiv paper, proofs, open problems
constraint-ranch 🎮 Gamified learning Puzzle games, agent breeding
constraint-flow 💼 Business automation Exact financial calculations, workflow orchestration
constraint-theory-agent 🤖 Implementation agent Code audit, refactoring, expert explanations

Core Rust Library Features

The Python bindings are powered by a Rust core that provides:

  • O(log n) KD-tree lookup for nearest-neighbor search
  • SIMD optimization for batch processing
  • Zero-copy where possible for Python interop
  • Thread-safe immutable data structures

See constraint-theory-core for the Rust API.

Web Visualizations

Explore the manifold interactively at constraint-theory-web.pages.dev:

  • Visualize Pythagorean triple distribution on the unit circle
  • Interactive snapping demonstrations
  • Performance comparisons
  • Real-time density adjustment

Research Background

This library implements the mathematical framework described in:

  • "Deterministic Geometric Snapping via Pythagorean Manifolds" — core algorithm
  • "Cross-Platform Reproducibility in Scientific Computing" — applications
  • See constraint-theory-research for papers

📦 Install from Source

git clone https://github.com/SuperInstance/constraint-theory-python
cd constraint-theory-python

pip install maturin
maturin develop --release

🤝 Contributing

Good First Issues · CONTRIBUTING.md


📜 License

MIT — see LICENSE.


Stop debugging floating-point drift. Your competitors already did.

⭐ Star this repo · Try the live demo

Release files for constraint-theory 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for constraint-theory 1.0.1
File Size Uploaded
constraint_theory-1.0.1.tar.gz 545.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for constraint-theory 1.0.1
File Interpreter ABI Platform
constraint_theory-1.0.1-cp310-cp310-manylinux_2_35_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.35+ x86-64 Details

Total release size: 918.5 kB

Release files / constraint_theory-1.0.1.tar.gz

Download URL constraint_theory-1.0.1.tar.gz
Size 545.7 kB
Tags Source
SHA-256 checksum
How to use checksums
0551b6875af5a3297113538e62cf2cbdb2d54269febdd6caa85935e082fddbac
BLAKE2b-256 checksum
How to use checksums
bd8528a68bf7050c06675c790583f25a395667b251a4fe50858b80c87228c4cc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release files / constraint_theory-1.0.1-cp310-cp310-manylinux_2_35_x86_64.whl

Download URL constraint_theory-1.0.1-cp310-cp310-manylinux_2_35_x86_64.whl
Size 372.8 kB
Tags CPython 3.10 Linux glibc 2.35+ x86-64
SHA-256 checksum
How to use checksums
052ee32d6babb6439442051aaca58b6fa09d99f14d8def6d658e3ed2bd1ba9fa
BLAKE2b-256 checksum
How to use checksums
53c43a9a321cdfcae4df8141c35c460662503061eaf6999982d1514cec45db98
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.12

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

0.3.0

1 release file

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page