Public task and development documentation. Official evaluation boundary.
Aggregate and paired statistics (statistics version 1.0)
This document defines the statistical summaries that EMBERBench computes over evaluation results.
There is no EMBER score or global winner in this module. (The EMBER Score is a separate module: see scoring.md.) This module does not rank models, combine metrics or produce a leaderboard. Every number belongs to one named metric. Win/loss/tie counts exist per metric only.
Out of scope here: leaderboards, a composite score, model rankings, provider adapters, procedural generation and a CLI.
1. Fail-closed input
An evaluation result in memory is not trusted as given. Before any episode is used, both functions:
- rebuild the evaluation manifest from its dictionary and require that it is equal to the original;
- call the manifest check: the suite ID, version and hash and the simulator, observation and metrics versions must match the running code;
- rebuild the evaluation result, which repeats its structural checks (manifest order, no duplicates, every episode equal to its manifest entry, record headers equal to the manifest);
- for every episode: resolve its scenario from the suite by ID and content hash, recompute episode metrics from the run record (this authenticates the record by simulator replay), and require that the stored metrics equal the recomputed metrics exactly (canonical JSON).
Any failure raises a statistics input error (a subclass of evaluation error). Nothing is repaired, skipped or partly summarized.
The paired comparison first calls the result pairing. Results from different evaluation manifests raise an evaluation error before any replay.
2. Supported metrics and directions
Each metric is a per-episode scalar from episode metrics. The module rebuilds
it as an exact Fraction from the integer counts in the metrics (see §10) and
requires that the float of that fraction equals the stored value.
| Metric | Source field | Kind | Direction | Exact definition (per episode) | Undefined when |
|---|---|---|---|---|---|
evacuated_rate |
safety.evacuated_rate |
outcome | higher is better | evacuated / population |
never |
casualty_rate |
safety.casualty_rate |
outcome | lower is better | casualties / population |
never |
stranded_rate |
safety.stranded_rate |
outcome | lower is better | stranded / population |
never |
terminal_trapped_rate |
safety.terminal_trapped_rate |
outcome | lower is better | terminal_trapped_count / population |
never |
mean_person_time_to_safety |
time.mean_person_time_to_safety |
outcome | lower is better | person_time_to_safety_total / population |
never |
blocked_rate |
movement.blocked_rate |
behaviour | lower is better | blocked_moves / movement_attempts |
no movement attempts |
congestion_block_rate |
movement.congestion_block_rate |
behaviour | lower is better | congestion_blocks / movement_attempts |
no movement attempts |
aggregate_path_efficiency |
path_efficiency.aggregate_path_efficiency |
proxy | higher is better | total_static_lower_bound / total_cells_moved |
no measured movement |
mean_exposure |
fire_exposure.mean_exposure |
proxy | lower is better | (Σ_d count_d / d) / active_person_states |
never |
exits_used |
exits.exits_used |
descriptive | none | number of exits with n_e >= 1 |
never |
max_exit_share |
exits.max_exit_share |
descriptive | none | max_e n_e / E |
E = 0 |
exit_balance |
exits.exit_balance |
descriptive | none | normalized Gini-Simpson index | K = 1 or E = 0 |
The per-episode definitions are in metrics.md. Notes:
- Kinds. Outcome metrics are terminal safety and time results. Behaviour metrics describe observed movement. Proxy metrics approximate a quantity that is not measured directly (path optimality, fire danger). Descriptive metrics describe the run and are not objectives.
- Directions are used only to read the sign of a paired difference (§8). They do not make a metric an objective by itself.
mean_person_time_to_safetycounts every non-evacuee atmax_steps(censoring), so it mixes speed and safety. Read it with the safety rates.blocked_rateandcongestion_block_rateare lower-is-better per metric, but a run can lower them by not moving. Never read them alone.- Exit metrics have no direction. Equal exit use is often not optimal (one
exit can be much closer, or threatened by fire).
exit_balanceis never an objective, and no win/loss/tie count exists for any exit metric.
3. Groups: overall, per scenario, per family
Each artifact holds the same summaries for three kinds of group:
| Group | Episodes | Order |
|---|---|---|
overall |
every scheduled episode | — |
scenarios |
every scheduled episode of one scenario | suite manifest order |
families |
every scheduled episode of every scenario in the family | Scenario family declaration order |
A scenario with several families contributes all of its episodes to every one of those families. Family views can therefore overlap, and the family counts do not add up to the overall counts. A family with no scheduled scenario is not listed.
Overall statistics use the episode observations directly. They are never an
average of scenario or family means. With unequal group sizes (for example
after missing episodes) the two are different, and only the episode-level value
is reported. Each episode has equal weight; a scenario with more scheduled
seeds has more weight in overall.
4. Descriptive statistics
For one metric in one group, let x_1, …, x_n be the defined values of the
observed episodes, and x_(1) <= … <= x_(n) the same values in ascending
order.
| Field | Formula | Defined when |
|---|---|---|
n |
number of defined values | always |
mean |
(Σ_i x_i) / n |
n >= 1 |
median |
the type-7 quantile at p = 1/2 (the mean of the two middle values when n is even) |
n >= 1 |
variance |
sample variance Σ_i (x_i - mean)² / (n - 1) |
n >= 2 |
std |
sqrt(variance) |
n >= 2 |
min, max |
x_(1), x_(n) |
n >= 1 |
quantiles |
type-7 quantiles at p25, p50, p75, p90, p95 |
n >= 1 |
An undefined statistic is null (None). It is never 0.
Quantile rule (Hyndman-Fan type 7)
With 0-based sorted values y[0] <= … <= y[n-1] and a level p in [0, 1]:
h = (n - 1) · p
j = floor(h)
g = h - j
Q(p) = y[j] + g · (y[j+1] - y[j]) (Q(p) = y[j] when g = 0)
This is the default of R (type = 7) and of NumPy (method = "linear"). The
levels are fixed: p25 = 1/4, p50 = 1/2, p75 = 3/4, p90 = 9/10,
p95 = 19/20. With n = 1 every quantile is the single value.
Example: for 1, 2, 3, 4 the quantiles are p25 = 1.75, p50 = 2.5,
p75 = 3.25, p90 = 3.7, p95 = 3.85, and the sample variance is 5/3.
5. Robustness and completeness counts
Each aggregate group has a robustness object of raw episode counts. There
are no rates here, so nothing hides the denominators.
| Field | Counts episodes … |
|---|---|
scheduled |
in the manifest for this group |
observed |
with an authenticated result |
missing |
scheduled, with no result (scheduled - observed) |
all_resolved |
observed, terminated with all_resolved |
max_steps |
observed, terminated at the step limit |
with_casualties |
observed, casualties > 0 |
with_stranded |
observed, stranded > 0 |
zero_evacuation |
observed, evacuated = 0 |
all_resolved + max_steps = observed. An episode can count in several of the
last four rows.
6. Missing and undefined data
There are two different kinds of absent value. Both are reported; neither is imputed.
- Missing episode. The manifest schedules it but the result has no entry
for it (for example, an interrupted run). It is missing, not a model
failure: it is not counted as a casualty, a timeout or zero evacuation. The
artifact lists every missing episode key (
missing_episodes), and every group givesmissing_indicesandrobustness.missing. - Undefined metric. The episode has a result, but the metric is
Nonefor it (for exampleblocked_ratewhen nobody tried to move). The per-metric summary counts it inundefined.
For each metric summary:
scheduled = observed + missing
n = observed - undefined
The statistics use the n defined values only. No value is filled in with
zero, a mean, a worst case or a value from another episode.
7. Paired comparison
The paired comparison uses the result pairing for the exact episode
join. An episode is paired only when both results contain the same key
(manifest hash, index, scenario ID, scenario hash, seed). Unpaired episodes
are never compared; they are listed in missing_from_a and missing_from_b.
For one metric in one group, with paired episodes k where the metric is
defined for both A and B:
delta_k = value_A(k) - value_B(k) (always A - B)
Each paired metric comparison reports:
| Field | Meaning |
|---|---|
paired |
paired episodes in the group |
missing_from_a, missing_from_b |
scheduled episodes in the group that A or B does not have |
undefined |
paired episodes where the metric is None for A or for B |
deltas |
every (episode index, delta_k), in manifest order |
statistics |
§5 statistics of the deltas: mean, median, std, quantiles, … (n = paired - undefined) |
mean_delta_ci |
§9 interval for the mean delta |
delta_positive, delta_negative, delta_zero |
counts of delta > 0, < 0, = 0 |
a_better, b_better, ties |
win/loss/tie counts by the metric's direction |
Win/loss/tie, per metric:
| Direction | a_better |
b_better |
ties |
|---|---|---|---|
| higher is better | delta > 0 |
delta < 0 |
delta = 0 |
| lower is better | delta < 0 |
delta > 0 |
delta = 0 |
| descriptive | null |
null |
null |
There is no count across metrics, no majority vote and no composite. Swapping
A and B negates every delta and swaps a_better and b_better.
8. Confidence intervals
Each metric summary has mean_ci (aggregate) or mean_delta_ci (paired): a
95 % percentile bootstrap interval for the mean.
- Let
x_1, …, x_nbe the defined values (aggregate) or the paired deltas (paired). Ifn < 5the interval isnull. - For each of
Rresamples, drawnindices uniformly with replacement from0 … n-1and take the mean of the selected values. In a paired comparison the resampling unit is the paired episode, so A and B stay together in the delta. - Sort the
Rresample means. The bounds are their type-7 quantiles at0.025and0.975.
R is resamples: the default is 2000; any integer in [100, 1 000 000]
is accepted. All means are exact fractions; only the bounds become floats.
Determinism. The bootstrap never uses random, the time or OS entropy.
Its stream seed is
seed = SHA-256( canonical JSON of {
statistics_version, purpose ("aggregate_mean" or "paired_mean_delta"),
evaluation_manifest_hash, result_digests, group [kind, name], metric, resamples } )
where each result digest is the SHA-256 of the canonical evaluation result
(the artifact as saved). The 64-bit words come from SHAKE-256 in counter mode:
block k is SHAKE-256("emberbench/statistics/bootstrap/v1\0" || seed || k)
(k as 8 big-endian bytes), read as 512 big-endian unsigned 64-bit words. An
index below n is drawn by rejection sampling (word < 2^64 - 2^64 mod n,
then word mod n), so there is no modulo bias. The seed is in the output for
audit. Identical inputs give identical intervals on every platform. Different
data, labels or manifests give different streams. This stream shares nothing
with the simulator's SplitMix64 streams.
Interpretation. An interval describes the uncertainty of the mean over this evaluation sample of scenarios and seeds, resampled at the episode level. It does not prove that one model is better in general, on other scenarios or on other seeds. Episodes of one scenario are not independent of each other, and the public suite is small, so treat intervals as descriptive.
9. Exact arithmetic and serialization
- Per-episode values are exact
Fractions rebuilt from integer counts (formean_exposure, from the fire-distance histogram:Σ count_d / d). - Means, medians, variances, quantiles, min/max, deltas and bootstrap means
are exact
Fractions in the dataclasses. - The output boundary is the dictionary: each exact value becomes its
correctly rounded
float. The standard deviation is the one irrational value: it ismath.sqrt(float(variance)), which IEEE 754 rounds correctly. - Every list is in manifest, suite or scenario family order. No result
depends on
dictorsetiteration order or onPYTHONHASHSEED. - The JSON text is canonical JSON (sorted keys, no whitespace, ASCII, no NaN).
The digest is its SHA-256. The model ID label, the input result digests and
resamplesare part of the artifact, so a change to any of them changes the digest.
10. Artifact layout
The aggregate statistics dictionary form:
statistics_version, artifact = "aggregate", model_id,
evaluation_manifest_hash, suite_id, suite_version, suite_hash,
simulator_version, observation_version, metrics_version,
result_digest, scheduled_episodes, observed_episodes, missing_episodes[],
metric_definitions[], methods{quantiles, variance, std, bootstrap},
overall{kind, name, episode_indices, missing_indices, robustness, metrics[]},
scenarios[], families[]
Each metrics[] entry: metric, scheduled, observed, missing, undefined, statistics{n, mean, median, variance, std, min, max, quantiles{p25…p95}}, mean_ci{method, statistic, level, resamples, seed, lower, upper} | null.
The paired statistics dictionary form has the same header with model_a, model_b,
result_digest_a, result_digest_b, delta = "A - B", paired_count,
missing_from_a[], missing_from_b[], and groups with paired_indices,
missing_from_a, missing_from_b and the §8 fields per metric.
11. Summary of what each section is
| Concept | Where | Is it a judgement? |
|---|---|---|
| Descriptive statistics | §5, statistics |
no: a summary of observed values |
| Robustness counts | §6, robustness |
no: raw episode counts |
| Missing / undefined | §7 | no: completeness accounting |
| Paired differences | §8, deltas |
no: signed A - B values |
| Per-metric win/loss/tie | §8 | per metric only, by its direction |
| Metrics with no direction | §3, exit metrics | never a winner |
| Confidence intervals | §9 | uncertainty over this sample only |
There is no EMBER score or global winner in this module.
Reviewed public benchmark contract. Apache License 2.0. Download Markdown