Files
ldpc_optical/model/test_ldpc_analysis.py
cah ad7cb5098c feat: add code analysis tool with rate, matrix, quantization, and Shannon analyses
Implements four LDPC code analyses for photon-starved optical channels:
- Rate sweep: compare FER across 1/2, 1/3, 1/4, 1/6, 1/8 IRA staircase codes
- Matrix comparison: original staircase vs improved staircase vs PEG ring
- Quantization sweep: 4-16 bit and float precision impact on FER
- Shannon gap: binary-input Poisson channel capacity limits via binary search

Core infrastructure includes generic IRA staircase builder, GF(2) Gaussian
elimination encoder for non-triangular matrices, parameterized layered
min-sum decoder with variable check degree, and BFS girth computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 04:46:39 -07:00

86 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""
Tests for LDPC code analysis module (ldpc_analysis.py).
Covers IRA staircase code construction and rate sweep functionality.
Run:
python3 -m pytest model/test_ldpc_analysis.py -v
"""
import numpy as np
import pytest
from ldpc_analysis import (
build_ira_staircase,
ira_encode,
generic_decode,
rate_sweep_single,
)
from ldpc_sim import poisson_channel, quantize_llr
# =============================================================================
# TestIRAStaircase
# =============================================================================
class TestIRAStaircase:
"""Validate generic IRA staircase code construction for various rates."""
def test_rate_1_2(self):
"""m_base=1 -> rate 1/2: (1,2) base matrix, (32,64) full matrix, rank=32."""
H_base, H_full = build_ira_staircase(m_base=1, z=32)
assert H_base.shape == (1, 2), f"Base shape: {H_base.shape}"
assert H_full.shape == (32, 64), f"Full shape: {H_full.shape}"
rank = np.linalg.matrix_rank(H_full.astype(float))
assert rank == 32, f"Rank: {rank}, expected 32"
def test_rate_1_4(self):
"""m_base=3 -> rate 1/4: (3,4) base matrix, (96,128) full matrix, rank=96."""
H_base, H_full = build_ira_staircase(m_base=3, z=32)
assert H_base.shape == (3, 4), f"Base shape: {H_base.shape}"
assert H_full.shape == (96, 128), f"Full shape: {H_full.shape}"
rank = np.linalg.matrix_rank(H_full.astype(float))
assert rank == 96, f"Rank: {rank}, expected 96"
def test_rate_1_8_matches_existing(self):
"""m_base=7 -> rate 1/8: (7,8) base matrix, (224,256) full matrix."""
H_base, H_full = build_ira_staircase(m_base=7, z=32)
assert H_base.shape == (7, 8), f"Base shape: {H_base.shape}"
assert H_full.shape == (224, 256), f"Full shape: {H_full.shape}"
def test_encode_decode_roundtrip(self):
"""For m_base in [1,2,3,5], encode random info, verify syndrome=0."""
np.random.seed(42)
for m_base in [1, 2, 3, 5]:
H_base, H_full = build_ira_staircase(m_base=m_base, z=32)
z = 32
k = z # info bits = Z
info = np.random.randint(0, 2, k).astype(np.int8)
codeword = ira_encode(info, H_base, H_full, z=z)
syndrome = H_full @ codeword % 2
assert np.all(syndrome == 0), (
f"m_base={m_base}: syndrome weight = {syndrome.sum()}"
)
# =============================================================================
# TestRateSweep
# =============================================================================
class TestRateSweep:
"""Validate rate sweep simulation."""
def test_high_snr_all_rates_decode(self):
"""At lam_s=20, all rates should achieve FER=0 with 10 frames."""
np.random.seed(42)
for m_base in [1, 2, 3, 5, 7]:
result = rate_sweep_single(
m_base=m_base, z=32, lam_s=20.0, lam_b=0.1,
n_frames=10, max_iter=30, q_bits=6,
)
assert result['fer'] == 0.0, (
f"m_base={m_base} (rate 1/{m_base+1}): FER={result['fer']} at lam_s=20, "
f"expected 0.0"
)