PDDL Basics
Planning Domain Definition Language, or PDDL, is the common file format used to describe planning problems. It gives you a standard way to say what actions are available, what is true at the start, and what you want to be true at the end.
A small example
Here is a small domain file and problem file for a truck carrying a package
from A to B.
;; domain.pddl
(define (domain delivery)
(:predicates
(truck-at ?loc)
(package-at ?loc)
(package-loaded)
(road ?from ?to))
(:action load-package
:parameters (?loc)
:precondition
(and
(truck-at ?loc)
(package-at ?loc))
:effect
(and
(package-loaded)
(not (package-at ?loc))))
(:action move-truck
:parameters (?from ?to)
:precondition
(and
(truck-at ?from)
(road ?from ?to))
:effect
(and
(not (truck-at ?from))
(truck-at ?to)))
(:action unload-package
:parameters (?loc)
:precondition
(and
(truck-at ?loc)
(package-loaded))
:effect
(and
(package-at ?loc)
(not (package-loaded))))
)
;; problem.pddl
(define (problem deliver-package)
(:domain delivery)
(:objects A B)
(:init
(truck-at A)
(package-at A)
(road A B))
(:goal
(package-at B))
)
This is enough to describe the whole problem: what facts can exist, what is true at the start, what needs to be true at the end, and what actions the planner can use in between.
Breaking it down
The domain file and problem file each do a different job.
- The domain file defines the actions.
- The problem file defines the specific objects, starting facts, and goal.
Predicates
Predicates are the properties and relationships that can be true in a state.
In the example above, truck-at, package-at, package-loaded, and road
are the predicates.
They let the planner describe things like where the truck is, where the package is, whether the package is loaded, and whether two locations are connected.
(:predicates
(truck-at ?loc)
(package-at ?loc)
(package-loaded)
(road ?from ?to))
Facts
Facts are the statements that are true in one specific run of the problem.
(truck-at A) is a fact. (package-loaded) is a fact. (road A B) is a fact.
Facts are what make the abstract predicates concrete. The predicate says what kind of thing can be stated. The fact says what is actually true here.
(:init
(truck-at A)
(package-at A)
(road A B))
Initial state
The initial state is the set of facts that are true before anything happens.
In the example, the truck starts at A, the package starts at A, and there
is a road from A to B.
This is the starting point the planner begins from.
(truck-at A)
(package-at A)
(road A B)
Goal state
The goal state is the set of facts that must be true at the end. In the
example, the package must be at B.
The planner is trying to find actions that make the goal true from the initial state.
(:goal
(package-at B))
Actions
Actions are the steps the planner can choose from. Each action has a name, preconditions, and effects.
load-packagemakes the package loaded.move-truckmoves the truck from one location to another.unload-packageputs the package down at the current location.
The preconditions say when an action is allowed. The effects say what changes after it runs.
(:action move-truck
:parameters (?from ?to)
:precondition
(and
(truck-at ?from)
(road ?from ?to))
:effect
(and
(not (truck-at ?from))
(truck-at ?to)))
Why the split matters
The split between domain and problem makes the planning setup reusable. The same actions and predicates can be used again and again while the starting facts and goal change for each new case. That is useful when the workflow repeats with different locations, items, or starting conditions.