Skip to content

wickerlab/swarm_is

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SWARM-IS

Code release accompanying a research-paper submission on adaptive swarm-based surveillance of invasive predators. The repository contains a spatially-explicit discrete-time simulation framework and the SWARM-IS search strategy described in the paper, together with the baseline strategies (Random, Systematic) and the experimental configurations used in the paper's sensitivity sweep, re-infestation, and scaling experiments.

Requirements

Python 3.12+. Install runtime dependencies:

pip install -r requirements.txt

Repository layout

src/                  Simulation framework + SWARM-IS implementation
  estimation/         Belief-surface estimators
  sensor_planning/    Sensor planners (incl. info-gain Steiner-tree)
  control_planning/   Control planners (probabilistic removal)
  simulation/         Main loop and Hungarian matching
  experiment/         Config loading, experiment runner
  tuning/             Ray Tune + Ax integration
  metrics/            Loss and distance metrics
  observation/        Per-node detection broker
  utils/              Visualisation, video, IO helpers
experiments/          Strategy + sweep + sub-config JSONs (see below)
risk_maps/            Pre-computed CSV risk maps
scripts/              run_all_experiments.sh, run_from_tuning.py, concat_*.py
docs/design.md        Architecture, component interfaces, extension points
cli.py                Single entry point (single-run, tune, resume, video)

Quickstart: single simulation

Run one ready-to-execute example per strategy:

python cli.py -c experiments/example_dual_steiner.json    # SWARM-IS
python cli.py -c experiments/example_random.json          # Random baseline
python cli.py -c experiments/example_systematic.json      # Systematic baseline

Each example combines a strategy with one representative sensitivity-sweep cell (the paper's headline operating point: g0_intercept = 5.5, false_positive_probability = 0.15, predator_elimination_probability = 0.8, initial_density_pha = 5, prior_risk_estimate = "Patchy"). Strategy hyperparameters are the Ax-best configurations extracted from our actual tuning runs at this cell, so a single-seed example invocation reproduces the per-condition tuned performance (within seed noise): SWARM-IS $\approx 0.49$ final loss vs Random $\approx 0.53$ and Systematic $\approx 0.78$.

Results are written to results/<config.name>/<timestamp>/:

  • results.csv — per-iteration loss and distance_moved.
  • config.json — exact config used.
  • Optional artefacts (video, plots, distribution frames) per CLI flag.

The strategy templates experiments/strategy_{dual_steiner,random,systematic}.json encode the same strategies with sample directives ("uniform(...)", "loguniform(...)", "randint(...)") in place of literal hyperparameter values. They are the inputs to --tune; they are not runnable directly.

Two-phase paper-experiment workflow

The paper experiments use a tune-then-evaluate workflow because each strategy's optimal hyperparameters depend on the experimental condition.

Phase 1: tune each strategy

Run Bayesian optimisation (Ax via Ray Tune) over each strategy's hyperparameter space, across the full grid of environmental conditions defined in experiments/sensitivity_sweep.json:

for strat in random systematic dual_steiner; do
    python cli.py --tune \
        -c experiments/strategy_${strat}.json \
        --sensitivity_combinations experiments/sensitivity_sweep.json \
        --n_samples 100
done

Each tuning run produces per-condition trial CSVs under results/<strategy-name>/<timestamp>/. The strategy name is taken from the "name" field of the strategy config (random, systematic, dual_steiner).

Useful tuning flags:

  • --n_samples N — number of Ax trials per sensitivity cell.
  • --max_concurrent K — number of trials evaluated concurrently (1 = fully sequential Bayesian).
  • --cpus_per_trial C — Ray per-trial CPU budget.
  • --contextual — single joint GP across tuning + sensitivity dimensions instead of independent per-cell searches.
  • --resume <path> — resume a partial tuning run.
  • --extract_bests --resume <path> — extract empirical and model-predicted best configs per cell from a completed contextual run.

Phase 2: evaluate the tuned strategies

After tuning, the driver script reads the tuning result CSVs, picks the best configuration per sensitivity cell, and runs n_repeats evaluation simulations for each (strategy, sweep cell, sub-experiment) combination:

bash scripts/run_all_experiments.sh results/all results/experiments

Arguments:

  • $1 (default results/all) — root directory containing one subdir per strategy. The driver expects results/all/{random,systematic,dual_steiner}/, each holding the tuning CSVs from Phase 1. Symlink or move your tuning outputs accordingly.
  • $2 (default results/experiments) — destination for evaluation summaries.

Environment overrides:

  • N_REPEATS (default 10) — number of evaluation seeds per cell.
  • N_WORKERS (default 1) — parallel workers for base-experiment cells.

The driver runs three sub-experiments per strategy, each defined by a sub-config in experiments/:

  • base_experiment.json — full 432-cell sensitivity grid, no overrides.
  • reinfestation_d{0.5,2.5,5,7.5}.json — per-density re-infestation scenarios; concatenated post-hoc by scripts/concat_reinfestation_summaries.py.
  • scaling_experiment.json — swarm-size scaling sweep.

Sub-configs have the shape:

{
  "tuning_filters": { /* fix some dimensions of the tuning run */ },
  "sweep":          { /* Cartesian sweep over result selection */ },
  "overrides":      { /* per-run overrides applied after best-config lookup */ }
}

Outputs:

results/experiments/<strategy>/<sub-experiment>/summary.csv
results/experiments/<strategy>/reinfestation_experiment/summary.csv  (concat)

Optional utilities

cli.py supports several output artefacts (single-run mode only):

  • --make_video — render an MP4 of the simulation. Saved to the run's output directory. Requires opencv-python.
  • --make_plots — emit PNGs of node trajectories and the final belief / posterior surface.
  • --render_distributions — save per-iteration frames of the belief surface as PNGs for offline animation.
  • --track_simulation_progression / -k — record per-iteration belief surfaces and predator positions in the result file (off by default to keep file sizes small).
  • --tag <str> — prefix the run's timestamp directory with a custom tag.

Extending

  • New estimator: subclass BaseEstimator (src/estimation/base.py), implement update(reports), export from src/estimation/__init__.py, set "detection_surface.name" in config.
  • New sensor planner: subclass BasePlanner (src/sensor_planning/base.py), implement get_initial_locations and get_new_detector_locations, export from src/sensor_planning/__init__.py, set "planner.name" in config.
  • New control planner: subclass BaseControlPlanner, implement decide(...), wire into build_components() in src/experiment/config.py.

See docs/design.md for the full interface specification and the main loop step ordering.

Credits

This release uses pre-computed risk maps produced by the third-party landscape generator flsgen (GPLv3). See CREDITS.md.

License

Copyright (c) 2026 Hugh Parsons.

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for the full text.

If you are interested in using the code under a different license, please contact us.

About

Algorithm from the paper "SWARM-IS: Adaptive Sensor Swarm Search Strategy and Simulation Framework for Predator Surveillance and Control"

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors