【翻译】PDDL 入门指南

740 阅读5分钟

Getting Started with PDDL

注:本指南译自 LearnPDDL

Introduction

PDDL 是为数不多的旨在创建人工智能 (AI) 规划标准的语言之一,它于 1998 年开发并在 ICAPS 引入,多年来一直在改进和扩展。

目前最流行的 PDDL 是 PDDL 2.1,它是 PDDL 的扩展,用于表达时域; PDDL 3 为 PDDL 2.1 添加了轨迹约束和偏好,而 PDDL+ 则允许在 PDDL 中对混合离散连续域进行建模。

Components of PDDL

在开始编写 PDDL 之前,我们需要了解如何在 PDDL 中对“世界”进行建模。

一个“世界”由一组状态描述,每个状态包含一个事实和/或对象列表。 一个“世界”从一个初始状态开始,并受一组规则和约束的约束,这些规则和约束限制了在每个状态下可以采取的行动,每个行动通常代表到不同状态的转换。

在这个“世界”中,我们需要跟踪以下事物:

  • 对象(Objects):“世界”中我们所感兴趣的事物。
  • 谓词(Predicates):我们感兴趣的事实(例如对象的属性),可以是真或假。
  • 初始状态(An Initial State):我们开始所处的“世界”状态,即开始时为真的事物。
  • 目标规范(Goal Specification):我们期望的结束时的世界状态,即我们希望最终成为真实的事物。
  • 行为/操作(Actions/Operators):改变世界状态的方式,即发生后能改变事实(真与假)的事情。

PDDL Syntax

首先你需要知道的是,通常 PDDL 文件的扩展名为 .pddl.

您需要学习以下两个 PDDL 文件的语法:

The Domain File(域文件)

Domain 文件建立了世界的背景。 它决定了状态可以包含哪些细节(谓词),以及我们可以做些什么来在世界上的状态之间移动(动作)。

Domain 文件的基本语法是:

(define (domain <domain-name>)
  (:predicates
    <predicate-list>
  )
  
  (:action
    <action-details>
  )
)

The Problem/Fact File

Problem 文件代表我们在域中建立的世界的一个实例。 它决定了计划开始时什么是真的(初始状态),以及我们希望在计划结束时是什么(目标状态)。

Problem 文件的基本语法是:

(define (problem <title>)
    (:domain <domain-name>)
    (:objects
        <object-list>
    )

    (:init
        <predicates>
    )
    (:goal 
        <predicates>
    )
)

注意: <title> 是 problem 的标题; <domain-name> 是对应的 domain 名称,需要与 domain 文件中定义的 <domain-name> 一致,而非 domain 文件名。

简单示例:Let’s Eat!

arm-cupcake.png

假设我们有一个机械手、一个纸杯蛋糕和一个盘子。 夹子是空的,纸杯蛋糕在桌子上,我们想把纸杯蛋糕放在盘子上。

在我们用 PDDL 建模之前,让我们看一下 PDDL 问题的组成部分:

首先我们定义 domain

(define (domain letseat)

然后我们定义 objects :盘子、抓手、纸杯蛋糕。 我们还将纸杯蛋糕和手臂标记为可定位,这是一个小技巧,可以帮助我们使用稍后创建的谓词查询这些对象的位置。

(:requirements :typing) 

(:types         
    location locatable - object
    bot cupcake - locatable
    robot - bot
)

我们还需要定义一些 predicates 。 夹臂是空的吗? 纸杯蛋糕在哪里?

(:predicates
    (on ?obj - locatable ?loc - location)
    (holding ?arm - locatable ?cupcake - locatable)
    (arm-empty)
    (path ?location1 - location ?location2 - location)
)

我们还必须定义 actions/operators 。 我们需要能够拿起和放下纸杯蛋糕,以及在桌子和盘子之间移动手臂。

(:action pick-up
  :parameters
   (?arm - bot
    ?cupcake - locatable
    ?loc - location)
  :precondition
   (and 
      ; Note how we use the same variable loc
      ; in both lines below. This is to make
      ; sure it's looking at the same location.
      (on ?arm ?loc) 
      (on ?cupcake ?loc) 
      (arm-empty)
    )
  :effect
   (and 
      (not (on ?cupcake ?loc))
      (holding ?arm ?cupcake)
      (not (arm-empty))
   )
)

(:action drop
  :parameters
   (?arm - bot
    ?cupcake - locatable
    ?loc - location)
  :precondition
   (and 
      (on ?arm ?loc)
      (holding ?arm ?cupcake)
    )
  :effect
   (and 
      (on ?cupcake ?loc)
      (arm-empty)
      (not (holding ?arm ?cupcake))
   )
)

(:action move
  :parameters
   (?arm - bot
    ?from - location
    ?to - location)
  :precondition
   (and 
    (on ?arm ?from) 
    (path ?from ?to)
   )
  :effect
   (and 
    (not (on ?arm ?from))
    (on ?arm ?to)
   )
)

将以上所有内容放入一个文件中,您就有了一个 domain 文件

现在我们来看看 problem 文件。 我们将首先让它知道它与哪个域相关联,并定义世界上存在的对象。 

(define (problem letseat-simple)
	(:domain letseat)
	(:objects
    	arm - robot
    	cupcake - cupcake
    	table - location
    	plate - location
	)

然后,我们将定义 initial state :抓手是空的,纸杯蛋糕在桌子上,手臂可以在两者之间移动。

(:init
	(on arm table)
	(on cupcake table)
	(arm-empty)
	(path table plate)
)

最后,我们定义 goal specification :盘子里的纸杯蛋糕。

(:goal 
	(on cupcake plate)
)

组合以上部分,你就会得到 problem 文件

如果你使用 OPTIC 运行它,你会得到如下解决方案:

Initial heuristic = 3
Initial stats: t=0s, 4299060kb
b (2 @ n=3, t=0s, 4300084kb)b (1 @ n=6, t=0s, 4308276kb)
;;;; Solution Found
; Time 0.00
; Peak memory 4308276kb
; Nodes Generated: 5
; Nodes Expanded:  3
; Nodes Evaluated: 6
; Nodes Tunneled:  1
; Nodes memoised with open actions: 0
; Nodes memoised without open actions: 6
; Nodes pruned by memoisation: 0
0: (pick-up arm cupcake table) [1]
1: (move arm table plate) [1]
2: (drop arm cupcake plate) [1]

练习

请思考以下任务,其中的场景更加复杂,这将有助于加深你的理解:

  • 在桌子上添加第二个蛋糕,并将其添加到目标规划中,以确保它也放在盘子上。
  • 向域中添加一个独角兽对象,并为独角兽定义吃蛋糕的目标。 独角兽只能吃盘子里的蛋糕。

稍难示例

如果想查看更复杂的内容,请查看 driverlog domain

基础之上

如果你是初学者,请在充分理解基础知识之后再阅读这部分。

Durative Actions

为了在时域中工作,可以给动作定义持续时间。

每个条件(condition)和结果(effect)都给出了它们应该发生的时间。

几种类型的时间约束:

  • (at start (<condition/effect>)):必须为真或在动作开始时发生。
  • (at end (<condition/effect>)):必须为真或发生在动作结束时。
  • (over all (<condition>)):在操作的整个持续时间内这必须为真。

以下是上文示例中的(move)动作转换为持续性动作的示例:

(:durative-action move
  :duration (= ?duration 10) ; Duration goes here.
  :parameters
   (?arm - bot
    ?from - location
    ?to - location)
  :condition ; Note how this is "condition" not "pre-condition"
   (and 
    (at start (on ?arm ?from))
    (over all (path ?from ?to))
   )
  :effect
   (and 
    (at start (not (on ?arm ?from)))
    (at end (on ?arm ?to))
   )
)

Functions

待续

Processes & Events

待续