feat: add SC-LDPC density evolution with threshold computation
Implement position-aware density evolution for SC-LDPC codes: - sc_density_evolution(): flooding-schedule DE tracking per-position error rates, demonstrating the wave decoding effect - compute_sc_threshold(): binary search for SC-LDPC threshold Uses flooding schedule (not layered) to avoid belief divergence from cross-position message interference in the coupled chain. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -140,3 +140,63 @@ class TestWindowedDecode:
|
||||
assert err_large <= err_small + 0.05, (
|
||||
f"Large window error {err_large} should be <= small window {err_small} + tolerance"
|
||||
)
|
||||
|
||||
|
||||
class TestSCDensityEvolution:
|
||||
"""Tests for SC-LDPC density evolution."""
|
||||
|
||||
def test_sc_de_converges_at_high_snr(self):
|
||||
"""SC-DE should converge at lam_s=10 (well above threshold)."""
|
||||
from sc_ldpc import sc_density_evolution
|
||||
from ldpc_sim import H_BASE
|
||||
np.random.seed(42)
|
||||
converged, pos_errors, iters = sc_density_evolution(
|
||||
H_BASE, L=10, w=2, lam_s=10.0, lam_b=0.1,
|
||||
z_pop=5000, max_iter=50, cn_mode='normalized', alpha=0.75
|
||||
)
|
||||
assert converged, f"SC-DE should converge at lam_s=10, max error={max(pos_errors):.4f}"
|
||||
|
||||
def test_sc_threshold_lower_than_uncoupled(self):
|
||||
"""SC threshold should be lower than uncoupled threshold (~3.05)."""
|
||||
from sc_ldpc import compute_sc_threshold
|
||||
from ldpc_sim import H_BASE
|
||||
np.random.seed(42)
|
||||
sc_thresh = compute_sc_threshold(
|
||||
H_BASE, L=20, w=2, lam_b=0.1,
|
||||
z_pop=5000, tol=0.5, cn_mode='normalized', alpha=0.75
|
||||
)
|
||||
# Uncoupled threshold is ~3.05 for offset, ~2.9 for normalized
|
||||
# SC should be lower (threshold saturation)
|
||||
assert sc_thresh < 3.5, f"SC threshold {sc_thresh} should be < 3.5"
|
||||
|
||||
def test_sc_de_wave_effect(self):
|
||||
"""SC-LDPC should show position-dependent error profile.
|
||||
|
||||
In SC-LDPC with flooding DE, boundary positions have fewer CN
|
||||
connections (lower effective VN degree), so they typically show
|
||||
different error rates than interior positions. The error profile
|
||||
should NOT be uniform -- the spatial coupling creates a non-trivial
|
||||
position-dependent structure.
|
||||
"""
|
||||
from sc_ldpc import sc_density_evolution
|
||||
from ldpc_sim import H_BASE
|
||||
np.random.seed(42)
|
||||
# Run at a moderate SNR where errors are visible but not saturated
|
||||
converged, pos_errors, iters = sc_density_evolution(
|
||||
H_BASE, L=20, w=2, lam_s=2.5, lam_b=0.1,
|
||||
z_pop=5000, max_iter=100, cn_mode='normalized', alpha=0.75
|
||||
)
|
||||
# The error profile should be non-uniform across positions
|
||||
# (spatial coupling creates position-dependent behavior)
|
||||
err_std = np.std(pos_errors)
|
||||
assert err_std > 0.001, (
|
||||
f"Error profile std {err_std:.6f} too uniform; "
|
||||
f"SC-LDPC should show position-dependent errors"
|
||||
)
|
||||
# Interior positions (well-connected) should have lower error
|
||||
# than the max error across all positions
|
||||
interior_err = np.mean(pos_errors[len(pos_errors)//3 : 2*len(pos_errors)//3])
|
||||
max_err = max(pos_errors)
|
||||
assert interior_err < max_err, (
|
||||
f"Interior error {interior_err:.4f} should be less than max {max_err:.4f}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user