Toy channel equalization¶
Tutorial goal
Small fixed-denominator equalization/system-identification prototype.
Note
New to the terminology? See the lattice DSP concept map and the causality/data-use guide for how online, offline, block, and MIMO examples should be read.
Context¶
This example is a compact equalization-style demo. It keeps the setting small so readers can inspect the signal, filter, and error terms without needing a communication-system framework.
Key idea and equations¶
Equalization tries to learn an inverse or compensating filter so the output approaches a desired reference signal.
How to read the result¶
Inspect the printed MSE or improvement metric and remember this is a toy diagnostic, not a modem benchmark.
Run command¶
python examples/channel_equalization_toy.py
Run status¶
Return code: 0
Captured stdout¶
estimated equalizer numerator: [1.25116, 0.29751, -0.46007]
initial MSE: 0.04211684200241321
final MSE: 0.0010456849376973291
Source code¶
1"""Toy fixed-denominator equalization/system-identification demo.
2
3This is intentionally small: it estimates numerator coefficients while keeping a
4stable reflection-parameterized denominator fixed. Full decision-directed channel
5equalization will be a later application layer.
6"""
7
8import numpy as np
9
10from lattice_dsp import LatticeIIR, LatticeLadderNLMS
11
12rng = np.random.default_rng(5)
13symbols = rng.choice([-1.0, 1.0], size=6000)
14
15# A compact stable IIR channel.
16channel_reflection = [0.45, -0.25]
17channel_num = [0.8, 0.35, -0.1]
18channel = LatticeIIR(channel_reflection, channel_num)
19received = channel.process(symbols) + 0.02 * rng.normal(size=symbols.size)
20
21# Estimate a stable inverse-ish numerator with a fixed denominator for the demo.
22equalizer = LatticeLadderNLMS(channel_reflection, [0.0, 0.0, 0.0], mu=0.08)
23errors = np.array(equalizer.adapt_block(received.tolist(), symbols.tolist()))
24
25print("estimated equalizer numerator:", [round(v, 5) for v in equalizer.numerator])
26print("initial MSE:", float(np.mean(errors[:500] ** 2)))
27print("final MSE:", float(np.mean(errors[-500:] ** 2)))