Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Reading and recording results

A model holds state in two places: the component columns (per-agent data) and the environment (model-wide values). Per-agent data is read with a reduction; model-wide data is read from the environment.

Reducing over the population

A reduction runs a query over every matching component column, folds each value into an accumulator, and combines the per-chunk accumulators. Run one against the world reference the model exposes:

let query = QueryBuilder::with_registry(registry)
    .read::<Position>()?
    .build()?;

let stats = model.ecs().world_ref().reduce_read::<Position, Welford>(
    query,
    Welford::default,
    |acc, pos| acc.push(pos.x as f64),
    |acc, other| acc.combine(other),
)?;
println!("count={} mean={:.3} variance={:.3}", stats.n, stats.mean, stats.variance());

The built-in accumulators are Count, Sum, MinMax, and Welford (count, mean, and variance). Welford::combine merges partials so a reduction returns the same result regardless of how the population is partitioned across threads. For two-component folds, use reduce_read2.

Reading the environment

Model-wide values live in the environment, keyed by name and type. Read the current value with the model's environment handle:

let value: MyState = model.environment().get::<MyState>("my_state")?;

The environment holds aggregates a system computes once per tick (for example, a price index) and audit records. See use environment values.

Recording a time series

To record a trajectory, read after each tick and append a row. Define each output schema's column names once, next to the code that formats the row, so the header and the values stay aligned. The macroeconomy example uses this pattern; see collect results and profiles.