The modern standard for representing planning problems
PDDL is a standardized language for representing planning problems. It extends STRIPS with modern features like types, variables, and structured syntax.
Think of PDDL as the "programming language" for planning - it provides a common format that any planning system can read and solve.
Why PDDL?
Before PDDL, every planner used its own format. PDDL unified the field!
Quick reference guide for PDDL syntax elements
| Element | Syntax | Example | File |
|---|---|---|---|
| Domain Header | (define (domain <name>) ...) |
(define (domain blocks) ...) |
Domain |
| Requirements | (:requirements <feature>...) |
(:requirements :strips :typing) |
Domain |
| Types | (:types <type>...) |
(:types robot location cargo) |
Domain |
| Predicates | (:predicates (<name> ?var - type)...) |
(at ?robot - robot ?loc - location) |
Domain |
| Action | (:action <name> ...) |
(:action move ...) |
Domain |
| Parameters | :parameters (?var - type...) |
:parameters (?r - robot ?from ?to - location) |
Domain |
| Precondition | :precondition <formula> |
:precondition (at ?r ?from) |
Domain |
| Effect | :effect <formula> |
:effect (at ?r ?to) |
Domain |
| Conjunction | (and <formula>...) |
(and (at ?r ?loc) (clear ?loc)) |
Domain |
| Negation | (not <formula>) |
(not (at ?r ?from)) |
Domain |
| Problem Header | (define (problem <name>) ...) |
(define (problem blocks-1) ...) |
Problem |
| Domain Link | (:domain <name>) |
(:domain blocks) |
Problem |
| Objects | (:objects <obj> - type...) |
(:objects robot1 - robot kitchen - location) |
Problem |
| Initial State | (:init <fluent>...) |
(:init (at robot1 kitchen) (clear table)) |
Problem |
| Goal | (:goal <formula>) |
(:goal (at robot1 bedroom)) |
Problem |
| Variables | ?<name> |
?robot ?from ?to |
Both |
| Constants | <lowercase-name> |
robot1 kitchen block-a |
Both |
?A PDDL planning task consists of TWO separate files:
Defines the general planning domain
(define (domain blocks) (:types block) (:predicates (on ?x ?y - block) (clear ?x - block)) (:action move :parameters (?x ?y - block) :precondition (clear ?x) :effect (on ?x ?y)) )
Reusable across many problems
Defines a specific problem instance
(define (problem blocks-1) (:domain blocks) (:objects a b c - block) (:init (on a b) (clear a) (clear c)) (:goal (on a c)) )
Specific instance to solve
Let's build a complete domain file for the Spare Tire problem:
;; Spare Tire Domain (define (domain spare-tire) ;; 1. Requirements (optional features) (:requirements :strips :typing) ;; 2. Types - Categories of objects (:types tire location ) ;; 3. Predicates - Relations that can be true/false (:predicates (tire-at ?t - tire ?loc - location) ;; tire ?t is at location ?loc ) ;; 4. Actions - What can be done (:action remove :parameters (?tire - tire ?from - location) :precondition (tire-at ?tire ?from) :effect (and (not (tire-at ?tire ?from)) (tire-at ?tire ground) ) ) (:action put-on :parameters (?tire - tire) :precondition (tire-at ?tire ground) :effect (and (not (tire-at ?tire ground)) (tire-at ?tire axle) ) ) )
(define (domain spare-tire) ...)
Names the domain. This name will be referenced by problem files.
(:types tire location)
Defines categories of objects. Like classes in OOP!
tire type includes: flat-tire, spare-tirelocation type includes: axle, trunk, ground
(:predicates (tire-at ?t - tire ?loc - location))
Defines relations. Variables start with ?
(tire-at flat-tire axle) means "flat-tire is at axle"
(:action remove :parameters (?tire - tire ?from - location) :precondition (tire-at ?tire ?from) :effect (and (not (tire-at ?tire ?from)) (tire-at ?tire ground)) )
Parameterized actions! The ?tire and ?from are variables that get instantiated with actual objects.
Watch how we convert a plain text description into formal PDDL syntax!
Now let's define a specific problem instance using the domain:
;; Spare Tire Problem Instance (define (problem tire-problem-1) ;; 1. Link to domain file (:domain spare-tire) ;; 2. Objects - Specific instances (:objects flat-tire spare-tire - tire axle trunk ground - location ) ;; 3. Initial State - What's true at start (:init (tire-at flat-tire axle) (tire-at spare-tire trunk) ) ;; 4. Goal - What we want to achieve (:goal (tire-at spare-tire axle) ) )
(define (problem tire-problem-1) (:domain spare-tire) ...)
Names the problem and links to the domain.
(:objects flat-tire spare-tire - tire ...)
Lists specific objects with their types.
(:init (tire-at flat-tire axle) (tire-at spare-tire trunk))
Ground atomic fluents that are true initially.
(:goal (tire-at spare-tire axle))
What we want to achieve. Can be a conjunction of facts.
(:goal (and (tire-at spare-tire axle) (tire-at flat-tire ground)))
Watch how we convert a problem description into formal PDDL syntax!
PDDL uses Action Schemas - parameterized templates that define families of actions using variables instead of specific objects.
From STRIPS to PDDL: STRIPS used ground actions (e.g., Move(Robot1, Kitchen, Bedroom)).
PDDL generalizes with schemas: move(?r, ?from, ?to)
(:action move
:parameters (?robot - robot ?from - location ?to - location)
:precondition (and (at ?robot ?from) (connected ?from ?to))
:effect (and (not (at ?robot ?from)) (at ?robot ?to))
)
Instantiates to...
move(robot1, kitchen, bedroom)
move(robot2, hallway, office)
move(robot1, bedroom, bathroom)
| Action Name | move |
| :parameters | Typed variables (?robot - robot) |
| :precondition | Conditions using variables |
| :effect | Changes using variables |
(:action pick-up
:parameters (?pkg - package
?truck - truck
?loc - location)
:precondition (and
(at ?truck ?loc)
(at ?pkg ?loc)
)
:effect (and
(not (at ?pkg ?loc))
(in ?pkg ?truck)
)
)
pick-up(pkg1, truck1, warehouse)
pick-up(pkg1, truck2, warehouse)
pick-up(pkg2, truck1, depot)
pick-up(pkg2, truck2, depot)
...and many more combinations!
?x - type) and structured representation.
Variables in PDDL (marked with ?) are placeholders that get replaced
with actual objects when creating ground actions. This is called instantiation or grounding.
(:action remove :parameters (?tire - tire ?from - location) ... )
Instantiate
remove(flat-tire, axle)remove(flat-tire, trunk)remove(spare-tire, axle)remove(spare-tire, trunk)remove)
;; Action Schema (:action move :parameters (?robot - robot ?from - location ?to - location) :precondition (at ?robot ?from) :effect (and (not (at ?robot ?from)) (at ?robot ?to)) ) ;; Objects (:objects robot1 - robot kitchen bedroom bathroom - location) ;; This generates ground actions like: ;; move(robot1, kitchen, bedroom) ;; move(robot1, kitchen, bathroom) ;; move(robot1, bedroom, kitchen) ;; ... etc (3×2 = 6 total moves)
A more complex example with multiple types and actions:
(define (domain air-cargo) (:requirements :strips :typing) (:types cargo plane city) (:predicates (at-cargo ?c - cargo ?city - city) (at-plane ?p - plane ?city - city) (in-cargo ?c - cargo ?p - plane) ) (:action load :parameters (?c - cargo ?p - plane ?city - city) :precondition (and (at-cargo ?c ?city) (at-plane ?p ?city)) :effect (and (not (at-cargo ?c ?city)) (in-cargo ?c ?p)) ) (:action unload :parameters (?c - cargo ?p - plane ?city - city) :precondition (and (in-cargo ?c ?p) (at-plane ?p ?city)) :effect (and (not (in-cargo ?c ?p)) (at-cargo ?c ?city)) ) (:action fly :parameters (?p - plane ?from - city ?to - city) :precondition (at-plane ?p ?from) :effect (and (not (at-plane ?p ?from)) (at-plane ?p ?to)) ) )
(define (problem cargo-problem-riyadh-jeddah) (:domain air-cargo) (:objects cargo1 cargo2 - cargo plane1 - plane riyadh jeddah dammam - city ) (:init ;; Initial locations (at-cargo cargo1 riyadh) (at-cargo cargo2 riyadh) (at-plane plane1 riyadh) ) (:goal (and (at-cargo cargo1 jeddah) (at-cargo cargo2 dammam) ) ) )
load(cargo1, plane1, riyadh)load(cargo2, plane1, riyadh)fly(plane1, riyadh, jeddah)unload(cargo1, plane1, jeddah)fly(plane1, jeddah, dammam)unload(cargo2, plane1, dammam)See how action schemas with variables expand into ground actions!
Execute PDDL actions step-by-step and see state changes in real-time!
You've successfully solved the problem! The spare tire is now on the axle.
Test your PDDL syntax knowledge! Type predicates and actions to validate them.
(at-robot ?r ?loc)?: ?robot, ?from, ?tomove, pick-up, put-downrobot1, kitchen, block-aLearn from these common errors to avoid frustration!
(:predicates at-robot ?r - robot ?loc - location holding ?r - robot ?b - box )
Problem: Predicates must be enclosed in parentheses!
(:predicates (at-robot ?r - robot ?loc - location) (holding ?r - robot ?b - box) )
Solution: Each predicate needs its own parentheses.
(:init (at ?robot1 kitchen) (empty ?robot1) )
Problem: Variables (?) only in domain, not problem!
(:init (at robot1 kitchen) (empty robot1) )
Solution: Use constants (no ?) in problem files.
(:action move :parameters (?r ?from ?to) :precondition (at ?r ?from) ... )
Problem: Parameters have no types! Planner won't know what they are.
(:action move :parameters (?r - robot ?from - location ?to - location) :precondition (at ?r ?from) ... )
Solution: Always specify types with - type syntax.
(:action move :parameters (?r - robot ?from - location ?to - location) :precondition (at ?r ?from) :effect (at ?r ?to) )
Problem: Robot will be in BOTH locations!
(:action move :parameters (?r - robot ?from - location ?to - location) :precondition (at ?r ?from) :effect (and (not (at ?r ?from)) (at ?r ?to)) )
Solution: Use not to remove old facts.
:init, it's automatically FALSE!
(:init (at robot1 kitchen) (not (at robot1 bedroom)) (not (at robot1 bathroom)) )
Problem: Don't explicitly state negative facts!
(:init (at robot1 kitchen) )
Solution: Only list TRUE facts. Everything else is false by CWA.
at-robot not ar:typing requirement - it prevents many errorsSee how Domain and Problem files work together!
(:types robot box room)
(at-robot ?r - robot ?loc - room)
(:action move
:parameters (?r ?from ?to)
...
)
Maps to
(:objects robot1 - robot kitchen - room)
(at-robot robot1 kitchen)
move(robot1, kitchen, bedroom)
Domain types define categories
robot box room
⬇
Problem objects are instances
robot1, box-a, kitchen
Domain uses variables
?r ?loc (with ?)
⬇
Problem uses constants
robot1 kitchen (no ?)
Domain defines action schemas
move(?r, ?from, ?to)
⬇
Problem produces ground actions
move(robot1, kitchen, bedroom)
See how everyday descriptions become formal PDDL code!
Scenario:
"We have a delivery robot that needs to move packages between rooms."
What the robot can do:
Current situation:
Goal:
Get Package-A to the office
(define (domain delivery) (:types robot package room) (:predicates (at-robot ?r - robot ?loc - room) (at-package ?p - package ?loc - room) (holding ?r - robot ?p - package) (empty ?r - robot) ) (:action move :parameters (?r - robot ?from ?to - room) :precondition (at-robot ?r ?from) :effect (and (not (at-robot ?r ?from)) (at-robot ?r ?to)) ) (:action pick-up :parameters (?r - robot ?p - package ?loc - room) :precondition (and (at-robot ?r ?loc) (at-package ?p ?loc) (empty ?r)) :effect (and (not (at-package ?p ?loc)) (not (empty ?r)) (holding ?r ?p)) ) (:action drop :parameters (?r - robot ?p - package ?loc - room) :precondition (and (at-robot ?r ?loc) (holding ?r ?p)) :effect (and (not (holding ?r ?p)) (at-package ?p ?loc) (empty ?r)) ) )
(define (problem delivery-task-1)
(:domain delivery)
(:objects
robot1 - robot
package-a - package
warehouse office - room
)
(:init
(at-robot robot1 warehouse)
(at-package package-a warehouse)
(empty robot1)
)
(:goal
(at-package package-a office)
)
)
robot typepackage typeroom type
move actionpick-up actiondrop action
(at-robot robot1 warehouse)(at-package package-a office)
| Natural Language | PDDL |
| "X can do Y" | (:action Y ...) |
| "X is in Y" | (at X Y) |
| "X is holding Y" | (holding X Y) |
| "X must be true before..." | :precondition |
| "After doing X, Y becomes true" | :effect Y |
| "X is no longer true" | (not X) |
| Feature | STRIPS (1971) | PDDL (1998+) |
|---|---|---|
| Variables | ❌ No variables (only ground actions) | ✅ Variables in action schemas |
| Types | ❌ No type system | ✅ Objects have types |
| Syntax | Informal notation | Structured Lisp-like syntax |
| Effects | Add/Delete lists | (and ... (not ...)) format |
| Files | Single representation | Separate domain + problem files |
| Standardization | Informal standard | Official standard for competitions |
| Example Action |
Remove(Flat, Axle)Ground action |
(:action remove :parameters (?t - tire ?from - location) ...)Parameterized schema |
?, get grounded to objects