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 |
|
Discover distributions |
Dig through |
|
Reference by index |
Look up key string manually |
|
Independent copies |
|
|
Input validation |
Silent corruption |
|
Zones / checkpoints |
Edit |
|
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()
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")
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)