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>
This commit is contained in:
63
model/test_sc_ldpc.py
Normal file
63
model/test_sc_ldpc.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/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}"
|
||||
Reference in New Issue
Block a user