Skip to main content

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-package makes the package loaded.
  • move-truck moves the truck from one location to another.
  • unload-package puts 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.