Skip to content

Add Search and Rescue example: overlapping meta-agents + scenario sweep - #491

Open
shipitdev wants to merge 1 commit into
mesa:mainfrom
shipitdev:search_and_rescue
Open

Add Search and Rescue example: overlapping meta-agents + scenario sweep#491
shipitdev wants to merge 1 commit into
mesa:mainfrom
shipitdev:search_and_rescue

Conversation

@shipitdev

Copy link
Copy Markdown
Contributor

Summary

Adds examples/search_and_rescue, filling the README's empty Continuous Space Examples section. It's the first example to exercise the meta-agent membership backend beyond static single-membership groups, and the first to use Responders sweep a continuous space to reach casualties before their survival deadlines, organising into crews, task forces and an incident command. All of that structure lives in the membership backend rather than on the agents, which is what makes the overlap possible:

Relation Group Meaning
member home crew permanent posting
on_call medical pool globally reachable
attached a borrowing crew temporarily seconded

A medic holds all three at once, and Crew.responders() enforces that exactly one crew commands it at a time. Hierarchy depth is read structurally via at_level() rather than stored — span_of_control is a query against the graph, not a counter.

This complements rather than duplicates the existing meta-agent examples: warehouse covers relation labels on as static structure, and alliance_formation covers find_combinations. Neither uses at_level, dissolve, query_memberships, or runtime formation and teardown.

Results

experiment.py runs 240 scenarios (6 crew sizes × 2 policies × 20 replications) and asserts the sequential and ProcessPoolExecutor backends agree — 0 mismatches.

  • Pooling scarce specialists beats embedding them at every crew size (+5.7 to +12.9 rescues), with the largest gain at small crews, which are least likely to hold a medic of their own.
  • Smaller crews rescue more but widen span of control (≈16 units at crew size 2 vs ≈4 at size 8) — the coordination load that real incident command systems bound.

Notes for reviewers

The example README documents several Mesa 4 sharp edges I hit while building this, in case they're useful beyond this PR:

  • MetaAgent.step shadows a step defined on the class passed as mesa_agent_type, since groups are built as type(name, (MetaAgent, *bases)). Crew behaviour is named advance() to avoid it.
  • extract_class raises StopIteration when a group name is reused after every group of that name has been dissolved — the agents_by_type bucket is retained but empty, so the name lookup succeeds and next(iter(...)) then fails. Worked around here with unique task-force names; happy to open a separate core issue with a minimal repro if that's wanted.
  • TableDataSet.data returns the whole accumulated table on every collection, so it re-snapshots if registered with a recorder. This example records a model-level time series instead.
  • Portrayal fields must be set on every agent — setting edgecolors on only some of them yields a ragged array and an IndexError in the matplotlib backend.
  • ipyvuetify<3 is pinned in requirements.txt because solara 1.61 can't drive the ipyvue 3.x line ("GlobalVue.use is not a function").

Test plan

  • pytest examples/search_and_rescue/tests/ — 26 passed
  • pytest test_examples.py — the new model constructs with no arguments and run_for(10) leaves time == 10.0
  • solara run app.py verified in a browser: space renders, crews form, medics visibly change crew colour when seconded and change back on release, plots update
  • python experiment.py --compare — 240 runs, both execution backends agree
  • ruff check and ruff format clean

Fills the empty Continuous Space section of the README with the first
example to exercise Mesa 4's meta-agent membership backend beyond static,
single-membership groups, and the first to use the scenarios runner.

Responders self-organise into crews, task forces and an incident command,
all held in the membership backend rather than on the agents. A medic is a
`member` of its home crew and `on_call` to the medical pool at the same
time, gaining a third `attached` edge when another crew borrows it, so
overlap and relation labels are load-bearing rather than decorative.
Hierarchy depth is read structurally via `at_level`.

The sweep runs 240 scenarios over crew size and specialist policy and
asserts the sequential and process-pool execution backends agree, which is
the point of the pluggable executor. Result: pooling scarce specialists
beats embedding them at every crew size, while smaller crews rescue more
at the cost of a wider span of control.

The README records several Mesa 4 sharp edges found while building this:
`MetaAgent.step` shadowing a `step` on the class passed as
`mesa_agent_type`, `extract_class` raising StopIteration when a group name
is reused after all groups of that name are dissolved, `TableDataSet`
re-snapshotting its whole table per collection, and portrayal fields
needing to be set on every agent to avoid a ragged-array IndexError.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant