Scenario API Demo: Route-Choice Sweep on RiMEA 10#

This notebook showcases the improved Scenario API for scripting workflows. Features demonstrated:

Feature

Old way

New way

Visualise layout

Manual matplotlib + raw dict coords

scenario.plot()

Discover distributions

Dig through raw["distributions"]

scenario.list_distributions()

Reference by index

Look up key string manually

scenario.set_agent_count(0, 50)

Independent copies

from copy import deepcopy; s2 = deepcopy(s)

s2 = s.copy()

Input validation

Silent corruption

ValueError on bad input

Zones / checkpoints

Edit raw dict by hand

set_zone_speed_factor(), set_checkpoint_waiting_time()

Scenario: RiMEA 10 — 12 rooms, 2 exits, pre-assigned routes. We sweep agent counts to see how crowd size affects evacuation time.

import logging
from datetime import datetime

# Silence jupedsim-scenarios' INFO/DEBUG output. See the howto
# "How do I inspect a scenario?" for the full list of levels.
logging.getLogger("jupedsim_scenarios").setLevel(logging.WARNING)

print(f"Executed on {datetime.now().strftime('%d.%m.%Y, %H:%M')}")

import matplotlib.pyplot as plt
import numpy as np

from jupedsim_scenarios import load_scenario, run_sweep

plt.rcParams.update({
    "figure.facecolor": "white",
    "axes.facecolor": "#f7f7f5",
    "axes.edgecolor": "#3a3a3a",
    "axes.labelcolor": "#1d1d1d",
    "axes.titleweight": "bold",
    "font.size": 11,
})
Executed on 21.07.2026, 09:39

1. Load and Discover#

list_distributions() returns a clean summary — no need to dig through nested dicts.

base = load_scenario("scenario_files/Rimea-10.zip")
print(base.summary())
print()

# Discovery: one call instead of navigating raw dicts
for d in base.list_distributions():
    print(d)
Scenario: /home/runner/work/jupedsim-scenarios/jupedsim-scenarios/docs/source/notebooks/cookbook/scenario_files/Rimea-10.zip
  Model:         CollisionFreeSpeedModel
  Seed:          420
  Max time:      300s
  Exits:         2
  Distributions: 12
  Stages:        0
  Zones:         0
  Journeys:      0
  Agents:        ~13
    jps-distributions_0: 1 agents
    jps-distributions_1: 1 agents
    jps-distributions_2: 1 agents
    jps-distributions_3: 1 agents
    jps-distributions_4: 1 agents
    jps-distributions_5: 1 agents
    jps-distributions_6: 1 agents
    jps-distributions_7: 2 agents
    jps-distributions_8: 1 agents
    jps-distributions_9: 1 agents
    jps-distributions_10: 1 agents
    jps-distributions_11: 1 agents

{'index': 0, 'id': 'jps-distributions_0', 'agents': 1, 'flow': False}
{'index': 1, 'id': 'jps-distributions_1', 'agents': 1, 'flow': False}
{'index': 2, 'id': 'jps-distributions_2', 'agents': 1, 'flow': False}
{'index': 3, 'id': 'jps-distributions_3', 'agents': 1, 'flow': False}
{'index': 4, 'id': 'jps-distributions_4', 'agents': 1, 'flow': False}
{'index': 5, 'id': 'jps-distributions_5', 'agents': 1, 'flow': False}
{'index': 6, 'id': 'jps-distributions_6', 'agents': 1, 'flow': False}
{'index': 7, 'id': 'jps-distributions_7', 'agents': 2, 'flow': False}
{'index': 8, 'id': 'jps-distributions_8', 'agents': 1, 'flow': False}
{'index': 9, 'id': 'jps-distributions_9', 'agents': 1, 'flow': False}
{'index': 10, 'id': 'jps-distributions_10', 'agents': 1, 'flow': False}
{'index': 11, 'id': 'jps-distributions_11', 'agents': 1, 'flow': False}

scenario.plot() renders the walkable area with labeled distributions, exits, zones, and checkpoints — one call to understand what you’re working with.

base.plot()
plt.show()
../../_images/5a5b592efa5e70ef5bbbb281fdd7e619fc31104d0a18ed7395b64cffac71af6c.png

2. Index Aliases and Input Validation#

Use integer indices instead of opaque string IDs like "jps-distributions_7". Invalid inputs raise immediately instead of silently corrupting the scenario.

# Index alias: set_agent_count(0, ...) instead of set_agent_count("jps-distributions_0", ...)
base.set_agent_count(0, 5)
print(f"Distribution 0 now has {base.list_distributions()[0]['agents']} agents")

# String keys still work
base.set_agent_count("jps-distributions_0", 1)
print(f"Distribution 0 reset to {base.list_distributions()[0]['agents']} agent")

# Validation catches mistakes early
for label, fn in [
    ("Negative count",    lambda: base.set_agent_count(0, -1)),
    ("Zero max time",     lambda: setattr(base, "max_simulation_time", 0)),
    ("Radius too large",  lambda: base.set_agent_params(0, radius=2.0)),
    ("Speed too large",   lambda: base.set_agent_params(0, desired_speed=10.0)),
]:
    try:
        fn()
        print(f"  {label}: ERROR — should have raised!")
    except ValueError:
        print(f"  {label}: caught ValueError")
Distribution 0 now has 5 agents
Distribution 0 reset to 1 agent
  Negative count: caught ValueError
  Zero max time: caught ValueError
  Radius too large: caught ValueError
  Speed too large: caught ValueError

3. Safe Copies for Parameter Sweeps#

scenario.copy() returns an independent deep copy. No more from copy import deepcopy boilerplate, and no risk of accidentally mutating the base scenario.

# Prove that copy() is independent
base.set_agent_count(0, 1)  # reset
s_copy = base.copy()
s_copy.set_agent_count(0, 99)

print(f"Original distribution 0: {base.list_distributions()[0]['agents']} agent")
print(f"Copy distribution 0:     {s_copy.list_distributions()[0]['agents']} agents")
assert base.list_distributions()[0]["agents"] == 1
assert s_copy.list_distributions()[0]["agents"] == 99
Original distribution 0: 1 agent
Copy distribution 0:     99 agents

4. Route-Choice Sweep: Crowd Size vs. Evacuation Time#

RiMEA 10 has 12 rooms feeding into 2 exits. We scale agent counts uniformly across all distributions and measure evacuation time over multiple seeds.

The sweep is driven by jupedsim_scenarios.run_sweep, which owns per-trial .copy()/cleanup, the cartesian product over the agent-count axis and seed values, and parallel dispatch via the loky backend. The mutator below uses index aliases (set_agent_count(i, n)) instead of string-key bookkeeping.

%%capture
# Sweep agents-per-room × seed via run_sweep — the library applies the
# per-distribution agent-count mutator to a fresh .copy() of the base
# for every trial and runs them in parallel (workers=4).
agents_per_room = [1, 3, 5, 8]
seeds = [42, 43, 44]
n_distributions = len(base.list_distributions())

base_with_time = base.copy()
base_with_time.max_simulation_time = 500


def _set_count_for_all_distributions(scenario, n):
    for i in range(n_distributions):
        scenario.set_agent_count(i, n)


sweep = run_sweep(
    base_with_time,
    axes={"n": agents_per_room},
    apply={"n": _set_count_for_all_distributions},
    seeds=seeds,
    workers=4,
)
df = sweep.to_dataframe()
sweep.cleanup()

# Reproduce the same `results = {total_agents: [evac_times]}` shape so
# downstream cells don't need to change.
results = {}
for n in agents_per_room:
    evac_times = df.loc[df["n"] == n, "evacuation_time"].to_numpy()
    total = n * n_distributions
    results[total] = evac_times
    print(f"{total:3d} agents -> {evac_times.mean():.1f}s (seeds: {list(evac_times)})")
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 1 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 1/1
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Variant v2_journey_2: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 3 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 3/3
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 5 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 5/5
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_0 has 1 journey variants
INFO - Variant v2_journey_0: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_1 has 1 journey variants
INFO - Variant v2_journey_1: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_2 has 1 journey variants
INFO - Variant v2_journey_4: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_3 has 1 journey variants
INFO - Variant v2_journey_5: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_4 has 1 journey variants
INFO - Variant v2_journey_6: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_5 has 1 journey variants
INFO - Variant v2_journey_7: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_6 has 1 journey variants
INFO - Variant v2_journey_3: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_7 has 1 journey variants
INFO - Variant v2_journey_2: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_8 has 1 journey variants
INFO - Variant v2_journey_11: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_9 has 1 journey variants
INFO - Variant v2_journey_10: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_10 has 1 journey variants
INFO - Variant v2_journey_9: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8
INFO - Distribution jps-distributions_11 has 1 journey variants
INFO - Variant v2_journey_8: 8 agents (weight=100.0, total=100.0)
INFO - Total agents assigned: 8/8

5. Results#

totals = sorted(results.keys())
means = np.array([results[t].mean() for t in totals])
stds = np.array([results[t].std(ddof=1) for t in totals])
cis = 1.96 * stds / np.sqrt(len(seeds))

fig, ax = plt.subplots(figsize=(9, 5.5))
ax.plot(totals, means, marker="o", color="#2563EB", linewidth=2.5, markersize=8,
        label="Mean evacuation time")
ax.fill_between(totals, means - cis, means + cis, color="#2563EB", alpha=0.15,
                label="95% CI")
for x, y in zip(totals, means, strict=False):
    ax.text(x, y + max(means) * 0.03, f"{y:.1f}s", ha="center", fontsize=10, color="#1e3a5f")

ax.set_xlabel("Total agents (12 rooms)")
ax.set_ylabel("Evacuation time [s]")
ax.set_title("RiMEA 10: Evacuation Time vs. Crowd Size", pad=12)
ax.grid(axis="y", linestyle="--", alpha=0.4)
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.legend(frameon=False)
plt.tight_layout()
plt.show()

for t in totals:
    vals = results[t]
    print(f"  {t:3d} agents -> mean {vals.mean():.2f}s, std {vals.std(ddof=1):.2f}s")
../../_images/ae6b1a13b97bc61db534c3fca47a5cc703935160426296dc2a1362bb824e88b8.png
   12 agents -> mean 13.32s, std 0.14s
   36 agents -> mean 27.13s, std 0.60s
   60 agents -> mean 41.76s, std 3.17s
   96 agents -> mean 500.00s, std 0.00s

6. Other setters#

Zones and checkpoints have dedicated setters too:

  • set_zone_speed_factor(zone_id, factor) — see the how-to How do I change a zone’s speed factor?

  • set_checkpoint_waiting_time(stage_id, seconds) — see the how-to How do I set a waiting time on a checkpoint?

Each replaces a few lines of raw dict editing with one validated call.

Summary#

The new API methods replace low-level dict manipulation with a clean, discoverable interface:

# Before (error-prone, verbose)
from copy import deepcopy
s2 = deepcopy(scenario)
dist_key = list(s2.distributions.keys())[7]
s2.distributions[dist_key]["parameters"]["number"] = 50
s2.raw["zones"]["jps-zones_0"]["speed_factor"] = 0.5

# After (concise, validated)
s2 = scenario.copy()
s2.set_agent_count(7, 50)
s2.set_zone_speed_factor(0, 0.5)