Weighted emitter selection validation¶
Validated with documented limitations.
1. The component¶
rfgen.planning records one reproducible choice of an emitter family and one
class before waveform generation. A categorical draw chooses one named
outcome from a finite list using the list’s relative weights. It does not
construct a waveform, determine duration, place a carrier, apply a channel, or
generate IQ samples. Concepts / Scenes places this
record among the other job-owned planning inputs.
The configured weights are caller-owned synthetic sampling priors. This validation does not treat them as measurements of RF occupancy, device prevalence, protocol traffic, or captured-corpus prevalence.
class WeightedEmitterSelector:
@staticmethod
def resolve(config: SelectionConfig | dict[str, object]) -> SelectionPlan: ...
@staticmethod
def write(
plan: SelectionPlan | dict[str, object], *, scene_id: str,
root: str | Path = "."
) -> Path: ...
@staticmethod
def read(path: str | Path) -> SelectionPlan: ...
Input or output |
Contract |
|---|---|
|
An ordered family/class mixture and an unsigned 64-bit |
|
The raw ordered weights, per-family conditional class probabilities, and the selected enabled pair. |
artifact path |
|
from rfgen.planning import WeightedEmitterSelector
plan = WeightedEmitterSelector.resolve(
{"seed": 1337, "families": [
{"selector": "analog", "weight": 3.0,
"classes": [{"name": "am", "weight": 2.0}, {"name": "fm"}]},
{"selector": "digital", "weight": 1.0,
"classes": [{"name": "bpsk"}, {"name": "qpsk"}]},
]}
)
path = WeightedEmitterSelector.write(plan, scene_id="capture-0001", root="output")
assert WeightedEmitterSelector.read(path) == plan
2. What we validated¶
This validation establishes three load-bearing claims. Each is supported in section 3.
Seeded two-stage selection (§3.1): the configured family and class mixture determines a repeatable draw.
Faithful selection artifact (§3.2): the stored record retains and validates the effective mixture and choice.
Statistical frequency check (§3.3): a long categorical draw stream agrees with its configured distribution.
Section 4 gives the numerical and modeling boundaries.
3. Evidence per claim¶
3.1 Seeded two-stage selection¶
WeightedEmitterSelector.resolve first chooses a family from normalized
family weights, then chooses a class from that family’s normalized class
weights. It delegates both draws to NumPy Generator.choice, rather than
implementing a random-selection algorithm. The focused acceptance suite
confirms that the same configuration and seed return equal plans and that a
zero-weight row remains visible but is not chosen.
The normalizer divides finite weights by the greatest weight before summing
with math.fsum. This preserves representable ratios while avoiding an
intermediate overflow. Equal family weights of 1e308 and equal class weights
of 1e308 each produced probabilities 0.5, 0.5, a valid draw, and a
successful artifact round trip.
3.2 Faithful selection artifact¶
tests/unit/test_weighted_selection.py::test_seeded_plan_retains_yaml_order_uses_uniform_omission_and_round_trips
checks that family and class order survives, omitted weights become 1.0, each
stored class probability equals its normalized stored raw class weight, and a
write/read operation returns the same typed plan. A second write to the same
canonical path raises FileExistsError and preserves the existing bytes. The
canonical outer record
has exactly schema_version, seed, families, and draw.
The same focused suite rejects a stored probability that disagrees with its raw weight, a zero-total stored class distribution, a draw naming an absent or disabled outcome, a noncanonical artifact location, and an unsafe scene ID. These checks establish record integrity, not RF realism.
3.3 Statistical frequency check¶
For the documented mixture, the expected final outcome probabilities are
0.5, 0.25, 0.125, and 0.125. An independent 100,000-draw NumPy stream
seeded with 1337 observed 0.50047, 0.24941, 0.12608, and 0.12404.
A standard error is the expected sampling variation of a measured
proportion under repeated draws. The signed deviations were 0.297, -0.431,
1.033, and -0.918 standard errors, so every outcome is inside the stated
five-standard-error acceptance bound.
4. Limits and what is not validated¶
The caller supplies the mixture. This component does not establish that its weights represent measured RF occupancy, device prevalence, protocol traffic, or a captured corpus.
Probabilities use IEEE 754 binary64 floating point. A positive weight whose ratio to the greatest weight underflows that representation is stored with probability zero and cannot be sampled by the NumPy backend; the raw weight remains in the artifact. Inputs should use ratios that yield representable probabilities when every positive outcome must remain selectable.
Device identity, event count, timing, duration, placement, waveform generation, propagation, labels, and receiver behavior are outside this component.
5. References¶
NumPy
Generator.choicedocumentation. PyPI distribution:numpy; installed version: 2.4.1. It supplies the categorical draws and the independent frequency check.Pydantic documentation. PyPI distribution:
pydantic; installed version: 2.13.3. It supplies the strict immutable schemas for public input and persisted records.Weighted emitter selection API. Public input, artifact, ordering, and structured-error contract.