Pathfinding via Reinforcement and Imitation Multi-Agent Learning
Leveraging LaCAM3
Official PyTorch implementation and pretrained evaluation package for multi-agent pathfinding (MAPF).
Overview · Quick start · Evaluation · 1,000-agent run · Repository layout
PRIMAL3 is a learning-based framework for multi-agent pathfinding (MAPF) that combines reinforcement learning with structured coordination. It targets difficult topological situations—such as bottlenecks, dead ends, and persistent conflicts—while retaining decentralized policy execution.
| Component | Purpose |
|---|---|
| Topology-aware communication | Represents compatible following relationships and competing paths using complementary interaction graphs. |
| LaCAM3-guided training | Uses confidence-triggered expert interventions and imitation targets for uncertain decisions. |
| PIBT action refinement | Applies persistent, learned, and distance-aware priorities to refine joint actions and prevent collisions. |
| Cross-scale evaluation | Includes input clipping and fast path extraction for evaluation beyond the training scale. |
This repository provides reproducible 32 × 32 benchmark instances for 50, 100, 150, 200, 250, and 300 agents, a separate 72 × 72 random-map set for 1,000-agent evaluation, and a utility for downloading the pretrained checkpoint from Hugging Face.
The provided Conda environment uses Python 3.11 and includes the required PyTorch, Ray, scientific-computing, and visualization dependencies.
conda env create -f MAPF.yml
conda activate MAPFNote
Run all commands from the repository root. Evaluation paths are relative to this directory.
Download the model before running any evaluation:
python checkpoint_utils.pyThe script downloads hechengyang/PRIMAL3 from Hugging Face and places net_checkpoint.pkl at the path expected by all evaluation runners:
models/primal3/primal3_v22_pibt_inherit_v217-06-261404/26427392/net_checkpoint.pkl
The checkpoint is approximately 140 MiB. If it already exists, the script reuses the local file instead of downloading it again.
Important
Run checkpoint_utils.py after installing the environment and before running either the standard evaluator or the 1,000-agent evaluator.
python run_the_instances.pyThe default configuration evaluates the pretrained model with 50 agents on 200 saved instances. Inference runs on CPU and test cases are parallelized with Ray.
All evaluation commands below expect the checkpoint downloaded by checkpoint_utils.py to be present at the default model path.
Set EnvParameters.N_AGENTS in alg_parameters.py:
class EnvParameters:
N_AGENTS = 150The selected value must match one of the bundled instance sets:
| Agents | Instance file |
|---|---|
| 50 | 32length_50agents_0.2density.pth |
| 100 | 32length_100agents_0.2density.pth |
| 150 | 32length_150agents_0.2density.pth |
| 200 | 32length_200agents_0.2density.pth |
| 250 | 32length_250agents_0.2density.pth |
| 300 | 32length_300agents_0.2density.pth |
All instance files are stored under 32_size_maps/32_32_0.2/.
The main runtime settings are near the bottom of run_the_instances.py:
ray.init(num_cpus=25)
num_runs = 200- Lower
num_cpuswhen fewer CPU cores are available. - Lower
num_runsfor a shorter smoke test. - Keep
num_runswithin the number of cases stored in the selected instance file.
After evaluation, the script reports:
- success rate — fraction of instances in which every agent reaches its goal;
- average steps — mean episode length across evaluated instances;
- reach rate — fraction of agents that reach their goals.
The random_1000 runner evaluates PRIMAL3 on 200 saved random-map instances. Each instance contains 1,000 agents on a 72 × 72 map with obstacle density 0.2.
The runner constructs the instance filename from EnvParameters, so first set these values in alg_parameters.py:
class EnvParameters:
N_AGENTS = 1000
WORLD_SIZE = (72, 72)
OBSTACLE_PROB = (0.19, 0.2)This selects the bundled instance file:
32_size_maps/random_1000/72length_1000agents_0.2density.pth
Note
These values are shared with the standard evaluator. Restore N_AGENTS = 50 and WORLD_SIZE = (32, 32) before returning to the default 32 × 32 evaluation.
From the repository root, run all 200 cases:
python 32_size_maps/random_1000/run_the_instances.pyUse --num_cases for a shorter run:
python 32_size_maps/random_1000/run_the_instances.py --num_cases 5The runner uses 25 Ray CPU workers by default and reports the same success-rate, average-step, and reach-rate metrics as the standard evaluator. Adjust ray.init(num_cpus=25) inside the runner if the machine has fewer available cores.
SVG generation is optional. Pass --svg_save_dir to save one animated trajectory for each evaluated case:
python 32_size_maps/random_1000/run_the_instances.py \
--num_cases 5 \
--svg_save_dir 32_size_maps/random_1000/svgsThe files follow this naming scheme:
anim_<case-index>_<status>.svg
anim_0_success.svgmeans every agent in case0reached its goal before the episode limit.anim_12_fail.svgmeans case12reached the episode limit before all agents arrived.
Each SVG is a self-contained, looping animation of one 72 × 72 episode:
| Element | Appearance |
|---|---|
| Obstacles | Dark grid cells |
| Agent goals | Hollow circles outlined with the corresponding agent color |
| Agents | Filled colored circles moving along their recorded trajectories |
Open an SVG directly in a modern web browser to play it. The existing svgs/ directory contains pre-generated animations for the saved cases.
Warning
A 1,000-agent SVG stores every agent position at every timestep. Individual files can be several megabytes, and the full 200-case directory can exceed 600 MB. Use a small --num_cases value when testing, or omit --svg_save_dir when only aggregate metrics are needed.
The central configuration lives in alg_parameters.py.
| Setting | Default | Description |
|---|---|---|
EnvParameters.N_AGENTS |
50 |
Number of agents used by the bundled evaluator. |
EnvParameters.WORLD_SIZE |
(32, 32) |
Benchmark map dimensions. |
EnvParameters.OBSTACLE_PROB |
(0.19, 0.2) |
Obstacle-density range; evaluation instances use 0.2. |
EnvParameters.EPISODE_LEN |
512 |
Maximum number of steps per episode. |
EnvParameters.CLIP |
True |
Clips scale-dependent observations to their training range. |
EnvParameters.FAST_PATHS |
True |
Uses cached goal-BFS maps for large-scale path extraction. |
EnvParameters.PIBT_SVO_WEIGHT |
1 |
Weight of the learned social priority in PIBT shielding. |
The pretrained checkpoint downloaded by checkpoint_utils.py is stored at:
models/primal3/primal3_v22_pibt_inherit_v217-06-261404/26427392/net_checkpoint.pkl
.
├── alg_parameters.py # Environment, network, and optimization settings
├── checkpoint_utils.py # Hugging Face checkpoint downloader
├── run_the_instances.py # Parallel pretrained-model evaluation
├── sequence_test.py # Hand-authored scenario runner and SVG export
├── mapf_gym.py # MAPF environment and execution logic
├── model.py # Model interface, inference, and optimization
├── net.py # Policy/value network
├── dual_comms.py # Topology-aware agent communication
├── transformer.py # Attention modules
├── pibt_shielding.py # Priority-based action refinement
├── expert_guidance.py # LaCAM3 expert integration
├── lacam3/ # Bundled LaCAM3 Python bindings and source
├── pibt/ # PIBT implementation
├── models/ # Downloaded PRIMAL3 checkpoint destination
└── 32_size_maps/ # Saved benchmark instances
└── random_1000/ # 72 × 72 / 1,000-agent runner, cases, and SVGs
The pretrained checkpoint is missing
Activate the project environment and run python checkpoint_utils.py from the repository root. The downloader creates the expected model directory automatically.
huggingface_hub is not installed
Activate the MAPF environment. If it was created before the downloader dependency was added, update it with conda env update -f MAPF.yml and run the download command again.
Ray tries to start more workers than the machine can support
Reduce num_cpus in run_the_instances.py. For a quick local check, also reduce num_runs.
The selected instance file cannot be found
Confirm that N_AGENTS is one of the six supported values and that the command is being run from the repository root.
CUDA is unavailable during evaluation
The pretrained evaluator explicitly loads its checkpoint onto CPU, so a GPU is not required for run_the_instances.py.
This project is released under the MIT License.
For questions about PRIMAL3, contact Chengyang He at chengyanghe@u.nus.edu or hecy@stanford.edu.