Repository: https://github.com/SuperInstance/constraint-theory-python Language: Python (PyO3 bindings to Rust core) Version: 0.1.0 Last Updated: 2025-01-27
This repository provides Python bindings for Constraint Theory, enabling exact constraint satisfaction in Python applications including NumPy workflows.
- Installation and setup
- Core API usage
- NumPy integration
- Practical applications
- Performance optimization
- Python 3.8+
- pip or conda
- NumPy 1.20+ (for batch processing)
- PyTorch 2.0+ or TensorFlow 2.10+ (for ML integration patterns)
pip install constraint-theory# Clone repository
git clone https://github.com/SuperInstance/constraint-theory-python.git
cd constraint-theory-python
# Install with maturin (for development)
pip install maturin
maturin develop --releaseimport constraint_theory
print(f"Version: {constraint_theory.__version__}")
# Quick test
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=200)
print(f"Manifold has {manifold.state_count} states")
# Output: Manifold has 1013 statesfrom constraint_theory import PythagoreanManifold
# Create a manifold - the density parameter controls resolution
# Higher density = more exact states = finer resolution
manifold = PythagoreanManifold(density=200)
# Snap a point to the nearest Pythagorean triple
# Input: (0.577, 0.816) - approximate direction
# Output: (0.6, 0.8) - exact 3-4-5 triangle normalized
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.0236from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=200)
# Test vectors with different characteristics
test_cases = [
("Exact 3-4-5", (0.6, 0.8)), # Should snap exactly
("Exact 5-12-13", (0.384615, 0.923077)),
("Near 45°", (0.707, 0.707)), # Approximate
("Arbitrary", (0.543, 0.839)), # Random direction
]
for name, (x, y) in test_cases:
sx, sy, noise = manifold.snap(x, y)
print(f"{name}: ({x:.3f}, {y:.3f}) -> ({sx:.4f}, {sy:.4f}), noise={noise:.6f}")import numpy as np
from constraint_theory import PythagoreanManifold
# Create manifold
manifold = PythagoreanManifold(density=200)
# Generate random unit vectors
np.random.seed(42)
angles = np.random.uniform(0, 2 * np.pi, 1000)
vectors = np.column_stack([np.cos(angles), np.sin(angles)])
# Snap all vectors efficiently
results = manifold.snap_batch(vectors)
# Analyze results
snapped = np.array([[sx, sy] for sx, sy, _ in results])
noises = np.array([noise for _, _, noise in results])
print(f"Mean noise: {noises.mean():.6f}")
print(f"Max noise: {noises.max():.6f}")The PythagoreanManifold contains pre-computed normalized Pythagorean triples (a/c, b/c) where a² + b² = c². Each state represents an exact point on the unit circle.
from constraint_theory import PythagoreanManifold
# Density controls the maximum hypotenuse in Euclid's formula
# Higher density = more states = better resolution
manifold = PythagoreanManifold(density=200)
print(f"Total states: {manifold.state_count}")
# Each state is a point (x, y) where x² + y² = 1 EXACTLYDensity Guidelines:
| Density | Approximate States | Resolution | Use Case |
|---|---|---|---|
| 50 | ~250 | 0.02 | Quick prototypes |
| 100 | ~500 | 0.01 | Game physics |
| 200 | ~1000 | 0.005 | General purpose |
| 500 | ~2500 | 0.002 | ML augmentation |
| 1000 | ~5000 | 0.001 | Scientific computing |
The snapping algorithm uses a KD-tree for O(log n) lookup:
Input: (x, y) - any 2D vector
↓
Normalize: (x/|v|, y/|v|) - project to unit circle
↓
KD-Tree: O(log n) nearest neighbor search
↓
Output: (sx, sy, noise) - exact Pythagorean state + distance
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=200)
# Same input ALWAYS produces same output
for _ in range(5):
x, y, noise = manifold.snap(0.577, 0.816)
print(f"Result: ({x:.6f}, {y:.6f})")
# All outputs are IDENTICAL - deterministic!import numpy as np
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=200)
# Create vectors as NumPy array
vectors = np.array([
[0.6, 0.8],
[0.707, 0.707],
[0.1, 0.995],
], dtype=np.float32)
# snap_batch accepts NumPy arrays directly
results = manifold.snap_batch(vectors)
for i, (sx, sy, noise) in enumerate(results):
print(f"[{i}] ({vectors[i,0]:.3f}, {vectors[i,1]:.3f}) -> ({sx:.4f}, {sy:.4f})")import numpy as np
import time
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=500)
# Generate 100,000 random unit vectors
n = 100000
angles = np.random.uniform(0, 2 * np.pi, n)
vectors = np.column_stack([np.cos(angles), np.sin(angles)]).astype(np.float32)
# Process with timing
start = time.time()
results = manifold.snap_batch(vectors)
elapsed = time.time() - start
print(f"Processed {n:,} vectors in {elapsed*1000:.2f}ms")
print(f"Throughput: {n/elapsed:,.0f} vectors/second")
# Analyze noise distribution
noises = np.array([noise for _, _, noise in results])
print(f"Mean noise: {noises.mean():.6f}")
print(f"Max noise: {noises.max():.6f}")import numpy as np
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=200)
# Old way: floating-point normalization
def old_normalize(v):
return v / np.linalg.norm(v)
# New way: exact Pythagorean snapping
def exact_direction(x, y, manifold):
sx, sy, noise = manifold.snap(x, y)
return sx, sy, noise
# Compare
v = np.array([3, 4])
normalized = old_normalize(v)
print(f"Float normalization: ({normalized[0]:.10f}, {normalized[1]:.10f})")
# Note: 0.6 and 0.8 may have floating-point representation errors
sx, sy, noise = exact_direction(3, 4, manifold)
print(f"Exact snapping: ({sx:.10f}, {sy:.10f})")
# These are EXACT Pythagorean valuesWhile the core library provides geometric snapping, here are patterns for ML integration:
import numpy as np
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=500)
def augment_gradient(dx, dy):
"""Deterministic gradient augmentation for training."""
sx, sy, noise = manifold.snap(dx, dy)
# Return exact direction - reproducible across runs
return sx, sy
# Use in training loop for reproducible augmentation
gradients = np.random.randn(1000, 2)
augmented = [augment_gradient(g[0], g[1]) for g in gradients]import numpy as np
from constraint_theory import PythagoreanManifold
def quantize_directions(weights_2d, manifold):
"""Quantize 2D weight directions to exact Pythagorean states."""
# Normalize weights
norms = np.linalg.norm(weights_2d, axis=1, keepdims=True)
normalized = weights_2d / norms
# Snap to exact
results = manifold.snap_batch(normalized)
# Reconstruct with original magnitudes
quantized = np.array([[sx, sy] for sx, sy, _ in results])
return quantized * norms
# Example usage
manifold = PythagoreanManifold(density=200)
weights = np.random.randn(100, 2)
quantized = quantize_directions(weights, manifold)import torch
import numpy as np
from constraint_theory import PythagoreanManifold
class ExactDirectionLayer(torch.nn.Module):
"""Custom layer that snaps outputs to exact Pythagorean directions."""
def __init__(self, density=200):
super().__init__()
self.manifold = PythagoreanManifold(density)
def forward(self, x):
# x: (batch, 2) tensor
with torch.no_grad():
# Convert to numpy, snap, convert back
np_x = x.detach().cpu().numpy()
results = self.manifold.snap_batch(np_x)
snapped = np.array([[sx, sy] for sx, sy, _ in results])
return torch.from_numpy(snapped).to(x.device)
# Usage
layer = ExactDirectionLayer(density=200)
output = layer(torch.randn(32, 2))from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=150)
def process_player_input(vx, vy):
"""Convert player input to exact direction for networked physics."""
dx, dy, noise = manifold.snap(vx, vy)
return dx, dy # Same on ALL clients - no reconciliation needed
# All clients see identical physics
direction = process_player_input(0.7, 0.7)
print(f"Exact direction: {direction}")import numpy as np
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=300)
def monte_carlo_directions(n_samples, seed=42):
"""Generate reproducible random directions for Monte Carlo."""
np.random.seed(seed)
angles = np.random.uniform(0, 2 * np.pi, n_samples)
raw_directions = np.column_stack([np.cos(angles), np.sin(angles)])
# Snap to exact - reproducible on any platform
results = manifold.snap_batch(raw_directions)
return [(sx, sy) for sx, sy, _ in results]
# Same results on laptop, server, cluster
directions = monte_carlo_directions(10000)import math
from constraint_theory import PythagoreanManifold
manifold = PythagoreanManifold(density=200)
def navigate_toward(current, target):
"""Calculate exact heading toward target."""
dx = target[0] - current[0]
dy = target[1] - current[1]
# Get exact direction
sx, sy, noise = manifold.snap(dx, dy)
heading = math.degrees(math.atan2(sy, sx))
return heading, (sx, sy)
# Robot navigation with exact headings
heading, direction = navigate_toward((0, 0), (3, 4))
print(f"Heading: {heading:.2f}°, Direction: {direction}")class PythagoreanManifold:
"""Constraint manifold with Pythagorean lattice snapping."""
def __init__(self, density: int):
"""
Initialize manifold with specified density.
Args:
density: Maximum value of m in Euclid's formula.
Higher = more states = finer resolution.
"""
def snap(self, x: float, y: float) -> tuple[float, float, float]:
"""
Snap single vector to nearest Pythagorean triple.
Returns:
(snapped_x, snapped_y, noise) where noise is distance
from input to snapped point.
"""
def snap_batch(self, vectors) -> list[tuple[float, float, float]]:
"""
Snap multiple vectors efficiently.
Args:
vectors: List of [x, y] pairs or Nx2 NumPy array
Returns:
List of (snapped_x, snapped_y, noise) tuples
"""
@property
def state_count(self) -> int:
"""Number of exact Pythagorean states in the manifold."""def snap(manifold: PythagoreanManifold, x: float, y: float) -> tuple[float, float, float]:
"""Convenience function for one-off snapping."""
def generate_triples(max_c: int) -> list[tuple[int, int, int]]:
"""
Generate primitive Pythagorean triples with hypotenuse <= max_c.
Returns:
List of (a, b, c) tuples where a² + b² = c²
"""| Operation | Time | Throughput |
|---|---|---|
| Single snap | ~100 ns | 10M/sec |
| Batch 1,000 | ~74 μs | 13M/sec |
| Batch 10,000 | ~740 μs | 13M/sec |
| Batch 100,000 | ~7.4 ms | 13M/sec |
| Density | States | Memory |
|---|---|---|
| 100 | ~500 | ~40 KB |
| 200 | ~1000 | ~80 KB |
| 500 | ~2500 | ~200 KB |
| 1000 | ~5000 | ~400 KB |
- Reuse manifold instances - Construction is expensive
- Use batch operations - 2-5x faster than individual snaps
- Choose appropriate density - Balance resolution vs. memory
- Process in chunks - For very large datasets (>100K)
1. Import Error
ImportError: cannot import name 'PythagoreanManifold'
Solution: Ensure proper installation
pip install --upgrade constraint-theory2. Construction Error
RuntimeError: density must be positive
Solution: Use positive density values
manifold = PythagoreanManifold(density=200) # Correct3. Wrong API Usage
# WRONG - dimensions parameter doesn't exist
manifold = PythagoreanManifold(dimensions=2)
# CORRECT - use density parameter
manifold = PythagoreanManifold(density=200)4. NumPy Array Shape
# WRONG - 1D array
vectors = np.array([0.6, 0.8, 0.707, 0.707])
# CORRECT - Nx2 array
vectors = np.array([[0.6, 0.8], [0.707, 0.707]])- constraint-theory-core - Rust implementation
- constraint-theory-web - Interactive demos
- constraint-theory-research - Mathematical foundations
Run the included examples:
# Clone repository
git clone https://github.com/SuperInstance/constraint-theory-python.git
cd constraint-theory-python
# Run examples
python examples/quickstart.py
python examples/basic_usage.py
python examples/numpy_integration.py
python examples/batch_processing.py
python examples/game_dev.py
python examples/scientific.py
python examples/robotics.py# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/
# Build from source
maturin develop --releaseMIT License - See LICENSE for details.
- ✅ Install the package
- ✅ Run the quickstart example
- 📖 Explore the examples
- 🚀 Integrate into your project!
Happy coding with exact constraints! 🎉