constraint-theory-distributed 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- constraint_theory_distributed-0.1.0/LICENSE +21 -0
- constraint_theory_distributed-0.1.0/PKG-INFO +234 -0
- constraint_theory_distributed-0.1.0/README.md +210 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/__init__.py +96 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/__main__.py +27 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/exercises.py +1227 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/genre_brain.py +219 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/holonomy.py +213 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/lattice.py +415 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/metronome.py +320 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/rigidity.py +378 -0
- constraint_theory_distributed-0.1.0/constraint_theory_core/temporal.py +224 -0
- constraint_theory_distributed-0.1.0/constraint_theory_distributed.egg-info/PKG-INFO +234 -0
- constraint_theory_distributed-0.1.0/constraint_theory_distributed.egg-info/SOURCES.txt +28 -0
- constraint_theory_distributed-0.1.0/constraint_theory_distributed.egg-info/dependency_links.txt +1 -0
- constraint_theory_distributed-0.1.0/constraint_theory_distributed.egg-info/requires.txt +6 -0
- constraint_theory_distributed-0.1.0/constraint_theory_distributed.egg-info/top_level.txt +1 -0
- constraint_theory_distributed-0.1.0/pyproject.toml +51 -0
- constraint_theory_distributed-0.1.0/setup.cfg +4 -0
- constraint_theory_distributed-0.1.0/tests/test_benchmark.py +134 -0
- constraint_theory_distributed-0.1.0/tests/test_edge_cases.py +282 -0
- constraint_theory_distributed-0.1.0/tests/test_exercises.py +201 -0
- constraint_theory_distributed-0.1.0/tests/test_holonomy.py +111 -0
- constraint_theory_distributed-0.1.0/tests/test_integration.py +274 -0
- constraint_theory_distributed-0.1.0/tests/test_lattice.py +127 -0
- constraint_theory_distributed-0.1.0/tests/test_metronome.py +140 -0
- constraint_theory_distributed-0.1.0/tests/test_property.py +427 -0
- constraint_theory_distributed-0.1.0/tests/test_rigidity.py +101 -0
- constraint_theory_distributed-0.1.0/tests/test_soft_snap.py +423 -0
- constraint_theory_distributed-0.1.0/tests/test_temporal.py +51 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PurplePincher
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: constraint-theory-distributed
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified geometric constraint theory — Eisenstein lattices, deadband funnels, Laman rigidity, holonomy consensus
|
|
5
|
+
Author-email: Forgemaster <forgemaster@superinstance.ai>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: constraint-theory,eisenstein,laman,rigidity,deadband,holonomy,distributed-systems
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: hypothesis>=6.0; extra == "dev"
|
|
21
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
22
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# constraint-theory-distributed
|
|
26
|
+
|
|
27
|
+
> Extracted from a stray `master` branch on
|
|
28
|
+
> [`purplepincher/constraint-theory-core`](https://github.com/purplepincher/constraint-theory-core)
|
|
29
|
+
> (a different, unrelated Rust crate) during an org-wide branch cleanup —
|
|
30
|
+
> this is real, separately-authored work that doesn't belong mixed into
|
|
31
|
+
> that repo's history. Full commit history preserved on extraction.
|
|
32
|
+
|
|
33
|
+
Unified mathematical library for constraint theory — Eisenstein lattices, deadband funnels, Laman rigidity, distributed consensus, and holonomy verification. Five composable modules. 308 tests (83 core + property/edge-case/benchmark suites). Zero external dependencies.
|
|
34
|
+
|
|
35
|
+
## What It Does
|
|
36
|
+
|
|
37
|
+
Every distributed system has constraints: agents must agree on time, sensors must stay within tolerance, and the communication graph must carry enough information without waste. This package provides the mathematical primitives that make those constraints precise and provable.
|
|
38
|
+
|
|
39
|
+
The five modules compose into a unified architecture:
|
|
40
|
+
|
|
41
|
+
- **Lattice** quantizes continuous space onto the Eisenstein A₂ lattice — every point is within ρ = 1/√3 of a lattice point, guaranteed by geometry.
|
|
42
|
+
- **Temporal** wraps that quantization in a narrowing deadband funnel — ε(t) = ε₀ · e^(−λt) — so drift converges to zero or triggers an anomaly.
|
|
43
|
+
- **Rigidity** ensures the communication graph is minimally rigid (Laman) — exactly 2n−3 edges, every edge load-bearing, no waste.
|
|
44
|
+
- **Metronome** drives distributed consensus across Laman-connected agents — tick, agree, correct with optimal coupling α* = 2/(λ₂ + λₙ).
|
|
45
|
+
- **Holonomy** verifies cycle consistency in tiled constraint systems — detects and isolates faults in O(log N) via binary bisection.
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
┌─────────────┐
|
|
51
|
+
│ Lattice │
|
|
52
|
+
│ (Eisenstein │
|
|
53
|
+
│ A₂ snap) │
|
|
54
|
+
└──────┬──────┘
|
|
55
|
+
│
|
|
56
|
+
┌────────────┼────────────┐
|
|
57
|
+
│ │ │
|
|
58
|
+
┌──────▼──────┐ │ ┌───────▼───────┐
|
|
59
|
+
│ Temporal │ │ │ Holonomy │
|
|
60
|
+
│ (deadband │ │ │ (cycle verify)│
|
|
61
|
+
│ funnel) │ │ └───────┬───────┘
|
|
62
|
+
└──────┬──────┘ │ │
|
|
63
|
+
│ │ │
|
|
64
|
+
┌──────▼───────────▼──┐ ┌─────▼─────────┐
|
|
65
|
+
│ Metronome │ │ Rigidity │
|
|
66
|
+
│ (distributed │ │ (Laman graph) │
|
|
67
|
+
│ consensus) │ └───────┬───────┘
|
|
68
|
+
└──────────┬──────────┘ │
|
|
69
|
+
│ │
|
|
70
|
+
└──────┬──────────────┘
|
|
71
|
+
│
|
|
72
|
+
optimal coupling α*
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Compositions:**
|
|
76
|
+
- **Lattice + Temporal = bounded drift** — snap to lattice, then narrow the deadband over time.
|
|
77
|
+
- **Rigidity + Holonomy = zero-comm consensus** — Laman topology ensures minimal edges; holonomy verifies every cycle closes.
|
|
78
|
+
- **All five = full metronome** — agents snap to lattice, narrow via temporal, couple via Laman rigidity, agree via metronome, verify via holonomy.
|
|
79
|
+
|
|
80
|
+
## Installation
|
|
81
|
+
|
|
82
|
+
Not yet published to PyPI. Install from source:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/purplepincher/constraint-theory-distributed.git
|
|
86
|
+
cd constraint-theory-distributed
|
|
87
|
+
pip install -e .
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Requires Python ≥ 3.10. No external dependencies.
|
|
91
|
+
|
|
92
|
+
## Quick Start
|
|
93
|
+
|
|
94
|
+
### Lattice — Snap to Eisenstein Lattice
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from constraint_theory_core import snap, covering_radius, is_safe
|
|
98
|
+
|
|
99
|
+
# Any point in the plane snaps to the nearest A₂ lattice point
|
|
100
|
+
pt, error = snap(0.5, 0.3)
|
|
101
|
+
print(f"Snapped to ({pt.a}, {pt.b}), error = {error:.4f}")
|
|
102
|
+
|
|
103
|
+
# Error is always ≤ 1/√3 ≈ 0.577 (covering radius guarantee)
|
|
104
|
+
assert error <= covering_radius()
|
|
105
|
+
|
|
106
|
+
# If error < 1/2√3 ≈ 0.289, the snap is unambiguous
|
|
107
|
+
print(f"Safe: {is_safe(error)}")
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Temporal — Deadband Funnel
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from constraint_theory_core.temporal import TemporalAgent, FunnelPhase
|
|
114
|
+
|
|
115
|
+
agent = TemporalAgent(decay_rate=0.1)
|
|
116
|
+
|
|
117
|
+
for t in range(1, 50):
|
|
118
|
+
result = agent.observe(0.01, 0.01, t=float(t))
|
|
119
|
+
print(f"t={t:2d} phase={result.phase.value:10s} ε={result.deadband:.4f} err={result.error:.4f}")
|
|
120
|
+
if result.phase == FunnelPhase.ANOMALY:
|
|
121
|
+
print(" ⚠ Anomaly detected!")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Rigidity — Laman Graphs
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from constraint_theory_core import henneberg_construct, is_laman, algebraic_connectivity, optimal_coupling
|
|
128
|
+
|
|
129
|
+
# Build a minimally rigid graph for 9 agents
|
|
130
|
+
edges = henneberg_construct(9)
|
|
131
|
+
print(f"Edges: {len(edges)} (expected {2*9-3})")
|
|
132
|
+
assert is_laman(9, edges)
|
|
133
|
+
|
|
134
|
+
# Compute convergence properties
|
|
135
|
+
lam2 = algebraic_connectivity(edges, 9)
|
|
136
|
+
alpha = optimal_coupling(edges, 9)
|
|
137
|
+
print(f"λ₂ = {lam2:.4f}, α* = {alpha:.4f}")
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Metronome — Distributed Consensus
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from constraint_theory_core import Metronome, henneberg_construct
|
|
144
|
+
import math
|
|
145
|
+
|
|
146
|
+
def neighbors_of(edges, i):
|
|
147
|
+
"""Neighbor indices for vertex i in an undirected edge list."""
|
|
148
|
+
return [v if u == i else u for u, v in edges if u == i or v == i]
|
|
149
|
+
|
|
150
|
+
# 9 agents on a Laman graph
|
|
151
|
+
edges = henneberg_construct(9)
|
|
152
|
+
agents = [
|
|
153
|
+
Metronome(T=1.0, phi0=math.pi * i / 9, epsilon=0.5, delta=0.6,
|
|
154
|
+
neighbors=neighbors_of(edges, i),
|
|
155
|
+
edges=edges, n_agents=9)
|
|
156
|
+
for i in range(9)
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
# Run consensus
|
|
160
|
+
for tick in range(100):
|
|
161
|
+
for agent in agents:
|
|
162
|
+
agent.tick()
|
|
163
|
+
phases = [a.phase for a in agents]
|
|
164
|
+
for agent in agents:
|
|
165
|
+
neighbor_phases = [phases[j] for j in agent.neighbors]
|
|
166
|
+
agent.correct(neighbor_phases)
|
|
167
|
+
|
|
168
|
+
# Check convergence
|
|
169
|
+
print(f"All converged: {all(a.converged for a in agents)}")
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Holonomy — Cycle Verification
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from constraint_theory_core import verify_consistency, isolate_fault, fault_boundaries
|
|
176
|
+
|
|
177
|
+
# Each tile = (edges, direction_indices)
|
|
178
|
+
tiles = [
|
|
179
|
+
([(0,1), (1,2), (2,0)], [16, 16, 16]), # consistent: 48 ≡ 0 mod 48
|
|
180
|
+
([(0,1), (1,3), (3,0)], [16, 16, 16]), # consistent
|
|
181
|
+
([(2,3), (3,4), (4,2)], [1, 2, 3]), # INCONSISTENT: 6 ≠ 0
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
print(f"All consistent: {verify_consistency(tiles)}") # False
|
|
185
|
+
print(f"First fault at index: {isolate_fault(tiles)}") # 2
|
|
186
|
+
print(f"All faults: {fault_boundaries(tiles)}") # [2]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Modules
|
|
190
|
+
|
|
191
|
+
| Module | What | Key Functions |
|
|
192
|
+
|--------|------|---------------|
|
|
193
|
+
| `lattice` | Eisenstein A₂ lattice | `snap`, `covering_radius`, `is_safe`, `A2Point`, `encode_dodecet`, `vector48_encode` |
|
|
194
|
+
| `temporal` | Deadband funnel | `TemporalAgent`, `FunnelPhase`, `FunnelResult` |
|
|
195
|
+
| `rigidity` | Laman graph topology | `is_laman`, `henneberg_construct`, `algebraic_connectivity`, `optimal_coupling` |
|
|
196
|
+
| `metronome` | Distributed consensus | `Metronome`, `MetronomeState` |
|
|
197
|
+
| `holonomy` | Cycle verification | `cycle_holonomy`, `verify_consistency`, `isolate_fault`, `fault_boundaries` |
|
|
198
|
+
|
|
199
|
+
## Equations
|
|
200
|
+
|
|
201
|
+
| Concept | Equation | Meaning |
|
|
202
|
+
|---------|----------|---------|
|
|
203
|
+
| A₂ covering radius | ρ = 1/√3 ≈ 0.577 | Max distance from any point to nearest lattice point |
|
|
204
|
+
| Safe threshold | ρ/2 ≈ 0.289 | Below this, snap is unambiguous |
|
|
205
|
+
| Eisenstein norm | ‖(a,b)‖² = a² − ab + b² | Squared norm on the lattice |
|
|
206
|
+
| Deadband decay | ε(t) = ε₀ · e^(−λt) | Funnel narrows exponentially |
|
|
207
|
+
| Laman condition | \|E\| = 2n − 3 | Exactly the right number of edges |
|
|
208
|
+
| Algebraic connectivity | λ₂ (2nd Laplacian eigenvalue) | Convergence rate of consensus |
|
|
209
|
+
| Optimal coupling | α* = 2/(λ₂ + λₙ) | Fastest convergence without oscillation |
|
|
210
|
+
| Holonomy | Σ directions mod 48 | 0 means cycle closes exactly |
|
|
211
|
+
|
|
212
|
+
## Testing
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
pip install -e ".[dev]"
|
|
216
|
+
pytest # 308 tests (83 core + property/edge-case/benchmark suites)
|
|
217
|
+
pytest -v --tb=short # verbose
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Documentation
|
|
221
|
+
|
|
222
|
+
- [User Guide](docs/USER-GUIDE.md) — Complete usage documentation
|
|
223
|
+
- [Developer Guide](docs/DEVELOPER-GUIDE.md) — Contributing and internals
|
|
224
|
+
- [Examples](examples/) — Working code examples
|
|
225
|
+
|
|
226
|
+
## Related Projects
|
|
227
|
+
|
|
228
|
+
- [flux-tensor-midi](https://github.com/SuperInstance/flux-tensor-midi) — Musical constraint theory
|
|
229
|
+
- [plato](https://github.com/SuperInstance/plato) — PLATO tiling architecture
|
|
230
|
+
- [forgemaster](https://github.com/SuperInstance/forgemaster) — Constraint-theory specialist agent
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# constraint-theory-distributed
|
|
2
|
+
|
|
3
|
+
> Extracted from a stray `master` branch on
|
|
4
|
+
> [`purplepincher/constraint-theory-core`](https://github.com/purplepincher/constraint-theory-core)
|
|
5
|
+
> (a different, unrelated Rust crate) during an org-wide branch cleanup —
|
|
6
|
+
> this is real, separately-authored work that doesn't belong mixed into
|
|
7
|
+
> that repo's history. Full commit history preserved on extraction.
|
|
8
|
+
|
|
9
|
+
Unified mathematical library for constraint theory — Eisenstein lattices, deadband funnels, Laman rigidity, distributed consensus, and holonomy verification. Five composable modules. 308 tests (83 core + property/edge-case/benchmark suites). Zero external dependencies.
|
|
10
|
+
|
|
11
|
+
## What It Does
|
|
12
|
+
|
|
13
|
+
Every distributed system has constraints: agents must agree on time, sensors must stay within tolerance, and the communication graph must carry enough information without waste. This package provides the mathematical primitives that make those constraints precise and provable.
|
|
14
|
+
|
|
15
|
+
The five modules compose into a unified architecture:
|
|
16
|
+
|
|
17
|
+
- **Lattice** quantizes continuous space onto the Eisenstein A₂ lattice — every point is within ρ = 1/√3 of a lattice point, guaranteed by geometry.
|
|
18
|
+
- **Temporal** wraps that quantization in a narrowing deadband funnel — ε(t) = ε₀ · e^(−λt) — so drift converges to zero or triggers an anomaly.
|
|
19
|
+
- **Rigidity** ensures the communication graph is minimally rigid (Laman) — exactly 2n−3 edges, every edge load-bearing, no waste.
|
|
20
|
+
- **Metronome** drives distributed consensus across Laman-connected agents — tick, agree, correct with optimal coupling α* = 2/(λ₂ + λₙ).
|
|
21
|
+
- **Holonomy** verifies cycle consistency in tiled constraint systems — detects and isolates faults in O(log N) via binary bisection.
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
┌─────────────┐
|
|
27
|
+
│ Lattice │
|
|
28
|
+
│ (Eisenstein │
|
|
29
|
+
│ A₂ snap) │
|
|
30
|
+
└──────┬──────┘
|
|
31
|
+
│
|
|
32
|
+
┌────────────┼────────────┐
|
|
33
|
+
│ │ │
|
|
34
|
+
┌──────▼──────┐ │ ┌───────▼───────┐
|
|
35
|
+
│ Temporal │ │ │ Holonomy │
|
|
36
|
+
│ (deadband │ │ │ (cycle verify)│
|
|
37
|
+
│ funnel) │ │ └───────┬───────┘
|
|
38
|
+
└──────┬──────┘ │ │
|
|
39
|
+
│ │ │
|
|
40
|
+
┌──────▼───────────▼──┐ ┌─────▼─────────┐
|
|
41
|
+
│ Metronome │ │ Rigidity │
|
|
42
|
+
│ (distributed │ │ (Laman graph) │
|
|
43
|
+
│ consensus) │ └───────┬───────┘
|
|
44
|
+
└──────────┬──────────┘ │
|
|
45
|
+
│ │
|
|
46
|
+
└──────┬──────────────┘
|
|
47
|
+
│
|
|
48
|
+
optimal coupling α*
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Compositions:**
|
|
52
|
+
- **Lattice + Temporal = bounded drift** — snap to lattice, then narrow the deadband over time.
|
|
53
|
+
- **Rigidity + Holonomy = zero-comm consensus** — Laman topology ensures minimal edges; holonomy verifies every cycle closes.
|
|
54
|
+
- **All five = full metronome** — agents snap to lattice, narrow via temporal, couple via Laman rigidity, agree via metronome, verify via holonomy.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
Not yet published to PyPI. Install from source:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
git clone https://github.com/purplepincher/constraint-theory-distributed.git
|
|
62
|
+
cd constraint-theory-distributed
|
|
63
|
+
pip install -e .
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Requires Python ≥ 3.10. No external dependencies.
|
|
67
|
+
|
|
68
|
+
## Quick Start
|
|
69
|
+
|
|
70
|
+
### Lattice — Snap to Eisenstein Lattice
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from constraint_theory_core import snap, covering_radius, is_safe
|
|
74
|
+
|
|
75
|
+
# Any point in the plane snaps to the nearest A₂ lattice point
|
|
76
|
+
pt, error = snap(0.5, 0.3)
|
|
77
|
+
print(f"Snapped to ({pt.a}, {pt.b}), error = {error:.4f}")
|
|
78
|
+
|
|
79
|
+
# Error is always ≤ 1/√3 ≈ 0.577 (covering radius guarantee)
|
|
80
|
+
assert error <= covering_radius()
|
|
81
|
+
|
|
82
|
+
# If error < 1/2√3 ≈ 0.289, the snap is unambiguous
|
|
83
|
+
print(f"Safe: {is_safe(error)}")
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Temporal — Deadband Funnel
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from constraint_theory_core.temporal import TemporalAgent, FunnelPhase
|
|
90
|
+
|
|
91
|
+
agent = TemporalAgent(decay_rate=0.1)
|
|
92
|
+
|
|
93
|
+
for t in range(1, 50):
|
|
94
|
+
result = agent.observe(0.01, 0.01, t=float(t))
|
|
95
|
+
print(f"t={t:2d} phase={result.phase.value:10s} ε={result.deadband:.4f} err={result.error:.4f}")
|
|
96
|
+
if result.phase == FunnelPhase.ANOMALY:
|
|
97
|
+
print(" ⚠ Anomaly detected!")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Rigidity — Laman Graphs
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from constraint_theory_core import henneberg_construct, is_laman, algebraic_connectivity, optimal_coupling
|
|
104
|
+
|
|
105
|
+
# Build a minimally rigid graph for 9 agents
|
|
106
|
+
edges = henneberg_construct(9)
|
|
107
|
+
print(f"Edges: {len(edges)} (expected {2*9-3})")
|
|
108
|
+
assert is_laman(9, edges)
|
|
109
|
+
|
|
110
|
+
# Compute convergence properties
|
|
111
|
+
lam2 = algebraic_connectivity(edges, 9)
|
|
112
|
+
alpha = optimal_coupling(edges, 9)
|
|
113
|
+
print(f"λ₂ = {lam2:.4f}, α* = {alpha:.4f}")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Metronome — Distributed Consensus
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from constraint_theory_core import Metronome, henneberg_construct
|
|
120
|
+
import math
|
|
121
|
+
|
|
122
|
+
def neighbors_of(edges, i):
|
|
123
|
+
"""Neighbor indices for vertex i in an undirected edge list."""
|
|
124
|
+
return [v if u == i else u for u, v in edges if u == i or v == i]
|
|
125
|
+
|
|
126
|
+
# 9 agents on a Laman graph
|
|
127
|
+
edges = henneberg_construct(9)
|
|
128
|
+
agents = [
|
|
129
|
+
Metronome(T=1.0, phi0=math.pi * i / 9, epsilon=0.5, delta=0.6,
|
|
130
|
+
neighbors=neighbors_of(edges, i),
|
|
131
|
+
edges=edges, n_agents=9)
|
|
132
|
+
for i in range(9)
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
# Run consensus
|
|
136
|
+
for tick in range(100):
|
|
137
|
+
for agent in agents:
|
|
138
|
+
agent.tick()
|
|
139
|
+
phases = [a.phase for a in agents]
|
|
140
|
+
for agent in agents:
|
|
141
|
+
neighbor_phases = [phases[j] for j in agent.neighbors]
|
|
142
|
+
agent.correct(neighbor_phases)
|
|
143
|
+
|
|
144
|
+
# Check convergence
|
|
145
|
+
print(f"All converged: {all(a.converged for a in agents)}")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Holonomy — Cycle Verification
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from constraint_theory_core import verify_consistency, isolate_fault, fault_boundaries
|
|
152
|
+
|
|
153
|
+
# Each tile = (edges, direction_indices)
|
|
154
|
+
tiles = [
|
|
155
|
+
([(0,1), (1,2), (2,0)], [16, 16, 16]), # consistent: 48 ≡ 0 mod 48
|
|
156
|
+
([(0,1), (1,3), (3,0)], [16, 16, 16]), # consistent
|
|
157
|
+
([(2,3), (3,4), (4,2)], [1, 2, 3]), # INCONSISTENT: 6 ≠ 0
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
print(f"All consistent: {verify_consistency(tiles)}") # False
|
|
161
|
+
print(f"First fault at index: {isolate_fault(tiles)}") # 2
|
|
162
|
+
print(f"All faults: {fault_boundaries(tiles)}") # [2]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Modules
|
|
166
|
+
|
|
167
|
+
| Module | What | Key Functions |
|
|
168
|
+
|--------|------|---------------|
|
|
169
|
+
| `lattice` | Eisenstein A₂ lattice | `snap`, `covering_radius`, `is_safe`, `A2Point`, `encode_dodecet`, `vector48_encode` |
|
|
170
|
+
| `temporal` | Deadband funnel | `TemporalAgent`, `FunnelPhase`, `FunnelResult` |
|
|
171
|
+
| `rigidity` | Laman graph topology | `is_laman`, `henneberg_construct`, `algebraic_connectivity`, `optimal_coupling` |
|
|
172
|
+
| `metronome` | Distributed consensus | `Metronome`, `MetronomeState` |
|
|
173
|
+
| `holonomy` | Cycle verification | `cycle_holonomy`, `verify_consistency`, `isolate_fault`, `fault_boundaries` |
|
|
174
|
+
|
|
175
|
+
## Equations
|
|
176
|
+
|
|
177
|
+
| Concept | Equation | Meaning |
|
|
178
|
+
|---------|----------|---------|
|
|
179
|
+
| A₂ covering radius | ρ = 1/√3 ≈ 0.577 | Max distance from any point to nearest lattice point |
|
|
180
|
+
| Safe threshold | ρ/2 ≈ 0.289 | Below this, snap is unambiguous |
|
|
181
|
+
| Eisenstein norm | ‖(a,b)‖² = a² − ab + b² | Squared norm on the lattice |
|
|
182
|
+
| Deadband decay | ε(t) = ε₀ · e^(−λt) | Funnel narrows exponentially |
|
|
183
|
+
| Laman condition | \|E\| = 2n − 3 | Exactly the right number of edges |
|
|
184
|
+
| Algebraic connectivity | λ₂ (2nd Laplacian eigenvalue) | Convergence rate of consensus |
|
|
185
|
+
| Optimal coupling | α* = 2/(λ₂ + λₙ) | Fastest convergence without oscillation |
|
|
186
|
+
| Holonomy | Σ directions mod 48 | 0 means cycle closes exactly |
|
|
187
|
+
|
|
188
|
+
## Testing
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pip install -e ".[dev]"
|
|
192
|
+
pytest # 308 tests (83 core + property/edge-case/benchmark suites)
|
|
193
|
+
pytest -v --tb=short # verbose
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Documentation
|
|
197
|
+
|
|
198
|
+
- [User Guide](docs/USER-GUIDE.md) — Complete usage documentation
|
|
199
|
+
- [Developer Guide](docs/DEVELOPER-GUIDE.md) — Contributing and internals
|
|
200
|
+
- [Examples](examples/) — Working code examples
|
|
201
|
+
|
|
202
|
+
## Related Projects
|
|
203
|
+
|
|
204
|
+
- [flux-tensor-midi](https://github.com/SuperInstance/flux-tensor-midi) — Musical constraint theory
|
|
205
|
+
- [plato](https://github.com/SuperInstance/plato) — PLATO tiling architecture
|
|
206
|
+
- [forgemaster](https://github.com/SuperInstance/forgemaster) — Constraint-theory specialist agent
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
constraint_theory_core — unified geometric constraint theory.
|
|
3
|
+
|
|
4
|
+
The one package that brings together:
|
|
5
|
+
- Eisenstein A₂ lattice quantization
|
|
6
|
+
- Deadband temporal funnels
|
|
7
|
+
- Laman rigidity for topology
|
|
8
|
+
- Metronome consensus
|
|
9
|
+
- Holonomy consistency verification
|
|
10
|
+
|
|
11
|
+
All constants derived from first principles. Zero external dependencies.
|
|
12
|
+
|
|
13
|
+
Example
|
|
14
|
+
-------
|
|
15
|
+
>>> from constraint_theory_core import snap, covering_radius, is_safe
|
|
16
|
+
>>> pt, err = snap(0.5, 0.3)
|
|
17
|
+
>>> is_safe(err)
|
|
18
|
+
True
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from .exercises import (
|
|
22
|
+
generate_exercise,
|
|
23
|
+
)
|
|
24
|
+
from .genre_brain import (
|
|
25
|
+
GenreEpsilons,
|
|
26
|
+
custom_genre,
|
|
27
|
+
get_genre,
|
|
28
|
+
list_genres,
|
|
29
|
+
sweep_genre,
|
|
30
|
+
)
|
|
31
|
+
from .holonomy import (
|
|
32
|
+
cycle_holonomy,
|
|
33
|
+
fault_boundaries,
|
|
34
|
+
isolate_fault,
|
|
35
|
+
soft_verify_consistency,
|
|
36
|
+
verify_consistency,
|
|
37
|
+
)
|
|
38
|
+
from .lattice import (
|
|
39
|
+
COVERING_RADIUS,
|
|
40
|
+
DIRECTION_COUNT,
|
|
41
|
+
DODECET_DIRECTIONS, # noqa: F401 — re-exported for external use
|
|
42
|
+
SAFE_THRESHOLD,
|
|
43
|
+
SQRT_3,
|
|
44
|
+
A2Point,
|
|
45
|
+
covering_radius,
|
|
46
|
+
decode_dodecet,
|
|
47
|
+
encode_dodecet,
|
|
48
|
+
holonomy_product,
|
|
49
|
+
is_consistent,
|
|
50
|
+
is_safe,
|
|
51
|
+
norm_sq,
|
|
52
|
+
snap,
|
|
53
|
+
soft_snap,
|
|
54
|
+
vector48_decode,
|
|
55
|
+
vector48_encode,
|
|
56
|
+
)
|
|
57
|
+
from .metronome import (
|
|
58
|
+
Metronome,
|
|
59
|
+
MetronomeState,
|
|
60
|
+
)
|
|
61
|
+
from .rigidity import (
|
|
62
|
+
algebraic_connectivity,
|
|
63
|
+
henneberg_construct,
|
|
64
|
+
is_laman,
|
|
65
|
+
optimal_coupling,
|
|
66
|
+
soft_rigidity,
|
|
67
|
+
)
|
|
68
|
+
from .temporal import (
|
|
69
|
+
FunnelPhase,
|
|
70
|
+
FunnelResult,
|
|
71
|
+
TemporalAgent,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
__version__ = "0.1.0"
|
|
75
|
+
|
|
76
|
+
__all__ = [
|
|
77
|
+
# Lattice
|
|
78
|
+
"A2Point", "snap", "soft_snap", "covering_radius", "is_safe", "norm_sq",
|
|
79
|
+
"decode_dodecet", "encode_dodecet", "vector48_encode", "vector48_decode",
|
|
80
|
+
"holonomy_product", "is_consistent",
|
|
81
|
+
"COVERING_RADIUS", "SAFE_THRESHOLD", "SQRT_3", "DIRECTION_COUNT",
|
|
82
|
+
# Temporal
|
|
83
|
+
"TemporalAgent", "FunnelPhase", "FunnelResult",
|
|
84
|
+
# Rigidity
|
|
85
|
+
"is_laman", "henneberg_construct", "algebraic_connectivity", "optimal_coupling", "soft_rigidity",
|
|
86
|
+
# Metronome
|
|
87
|
+
"Metronome", "MetronomeState",
|
|
88
|
+
# Holonomy
|
|
89
|
+
"cycle_holonomy", "verify_consistency", "soft_verify_consistency", "isolate_fault", "fault_boundaries",
|
|
90
|
+
# Genre Brain
|
|
91
|
+
"GenreEpsilons", "get_genre", "list_genres", "custom_genre", "sweep_genre",
|
|
92
|
+
# Exercises
|
|
93
|
+
"generate_exercise",
|
|
94
|
+
# Meta
|
|
95
|
+
"__version__",
|
|
96
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""CLI entry-point: ``python -m constraint_theory_core <subcommand>``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main() -> None:
|
|
9
|
+
if len(sys.argv) < 2:
|
|
10
|
+
print("Usage: python -m constraint_theory_core <subcommand> [options]")
|
|
11
|
+
print("Subcommands: exercise")
|
|
12
|
+
sys.exit(1)
|
|
13
|
+
|
|
14
|
+
subcommand = sys.argv[1]
|
|
15
|
+
rest = sys.argv[2:]
|
|
16
|
+
|
|
17
|
+
if subcommand == "exercise":
|
|
18
|
+
from .exercises import _cli_exercise
|
|
19
|
+
_cli_exercise(rest)
|
|
20
|
+
else:
|
|
21
|
+
print(f"Unknown subcommand: {subcommand!r}")
|
|
22
|
+
print("Available: exercise")
|
|
23
|
+
sys.exit(1)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
if __name__ == "__main__":
|
|
27
|
+
main()
|