class: center, middle # Artificial Intelligence ### PDDL --- class: center, middle # Planning --- # Reminder: The Planning Problem A planning problem consists of three parts: * A definition of the current state of the world * A definition of a desired state of the world * A definition of the actions the agent can take All of these definitions are done in "some" formal language. --- class: medium # The Planning Domain Definition Language (PDDL) * In The Olden Days every planner used their own input format * The formats not only differed in syntax, but also in capabilities * In 1998 Drew McDermott and colleagues developed a standardized language for planning problems: PDDL * This made comparisons between different planners easier and lead to the creating of the International Planning Competition --- class: medium # PDDL Influences * STRIPS, represented operators as preconditions, additions and deletions * Other languages, such as ADL, supported a wider variety of formulas as preconditions and effects * The idea of actions having "preconditions", that describe when they are applicable, and "effects" that describe what is changed, was common to many of them * The "core" of PDDL is therefore the definition of actions --- class: medium # PDDL Layout * PDDL separates a planning problem into two files - The domain, which defines how the actions operate - The problem, which defines the initial state and the goal * The idea is that the domain can be reused for many different problems * Since historically many planners were written in LISP, PDDL uses the same basic syntax: S-Expressions --- # S-Expressions * Simply put, an S-Expression consists of parenthesized list, where each element can be either a literal string or another S-Expression * (Classically S-Expressions are defined as having two elements, which are concatenated with a period `.`, but this is not commonly explicitly used anymore) * For example, these are all valid S-Expression: ```Lisp () (and (or (not a) b (and (not x) c d e) e)) (defun fib (n) (if (lt n 2) 1 (+ (fib (- n 1)) (fib (- n 2))))) ``` --- # S-Expressions and Logic Logic: $$ \mathit{lift-at}(\mathit{f0}) \wedge \mathit{origin}(\mathit{p0}, \mathit{f0})\\\\ \forall p \in \mathit{Ps}: \left(\mathit{served}(p) \vee \neg \mathit{boarded}(p)\right)\\\\ \forall p \in \mathit{Ps}: \forall f \in \mathit{Fs}: \left(\text{when}\:(\mathit{liftat}(f)\wedge\mathit{origin}(p,f))\quad \mathit{boarded}(p)\right) $$ ```Lisp (and (lift-at f0) (origin p0 f0)) (forall (p - Ps) (or (served p) (not (boarded p)))) (forall (p - Ps) (forall (f - Fs) (when (and (liftat f) (origin p f) ) (boarded p) ) ) ) ``` --- # S-Expressions * Why are S-Expressions useful? * They are very simple to parse, and we can use them to represent syntax trees * Remember when we discussed how one would implement logic? We can basically take S-Expressions and directly use them with these data structures --- # Structure of a PDDL Domain File .left-column[
] .right-column[ * Now we have our PDDL domain file as a parse-tree * Let's extract the individual parts * For each part we have to do some processing * After all processing, we have our domain ] --- # Structure of a PDDL Domain File .left-column[
] .right-column[ * **Requirements** * Types/Objects * Predicates * Actions ] --- # Structure of a PDDL Domain File .left-column[
] .right-column[ * Requirements * **Types/Objects** * Predicates * Actions ] --- # Structure of a PDDL Domain File .left-column[
] .right-column[ * Requirements * Types/Objects * **Predicates** * Actions ] --- # Structure of a PDDL Domain File .left-column[
] .right-column[ * Requirements * Types/Objects * Predicates * **Actions** ] --- class: medium # Extensions: "Requirements" * PDDL is a standard, but it allows for several extensions * The planner you use in lab 3 supports - `:strips` - `:typing` - `:adl`, which is an abbreviation for `:disjunctive-preconditions`, `:equality`, `:existential-preconditions`, `:universal-preconditions`, and `:conditional-effects` * There are many other extensions, related to numbers, temporal planning, probabilistic effects, etc. --- # Types * Objects and variables in PDDL can have types * Types form a hierarchy, with a root type containing *all* objects * We need to store these types so we can expand variables in e.g. forall expressions --- # Types * Types are written *after* objects * A type can be applied to multiple objects at the same time ``` p3 p6 - going_up p5 p3 p6 p2 p9 p1 - attendant p7 - never_alone p2 p7 - conflict_A p0 p9 p3 p6 p1 p8 p5 p4 - conflict_B f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 - floor ``` --- # Type Hierarchy * Similar to giving types to objects, types can also be "applied" to other types * This is used to create a type hierarchy, by saying "everything that has type X or Y also has type Z" by writing `X Y - Z` ``` passenger - object going_up going_down vip going_nonstop attendant never_alone conflict_A conflict_B - passenger floor - object ``` --- # Actions * "Actions" in PDDL are actually *operators* * That means they contain free variables, or **parameters** (often with types) * Each operator may represent multiple actions * Additionally, each operator contains a precondition and an effect --- # Action Example ```Lisp (:action up :parameters (?f1 - floor ?f2 - floor) :precondition (and (lift-at ?f1) (above ?f1 ?f2)) :effect (and (lift-at ?f2) (not (lift-at ?f1))) ) ``` --- # Structure of a PDDL Problem File .left-column[
] .right-column[ * The *domain* defines the available operators of the world * The *problem* defines the initial state and the goal condition * Objects may be spread out over both files ] --- # Structure of a PDDL Problem File .left-column[
] .right-column[ * **Domain Reference** * Additional Objects * Initial State * Goal Condition ] --- # Structure of a PDDL Problem File .left-column[
] .right-column[ * Domain Reference * **Additional Objects** * Initial State * Goal Condition ] --- # Structure of a PDDL Problem File .left-column[
] .right-column[ * Domain Reference * Additional Objects * **Initial State** * Goal Condition ] --- # Structure of a PDDL Problem File .left-column[
] .right-column[ * Domain Reference * Additional Objects * Initial State * **Goal Condition** ] --- class: center, middle # PDDL Example: Elevator --- # Domain: Types and Predicates ```Lisp (:types passenger - object floor - object ) (:predicates (origin ?person - passenger ?floor - floor) (destin ?person - passenger ?floor - floor) (above ?floor1 - floor ?floor2 - floor) (boarded ?person - passenger) (served ?person - passenger) (lift-at ?floor - floor) ) ``` --- # Domain: Drive Up and Down ```Lisp ;;drive up (:action up :parameters (?f1 - floor ?f2 - floor) :precondition (and (lift-at ?f1) (above ?f1 ?f2)) :effect (and (lift-at ?f2) (not (lift-at ?f1))) ) ;;drive down (:action down :parameters (?f1 - floor ?f2 - floor) :precondition (and (lift-at ?f1) (above ?f2 ?f1)) :effect (and (lift-at ?f2) (not (lift-at ?f1))) ) ``` --- # Domain: Stop at Floor ```Lisp (:action stop :parameters (?f - floor) :precondition (lift-at ?f) :effect (and (forall (?p - passenger) (when (and (boarded ?p) (destin ?p ?f)) (and (not (boarded ?p)) (served ?p)))) (forall (?p - passenger) (when (and (origin ?p ?f) (not (served ?p))) (boarded ?p))) ) ) ``` --- # Problem ```Lisp (:objects p0 - passenger f0 f1 - floor) (:init (above f0 f1) (origin p0 f1) (destin p0 f0) (lift-at f0) ) (:goal (forall (?p - passenger) (served ?p))) ``` --- class: center, middle # Planners --- class: small # Running a Planner * Most planners will provide you with some executable that expects two parameters: a domain file, and a problem file * Some will then perform some preprocessing step and translate the problem into some internal representation, and you may have to run a second executable on that * Then you wait ... -- * And wait ... -- * And wait ... -- * And then you get a solution (or not)! --- # Some Planners * [FastForward](https://fai.cs.uni-saarland.de/hoffmann/ff.html) * [FastDownward](http://www.fast-downward.org/) * [Glaive](http://nil.cs.uno.edu/projects/glaive/) --- # Plans * So you run a planner and it finishes * The output will be a "plan" * However, unlike for the input, there is no real standard for the output * Some/most planners will print the required actions in a PDDL/LISP-like syntax --- # planning.domains * Since planning is a very active field of research, there are many planning domains out there * [planning.domains](http://planning.domains) contains a collection of known domains, drawing from planning competitions and other sources * All of the files in that repository are PDDL files * However, they may require various extensions --- class: center, middle # Lab 3 --- # Lab 3 * In Lab 3 you will get a simple (educational) planner written in python * It parses a domain and a problem file and then performs A* to find a plan * The heuristic it uses is a very simple one, vaguely based on FastForward * Don't expect it to win any performance awards --- class: medium # Lab 3 * The planner comes with the elevator domain (and some others, you can also look at other domains from [planning.domains](http://planning.domains) if you want) * The task is to modify the domain to include **two or more** elevators * You will need an additional type ("elevators"), and additional constants * Then you have to change the actions so that they include an elevator parameter * When you set up a problem, you may observe that the planner only uses one of the elevators --- class: medium # Lab 3 For the final part of the lab, add restrictions to your elevators: - One elevator can only stop at even floors (0 is even for our purposes) - One elevator can only stop at odd floors - One elevator can only stop at floors divisible by 3 Come up with at least one more problem, with at least 8 floors and 5 customers --- class: small # Resources * [International Planning Competition](http://icaps-conference.org/index.php/Main/Competitions) * [Planning Domain Repository](https://github.com/AI-Planning/classical-domains)