Files
ldpc_optical/model/test_sc_ldpc.py
cah 5b6ad4d3f2 feat: add SC-LDPC chain construction
Implement spatially-coupled LDPC code construction with:
- split_protograph(): split base matrix edges into w components
- build_sc_chain(): build full SC-LDPC H matrix with L positions
- sc_encode(): GF(2) Gaussian elimination encoder for SC chain

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 16:49:57 -07:00

64 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Tests for SC-LDPC construction."""
import numpy as np
import pytest
import sys
import os
sys.path.insert(0, os.path.dirname(__file__))
class TestSCLDPCConstruction:
"""Tests for SC-LDPC chain construction."""
def test_split_preserves_edges(self):
"""Split B into components, verify sum(B_i >= 0) == (B >= 0) for each position."""
from sc_ldpc import split_protograph
from ldpc_sim import H_BASE
components = split_protograph(H_BASE, w=2, seed=42)
assert len(components) == 2
# Each edge in B should appear in exactly one component
for r in range(H_BASE.shape[0]):
for c in range(H_BASE.shape[1]):
if H_BASE[r, c] >= 0:
count = sum(1 for comp in components if comp[r, c] >= 0)
assert count == 1, f"Edge ({r},{c}) in {count} components, expected 1"
else:
for comp in components:
assert comp[r, c] < 0, f"Edge ({r},{c}) should be absent"
def test_chain_dimensions(self):
"""Build chain with L=5, w=2, Z=32. Verify H dimensions."""
from sc_ldpc import build_sc_chain
from ldpc_sim import H_BASE
m_base, n_base = H_BASE.shape
L, w, z = 5, 2, 32
H_full, components, meta = build_sc_chain(H_BASE, L=L, w=w, z=z, seed=42)
expected_rows = L * m_base * z # 5*7*32 = 1120
expected_cols = (L + w - 1) * n_base * z # 6*8*32 = 1536
assert H_full.shape == (expected_rows, expected_cols), (
f"Expected ({expected_rows}, {expected_cols}), got {H_full.shape}"
)
def test_chain_has_coupled_structure(self):
"""Verify non-zero blocks only appear at positions t and t+1 for w=2."""
from sc_ldpc import build_sc_chain
from ldpc_sim import H_BASE
m_base, n_base = H_BASE.shape
L, w, z = 5, 2, 32
H_full, components, meta = build_sc_chain(H_BASE, L=L, w=w, z=z, seed=42)
# For each CN position t, check which VN positions have connections
for t in range(L):
cn_rows = slice(t * m_base * z, (t + 1) * m_base * z)
for v in range(L + w - 1):
vn_cols = slice(v * n_base * z, (v + 1) * n_base * z)
block = H_full[cn_rows, vn_cols]
has_connections = np.any(block != 0)
if t <= v <= t + w - 1:
# Should have connections (t connects to t..t+w-1)
assert has_connections, f"CN pos {t} should connect to VN pos {v}"
else:
# Should NOT have connections
assert not has_connections, f"CN pos {t} should NOT connect to VN pos {v}"