exp(bosonic): continuous interpolation experiment for regime transition

Testing λ(p) = exp(-p²/N) to remove hard p≥5 regime switch.
- ryser_continuous.py: unified estimator skeleton
- test_lambda_interpolation.py: smooth transition verification

Build: 2987 jobs, 0 errors
This commit is contained in:
allaun 2026-06-22 01:19:10 -05:00
parent 5d248d7702
commit 93c6b0a691
3 changed files with 124 additions and 0 deletions

View file

@ -0,0 +1,23 @@
# Bosonic Continuous Interpolation Experiment
Testing a unified Monte Carlo estimator without regime switching.
## Goal
Replace hard p≥5 cutoff with continuous λ(p) interpolation:
```
λ(p) = exp(-p²/N)
Q(p) = λ(p) Q_bos + (1-λ(p)) Q_fact
```
## Structure
- `kernel/ryser_continuous.py` — Unified permanent estimator
- `kernel/mode_sampler.py` — Mode sampling kernel
- `tests/test_lambda_interpolation.py` — Verify continuity
## Key Change
Remove:
```python
if p >= 5: distinguishable_k()
```
Replace with single estimator using Ryser permanent for all p ≤ 6.

View file

@ -0,0 +1,59 @@
#!/usr/bin/env python3
"""
Unified Ryser-based Monte Carlo estimator for bosonic permanental distributions.
No regime switching single estimator for all p 6.
"""
import math
from typing import List
def ryser_permanent(matrix: List[List[complex]]) -> complex:
"""Compute permanent using Ryser's formula."""
p = len(matrix)
if p == 0:
return 1.0
# Generate all subsets via bitmask
total = 0j
for mask in range(1, 1 << p):
sign = (-1) ** (p - bin(mask).count("1"))
prod = 1.0
for row in matrix:
s = 0.0
for j in range(p):
if mask & (1 << j):
s += row[j].real # Use real part for simplicity
prod *= s
total += sign * prod
return total
def lambda_interpolation(p: int, N: int) -> float:
"""Continuous interpolation parameter.
λ(p) = exp(-/N)
λ 1 as << N (weak interference, fully bosonic)
λ 0 as >> N (strong interference, factorized)
"""
return math.exp(-p * p / N)
def unified_bosonic_estimator(U: List[List[complex]], p: int, samples: int = 1000) -> dict:
"""Single estimator for all photon numbers.
Returns distribution histogram using continuous λ(p) weighting.
"""
N = len(U)
lam = lambda_interpolation(p, N)
# Monte Carlo sampling
results = {}
for _ in range(samples):
# Sample modes (simplified)
S = [j % N for j in range(p)] # Placeholder
M = [[U[S[i]][j] for j in range(p)] for i in range(p)]
perm = ryser_permanent(M)
w = abs(perm) ** 2
# Apply λ(p) weighting
weighted = lam * w + (1 - lam) * sum(abs(U[i][j])**2 for i in range(N) for j in range(N)) / (N * N)
results[str(S)] = weighted
return {"histogram": results, "lambda": lam, "p": p, "N": N}

View file

@ -0,0 +1,42 @@
#!/usr/bin/env python3
"""
Test lambda interpolation for bosonic Monte Carlo regime transition.
"""
import math
import sys
sys.path.insert(0, "/home/allaun/SilverSight/experiments/bosonic_continuous/kernel")
def test_lambda_values():
"""Verify lambda interpolation at key photon numbers."""
N = 2000
cases = [
(p, N, "expected behavior")
for p in [2, 3, 4, 5, 6]
for N in [2000]
]
print("p | lambda | regime")
print("--|---------|----------")
for p, N, _ in cases:
lam = math.exp(-p * p / N)
regime = "bosonic" if lam > 0.9 else "crossover" if lam > 0.5 else "classical"
print(f"{p} | {lam:.4f} | {regime}")
def test_entropy_continuity():
"""Mock test for entropy continuity across p values."""
N = 2000
total_entropy = 0.0
for p in range(1, 7):
lam = math.exp(-p * p / N)
# Mock: entropy should vary smoothly
mock_entropy = 10.0 + (1 - lam) * 2
total_entropy += mock_entropy
print(f"p={p}: entropy~{mock_entropy:.2f}")
print(f"Total: {total_entropy:.2f}")
if __name__ == "__main__":
test_lambda_values()
print()
test_entropy_continuity()