Expand description
Scenarios and the metrics of a trial.
A Scenario is what one Monte Carlo trial does, the counterpart of a
LightningModule:
Scenario::setupruns once per condition, before its trials, and returns a state shared (read-only) by all of them: a constellation, a filter, a designed or trained receiver, a fibre plan… (setuphook of Lightning);Scenario::trialruns one trial with its own random generator and records its metrics in aRecord(training_stepandself.log).
Trials run in parallel, so the scenario and its state are Sync and a trial must
not mutate shared data. from_fn makes a scenario from a closure when no state
is needed.
A Record maps metric names to Estimates: Record::errors adds error counts
(an error rate with a Wilson interval), Record::value adds a real value (a mean
with a normal interval). The runner merges the records of all the trials of a
condition.
A value that cannot enter its metric is dropped and counted, never folded into
the estimate: a non-finite value (the SNR of an error-free trial, +∞ dB), or an
addition to a metric of the other kind (errors on a mean, value on a rate).
Record::dropped gives the count of a metric; the runner keeps the counts of the
merged record and the JSON report lists them (dropped), so that a mean that
leaves values out shows it.
§Examples
use comnum_sim::prelude::*;
use comnum_mapping::{constellation::{Constellation, ConstellationKind}, source as sources};
use comnum_channel::awgn as channels;
use comnum_metrics as metrics;
/// SER of M-PSK over AWGN; the constellation is built once per condition.
struct Psk;
impl Scenario for Psk {
type State = Constellation;
fn name(&self) -> &str { "psk-ser" }
fn setup(&self, cond: &Condition) -> Result<Constellation> {
Constellation::psk(cond.usize("m")?)
}
fn trial(&self, c: &Constellation, cond: &Condition, rng: &mut Rng, rec: &mut Record)
-> Result<()> {
let (idx, x) = sources::symbols(c, 1000, None, rng)?;
let b = c.bits_per_symbol();
let y = channels::awgn_ebn0(&x, cond.f64("ebn0_db")?, b as f64, 1.0, rng);
let dec = c.decide(&y);
rec.errors("ser", metrics::symbol_errors(&dec, &idx)? as u64, idx.len() as u64);
rec.value("snr_db", metrics::snr_db(&y, &x)?);
Ok(())
}
}
let grid = Grid::new().axis("m", [8usize]).axis("ebn0_db", [10.0]);
let r = Runner::new().batch(10).stop(Stop::max_trials(20)).run(&Psk, &grid).unwrap();
assert_eq!(r[0].trials, 20); // the rule is checked after every batch of 10 trials
assert!((r[0].metric("snr_db").unwrap().value() - (10.0 + comnum_math::lin2db(3.0))).abs() < 0.1);Structs§
- FnScenario
- A scenario made of a closure (no per-condition state); see
from_fn. - Record
- The metrics reported by one trial, or merged over many.
Traits§
- Scenario
- One random trial of a link, evaluated under many conditions.
Functions§
- from_fn
- A scenario from a name and a closure
|condition, rng, record| -> Result<()>.