A PDDL planner library built around the pddl crate.
miniplan is a grounded, classical PDDL planner focused on simplicity and performance. It targets STRIPS-level domains with support for typing, negative preconditions, and conditional effects. Use it as a library in your own projects or as a CLI (miniplan) for quick planning experiments.
- PDDL 3.x parsing via pddl-rs
- Grounding to a compact bitset-based internal representation
- Planners:
bfs— blind breadth-first search (optimal)astar— A* with pluggable heuristics (optimal)gbfs— greedy best-first search (fast, non-optimal)bidij— bidirectional Dijkstra (cost-aware, optimal)bibfs-uc— bidirectional BFS (uniform-cost, optimal)nbs— Near-Optimal Bidirectional Search (heuristic-guided, non-optimal with HFF)bae— Bidirectional A* with Error / BAE* (heuristic-guided, non-optimal with HFF)
- Bidirectional heuristic search:
bidij,bibfs-uc,nbs(NBS),bae(BAE*) - Heuristics:
hff(relaxed-plan),hadd,hmax,goal-count,blind - Output formats: plain, IPC, JSON
- Search limits: time budget, node budget
- Structured logging via
tracing
[dependencies]
miniplan = "0.1"cargo install miniplan-cli --lockedThe resulting binary is miniplan (not miniplan-cli).
Or install from the git repository:
cargo install --git https://github.com/sunsided/miniplan miniplan-cligit clone https://github.com/sunsided/miniplan
cd miniplan
cargo build --releaseSolve a bundled example with search statistics:
$ miniplan solve --stats examples/pddl/blocksworld.pddl
; cost = 8
; length = 8
(unstack(a,c))
(put-down(a))
(pick-up(c))
(stack(c,d))
(pick-up(b))
(stack(b,c))
(pick-up(a))
(stack(a,b))
Search stats:
Nodes expanded: 27
Nodes generated: 45
Plan cost: 8.00
Plan length: 8
Time: 3.451169ms
Parse and ground a problem without solving:
miniplan check examples/pddl/gripper.pddlList available planners and heuristics:
$ miniplan list-planners
Available planners:
bfs Breadth-first search
astar A* search with pluggable heuristic
gbfs Greedy best-first search
bibfs-uc Bidirectional BFS (uniform-cost, not cost-aware)
bidij Bidirectional Dijkstra (cost-aware)
nbs Near-Optimal Bidirectional Search (Chen et al. 2017)
bae Bidirectional A* with Error (BAE*, Sadhukhan 2013)
Available heuristics:
goal-count
hff
blind
hadd
hmax
| Command | Description |
|---|---|
solve |
Solve a PDDL problem |
check |
Parse and ground a problem (no search) |
list-planners |
Show available planners and heuristics |
| Flag | Default | Description |
|---|---|---|
-p, --planner |
astar |
Planner to use (bfs, astar, gbfs, bidij, bibfs-uc, nbs, bae) |
-H, --heuristic |
ff |
Heuristic (hff, hadd, hmax, goal-count, blind) |
-t, --timeout |
— | Time budget (e.g. 30s, 2m) |
--max-nodes |
— | Maximum nodes to expand |
-o, --output |
- |
Output file (- for stdout) |
--format |
plain |
Output format (plain, ipc, json) |
--stats |
— | Print search statistics to stderr |
--domain |
— | Domain name (when input contains multiple) |
--problem |
— | Problem name (when input contains multiple) |
-v |
— | Verbosity (count-based: -v info, -vv debug, -vvv trace) |
| Code | Meaning |
|---|---|
| 0 | Plan found |
| 1 | Provably unsolvable |
| 2 | Search limit reached (time or nodes) |
| 3 | Unknown outcome |
use std::path::PathBuf;
use miniplan::pddl_io::load_files_named;
use miniplan::ground::ground;
use miniplan::search::{Solver, PlannerChoice, PlannerKind, PlannerConfig, SearchLimits, SearchOutcome};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load PDDL files (one combined, or domain + problem)
let files = [PathBuf::from("examples/pddl/blocksworld.pddl")];
let (domain, problem) = load_files_named(&files, None, None)?;
// Ground the task
let task = ground(&domain, &problem)?;
// Configure and run the solver
let solver = Solver::new();
let mut config = PlannerConfig::default();
config.opts.insert("heuristic".to_owned(), "hff".to_owned());
let choice = PlannerChoice {
kind: PlannerKind::Astar,
heuristic: Some("hff".to_owned()),
config,
};
let limits = SearchLimits::default();
let outcome = solver.solve_task(&task, &choice, &limits)?;
match outcome {
SearchOutcome::Plan(plan, stats) => {
println!("Plan found (cost={:.2}, length={}):", stats.plan_cost, stats.plan_length);
println!("{}", plan);
}
SearchOutcome::Unsolvable(_) => {
eprintln!("Problem is provably unsolvable.");
}
SearchOutcome::LimitReached(_) => {
eprintln!("Search limit reached.");
}
}
Ok(())
}See docs.rs for the full API.
| Feature | Status |
|---|---|
| STRIPS | Supported |
| Typing | Supported |
| Negative preconditions | Supported |
| Conditional effects | Supported |
| Disjunctive preconditions | Supported (via DNF grounding) |
| Quantified preconditions | Partial |
| Derived predicates (static bodies) | Supported |
| Numeric fluents | Not yet |
| Durative actions | Not yet |
Five PDDL problems are bundled in examples/pddl/:
| Problem | Domain | Recommended Planner |
|---|---|---|
blocksworld.pddl |
Blocksworld | astar |
gripper-small.pddl |
Gripper | bfs |
gripper.pddl |
Gripper | astar |
logistics.pddl |
Logistics | bfs |
air-cargo.pddl |
Air Cargo | astar / gbfs |
Run all examples via the Taskfile:
task example # Full demo sweep
task example:blocksworld # Single exampleThis project uses Task for automation.
task --list-all # List all available tasks
task verify # fmt + check + lint + test (full gate)
task example # Run the full example suiteA pre-commit configuration is included (.pre-commit-config.yaml) for lint checks before commits.
crates/miniplan/ Core library
src/
ground/ PDDL grounding
heuristic/ Heuristic implementations (h^FF, h^add, h^max, …)
pddl_io.rs PDDL file loading
plan.rs Plan representation and formatting
search/ Planner implementations (BFS, A*, GBFS)
task.rs Grounded task representation
util/ Utilities (bitsets, etc.)
bins/miniplan-cli/ CLI binary (produces `miniplan`)
examples/pddl/ Bundled PDDL problems
Taskfile.dist.yaml Task definitions
- Current: grounded STRIPS, BFS/A*/GBFS, h^FF
- Planned: landmark heuristics, plan validation, more PDDL coverage (numerics, durative actions)
Licensed under the European Union Public Licence 1.2 (EUPL-1.2). See the SPDX entry or the official EU page for details.
- pddl-rs — PDDL parser, forked and maintained for this project.
- Jörg Hoffmann & Bernhard Nebel — The FF planning system and relaxed-plan heuristic (Hoffmann & Nebel, The FF Planning System: Fast Planning Generation, JAIR 2001).