MIMO Detection
The MIMO Detection Problem
In MIMO, the receiver must separate spatially multiplexed streams from the mixed received signals. The challenge is that the channel mixes all transmitted signals together: . Detection algorithms trade complexity for performance.
Definition: MIMO System Model
MIMO System Model
The MIMO system model is:
where (each entry from constellation ), , and .
def mimo_channel(H, x, N0, rng=None):
if rng is None: rng = np.random.default_rng()
Nr = H.shape[0]
n = np.sqrt(N0/2) * (rng.standard_normal(Nr) + 1j*rng.standard_normal(Nr))
return H @ x + n
Definition: Zero-Forcing (ZF) MIMO Detection
Zero-Forcing (ZF) MIMO Detection
ZF detection applies the pseudoinverse of :
then quantizes each entry to the nearest constellation point.
def zf_detect(y, H, constellation):
G = np.linalg.pinv(H)
x_hat = G @ y
# Quantize each stream
det = np.array([constellation[np.argmin(np.abs(xi - constellation))] for xi in x_hat])
return det
ZF eliminates inter-stream interference but amplifies noise, especially when is ill-conditioned.
Definition: MMSE MIMO Detection
MMSE MIMO Detection
MMSE detection balances interference suppression and noise:
The regularization term prevents noise amplification.
def mmse_detect(y, H, constellation, N0, Es=1.0):
Nt = H.shape[1]
G = np.linalg.inv(H.conj().T @ H + (N0/Es)*np.eye(Nt)) @ H.conj().T
x_hat = G @ y
det = np.array([constellation[np.argmin(np.abs(xi - constellation))] for xi in x_hat])
return det
Definition: Maximum Likelihood (ML) MIMO Detection
Maximum Likelihood (ML) MIMO Detection
ML detection searches over all possible transmit vectors:
This is optimal but has complexity β exponential in the number of antennas.
from itertools import product
def ml_detect(y, H, constellation):
Nt = H.shape[1]
best_dist = np.inf
best_x = None
for x_cand in product(constellation, repeat=Nt):
x_vec = np.array(x_cand)
dist = np.sum(np.abs(y - H @ x_vec)**2)
if dist < best_dist:
best_dist = dist
best_x = x_vec
return best_x
For with 16-QAM, ML searches vectors per symbol interval β often impractical for real-time systems.
Definition: Sphere Decoding
Sphere Decoding
The sphere decoder finds the ML solution efficiently by searching only within a sphere of radius around :
Using QR decomposition , the search becomes a tree-search problem that prunes branches exceeding the radius. Average complexity is polynomial (roughly ) for typical SNR.
Theorem: ZF Noise Enhancement
The post-ZF noise covariance on stream is:
The noise is amplified by , where is the smallest singular value of .
When is nearly rank-deficient (high condition number), ZF amplifies noise enormously on weak streams.
Theorem: MMSE Post-Detection SINR
The post-MMSE SINR on stream is:
This is always the post-ZF SNR, with the gap largest at low SNR.
MMSE accepts some residual inter-stream interference to avoid noise amplification. At high SNR, MMSE converges to ZF.
Theorem: Optimality of ML Detection
ML detection minimizes the symbol/bit error rate among all detectors. For equal-energy constellations with equal priors:
However, ML complexity is , making it impractical for large or .
ML considers all possible transmit vectors and picks the most likely given the received signal. Linear detectors (ZF, MMSE) are suboptimal approximations with polynomial complexity.
Example: Comparing ZF, MMSE, and ML for 2x2 MIMO
Simulate a 2x2 MIMO system with QPSK and compare BER of ZF, MMSE, and ML detectors.
Implementation
# See code supplement ch23/python/mimo_detection.py
Example: Effect of Channel Condition Number on ZF
Show that ZF detection fails when the channel matrix is ill-conditioned.
Analysis
# Well-conditioned
H_good = np.array([[1, 0.1], [0.1, 1]], dtype=complex)
# Ill-conditioned
H_bad = np.array([[1, 0.99], [1, 1.01]], dtype=complex)
print(f"Good: cond = {np.linalg.cond(H_good):.1f}")
print(f"Bad: cond = {np.linalg.cond(H_bad):.1f}")
Example: V-BLAST with SIC
Implement V-BLAST (ordered successive interference cancellation) for a 4x4 MIMO system.
Implementation
def vblast_detect(y, H, constellation):
Nr, Nt = H.shape
x_hat = np.zeros(Nt, dtype=complex)
y_rem = y.copy()
H_rem = H.copy()
detected = []
for _ in range(Nt):
# Find stream with highest post-ZF SNR
G = np.linalg.pinv(H_rem)
norms = np.sum(np.abs(G)**2, axis=1)
k = np.argmin(norms)
# Detect stream k
x_k = G[k] @ y_rem
x_hat_k = constellation[np.argmin(np.abs(x_k - constellation))]
# Cancel from received signal
y_rem = y_rem - H_rem[:, k] * x_hat_k
H_rem = np.delete(H_rem, k, axis=1)
detected.append((k, x_hat_k))
return x_hat
MIMO Detection BER Comparison
Compare BER of ZF, MMSE, and ML detectors for different MIMO configurations.
Parameters
Channel Condition Number vs BER
Explore how channel correlation affects the condition number and detection performance.
Parameters
MIMO Detection: ZF vs MMSE vs ML
Watch the detected constellation improve with SNR for different detectors.
Parameters
MIMO Detector Complexity vs Performance
Quick Check
What is the complexity of ML detection for 4x4 MIMO with 64-QAM?
ML searches all candidate vectors.
Quick Check
When does MMSE detection significantly outperform ZF?
At high SNR
When
At low SNR with correlated channels
When the constellation is BPSK
ZF amplifies noise at low SNR; MMSE avoids this via regularization.
Common Mistake: ZF with
Mistake:
Applying ZF detection when (more TX antennas than RX), where is singular.
Correction:
ZF requires . For , use MMSE (which always works due to regularization) or reduce the number of streams.
Key Takeaway
MIMO detection algorithms span a wide complexity-performance trade-off: ZF () is simple but noise-amplifying; MMSE () is better at low SNR; ML () is optimal but exponentially complex. SIC (V-BLAST) offers a middle ground.
Key Takeaway
MMSE detection always outperforms or matches ZF. The gap is largest at low SNR and with correlated channels. Use MMSE as the default linear detector.
Why This Matters: MIMO Detection in 5G NR
5G NR supports up to 8-layer spatial multiplexing (8 streams) in the downlink. Base stations typically use MMSE-IRC (interference rejection combining) detection with SIC for multi-user MIMO. ML detection is used in research but not in commercial systems due to complexity.
See full treatment in Chapter 24
Historical Note: V-BLAST: The First Spatial Multiplexing Demo
1998V-BLAST (Vertical Bell Labs Layered Space-Time) was demonstrated by Foschini et al. in 1998, achieving 40 bps/Hz spectral efficiency in a laboratory setting with 8 TX and 12 RX antennas. This landmark experiment proved that MIMO spatial multiplexing was practical.
Historical Note: Sphere Decoding for Communications
1999Sphere decoding was introduced to communications by Viterbo and Boutros (1999), adapting the lattice reduction algorithm of Fincke and Pohst (1985) to MIMO detection. It achieves ML performance with polynomial average complexity.
Zero-Forcing Detection
A linear MIMO detector that applies the pseudoinverse to separate spatial streams, eliminating inter-stream interference.
Related: MMSE Detection
MMSE Detection
A linear MIMO detector that minimizes mean-square error, balancing inter-stream interference suppression with noise enhancement.
ML Detection
The optimal MIMO detector that exhaustively searches all possible transmit vectors for the one closest to the received signal.
Successive Interference Cancellation
A detection strategy that detects one stream at a time, subtracting its contribution before detecting the next.
Condition Number
The ratio of the largest to smallest singular value of ; indicates how much ZF detection amplifies noise.
MIMO Detection Algorithm Comparison
| Property | ZF | MMSE | ML | V-BLAST/SIC |
|---|---|---|---|---|
| Complexity | ||||
| Requires ? | Yes | No (but helps) | No | Yes |
| Noise enhancement | High | Low | None | Moderate |
| BER performance | Worst | Good | Optimal | Near-ML |
| Practical for large ? | Yes | Yes | No | Yes |