BBE is a simulation framework for closed-loop selection between interleaved and non-interleaved error-control coding over a bursty interference channel.
The transmitter chooses between two realizations of the same code:
- Arm A: a non-interleaved random linear code
- Arm B: the same code with cross-codeword block interleaving
The receiver uses GRAND—Guessing Random Additive Noise Decoding—with a replaceable noise model. Aggregate receiver statistics are fed back to a channel learner at the transmitter. As the interference estimate improves, the receiver can replace its generic decoding model with a learned hidden Markov model. This changes the relative reliability and latency of the two arms, and a discounted Thompson sampler adapts the transmitter’s choice.
The repository accompanies the technical report:
B. Krishnamachari, “Closed-Loop Bayesian Bandit Encoder with GRAND Receiver for a Bursty Interference Channel,” technical report, in preparation, 2026.
The code supports experiments in which:
- a channel contains an unknown number of asynchronous on/off interferers;
- the receiver collects compact statistics from decoded packets;
- a transmitter-side learner estimates interference amplitudes and timing;
- the estimate is used to update the receiver’s GRAND query ordering;
- a bandit selects between interleaved and non-interleaved transmission;
- the preferred arm may change after receiver adaptation.
The implementation is modular: codes, channels, GRAND noise models, estimators, bandit policies, feedback statistics, and utility predictors can be replaced independently.
BBE requires Python 3.11 or later.
git clone https://github.com/ANRGUSC/BBE.git
cd BBE
python -m venv .venv
source .venv/bin/activate
pip install -e .Main dependencies include:
- NumPy
- SciPy
- scikit-learn
- Matplotlib
- PyYAML
A minimal simulation can be run from Python:
from bbe.config import (
SimConfig,
GrandConfig,
LearnerConfig,
BanditConfig,
)
from bbe.sim.simulator import Simulator
cfg = SimConfig(
seed=0,
n_packets=20_000,
grand=GrandConfig(
noise_model="learned",
max_queries=100_000,
),
learner=LearnerConfig(
kind="bayes",
placement="tx",
),
bandit=BanditConfig(
kind="ts", # alternatives: "informed", "fixed"
),
)
metrics = Simulator(cfg).run()Simulator.run() returns a metrics recorder holding per-packet outcomes (arm, success, abandonment, query count, reward) and per-feedback-period estimator snapshots.
At each decision point, the simulator performs the following steps:
- The bandit selects the non-interleaved or interleaved arm.
- The selected encoder produces one or more codewords.
- The channel adds AWGN and asynchronous burst interference.
- GRAND decodes using the active noise-model ordering.
- The receiver updates aggregate deviation and burst-run statistics.
- Feedback statistics are periodically sent to the learner.
- The learner updates the estimated channel model.
- The estimate may retune the receiver’s GRAND noise model.
- ACK/NACK outcomes update the bandit reward.
- In the model-informed policy, predicted arm utilities are also supplied to the sampler.
flowchart LR
subgraph TX ["Transmitter side"]
BANDIT["bandit/<br/>fixed | discounted TS | model-informed TS"]
LEARNER["learner/<br/>run-mean estimator | oracle"]
PRED["sim/utility_predictor.py<br/>Monte Carlo utility prediction"]
end
subgraph CODES ["codes/"]
RLC["rlc.py<br/>random linear code<br/>packed syndrome"]
IL["interleaver.py<br/>cross-codeword block interleaver"]
end
CH["channel/<br/>AWGN + asynchronous<br/>on/off interferers"]
subgraph RX ["Receiver side"]
DEC["grand/decoder.py<br/>GRANDAB query loop"]
NM["grand/noise_models/<br/>iid | Markov | ORBGRAND | learned HMM"]
STATS["feedback/stats.py<br/>deviation and burst-run statistics"]
end
BANDIT -->|"arm choice"| RLC
RLC --> IL
RLC --> CH
IL --> CH
CH -->|"received samples"| DEC
NM -->|"query order"| DEC
DEC -->|"decoded deviations"| STATS
STATS -->|"aggregate feedback"| LEARNER
LEARNER -->|"channel estimate"| NM
LEARNER -->|"channel estimate"| PRED
PRED -->|"predicted utilities"| BANDIT
DEC -.->|"ACK/NACK reward"| BANDIT
src/bbe/
├── config.py
│ Experiment configuration dataclasses.
│
├── rng.py
│ Per-component random-number streams, including support for
│ common-random-number comparisons.
│
├── codes/
│ ├── rlc.py
│ │ Random linear code with bit-packed incremental syndrome checks.
│ └── interleaver.py
│ Cross-codeword block interleaver.
│
├── channel/
│ AWGN plus asynchronous on/off interferers, including channel
│ synthesis from learned parameter estimates.
│
├── grand/
│ ├── decoder.py
│ │ GRANDAB decoding loop with a configurable query budget.
│ └── noise_models/
│ Candidate-noise orderings:
│ - iid Hamming-weight order
│ - Gilbert–Elliott-style Markov order
│ - ORBGRAND
│ - learned HMM posteriors with SGRAND-style ordering
│
├── feedback/
│ Receiver-side statistics collection and compact feedback messages.
│
├── learner/
│ Run-mean interference estimator with truncation-bias inversion,
│ together with an oracle estimator for controlled experiments.
│
├── bandit/
│ Arm-selection policies:
│ - fixed policy
│ - discounted Normal-Gamma Thompson sampling
│ - model-informed Thompson sampling
│
└── sim/
Simulator loop, arm bindings, metrics, and Monte Carlo utility
prediction.
The configuration studied in the accompanying report uses:
- BPSK modulation
- a fixed RLC(128, 105) on both arms
- a depth-16 cross-codeword interleaver on Arm B
- AWGN plus three hidden on/off interferers
- aggregate receiver feedback every fixed number of packets
- a learned HMM-based GRAND ordering on the non-interleaved arm
- discounted Thompson sampling for arm selection
The learner runs at the transmitter using aggregate receiver feedback. Its estimate is used in two places:
- to update the receiver’s GRAND noise model;
- to predict per-arm utilities for the model-informed bandit.
GrandConfig(
noise_model="learned",
max_queries=100_000,
)Supported noise-model choices include:
- generic iid ordering;
- Markov burst ordering;
- ORBGRAND;
- learned HMM ordering.
The query budget controls GRANDAB abandonment and therefore trades decoding work against block error rate.
LearnerConfig(
kind="bayes",
placement="tx",
)The run-mean learner estimates interference structure from thresholded deviation-run statistics. An oracle learner is also available for separating estimation error from decoder performance.
BanditConfig(kind="ts")Available policies include:
"fixed"— always use a configured arm;"ts"— discounted Thompson sampling from observed rewards;"informed"— Thompson sampling augmented with confidence-weighted, model-predicted utilities.
The simulator is designed around interchangeable components. Typical extensions include:
- adding a new code or interleaver under
codes/; - implementing a new channel model under
channel/; - adding a GRAND query ordering under
grand/noise_models/; - replacing the run-mean estimator under
learner/; - adding a bandit or contextual policy under
bandit/; - defining new receiver feedback statistics under
feedback/; - adding new experiment metrics or utility models under
sim/.
When adding a component, keep randomness on its own stream through bbe.rng. This makes paired comparisons and common-random-number experiments easier to reproduce.
Simulation behavior is controlled by SimConfig and its nested component configurations. Set seed explicitly for reproducible runs:
cfg = SimConfig(
seed=0,
n_packets=20_000,
# ...
)For fair comparisons between algorithms, use the same seed and channel realization where possible. The repository’s per-component RNG streams are intended to keep unrelated implementation changes from perturbing every random draw in an experiment.
BBE is a research simulator rather than a deployment-ready communications stack. The reference experiments use a synthetic on/off interference model and idealized control feedback. Runtime, feedback overhead, delayed acknowledgments, and integration with a complete PHY/MAC stack require separate evaluation.
@techreport{krishnamachari2026bbe,
author = {Bhaskar Krishnamachari},
title = {Closed-Loop Bayesian Bandit Encoder with GRAND Receiver
for a Bursty Interference Channel},
institution = {University of Southern California},
note = {In preparation},
year = {2026}
}This repository is released under the PolyForm Noncommercial License 1.0.0.
Noncommercial use, including academic research and teaching, is permitted. Commercial use is not permitted under this license. Contact the author to discuss commercial licensing.