From 77129f13b399c5c6d90a74744759858cd19626dd Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Thu, 9 May 2024 10:41:18 +0000 Subject: [PATCH] build based on e34cc1f --- dev/index.html | 2 +- dev/ref/absint/index.html | 10 +-- dev/ref/compiler/index.html | 2 +- dev/ref/datatypes/index.html | 72 ++++++++++----------- dev/ref/extensions/index.html | 20 +++--- dev/ref/interface/index.html | 24 +++---- dev/ref/interpreter/index.html | 2 +- dev/ref/overview/index.html | 2 +- dev/ref/parser_writer/index.html | 18 +++--- dev/ref/utilities/index.html | 78 +++++++++++------------ dev/search/index.html | 2 +- dev/tutorials/getting_started/index.html | 2 +- dev/tutorials/speeding_up/index.html | 2 +- dev/tutorials/writing_planners/index.html | 2 +- 14 files changed, 119 insertions(+), 119 deletions(-) diff --git a/dev/index.html b/dev/index.html index d7d4665..a4cf612 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -PDDL.jl · PDDL.jl

PDDL.jl

A extensible and performant interface for symbolic planning domains specified in the Planning Domain Definition Language (PDDL), with support for PDDL parsing, interpretation, and compilation.

Features

  • Parsing and writing of PDDL domain and problem files
  • A high-level symbolic planning API for use by algorithms and applications
  • Execution of PDDL actions and plans
  • Abstract interpretation of PDDL semantics
  • Domain grounding and compilation for increased performance
  • Semantic extensibility through modular theories

PDDL.jl does not include any planning algorithms. Rather, it provides an interface so that planners for PDDL domains can easily be written, as in SymbolicPlanners.jl.

Tutorials

Learn how to install and use PDDL.jl by following these tutorials:

Architecture and Interface

Learn about the architecture of PDDL.jl, its high-level interface for symbolic planning, and the built-in implementations of this interface:

+PDDL.jl · PDDL.jl

PDDL.jl

A extensible and performant interface for symbolic planning domains specified in the Planning Domain Definition Language (PDDL), with support for PDDL parsing, interpretation, and compilation.

Features

  • Parsing and writing of PDDL domain and problem files
  • A high-level symbolic planning API for use by algorithms and applications
  • Execution of PDDL actions and plans
  • Abstract interpretation of PDDL semantics
  • Domain grounding and compilation for increased performance
  • Semantic extensibility through modular theories

PDDL.jl does not include any planning algorithms. Rather, it provides an interface so that planners for PDDL domains can easily be written, as in SymbolicPlanners.jl.

Tutorials

Learn how to install and use PDDL.jl by following these tutorials:

Architecture and Interface

Learn about the architecture of PDDL.jl, its high-level interface for symbolic planning, and the built-in implementations of this interface:

diff --git a/dev/ref/absint/index.html b/dev/ref/absint/index.html index 49e42c6..f4915dc 100644 --- a/dev/ref/absint/index.html +++ b/dev/ref/absint/index.html @@ -1,9 +1,9 @@ -Abstract Interpretation · PDDL.jl

Abstract Interpretation

PDDL.jl supports abstract interpretation of PDDL domains. This functionality is exposed by the abstracted and abstractstate functions:

PDDL.abstractedFunction
abstracted(domain; options...)

Construct an abstract domain from a concrete domain. See PDDL.AbstractInterpreter for the list of options.

source
abstracted(domain, state; options...)
-abstracted(domain, problem; options...)

Construct an abstract domain and state from a concrete domain and state. A problem can be provided instead of a state. See PDDL.AbstractInterpreter for the list of options.

source
PDDL.abstractstateFunction
abstractstate(domain, state)

Construct a state in an abstract domain from a concrete state.

source

The behavior of the abstract interpreter can be customized by specifying the Julia type used to represent abstract values for a particular fluent or PDDL type:

PDDL.AbstractInterpreterType
AbstractInterpreter(
+Abstract Interpretation · PDDL.jl

Abstract Interpretation

PDDL.jl supports abstract interpretation of PDDL domains. This functionality is exposed by the abstracted and abstractstate functions:

PDDL.abstractedFunction
abstracted(domain; options...)

Construct an abstract domain from a concrete domain. See PDDL.AbstractInterpreter for the list of options.

source
abstracted(domain, state; options...)
+abstracted(domain, problem; options...)

Construct an abstract domain and state from a concrete domain and state. A problem can be provided instead of a state. See PDDL.AbstractInterpreter for the list of options.

source
PDDL.abstractstateFunction
abstractstate(domain, state)

Construct a state in an abstract domain from a concrete state.

source

The behavior of the abstract interpreter can be customized by specifying the Julia type used to represent abstract values for a particular fluent or PDDL type:

PDDL.AbstractInterpreterType
AbstractInterpreter(
     type_abstractions = PDDL.default_abstypes(),
     fluent_abstractions = Dict(),
     autowiden = false
-)

Abstract PDDL interpreter based on Cartesian abstract interpretation of the PDDL state. Fluents in the state are converted to abstract values based on either their concrete type or fluent name, with fluent-specific abstractions overriding type-based abstractions.

Arguments

  • type_abstractions: Mapping from PDDL types to the Julia type for abstract fluent values.

  • fluent_abstractions: Mapping from fluent names to the Julia type for abstract fluent values.

  • autowiden: Flag for automatic widening of values after a state transition.

source

Abstract semantics can also be compiled by calling compiled on an abstracted domain and state:

domain, state = abstracted(domain, state)
-domain, state = compiled(domain, state)

Abstract Values and Types

Abstract interpretation requires each concrete value to be mapped to an abstract value of a particular type, which represents an (over-approximation) of the set of the possible values reachable after a series of actions have been executed. By default, Boolean values (i.e. predicates) are mapped to the BooleanAbs abstraction, while scalar numbers (corresponding to PDDL types like integer, number and numeric) are mapped to the IntervalAbs abstraction. Other types of values may use the SetAbs abstraction.

PDDL.BooleanAbsType
BooleanAbs

Belnap logic abstraction for Boolean values. In addition to true, false and missing, the abstract value both can be used to represent when a predicate is both false and true.

source

When introducing a new global datatype using the PDDL.jl extension interfaces, a default abstraction can be associated with the type by defining a new method for PDDL.default_abstype:

The PDDL.@register macro can also be used to register new default abstractions.

+)

Abstract PDDL interpreter based on Cartesian abstract interpretation of the PDDL state. Fluents in the state are converted to abstract values based on either their concrete type or fluent name, with fluent-specific abstractions overriding type-based abstractions.

Arguments

  • type_abstractions: Mapping from PDDL types to the Julia type for abstract fluent values.

  • fluent_abstractions: Mapping from fluent names to the Julia type for abstract fluent values.

  • autowiden: Flag for automatic widening of values after a state transition.

source

Abstract semantics can also be compiled by calling compiled on an abstracted domain and state:

domain, state = abstracted(domain, state)
+domain, state = compiled(domain, state)

Abstract Values and Types

Abstract interpretation requires each concrete value to be mapped to an abstract value of a particular type, which represents an (over-approximation) of the set of the possible values reachable after a series of actions have been executed. By default, Boolean values (i.e. predicates) are mapped to the BooleanAbs abstraction, while scalar numbers (corresponding to PDDL types like integer, number and numeric) are mapped to the IntervalAbs abstraction. Other types of values may use the SetAbs abstraction.

PDDL.BooleanAbsType
BooleanAbs

Belnap logic abstraction for Boolean values. In addition to true, false and missing, the abstract value both can be used to represent when a predicate is both false and true.

source

When introducing a new global datatype using the PDDL.jl extension interfaces, a default abstraction can be associated with the type by defining a new method for PDDL.default_abstype:

The PDDL.@register macro can also be used to register new default abstractions.

diff --git a/dev/ref/compiler/index.html b/dev/ref/compiler/index.html index 33e7fa9..2a5bb13 100644 --- a/dev/ref/compiler/index.html +++ b/dev/ref/compiler/index.html @@ -1,3 +1,3 @@ Compiler · PDDL.jl

Compiler

PDDL.jl supports compilation of the semantics of PDDL domains through code-generation for PDDL actions and custom datatypes for PDDL states. See Speeding Up PDDL.jl for a more detailed explanation.

PDDL.compiledFunction
compiled(domain, state)
-compiled(domain, problem)

Compile a domain and state and return the resulting compiled domain and compiled state. A problem maybe provided instead of a state.

Top-Level Only

Because compiled defines new types and methods, it should only be called at the top-level in order to avoid world-age errors.

Precompilation Not Supported

Because compiled evaluates code in the PDDL module, it will lead to precompilation errors when used in another module or package. Modules which call compiled should hence disable precompilation.

source
PDDL.compilestateFunction
compilestate(domain, state)

Return compiled version of a state compatible with the compiled domain.

source
+compiled(domain, problem)

Compile a domain and state and return the resulting compiled domain and compiled state. A problem maybe provided instead of a state.

Top-Level Only

Because compiled defines new types and methods, it should only be called at the top-level in order to avoid world-age errors.

Precompilation Not Supported

Because compiled evaluates code in the PDDL module, it will lead to precompilation errors when used in another module or package. Modules which call compiled should hence disable precompilation.

source
PDDL.compilestateFunction
compilestate(domain, state)

Return compiled version of a state compatible with the compiled domain.

source
diff --git a/dev/ref/datatypes/index.html b/dev/ref/datatypes/index.html index f2e3b1c..074afa6 100644 --- a/dev/ref/datatypes/index.html +++ b/dev/ref/datatypes/index.html @@ -8,43 +8,43 @@ 1: Const name: Symbol a 2: Const - name: Symbol b

Fluent Signatures

In the context of a planning Domain, (lifted) fluents often have specific type signatures. For example, fluent arguments may be restricted to objects of particular types, and their values may be :boolean or :numeric. This type information is stored in the PDDL.Signature data type:

PDDL.SignatureType
Signature

Type signature for a PDDL fluent (i.e. predicate or function).

Fields

  • name: Name of fluent.

  • type: Output datatype of fluent, represented as a Symbol.

  • args: Argument variables.

  • argtypes: Argument datatypes, represented as Symbols.

source
PDDL.arityFunction
arity(signature)
-

Returns the arity (i.e. number of arguments) of a fluent signature.

source

States

In symbolic planning, states are symbolic descriptions of the environment and its objects at a particular point in time. Formally, given a finite set of fluents $\mathcal{F}$, a state $s$ is composed of a set of (optionally typed) objects $\mathcal{O}$, and valuations of ground fluents $\mathcal{F}(\mathcal{O})$ defined over all objects in $\mathcal{O}$ of the appropriate types. Each ground fluent thus refers to a state variable. For a ground fluent $f \in \mathcal{F}(\mathcal{O})$, we will use the notation $s[f] = v$ to denote that $f$ has value $v$ in state $s$.

Example

Given the fluents (on ?x ?y) and (on-table ?x) that describe a state $s$ with objects a and b, there are six ground fluents whose values are defined in the state: (on a a), (on a b), (on b a), (on b b), (on-table a) and (on-table b). The expression $s[$(on a b)$] =$ true means that object a is on top of b in state $s$.

In PDDL.jl, states are represented by the State abstract type:

PDDL.StateType
State

Abstract supertype for symbolic states. A State is a symbolic description of the environment and its objects at a particular point in time. It consists of a set of objects, and a set of ground fluents (predicates or functions) with values defined over those objects.

source

The following accessor methods are defined for a State:

PDDL.get_objectsMethod
get_objects(state::State, [type::Symbol])
-get_objects(domain::Domain, state::State, type::Symbol)

Returns an iterator over objects in the state. If a type is specified, the iterator will contain objects only of that type (but not its subtypes). If a domain is provided, then the iterator will contain all objects of that type or any of its subtypes.

source
PDDL.get_objtypesMethod
get_objtypes(state)
-

Returns a map (dictionary, named tuple, etc.) from state objects to their types.

source
PDDL.get_objtypeMethod
get_objtype(state, object)
-

Returns the type of an object in a state.

source
PDDL.get_factsMethod
get_facts(state)
-

Returns an iterator over true Boolean predicates in a state.

source
PDDL.get_fluentMethod
get_fluent(state, term)
-

Gets the value of a (non-derived) fluent.Equivalent to using the index notation state[term].

source
PDDL.set_fluent!Method
set_fluent!(state, val, term)
-

Sets the value of a (non-derived) fluent. Equivalent to using the index notation state[term] = val.

source
PDDL.get_fluentsMethod
get_fluents(state)
-

Returns a map from fluent names to values (false predicates may be omitted). Base.pairs is an alias.

source

Actions

As described in the Getting Started, symbolic planning formalisms distinguish between action schemas (also known as operators), which specify the general semantics of an action, and ground actions, which represent instantiations of an action schema for specific objects.

An action schema comprises:

Example

An example action schema definition in PDDL is shown below:

(:action stack
+      name: Symbol b

Fluent Signatures

In the context of a planning Domain, (lifted) fluents often have specific type signatures. For example, fluent arguments may be restricted to objects of particular types, and their values may be :boolean or :numeric. This type information is stored in the PDDL.Signature data type:

PDDL.SignatureType
Signature

Type signature for a PDDL fluent (i.e. predicate or function).

Fields

  • name: Name of fluent.

  • type: Output datatype of fluent, represented as a Symbol.

  • args: Argument variables.

  • argtypes: Argument datatypes, represented as Symbols.

source
PDDL.arityFunction
arity(signature)
+

Returns the arity (i.e. number of arguments) of a fluent signature.

source

States

In symbolic planning, states are symbolic descriptions of the environment and its objects at a particular point in time. Formally, given a finite set of fluents $\mathcal{F}$, a state $s$ is composed of a set of (optionally typed) objects $\mathcal{O}$, and valuations of ground fluents $\mathcal{F}(\mathcal{O})$ defined over all objects in $\mathcal{O}$ of the appropriate types. Each ground fluent thus refers to a state variable. For a ground fluent $f \in \mathcal{F}(\mathcal{O})$, we will use the notation $s[f] = v$ to denote that $f$ has value $v$ in state $s$.

Example

Given the fluents (on ?x ?y) and (on-table ?x) that describe a state $s$ with objects a and b, there are six ground fluents whose values are defined in the state: (on a a), (on a b), (on b a), (on b b), (on-table a) and (on-table b). The expression $s[$(on a b)$] =$ true means that object a is on top of b in state $s$.

In PDDL.jl, states are represented by the State abstract type:

PDDL.StateType
State

Abstract supertype for symbolic states. A State is a symbolic description of the environment and its objects at a particular point in time. It consists of a set of objects, and a set of ground fluents (predicates or functions) with values defined over those objects.

source

The following accessor methods are defined for a State:

PDDL.get_objectsMethod
get_objects(state::State, [type::Symbol])
+get_objects(domain::Domain, state::State, type::Symbol)

Returns an iterator over objects in the state. If a type is specified, the iterator will contain objects only of that type (but not its subtypes). If a domain is provided, then the iterator will contain all objects of that type or any of its subtypes.

source
PDDL.get_objtypesMethod
get_objtypes(state)
+

Returns a map (dictionary, named tuple, etc.) from state objects to their types.

source
PDDL.get_factsMethod
get_facts(state)
+

Returns an iterator over true Boolean predicates in a state.

source
PDDL.get_fluentMethod
get_fluent(state, term)
+

Gets the value of a (non-derived) fluent.Equivalent to using the index notation state[term].

source
PDDL.set_fluent!Method
set_fluent!(state, val, term)
+

Sets the value of a (non-derived) fluent. Equivalent to using the index notation state[term] = val.

source
PDDL.get_fluentsMethod
get_fluents(state)
+

Returns a map from fluent names to values (false predicates may be omitted). Base.pairs is an alias.

source

Actions

As described in the Getting Started, symbolic planning formalisms distinguish between action schemas (also known as operators), which specify the general semantics of an action, and ground actions, which represent instantiations of an action schema for specific objects.

An action schema comprises:

  • A name that identifies the action.
  • A list of (optionally typed) parameters or arguments that an action operates over.
  • A precondition formula, defined over the parameters, that has to hold true for the action to be executable.
  • An effect formula, defined over the parameters, specifying how the action modifies the state once it is executed.
Example

An example action schema definition in PDDL is shown below:

(:action stack
  :parameters (?x ?y - block)
  :precondition (and (holding ?x) (clear ?y) (not (= ?x ?y)))
- :effect (and (not (holding ?x)) (not (clear ?y)) (clear ?x) (handempty) (on ?x ?y)))

This schema defines the semantics of an action named stack and has two parameters of type block. Its precondition states that block ?x has to be held, block ?y has to be clear (no other block is on top of it), and that?x is not the same as ?y. Its effect states that in the next state, ?x will no longer be held, and that it will be instead be placed on top of block ?y.

In PDDL.jl, action schemas are represented by the Action abstract type:

PDDL.ActionType
Action

Abstract supertype for action schemas, which specify the general semantics of an action parameterized by a set of arguments.

source

The following accessor methods are defined for an Action:

PDDL.get_precondMethod
get_precond(action::Action)
+ :effect (and (not (holding ?x)) (not (clear ?y)) (clear ?x) (handempty) (on ?x ?y)))

This schema defines the semantics of an action named stack and has two parameters of type block. Its precondition states that block ?x has to be held, block ?y has to be clear (no other block is on top of it), and that?x is not the same as ?y. Its effect states that in the next state, ?x will no longer be held, and that it will be instead be placed on top of block ?y.

In PDDL.jl, action schemas are represented by the Action abstract type:

PDDL.ActionType
Action

Abstract supertype for action schemas, which specify the general semantics of an action parameterized by a set of arguments.

source

The following accessor methods are defined for an Action:

PDDL.get_precondMethod
get_precond(action::Action)
 get_precond(action::Action, args)
-get_precond(domain::Domain, action::Term)

Returns the precondition of an action schema as a Term, optionally parameterized by args. Alternatively, an action and its arguments can be specified as a Term.

source
PDDL.get_effectMethod
get_effect(action::Action)
+get_precond(domain::Domain, action::Term)

Returns the precondition of an action schema as a Term, optionally parameterized by args. Alternatively, an action and its arguments can be specified as a Term.

source
PDDL.get_effectMethod
get_effect(action::Action)
 get_effect(action::Action, args)
-get_effect(domain::Domain, action::Term)

Returns the effect of an action schema as a Term, optionally parameterized by args. Alternatively, an action and its arguments can be specified as a Term.

source

In contrast to action schemas, ground actions are represented with the Term data type. This is because the name property of a Term is sufficient to identify an action schema in the context of a planning domain, and the args property can be used to represent action parameters.

There also exists a special no-op action schema, denoted PDDL.NoOp() in Julia code. The corresponding ground action can be expressed as PDDL.no_op or pddl"(--)".

PDDL.NoOpType
NoOp()

Constructs a no-op action which has no preconditions or effects.

source
PDDL.no_opConstant
PDDL.no_op

An alias for pddl"(–)", the action Term for a NoOp action which has no preconditions or effects.

source

State Differences

For some use cases, such as action grounding or interpreted execution, it can be helpful to more explicitly represent the effects of an action as a difference between States. PDDL.jl uses the PDDL.Diff abstract data type to represent such differences, including PDDL.GenericDiffs and PDDL.ConditionalDiffs.

PDDL.DiffType
Diff

Abstract type representing differences between states.

source
PDDL.GenericDiffType
GenericDiff(add, del, ops)

Generic state difference represented as additions, deletions, and assignments.

Fields

  • add: List of added Terms

  • del: List of deleted Terms

  • ops: Dictionary mapping fluents to their assigned expressions.

source
PDDL.ConditionalDiffType
ConditionalDiff(conds, diffs)

Conditional state difference, represented as paired conditions and sub-diffs.

Fields

  • conds: List of list of condition Terms for each sub-diff.

  • diffs: List of sub-diffs.

source

Multiple PDDL.Diffs can be combined using the PDDL.combine! and PDDL.combine functions:

PDDL.combine!Function
combine!(diff::Diff, ds::Diff...)

Combine state differences, modifying the first Diff in place.

source
PDDL.combineFunction
combine(diff::Diff, ds::Diff...)

Combine state differences, returning a fresh Diff.

source

Domains

A planning domain is a (first-order) symbolic model of the environment, specifying the predicates and functions that can be used to describe the environment, and the actions that can be taken in the environment, including their preconditions and effects. Some domains may also specify the types of objects that exist, or include domain axioms that specify which predicates can be derived from others.

In PDDL.jl, domains are represented by the Domain abstract type:

PDDL.DomainType
Domain

Abstract supertype for planning domains, which specify a symbolic model of the environment and its transition dynamics.

source

The following accessor methods are defined for a Domain:

PDDL.get_subtypesMethod
get_subtypes(domain, type)
-

Returns an iterator over (immediate) subtypes of type in the domain.

source
PDDL.get_functionMethod
get_function(domain, name)
-

Returns the signature associated with a function name.

source
PDDL.get_fluentMethod
get_fluent(domain, name)
-

Returns the signature associated with a fluent name.

source
PDDL.get_axiomsMethod
get_axioms(domain)
-

Returns a map from names of derived predicates to their corresponding axioms.

source
PDDL.get_axiomMethod
get_axiom(domain, name)
-

Returns the axiom assocated with a derived predicate name.

source

Problems

A planning problem for a particular domain specifies both the initial state of the environment, and the task specification to be achieved. Typically, the task specification is a goal to be achieved, specified as a logical formula to be satisfied. However, planning problems can also include other specifications, such as a cost metric to minimize, and temporal constraints on the plan or state trajectory.

In PDDL.jl, problems are represented by the Problem abstract type:

PDDL.ProblemType
Problem

Abstract supertype for planning problems, which specify the initial state of a planning domain and the task specification to be achieved.

source

The following accessor methods are defined for a Problem:

+get_effect(domain::Domain, action::Term)

Returns the effect of an action schema as a Term, optionally parameterized by args. Alternatively, an action and its arguments can be specified as a Term.

source

In contrast to action schemas, ground actions are represented with the Term data type. This is because the name property of a Term is sufficient to identify an action schema in the context of a planning domain, and the args property can be used to represent action parameters.

There also exists a special no-op action schema, denoted PDDL.NoOp() in Julia code. The corresponding ground action can be expressed as PDDL.no_op or pddl"(--)".

PDDL.NoOpType
NoOp()

Constructs a no-op action which has no preconditions or effects.

source
PDDL.no_opConstant
PDDL.no_op

An alias for pddl"(–)", the action Term for a NoOp action which has no preconditions or effects.

source

State Differences

For some use cases, such as action grounding or interpreted execution, it can be helpful to more explicitly represent the effects of an action as a difference between States. PDDL.jl uses the PDDL.Diff abstract data type to represent such differences, including PDDL.GenericDiffs and PDDL.ConditionalDiffs.

PDDL.DiffType
Diff

Abstract type representing differences between states.

source
PDDL.GenericDiffType
GenericDiff(add, del, ops)

Generic state difference represented as additions, deletions, and assignments.

Fields

  • add: List of added Terms

  • del: List of deleted Terms

  • ops: Dictionary mapping fluents to their assigned expressions.

source
PDDL.ConditionalDiffType
ConditionalDiff(conds, diffs)

Conditional state difference, represented as paired conditions and sub-diffs.

Fields

  • conds: List of list of condition Terms for each sub-diff.

  • diffs: List of sub-diffs.

source

Multiple PDDL.Diffs can be combined using the PDDL.combine! and PDDL.combine functions:

PDDL.combine!Function
combine!(diff::Diff, ds::Diff...)

Combine state differences, modifying the first Diff in place.

source
PDDL.combineFunction
combine(diff::Diff, ds::Diff...)

Combine state differences, returning a fresh Diff.

source

Domains

A planning domain is a (first-order) symbolic model of the environment, specifying the predicates and functions that can be used to describe the environment, and the actions that can be taken in the environment, including their preconditions and effects. Some domains may also specify the types of objects that exist, or include domain axioms that specify which predicates can be derived from others.

In PDDL.jl, domains are represented by the Domain abstract type:

PDDL.DomainType
Domain

Abstract supertype for planning domains, which specify a symbolic model of the environment and its transition dynamics.

source

The following accessor methods are defined for a Domain:

PDDL.get_nameMethod
get_name(domain)
+

Returns the name of a domain.

source
PDDL.get_typetreeMethod
get_typetree(domain)
+

Returns a map from domain types to subtypes.

source
PDDL.get_typesMethod
get_types(domain)
+

Returns an iterator over types in the domain.

source
PDDL.get_subtypesMethod
get_subtypes(domain, type)
+

Returns an iterator over (immediate) subtypes of type in the domain.

source
PDDL.get_predicatesMethod
get_predicates(domain)
+

Returns a map from predicate names to predicate Signatures.

source
PDDL.get_predicateMethod
get_predicate(domain, name)
+

Returns the signature associated with a predicate name.

source
PDDL.get_functionsMethod
get_functions(domain)
+

Returns a map from function names to function Signatures.

source
PDDL.get_functionMethod
get_function(domain, name)
+

Returns the signature associated with a function name.

source
PDDL.get_fluentsMethod
get_fluents(domain)
+

Returns a map from domain fluent names to fluent Signatures.

source
PDDL.get_fluentMethod
get_fluent(domain, name)
+

Returns the signature associated with a fluent name.

source
PDDL.get_axiomsMethod
get_axioms(domain)
+

Returns a map from names of derived predicates to their corresponding axioms.

source
PDDL.get_axiomMethod
get_axiom(domain, name)
+

Returns the axiom assocated with a derived predicate name.

source
PDDL.get_actionsMethod
get_actions(domain)
+

Returns a map from action names to action schemata.

source
PDDL.get_actionMethod
get_action(domain, name)
+

Returns the action schema specified by name.

source

Problems

A planning problem for a particular domain specifies both the initial state of the environment, and the task specification to be achieved. Typically, the task specification is a goal to be achieved, specified as a logical formula to be satisfied. However, planning problems can also include other specifications, such as a cost metric to minimize, and temporal constraints on the plan or state trajectory.

In PDDL.jl, problems are represented by the Problem abstract type:

PDDL.ProblemType
Problem

Abstract supertype for planning problems, which specify the initial state of a planning domain and the task specification to be achieved.

source

The following accessor methods are defined for a Problem:

PDDL.get_nameMethod
get_name(problem)
+

Returns the name of a problem.

source
PDDL.get_domain_nameMethod
get_domain_name(problem)
+

Returns the name of a problem's domain.

source
PDDL.get_objectsMethod
get_objects(problem)
+

Returns an iterator over objects in a problem.

source
PDDL.get_objtypesMethod
get_objtypes(problem)
+

Returns a map from problem objects to their types.

source
PDDL.get_init_termsMethod
get_init_terms(problem)
+

Returns a list of terms that determine the initial state.

source
PDDL.get_goalMethod
get_goal(problem)
+

Returns the goal specification of a problem.

source
PDDL.get_metricMethod
get_metric(problem)
+

Returns the metric specification of a problem.

source
PDDL.get_constraintsMethod
get_constraints(problem)
+

Returns the constraint specification of a problem.

source
diff --git a/dev/ref/extensions/index.html b/dev/ref/extensions/index.html index 5d63eee..7a8d63f 100644 --- a/dev/ref/extensions/index.html +++ b/dev/ref/extensions/index.html @@ -1,13 +1,13 @@ Extension Interfaces · PDDL.jl

Extension Interfaces

PDDL.jl provides a set of extension interfaces for adding new global predicates, functions, and types. Extensions can be added on a per-predicate or per-function basis, or by registering theories that provide a class of related functionality.

Built-in Types, Predicates and Functions

PDDL.jl stores mappings from (global) names to their implementations by making use of value-based dispatch. These mappings are stored by defining methods for the following functions:

PDDL.datatype_defFunction
datatype_def(name)
-

Mapping from PDDL data types to Julia types and default values.

source
PDDL.modifier_defFunction
modifier_def(name)
-

Mapping from PDDL modifiers (i.e. in-place assignments) to PDDL functions.

source

These mappings can also be accessed in dictionary form with the following utility functions:

Datatypes

By default, PDDL.jl supports fluents with Boolean and numeric values. These correspond to the PDDL datatypes named boolean, integer, number and numeric, and are implemented in Julia with the Bool, Int and Float64 types:

PDDL.datatype_def(::Val{:boolean}) = (type=Bool, default=false)
+

Mapping from PDDL data types to Julia types and default values.

source
PDDL.modifier_defFunction
modifier_def(name)
+

Mapping from PDDL modifiers (i.e. in-place assignments) to PDDL functions.

source

These mappings can also be accessed in dictionary form with the following utility functions:

Datatypes

By default, PDDL.jl supports fluents with Boolean and numeric values. These correspond to the PDDL datatypes named boolean, integer, number and numeric, and are implemented in Julia with the Bool, Int and Float64 types:

PDDL.datatype_def(::Val{:boolean}) = (type=Bool, default=false)
 PDDL.datatype_def(::Val{:integer}) = (type=Int, default=0)
 PDDL.datatype_def(::Val{:number}) = (type=Float64, default=1.0)
 PDDL.datatype_def(::Val{:numeric}) = (type=Float64, default=1.0)

When declaring a function in a PDDL domain, it is possible to denote its (output) type as one of the aforementioned types. For example, the distance between two cities might be declared to have a number type:

(distance ?c1 - city ?c2 - city) - number

Predicates and Functions

PDDL.jl also supports built-in predicates and functions for comparisons and arithmetic operations. Since these functions can be used in any PDDL domain, they are called global functions. Global predicates and functions are implemented by mapping them to Julia functions:

# Built-in predicates
@@ -24,7 +24,7 @@
 PDDL.function_def(::Val{:/}) = /

Modifiers

Finally, PDDL.jl supports modifier expressions such as (increase fluent val), which modifies the current value of fluent by val, setting the new value of fluent to the modified value. Like global functions, modifiers are implemented by mapping their names to corresponding Julia functions:

PDDL.modifier_def(::Val{:increase}) = :+
 PDDL.modifier_def(::Val{:decrease}) = :-
 PDDL.modifier_def(::Val{Symbol("scale-up")}) = :*
-PDDL.modifier_def(::Val{Symbol("scale-down")}) = :/

Adding Types, Predicates and Functions

To add a new global datatype, predicate, function, or modifier to PDDL, it is enough to define a new method of PDDL.datatype_def, PDDL.predicate_def, PDDL.function_def, or PDDL.modifier_def respectively. Alternatively, one can use the @register macro to register new implementations at compile-time:

PDDL.@registerMacro
@register([:datatype|:predicate|:function|:modifier|:converter], name, x)

Register x as a global datatype, predicate, function, modifier, or term converter under the specified name.

source

In scripting contexts, run-time registration and de-registration can be achieved using PDDL.register! and PDDL.deregister!:

PDDL.register!Function
register!([:datatype|:predicate|:function|:modifier|:converter], name, x)

Register x as a global datatype, predicate, function or modifier, or term converter under the specified name.

Top-Level Only

Because register! defines new methods, it should only be called at the top-level in order to avoid world-age errors.

Precompilation Not Supported

Because register! evaluates code in the PDDL module, it will lead to precompilation errors when used in another module. For this reason, the @register macro is preferred, and this function should only be used in scripting contexts.

source
PDDL.deregister!Function
deregister!([:datatype|:predicate|:function|:modifier|:converter], name)

Deregister the datatype, predicate, function or modifier specified by name.

Top-Level Only

Because deregister! deletes existing methods, it should only be called at the top-level in order to avoid world-age errors. It should primarily be used in scripting contexts, and not by other packages or modules.

source

Defining and Registering Theories

Similar to Satisfiability Modulo Theories (SMT) solvers, PDDL.jl provides support for planning modulo theories. By registering a new theory, developers can extend the semantics of PDDL to handle new mathematical objects such as sets, arrays, and tuples.

A new theory can be implemented by writing a (sub)module annotated with the @pddltheory macro:

PDDL.@pddltheoryMacro
@pddltheory module M ... end

Declares a module M as a PDDL theory. This defines the M.@register, M.register!, M.deregister! and M.attach! functions automatically.

source

For example, a theory for how to handle sets of PDDL objects can be written as follows (adapting the example by Gregory et al (2012)):

@pddltheory module Sets
+PDDL.modifier_def(::Val{Symbol("scale-down")}) = :/

Adding Types, Predicates and Functions

To add a new global datatype, predicate, function, or modifier to PDDL, it is enough to define a new method of PDDL.datatype_def, PDDL.predicate_def, PDDL.function_def, or PDDL.modifier_def respectively. Alternatively, one can use the @register macro to register new implementations at compile-time:

PDDL.@registerMacro
@register([:datatype|:predicate|:function|:modifier|:converter], name, x)

Register x as a global datatype, predicate, function, modifier, or term converter under the specified name.

source

In scripting contexts, run-time registration and de-registration can be achieved using PDDL.register! and PDDL.deregister!:

PDDL.register!Function
register!([:datatype|:predicate|:function|:modifier|:converter], name, x)

Register x as a global datatype, predicate, function or modifier, or term converter under the specified name.

Top-Level Only

Because register! defines new methods, it should only be called at the top-level in order to avoid world-age errors.

Precompilation Not Supported

Because register! evaluates code in the PDDL module, it will lead to precompilation errors when used in another module. For this reason, the @register macro is preferred, and this function should only be used in scripting contexts.

source
PDDL.deregister!Function
deregister!([:datatype|:predicate|:function|:modifier|:converter], name)

Deregister the datatype, predicate, function or modifier specified by name.

Top-Level Only

Because deregister! deletes existing methods, it should only be called at the top-level in order to avoid world-age errors. It should primarily be used in scripting contexts, and not by other packages or modules.

source

Defining and Registering Theories

Similar to Satisfiability Modulo Theories (SMT) solvers, PDDL.jl provides support for planning modulo theories. By registering a new theory, developers can extend the semantics of PDDL to handle new mathematical objects such as sets, arrays, and tuples.

A new theory can be implemented by writing a (sub)module annotated with the @pddltheory macro:

PDDL.@pddltheoryMacro
@pddltheory module M ... end

Declares a module M as a PDDL theory. This defines the M.@register, M.register!, M.deregister! and M.attach! functions automatically.

source

For example, a theory for how to handle sets of PDDL objects can be written as follows (adapting the example by Gregory et al (2012)):

@pddltheory module Sets
 
 using PDDL
 using PDDL: SetAbs
@@ -113,4 +113,4 @@
 """
 
 state = initstate(domain, problem)

As is the case for registering new predicates and functions, the @register macro is preferred whenever packages that depend on PDDL.jl need to be precompiled. However, it is also possible register and deregister theories at runtime with register! and deregister!:

Sets.register!()
-Sets.deregister!()

Predefined Theories

Alongside the Sets example shown above, a theory for handling Arrays is predefined as part of PDDL.jl:

PDDL.SetsModule
PDDL.Sets

Extends PDDL with set-valued fluents. Set members must be PDDL objects. Register by calling PDDL.Sets.@register(). Attach to a specific domain by calling PDDL.Sets.attach!(domain).

Datatypes

  • set: A set of PDDL objects.

Predicates

  • (member ?x - object ?s - set): Is ?x a member of ?s?
  • (subset ?s1 ?s2 - set): Is ?s1 a subset of ?s2?

Functions

  • (construct-set ?x ?y ... - object): Constructs a set from ?x, ?y, etc.
  • (empty-set): Constructs an empty set.
  • (cardinality ?s - set): The number of elements in ?s.
  • (union ?s1 ?s2 - set): The union of ?s1 and ?s2.
  • (intersect ?s1 ?s2 - set): The intersection of ?s1 and ?s2.
  • (difference ?s1 ?s2 - set): The set difference of ?s1 and ?s2.
  • (add-element ?s - set? ?x - object): Add ?x to ?s.
  • (rem-element ?s - set? ?x - object): Remove ?x from ?s.
source
PDDL.ArraysModule
PDDL.Arrays

Extends PDDL with array-valued fluents. Register by calling PDDL.Arrays.@register(). Attach to a specific domain by calling PDDL.Arrays.attach!(domain).

Datatypes

Generic Arrays

  • array: A multidimensional array with untyped elements.
  • vector: A 1D array with untyped elements.
  • matrix: A 2D array with untyped elements.

Bit Arrays

  • bit-array: A multidimensional array with boolean elements.
  • bit-vector: A 1D array with boolean elements.
  • bit-matrix: A 2D array with boolean elements.

Integer Arrays

  • int-array: A multidimensional array with integer elements.
  • int-vector: A 1D array with integer elements.
  • int-matrix: A 2D array with integer elements.

Numeric Arrays

  • num-array: A multidimensional array with number elements.
  • num-vector: A 1D array with number elements.
  • num-matrix: A 2D array with number elements.

Array Indices

  • array-index: A multidimensional array index, represented as a Tuple.
  • vector-index: A 1D array index, represented as an Int.
  • matrix-index: A 2D array index, represented as a 2-tuple.

Predicates

  • (has-index ?a ?i): Checks if ?i is a valid index for ?a.
  • (has-row ?m ?i): Checks if ?i is a valid row index for matrix ?m.
  • (has-col ?m ?i): Checks if ?i is a valid column index for matrix ?m.

Functions

Array Constructors

  • (new-array ?v ?n1 ?n2 ...): Construct a new array filled with ?v.
  • (new-matrix ?v ?h ?w): Construct a new ?h x ?w matrix filled with ?v.
  • (new-vector ?v ?n): Construct a new vector of length ?n filled with ?v.
  • (vec ?x1 ?x2 ... ?xn): Construct a vector from ?x1, ?x2, etc.
  • (mat ?v1 ?v2 ... ?vn): Construct a matrix from column vectors ?v1, ?v2, etc.

Similar constructors are available for bit arrays, integer arrays, and numeric arrays.

Index Constructors

  • (index ?i1 ?i2 ...): Construct an array index from ?i1, ?i2, etc.
  • (vec-index ?i): Construct a 1D array index from ?i.
  • (mat-index ?i1 ?i2): Construct a 2D array index from ?i1, ?i2.

Accessors

  • (get-index ?a ?i ?j ...): Get element (?i, ?j, ...) of ?a.
  • (set-index ?a ?v ?i ?j ...): Set element (?i, ?j, ...) of ?a to ?v.

Array Dimensions

  • (length ?a): Get the number of elements in an array ?a.
  • (height ?a): Get the height of a matrix ?m.
  • (width ?a): Get the width of a matrix ?m.
  • (ndims ?a): Get the number of dimensions of an array ?a.

Array Manipulation

  • (push ?v ?x): Push ?x onto the end of ?v.
  • (pop ?v): Pop the last element of ?v.
  • (transpose ?m): Transpose a matrix ?m.

Index Manipulation

  • (get-row ?idx): Get the row number of a matrix-index.
  • (get-col ?idx): Get the column number of a matrix-index.
  • (set-row ?idx ?row): Set the row number of a matrix-index to ?row.
  • (set-col ?idx ?col): Set the column number of a matrix-index to ?col.
  • (increase-row ?idx ?d): Increase the row number of a matrix-index by ?d.
  • (increase-col ?idx ?d): Increase the column number of a matrix-index by ?d.
  • (decrease-row ?idx ?d): Decrease the row number of a matrix-index by ?d.
  • (decrease-col ?idx ?d): Decrease the column number of a matrix-index by ?d.
source

These theories are not registered by default, and should be registered with the @register macro before use.

+Sets.deregister!()

Predefined Theories

Alongside the Sets example shown above, a theory for handling Arrays is predefined as part of PDDL.jl:

PDDL.SetsModule
PDDL.Sets

Extends PDDL with set-valued fluents. Set members must be PDDL objects. Register by calling PDDL.Sets.@register(). Attach to a specific domain by calling PDDL.Sets.attach!(domain).

Datatypes

  • set: A set of PDDL objects.

Predicates

  • (member ?x - object ?s - set): Is ?x a member of ?s?
  • (subset ?s1 ?s2 - set): Is ?s1 a subset of ?s2?

Functions

  • (construct-set ?x ?y ... - object): Constructs a set from ?x, ?y, etc.
  • (empty-set): Constructs an empty set.
  • (cardinality ?s - set): The number of elements in ?s.
  • (union ?s1 ?s2 - set): The union of ?s1 and ?s2.
  • (intersect ?s1 ?s2 - set): The intersection of ?s1 and ?s2.
  • (difference ?s1 ?s2 - set): The set difference of ?s1 and ?s2.
  • (add-element ?s - set? ?x - object): Add ?x to ?s.
  • (rem-element ?s - set? ?x - object): Remove ?x from ?s.
source
PDDL.ArraysModule
PDDL.Arrays

Extends PDDL with array-valued fluents. Register by calling PDDL.Arrays.@register(). Attach to a specific domain by calling PDDL.Arrays.attach!(domain).

Datatypes

Generic Arrays

  • array: A multidimensional array with untyped elements.
  • vector: A 1D array with untyped elements.
  • matrix: A 2D array with untyped elements.

Bit Arrays

  • bit-array: A multidimensional array with boolean elements.
  • bit-vector: A 1D array with boolean elements.
  • bit-matrix: A 2D array with boolean elements.

Integer Arrays

  • int-array: A multidimensional array with integer elements.
  • int-vector: A 1D array with integer elements.
  • int-matrix: A 2D array with integer elements.

Numeric Arrays

  • num-array: A multidimensional array with number elements.
  • num-vector: A 1D array with number elements.
  • num-matrix: A 2D array with number elements.

Array Indices

  • array-index: A multidimensional array index, represented as a Tuple.
  • vector-index: A 1D array index, represented as an Int.
  • matrix-index: A 2D array index, represented as a 2-tuple.

Predicates

  • (has-index ?a ?i): Checks if ?i is a valid index for ?a.
  • (has-row ?m ?i): Checks if ?i is a valid row index for matrix ?m.
  • (has-col ?m ?i): Checks if ?i is a valid column index for matrix ?m.

Functions

Array Constructors

  • (new-array ?v ?n1 ?n2 ...): Construct a new array filled with ?v.
  • (new-matrix ?v ?h ?w): Construct a new ?h x ?w matrix filled with ?v.
  • (new-vector ?v ?n): Construct a new vector of length ?n filled with ?v.
  • (vec ?x1 ?x2 ... ?xn): Construct a vector from ?x1, ?x2, etc.
  • (mat ?v1 ?v2 ... ?vn): Construct a matrix from column vectors ?v1, ?v2, etc.

Similar constructors are available for bit arrays, integer arrays, and numeric arrays.

Index Constructors

  • (index ?i1 ?i2 ...): Construct an array index from ?i1, ?i2, etc.
  • (vec-index ?i): Construct a 1D array index from ?i.
  • (mat-index ?i1 ?i2): Construct a 2D array index from ?i1, ?i2.

Accessors

  • (get-index ?a ?i ?j ...): Get element (?i, ?j, ...) of ?a.
  • (set-index ?a ?v ?i ?j ...): Set element (?i, ?j, ...) of ?a to ?v.

Array Dimensions

  • (length ?a): Get the number of elements in an array ?a.
  • (height ?a): Get the height of a matrix ?m.
  • (width ?a): Get the width of a matrix ?m.
  • (ndims ?a): Get the number of dimensions of an array ?a.

Array Manipulation

  • (push ?v ?x): Push ?x onto the end of ?v.
  • (pop ?v): Pop the last element of ?v.
  • (transpose ?m): Transpose a matrix ?m.

Index Manipulation

  • (get-row ?idx): Get the row number of a matrix-index.
  • (get-col ?idx): Get the column number of a matrix-index.
  • (set-row ?idx ?row): Set the row number of a matrix-index to ?row.
  • (set-col ?idx ?col): Set the column number of a matrix-index to ?col.
  • (increase-row ?idx ?d): Increase the row number of a matrix-index by ?d.
  • (increase-col ?idx ?d): Increase the column number of a matrix-index by ?d.
  • (decrease-row ?idx ?d): Decrease the row number of a matrix-index by ?d.
  • (decrease-col ?idx ?d): Decrease the column number of a matrix-index by ?d.
source

These theories are not registered by default, and should be registered with the @register macro before use.

diff --git a/dev/ref/interface/index.html b/dev/ref/interface/index.html index d14eb60..ed647ce 100644 --- a/dev/ref/interface/index.html +++ b/dev/ref/interface/index.html @@ -2,15 +2,15 @@ Interface Functions · PDDL.jl

Interface Functions

PDDL.jl defines a set of interface functions that serve as basic operations in a wide variety of symbolic planning algorithms and applications. These functions are intended to be low-level enough such that planning algorithms can be expressed primarily in terms of the operations they represent, but high-level enough so as to abstract away from implementational details. A schematic overview of most of these interface functions is shown below.

A schematic diagram showing how the PDDL.jl interface functions relate to each other.

Evaluating Formulae and Expressions

The key distinguishing feature of symbolic planning is the ability to describe and determine whether certain facts about the world hold true (e.g. is the robot holding a block?), or evaluate numeric properties (e.g. the distance between two cities), with queries expressed in terms of first-order logic. As such, PDDL.jl provides the following functions which satisfy or evaluate first-order expressions in the context of a State:

Formula Satisfaction

Given a term representing a well-formed logical formula, or a collection of terms (treated as conjunctions of such formulae), the satisfy function returns whether they are satisfiable within a domain and state:

PDDL.satisfyFunction
satisfy(domain::Domain, state::State, term::Term)
-satisfy(domain::Domain, state::State, terms::AbstractVector{<:Term})

Returns whether the queried term or terms can be satisfied in the given domain and state.

source

When a term has free variables, satisfy returns true as long as one satisfying assignment exists. A related function, satisfiers, returns a list of all satisfying assignments to such variables (a.k.a. substitutions), including the empty list when a variable-free formula is satisfied. If no satisfying assignments exist, nothing is returned:

PDDL.satisfiersFunction
satisfiers(domain::Domain, state::State, term::Term)
-satisfiers(domain::Domain, state::State, terms::AbstractVector{<:Term})

Returns a list of satisfying substitutions of the queried term or terms within the given domain and state.

source

Term Evaluation

Given a term representing a ground expression (i.e. one with no free variables), the evaluate function returns the value of that expression in the context of a domain and state:

PDDL.evaluateFunction
evaluate(domain::Domain, state::State, term::Term)

Evaluates a grounded term in the given domain and state. If term refers to a numeric fluent, the value of the fluent is returned. For logical predicates, evaluate is equivalent to satisfy.

source

For example, if term refers to a fluent, the value of the fluent is returned. Compound numeric expressions (e.g., the sum of two fluents) can also be evaluated.

State Initialization and Transition

A PDDL domain specifies the transition dynamics of a first order symbolic model of the world, while a PDDL problem specifies the initial state and object set over which these dynamics are grounded. PDDL.jl thus provides functions for constructing an initial state for a domain and problem, and for simulating the transition dynamics:

State Initialization

Given a domain and problem, the initstate function returns the initial state, the type of which is concrete subtype of State:

PDDL.initstateFunction
initstate(domain::Domain, problem::Problem)
-initstate(domain::Domain, objtypes[, fluents])

Construct the initial state for a given planning domain and problem, or from a domain, a map of objects to their types (objtypes), and an optional list of fluents.

Fluents can either be provided as a list of Terms representing the initial fluents in a PDDL problem, or as a map from fluent names to fluent values.

source

The type of the returned state may vary depending on the type of the domain or problem provided. For example, providing a compiled domain as an argument leads initstate to return a compiled state representation.

State Transition

Given a domain, state and action, the transition function returns a successor state, including the effects of events and processes (as supported by PDDL+) and random sampling (in the case of probabilistic PDDL). To support future multi-agent extensions of PDDL.jl, transition may also accept a set of actions to be executed in parallel:

PDDL.transitionFunction
transition(domain::Domain, state::State, action::Term)
-transition(domain::Domain, state::State, actions)

Returns the successor to state in the given domain after applying a single action or a set of actions in parallel.

source
PDDL.transition!Function
transition!(domain::Domain, state::State, action::Term)
-transition!(domain::Domain, state::State, actions)

Variant of transition that modifies state in place.

source

Forward Action Semantics

A widely-used strategy in symbolic planning is forward state space search, guided by a planning heuristic. These algorithms are built upon two basic operations to search forward in state space: querying the actions that are available in any given state, and executing an action to generate a successor state. These operations can be performed using the following functions:

Action Availability

Given a domain, state, action schema and action arguments, the available function returns whether the corresponding action is available in the specified state – i.e. its precondition is fulfilled. An action may alternatively be provided as a Term (e.g. pddl"(stack a b)"):

PDDL.availableMethod
available(domain::Domain, state::State, action::Action, args)
-available(domain::Domain, state::State, action::Term)

Check if an action parameterized by args can be executed in the given state and domain. Action parameters can also be specified as the arguments of a compound Term.

source

When available is called without specifying an action, it returns an iterator over all actions available in the specified state, effectively encapsulating the logic for node expansion in a search algorithm:

PDDL.availableMethod
available(domain::Domain, state::State)

Return an iterator over available actions in a given state and domain.

source

Action Execution

Given a domain, state, action schema and action arguments, the execute function returns the result of applying the specified action to the state. An action may also be provided as a Term:

PDDL.executeFunction
execute(domain::Domain, state::State, action::Action, args)
-execute(domain::Domain, state::State, action::Term)

Execute an action parameterized by args in the given state, returning the resulting state. Action parameters can also be specified as the arguments of a compound Term.

source
PDDL.execute!Function
execute!(domain::Domain, state::State, action::Action, args)
-execute!(domain::Domain, state::State, action::Term)

Variant of execute that modifies state in-place.

source

Inverse Semantics

Regression-based planners (e.g. the classical STRIPS algorithm) make use of the fact that is possible to plan by working backwards from a goal, repeatedly selecting actions that are relevant to achieving a goal state or specification. This motivates the following interface methods for (i) constructing abstract states from goal specifications and (ii) exposing the inverse semantics of actions:

Goal State Construction

In symbolic planning, a logical goal formula $g$ effectively specifies the set of all concrete goal states where $g$ holds true. We can represent this set of concrete states as an abstract state $\bar s$. In the special case where the goal $g$ contains no disjunctions or functions, $\bar s$ can also be understood as a partial state that specifies the values of all predicates in $g$, and leaves all other predicates unspecified.

To support regression search in this abstract space, PDDL.jl provides the goalstate method for constructing an abstract state from the goal specification of a problem:

PDDL.goalstateFunction
goalstate(domain::Domain, problem::Problem)
-goalstate(domain::Domain, objtypes, terms)

Construct a (partial) goal state from a domain and problem, or from a domain, a map of objects to their types (objtypes), and goal terms.

source

As with initstate, the data type of the returned state $\bar s$ may depend on the type of domain or problem provided.

Action Relevance

Given a domain, state, action schema and action arguments, the relevant function returns whether the action is relevant to achieving the specified state – i.e., it achieves at least one predicate or numeric constraint in the state, and destroys none through deletion or modification. In the case where the action's effect reduces to a list of predicates to be added and a list to be deleted, this simplifies to checking that at least one added predicate is true in the state, and that none are deleted. An action may also be provided as a Term:

PDDL.relevantMethod
relevant(domain::Domain, state::State, action::Action, args)
-relevant(domain::Domain, state::State, action::Term)

Check if an action parameterized by args is relevant (can lead to) a state in the given domain. Action parameters can also be specified as the arguments of a compound Term.

source

When relevant is called without specifying an action, it returns an iterator over all actions relevant to the specified state, encapsulating the logic for node expansion in a regression search algorithm:

PDDL.relevantMethod
relevant(domain::Domain, state::State)

Return an iterator over relevant actions in a given state and domain.

source

Action Regression

Given a domain, state, action schema and action arguments, the regress function executes the action in reverse, returning a (potentially abstract) state that represents the pre-image of the action with respect to the input state. An action may also be provided as a Term:

PDDL.regressFunction
regress(domain::Domain, state::State, action::Action, args)
-regress(domain::Domain, state::State, action::Term)

Compute the pre-image of an action parameterized by args with respect to a state. Action parameters can also be specified as the arguments of a compound Term.

source
PDDL.regress!Function
regress!(domain::Domain, state::State, action::Action, args)
-regress!(domain::Domain, state::State, action::Term)

Variant of regress that modifies state in-place.

source
+satisfy(domain::Domain, state::State, terms::AbstractVector{<:Term})

Returns whether the queried term or terms can be satisfied in the given domain and state.

source

When a term has free variables, satisfy returns true as long as one satisfying assignment exists. A related function, satisfiers, returns a list of all satisfying assignments to such variables (a.k.a. substitutions), including the empty list when a variable-free formula is satisfied. If no satisfying assignments exist, nothing is returned:

PDDL.satisfiersFunction
satisfiers(domain::Domain, state::State, term::Term)
+satisfiers(domain::Domain, state::State, terms::AbstractVector{<:Term})

Returns a list of satisfying substitutions of the queried term or terms within the given domain and state.

source

Term Evaluation

Given a term representing a ground expression (i.e. one with no free variables), the evaluate function returns the value of that expression in the context of a domain and state:

PDDL.evaluateFunction
evaluate(domain::Domain, state::State, term::Term)

Evaluates a grounded term in the given domain and state. If term refers to a numeric fluent, the value of the fluent is returned. For logical predicates, evaluate is equivalent to satisfy.

source

For example, if term refers to a fluent, the value of the fluent is returned. Compound numeric expressions (e.g., the sum of two fluents) can also be evaluated.

State Initialization and Transition

A PDDL domain specifies the transition dynamics of a first order symbolic model of the world, while a PDDL problem specifies the initial state and object set over which these dynamics are grounded. PDDL.jl thus provides functions for constructing an initial state for a domain and problem, and for simulating the transition dynamics:

State Initialization

Given a domain and problem, the initstate function returns the initial state, the type of which is concrete subtype of State:

PDDL.initstateFunction
initstate(domain::Domain, problem::Problem)
+initstate(domain::Domain, objtypes[, fluents])

Construct the initial state for a given planning domain and problem, or from a domain, a map of objects to their types (objtypes), and an optional list of fluents.

Fluents can either be provided as a list of Terms representing the initial fluents in a PDDL problem, or as a map from fluent names to fluent values.

source

The type of the returned state may vary depending on the type of the domain or problem provided. For example, providing a compiled domain as an argument leads initstate to return a compiled state representation.

State Transition

Given a domain, state and action, the transition function returns a successor state, including the effects of events and processes (as supported by PDDL+) and random sampling (in the case of probabilistic PDDL). To support future multi-agent extensions of PDDL.jl, transition may also accept a set of actions to be executed in parallel:

PDDL.transitionFunction
transition(domain::Domain, state::State, action::Term)
+transition(domain::Domain, state::State, actions)

Returns the successor to state in the given domain after applying a single action or a set of actions in parallel.

source
PDDL.transition!Function
transition!(domain::Domain, state::State, action::Term)
+transition!(domain::Domain, state::State, actions)

Variant of transition that modifies state in place.

source

Forward Action Semantics

A widely-used strategy in symbolic planning is forward state space search, guided by a planning heuristic. These algorithms are built upon two basic operations to search forward in state space: querying the actions that are available in any given state, and executing an action to generate a successor state. These operations can be performed using the following functions:

Action Availability

Given a domain, state, action schema and action arguments, the available function returns whether the corresponding action is available in the specified state – i.e. its precondition is fulfilled. An action may alternatively be provided as a Term (e.g. pddl"(stack a b)"):

PDDL.availableMethod
available(domain::Domain, state::State, action::Action, args)
+available(domain::Domain, state::State, action::Term)

Check if an action parameterized by args can be executed in the given state and domain. Action parameters can also be specified as the arguments of a compound Term.

source

When available is called without specifying an action, it returns an iterator over all actions available in the specified state, effectively encapsulating the logic for node expansion in a search algorithm:

PDDL.availableMethod
available(domain::Domain, state::State)

Return an iterator over available actions in a given state and domain.

source

Action Execution

Given a domain, state, action schema and action arguments, the execute function returns the result of applying the specified action to the state. An action may also be provided as a Term:

PDDL.executeFunction
execute(domain::Domain, state::State, action::Action, args)
+execute(domain::Domain, state::State, action::Term)

Execute an action parameterized by args in the given state, returning the resulting state. Action parameters can also be specified as the arguments of a compound Term.

source
PDDL.execute!Function
execute!(domain::Domain, state::State, action::Action, args)
+execute!(domain::Domain, state::State, action::Term)

Variant of execute that modifies state in-place.

source

Inverse Semantics

Regression-based planners (e.g. the classical STRIPS algorithm) make use of the fact that is possible to plan by working backwards from a goal, repeatedly selecting actions that are relevant to achieving a goal state or specification. This motivates the following interface methods for (i) constructing abstract states from goal specifications and (ii) exposing the inverse semantics of actions:

Goal State Construction

In symbolic planning, a logical goal formula $g$ effectively specifies the set of all concrete goal states where $g$ holds true. We can represent this set of concrete states as an abstract state $\bar s$. In the special case where the goal $g$ contains no disjunctions or functions, $\bar s$ can also be understood as a partial state that specifies the values of all predicates in $g$, and leaves all other predicates unspecified.

To support regression search in this abstract space, PDDL.jl provides the goalstate method for constructing an abstract state from the goal specification of a problem:

PDDL.goalstateFunction
goalstate(domain::Domain, problem::Problem)
+goalstate(domain::Domain, objtypes, terms)

Construct a (partial) goal state from a domain and problem, or from a domain, a map of objects to their types (objtypes), and goal terms.

source

As with initstate, the data type of the returned state $\bar s$ may depend on the type of domain or problem provided.

Action Relevance

Given a domain, state, action schema and action arguments, the relevant function returns whether the action is relevant to achieving the specified state – i.e., it achieves at least one predicate or numeric constraint in the state, and destroys none through deletion or modification. In the case where the action's effect reduces to a list of predicates to be added and a list to be deleted, this simplifies to checking that at least one added predicate is true in the state, and that none are deleted. An action may also be provided as a Term:

PDDL.relevantMethod
relevant(domain::Domain, state::State, action::Action, args)
+relevant(domain::Domain, state::State, action::Term)

Check if an action parameterized by args is relevant (can lead to) a state in the given domain. Action parameters can also be specified as the arguments of a compound Term.

source

When relevant is called without specifying an action, it returns an iterator over all actions relevant to the specified state, encapsulating the logic for node expansion in a regression search algorithm:

PDDL.relevantMethod
relevant(domain::Domain, state::State)

Return an iterator over relevant actions in a given state and domain.

source

Action Regression

Given a domain, state, action schema and action arguments, the regress function executes the action in reverse, returning a (potentially abstract) state that represents the pre-image of the action with respect to the input state. An action may also be provided as a Term:

PDDL.regressFunction
regress(domain::Domain, state::State, action::Action, args)
+regress(domain::Domain, state::State, action::Term)

Compute the pre-image of an action parameterized by args with respect to a state. Action parameters can also be specified as the arguments of a compound Term.

source
PDDL.regress!Function
regress!(domain::Domain, state::State, action::Action, args)
+regress!(domain::Domain, state::State, action::Term)

Variant of regress that modifies state in-place.

source
diff --git a/dev/ref/interpreter/index.html b/dev/ref/interpreter/index.html index 8f9b84d..50bd571 100644 --- a/dev/ref/interpreter/index.html +++ b/dev/ref/interpreter/index.html @@ -1,2 +1,2 @@ -Interpreter · PDDL.jl
+Interpreter · PDDL.jl
diff --git a/dev/ref/overview/index.html b/dev/ref/overview/index.html index e3e4bbb..4173a32 100644 --- a/dev/ref/overview/index.html +++ b/dev/ref/overview/index.html @@ -2,4 +2,4 @@ Architecture Overview · PDDL.jl

Architecture Overview

PDDL.jl differs from standard automated planning systems in that it is designed not only for speed and efficiency, but also extensibility and interoperability. This is due to the fact that the design target of PDDL.jl is an interface, not just a particular algorithm or application. The diagram below provides an overview of the architecture of PDDL.jl and the ecosystem it enables (left), in comparison with the architecture of standard planning systems (right).

A diagram of the architecture and ecosystem of PDDL.jl A diagram of the architecture of a standard planning system -

Standard Planning Architectures

Standard architectures are designed primarily for fast and efficient planning, accepting PDDL domain and problem files as inputs (right, pink), rapidly translating and compiling them (orange) to more efficient representations (yellow), running planning algorithms and heuristics (blue) over those representations, then producing symbolic plans and metadata as outputs (green). This architecture enables performance optimization over the entire pipeline, but limits interaction with external applications to just two channels: (i) receiving domains and problems as inputs; and (ii) providing plans as outputs.

PDDL.jl Architecture and Ecosystem

In contrast, the core of PDDL.jl is its interface (left, green): a set of abstract data types and interface functions that expose the high-level functionality required to implement planning algorithms and applications. Centering PDDL.jl around its interface means that:

  • multiple implementations of the interface can coexist (yellow), providing either speed, generality or specialized functionality depending on engineering needs

  • multiple applications (light blue) can use the interface to achieve tighter integration between symbolic planning and other AI components

  • multiple extensions of PDDL are enabled by implementing and extending the interface through additional libraries (dark blue). (Note that the extension libraries shown in the diagram are still under development.)

By factoring out these components of traditional planning systems into separate software artifacts, PDDL.jl enables an ecosystem where implementations can evolve independently from applications (e.g. through future compiler improvements), applications can interoperate through a common interface (e.g. Bayesian agent models which incorporate planning algorithms), and extensions can be flexibly composed (e.g. multi-agent stochastic domains).

Built-in Implementations

Given this interface-centered design, PDDL.jl itself does not include any applications or extensions, which are intended to be provided by separate libraries (e.g. SymbolicPlanners.jl). However, PDDL.jl does include several built-in implementations of its interface: a standard interpreter, a compiler, and an abstract interpreter. Each of these implementations plays a different role in the context of a planning application and its development:

  • The standard interpreter is designed to be easily extended, and also comes with the ease of debugging and inspection usually associated with interpreters. As such, it is ideal for checking correctness when specifying a new PDDL domain, or when implementing a planning algorithm or extension library.

  • The compiler enables efficient planning through just-in-time compilation of specialized state representations and action semantics. While compilation is less easy to extend or debug, it provides orders of magnitude speed-ups over interpretation, allowing PDDL.jl applications to scale to much larger problems.

  • The abstract interpreter primary intended use is to compute planning heuristics that rely upon domain relaxation or abstraction. However, abstract interpreters have many other uses which future applications could take advantage of.

Other Components

In addition to implementations of its interface, PDDL.jl also provides a PDDL parser, writer, and a set of utilities to help analyze and work with PDDL domains. Extension interfaces also make it easier to support new functionality in PDDL.jl. Collectively, these components allow researchers, developers, and engineers to use symbolic planning in a wide variety of application contexts.

+

Standard Planning Architectures

Standard architectures are designed primarily for fast and efficient planning, accepting PDDL domain and problem files as inputs (right, pink), rapidly translating and compiling them (orange) to more efficient representations (yellow), running planning algorithms and heuristics (blue) over those representations, then producing symbolic plans and metadata as outputs (green). This architecture enables performance optimization over the entire pipeline, but limits interaction with external applications to just two channels: (i) receiving domains and problems as inputs; and (ii) providing plans as outputs.

PDDL.jl Architecture and Ecosystem

In contrast, the core of PDDL.jl is its interface (left, green): a set of abstract data types and interface functions that expose the high-level functionality required to implement planning algorithms and applications. Centering PDDL.jl around its interface means that:

By factoring out these components of traditional planning systems into separate software artifacts, PDDL.jl enables an ecosystem where implementations can evolve independently from applications (e.g. through future compiler improvements), applications can interoperate through a common interface (e.g. Bayesian agent models which incorporate planning algorithms), and extensions can be flexibly composed (e.g. multi-agent stochastic domains).

Built-in Implementations

Given this interface-centered design, PDDL.jl itself does not include any applications or extensions, which are intended to be provided by separate libraries (e.g. SymbolicPlanners.jl). However, PDDL.jl does include several built-in implementations of its interface: a standard interpreter, a compiler, and an abstract interpreter. Each of these implementations plays a different role in the context of a planning application and its development:

Other Components

In addition to implementations of its interface, PDDL.jl also provides a PDDL parser, writer, and a set of utilities to help analyze and work with PDDL domains. Extension interfaces also make it easier to support new functionality in PDDL.jl. Collectively, these components allow researchers, developers, and engineers to use symbolic planning in a wide variety of application contexts.

diff --git a/dev/ref/parser_writer/index.html b/dev/ref/parser_writer/index.html index 087865c..1542b4c 100644 --- a/dev/ref/parser_writer/index.html +++ b/dev/ref/parser_writer/index.html @@ -1,11 +1,11 @@ -Parser and Writer · PDDL.jl

Parser and Writer

PDDL.jl supports both parsing and writing of PDDL files and strings. In addition, the parser is designed to be extensible, allowing variants or extensions of PDDL to be easily supported.

General Parsing

The PDDL.Parser submodule contains all functionality related to parsing PDDL strings and loading of PDDL files. To parse a string in PDDL, use the macro @pddl or the function parse_pddl. Both of these return a list of parsed results if multiple strings are provided.

PDDL.Parser.@pddlMacro
@pddl(strs...)

Parse string(s) to PDDL construct(s).

When parsing PDDL formulae, the variable x can be interpolated into the string using the syntax \$x. For example, @pddl("(on \$x \$y)") will parse to Compound(:on, Term[x, y]) if x and y are Terms.

Julia expressions can be interpolated by surrounding the expression with curly braces, i.e. \${...}.

source

Below we use @pddl to parse a sequence of predicates, and use parse_pddl to parse a PDDL axiom (a.k.a. derived predicate):

julia> @pddl("(on a b)", "(on b c)")
+Parser and Writer · PDDL.jl

Parser and Writer

PDDL.jl supports both parsing and writing of PDDL files and strings. In addition, the parser is designed to be extensible, allowing variants or extensions of PDDL to be easily supported.

General Parsing

The PDDL.Parser submodule contains all functionality related to parsing PDDL strings and loading of PDDL files. To parse a string in PDDL, use the macro @pddl or the function parse_pddl. Both of these return a list of parsed results if multiple strings are provided.

PDDL.Parser.@pddlMacro
@pddl(strs...)

Parse string(s) to PDDL construct(s).

When parsing PDDL formulae, the variable x can be interpolated into the string using the syntax \$x. For example, @pddl("(on \$x \$y)") will parse to Compound(:on, Term[x, y]) if x and y are Terms.

Julia expressions can be interpolated by surrounding the expression with curly braces, i.e. \${...}.

source

Below we use @pddl to parse a sequence of predicates, and use parse_pddl to parse a PDDL axiom (a.k.a. derived predicate):

julia> @pddl("(on a b)", "(on b c)")
 2-element Vector{Compound}:
  on(a, b)
  on(b, c)
 julia> parse_pddl("(:derived (handempty) (forall (?x) (not (holding ?x))))")
 handempty <<= forall(object(X), not(holding(X)))

In addition, there exists a string macro pddl"...", which is useful for parsing single string literals:

julia> pddl"(on a b)"
-on(a, b)
PDDL.Parser.@pddl_strMacro
pddl"..."

Parse string "..." to PDDL construct.

When parsing PDDL formulae, the variable x can be interpolated into the string using the syntax $x. For example, pddl"(on $x $y)" will parse to Compound(:on, Term[x, y]) if x and y are Terms.

Julia expressions can be interpolated by surrounding the expression with curly braces, i.e. ${...}.

source

Interpolation

The string macro pddl"... (as well as the @pddl macro) supports the interpolation of Julia variables using the $ operator when parsing PDDL formulae. This makes it easier to construct predicates or expressions with a fixed structure but variable contents:

obj = Const(:a)
+on(a, b)
PDDL.Parser.@pddl_strMacro
pddl"..."

Parse string "..." to PDDL construct.

When parsing PDDL formulae, the variable x can be interpolated into the string using the syntax $x. For example, pddl"(on $x $y)" will parse to Compound(:on, Term[x, y]) if x and y are Terms.

Julia expressions can be interpolated by surrounding the expression with curly braces, i.e. ${...}.

source

Interpolation

The string macro pddl"... (as well as the @pddl macro) supports the interpolation of Julia variables using the $ operator when parsing PDDL formulae. This makes it easier to construct predicates or expressions with a fixed structure but variable contents:

obj = Const(:a)
 sym = :b
 pddl"(on $obj $sym)"
 # Parses to the same value as pddl"(on a b)"
@@ -19,16 +19,16 @@
 pddl"(forall ($var - $type) (on-table $var))"
 # Parses to pddl"(forall (?x - block) (on-table ?x))"

It is also possible to interpolate entire Julia expressions by surrounding the expression in curly braces (note that the expression itself must not contain any curly braces):

pddl"(= cost ${1 + 2})"     # Parses to pddl"(= cost 3)"
 pddl"(= cost ${zero(Int)})" # Parses to pddl"(= cost 0)"

Interpolation is not supported when parsing larger PDDL constructs, such as actions, domains, and problems.

Parsing Domains and Problems

To parse domains and problems specified as PDDL strings, use parse_domain and parse_problem.

To load domains or problems from a file, use load_domain and load_problem.

PDDL.Parser.load_domainFunction
load_domain(path::AbstractString)
-load_domain(io::IO)

Load PDDL domain from specified path or IO object.

source
PDDL.Parser.load_problemFunction
load_problem(path::AbstractString)
-load_problem(io::IO)

Load PDDL problem from specified path or IO object.

source

Extending the Parser

The parser can be extended to handle new PDDL constructs using the following macros:

General Writing

The PDDL.Writer submodule contains all functionality related to writing PDDL strings and saving of PDDL files. To write a string in PDDL syntax, use the function write_pddl.

Below we use write_pddl to write out an Action from the Blocksworld domain.

julia> write_pddl(PDDL.get_action(domain, :stack)) |> print
+

Parse PDDL domain description.

source

To load domains or problems from a file, use load_domain and load_problem.

PDDL.Parser.load_domainFunction
load_domain(path::AbstractString)
+load_domain(io::IO)

Load PDDL domain from specified path or IO object.

source
PDDL.Parser.load_problemFunction
load_problem(path::AbstractString)
+load_problem(io::IO)

Load PDDL problem from specified path or IO object.

source

Extending the Parser

The parser can be extended to handle new PDDL constructs using the following macros:

General Writing

The PDDL.Writer submodule contains all functionality related to writing PDDL strings and saving of PDDL files. To write a string in PDDL syntax, use the function write_pddl.

Below we use write_pddl to write out an Action from the Blocksworld domain.

julia> write_pddl(PDDL.get_action(domain, :stack)) |> print
 (:action stack
  :parameters (?x ?y - block)
  :precondition (and (holding ?x) (clear ?y) (not (= ?x ?y)))
  :effect (and (not (holding ?x)) (not (clear ?y)) (clear ?x) (handempty) (on ?x ?y)))

Writing Domains and Problems

To write domains and problem as PDDL strings, use write_domain and write_problem.

To save domains or problems as text files to a path, use save_domain and save_problem.

+

Write problem in PDDL syntax.

source

To save domains or problems as text files to a path, use save_domain and save_problem.

PDDL.Writer.save_domainFunction
save_domain(path::String, domain::Domain)

Save PDDL domain to specified path.

source
PDDL.Writer.save_problemFunction
save_problem(path::String, problem::Problem)

Save PDDL problem to specified path.

source
diff --git a/dev/ref/utilities/index.html b/dev/ref/utilities/index.html index c7a37fe..414d83a 100644 --- a/dev/ref/utilities/index.html +++ b/dev/ref/utilities/index.html @@ -1,43 +1,43 @@ -Utilities · PDDL.jl

Utilities

PDDL.jl provides a variety of utilities for working with and manipulating planning domains, including plan simulation, domain grounding, domain caching, and tools for domain and formula analysis.

Simulation

It is often useful to simulate the results of applying a series of actions to an initial state. PDDL.jl supports this with the Simulator data type, and the associated PDDL.simulate method.

PDDL.simulateFunction
simulate([sim=StateRecorder()], domain::Domain, state::State, actions)

Simulates the evolution of a PDDL domain as a sequence of actions are executed from an initial state. The type of simulator, sim, specifies what information is collected and returned.

By default, sim is a StateRecorder, which records and returns the state trajectory.

source

The following types of Simulator are provided, depending on what results are desired:

PDDL.StateRecorderType
StateRecorder(max_steps::Union{Int,Nothing} = nothing)

Simulator that records the state trajectory, including the start state.

source
PDDL.EndStateSimulatorType
EndStateSimulator(max_steps::Union{Int,Nothing} = nothing)

Simulator that returns the end state of simulation.

source

Grounding

Many planning algorithms and search heuristics benefit from grounding of actions and axioms with respect to the fixed set of objects in the initial state. PDDL.jl provides the GroundAction data type to represent grounded actions, as well as the groundactions and groundaxioms functions to convert lifted Actions and axiom Clauses into lists of grounded actions:

PDDL.groundactionsFunction
groundactions(domain::Domain, state::State, action::Action)

Returns ground actions for a lifted action in a domain and initial state.

source
groundactions(domain::Domain, state::State)

Returns all ground actions for a domain and initial state.

source
PDDL.groundaxiomsFunction
groundaxioms(domain::Domain, state::State, axiom::Clause)

Converts a PDDL axiom to a set of ground actions.

source
groundaxioms(domain::Domain, state::State)

Convert all axioms into ground actions for a domain and initial state.

source

PDDL.jl also provides the ground function, which can be used to ground specific actions:

PDDL.groundMethod
ground(domain::Domain, state::State, action::Action, args)

Return ground action given a lifted action and action args. If the action is never satisfiable given the domain and state, return nothing.

source
PDDL.groundMethod
ground(domain::Domain, state::State, action::Action)

Grounds a lifted action in a domain and initial state, returning a group of grounded actions.

source

The ground function can also be used to ground an entire domain with respect to an initial state, returning a GroundDomain that can be used in place of the original domain:

PDDL.groundMethod
ground(domain::Domain, state::State)
-ground(domain::Domain, problem::Problem)

Grounds a lifted domain with respect to a initial state or problem.

source
PDDL.GroundDomainType
GroundDomain(name, source, actions)

Ground PDDL domain, constructed from a lifted source domain, with a dictionary of ground actions.

source

Caching

Some applications of the PDDL.jl interface may result in repeated calls to costly interface functions with the same set of input arguments (e.g. repeatedly determining the set of available actions in value iteration). In such cases, it is useful to be able to memoize the outputs of these functions. PDDL.jl supports this via CachedDomains:

PDDL.CachedDomainType
CachedDomain{D, Ks, Vs}

Wraps an existing domain of type D, caching the outputs of calls to a subset of interface methods. Ks is a tuple of method identifiers, and Vs is a a tuple of corresponding cache types.

source
PDDL.CachedDomainMethod
CachedDomain(source::Domain)
-CachedDomain(source::Domain, method_keys)

Construct a CachedDomain from a source domain, along with the associated caches for each cached method. A list of method_keys can be provided, where each key is a Symbol specifying the method to be cached.

By default, the following methods are cached: [:available, :relevant, :infer_static_fluents, :infer_affected_fluents, :infer_axiom_hierarchy].

source

Analysis

Static analysis of domains, actions, and formulae is often used in a variety of downstream tasks such as grounding, compilation, and relevance pruning. PDDL.jl provides a suite of analysis tools that can be helpful for these purposes.

Domain Analysis

Certain analyses are performed on planning domains as whole (e.g. inferring the set of static fluents). The following domain-level analyses are provided by PDDL.jl:

PDDL.infer_relevant_fluentsFunction
infer_relevant_fluents(domain)
-

Infer fluents that are relevant to some action precondition.

source
infer_relevant_fluents(domain, goals)
+Utilities · PDDL.jl

Utilities

PDDL.jl provides a variety of utilities for working with and manipulating planning domains, including plan simulation, domain grounding, domain caching, and tools for domain and formula analysis.

Simulation

It is often useful to simulate the results of applying a series of actions to an initial state. PDDL.jl supports this with the Simulator data type, and the associated PDDL.simulate method.

PDDL.simulateFunction
simulate([sim=StateRecorder()], domain::Domain, state::State, actions)

Simulates the evolution of a PDDL domain as a sequence of actions are executed from an initial state. The type of simulator, sim, specifies what information is collected and returned.

By default, sim is a StateRecorder, which records and returns the state trajectory.

source

The following types of Simulator are provided, depending on what results are desired:

PDDL.StateRecorderType
StateRecorder(max_steps::Union{Int,Nothing} = nothing)

Simulator that records the state trajectory, including the start state.

source
PDDL.EndStateSimulatorType
EndStateSimulator(max_steps::Union{Int,Nothing} = nothing)

Simulator that returns the end state of simulation.

source

Grounding

Many planning algorithms and search heuristics benefit from grounding of actions and axioms with respect to the fixed set of objects in the initial state. PDDL.jl provides the GroundAction data type to represent grounded actions, as well as the groundactions and groundaxioms functions to convert lifted Actions and axiom Clauses into lists of grounded actions:

PDDL.groundactionsFunction
groundactions(domain::Domain, state::State, action::Action)

Returns ground actions for a lifted action in a domain and initial state.

source
groundactions(domain::Domain, state::State)

Returns all ground actions for a domain and initial state.

source
PDDL.groundaxiomsFunction
groundaxioms(domain::Domain, state::State, axiom::Clause)

Converts a PDDL axiom to a set of ground actions.

source
groundaxioms(domain::Domain, state::State)

Convert all axioms into ground actions for a domain and initial state.

source

PDDL.jl also provides the ground function, which can be used to ground specific actions:

PDDL.groundMethod
ground(domain::Domain, state::State, action::Action, args)

Return ground action given a lifted action and action args. If the action is never satisfiable given the domain and state, return nothing.

source
PDDL.groundMethod
ground(domain::Domain, state::State, action::Action)

Grounds a lifted action in a domain and initial state, returning a group of grounded actions.

source

The ground function can also be used to ground an entire domain with respect to an initial state, returning a GroundDomain that can be used in place of the original domain:

PDDL.groundMethod
ground(domain::Domain, state::State)
+ground(domain::Domain, problem::Problem)

Grounds a lifted domain with respect to a initial state or problem.

source
PDDL.GroundDomainType
GroundDomain(name, source, actions)

Ground PDDL domain, constructed from a lifted source domain, with a dictionary of ground actions.

source

Caching

Some applications of the PDDL.jl interface may result in repeated calls to costly interface functions with the same set of input arguments (e.g. repeatedly determining the set of available actions in value iteration). In such cases, it is useful to be able to memoize the outputs of these functions. PDDL.jl supports this via CachedDomains:

PDDL.CachedDomainType
CachedDomain{D, Ks, Vs}

Wraps an existing domain of type D, caching the outputs of calls to a subset of interface methods. Ks is a tuple of method identifiers, and Vs is a a tuple of corresponding cache types.

source
PDDL.CachedDomainMethod
CachedDomain(source::Domain)
+CachedDomain(source::Domain, method_keys)

Construct a CachedDomain from a source domain, along with the associated caches for each cached method. A list of method_keys can be provided, where each key is a Symbol specifying the method to be cached.

By default, the following methods are cached: [:available, :relevant, :infer_static_fluents, :infer_affected_fluents, :infer_axiom_hierarchy].

source

Analysis

Static analysis of domains, actions, and formulae is often used in a variety of downstream tasks such as grounding, compilation, and relevance pruning. PDDL.jl provides a suite of analysis tools that can be helpful for these purposes.

Domain Analysis

Certain analyses are performed on planning domains as whole (e.g. inferring the set of static fluents). The following domain-level analyses are provided by PDDL.jl:

PDDL.infer_relevant_fluentsFunction
infer_relevant_fluents(domain)
+

Infer fluents that are relevant to some action precondition.

source
infer_relevant_fluents(domain, goals)
 infer_relevant_fluents(domain, goals, axiom_parents)
-

Infer fluents that are relevant to achieving a set of goal fluents.

source

An associated set of (un-exported) utility functions are provided:

PDDL.is_staticFunction
is_static(term, domain)
+

Infer fluents that are relevant to achieving a set of goal fluents.

source

An associated set of (un-exported) utility functions are provided:

PDDL.is_staticFunction
is_static(term, domain)
 is_static(term, domain, statics)
-

Check if term is static or composed of static subterms.

source
PDDL.is_affectedFunction
is_affected(term, domain)
+

Check if term is static or composed of static subterms.

source
PDDL.is_affectedFunction
is_affected(term, domain)
 is_affected(term, domain, affected)
-

Check if term is affected by some action or composed of affected subterms.

source
PDDL.substitute_axiomsFunction
substitute_axioms(term, domain; ignore)
-

Substitute derived predicates in a term with their axiom bodies.

source

Formula Analysis

PDDL.jl also provides a list of utilities for analyzing formula properties (some of which may be specific to the domain they are defined in). Note that these utilities are not exported.

The following utilities determine top-level properties of a Term.

PDDL.is_global_predFunction
is_global_pred(name)
-

Return whether a symbol refers to global predicate.

source
is_global_pred(term)
-

Check if term is a global predicate (comparison, equality, etc.).

source
PDDL.is_funcFunction
is_func(term, domain)
-

Check if term is a non-Boolean fluent (i.e. function).

source
PDDL.is_global_funcFunction
is_global_func(name)
-

Return whether a symbol refers to global function.

source
is_global_func(term)
-

Check if term is a global function, including global predicates.

source
PDDL.is_fluentFunction
is_fluent(term, domain)
-

Check if term is a (non-external) domain fluent.

source
PDDL.is_literalFunction
is_literal(term)
-

Check if term is a literal (an atomic formula or its negation.)

source

The following utilities determine properties of a Term or any of its nested subterms.

PDDL.has_funcFunction
has_func(term, domain)
-

Check if term contains a non-Boolean fluent (i.e. function).

source
PDDL.has_typeFunction
has_type(term, domain)
-

Check if term contains a type predicate.

source

The PDDL.constituents function can be used to decompose a formula into a list of its constituent fluent terms:

+

Check if term is affected by some action or composed of affected subterms.

source
PDDL.substitute_axiomsFunction
substitute_axioms(term, domain; ignore)
+

Substitute derived predicates in a term with their axiom bodies.

source

Formula Analysis

PDDL.jl also provides a list of utilities for analyzing formula properties (some of which may be specific to the domain they are defined in). Note that these utilities are not exported.

The following utilities determine top-level properties of a Term.

PDDL.is_global_predFunction
is_global_pred(name)
+

Return whether a symbol refers to global predicate.

source
is_global_pred(term)
+

Check if term is a global predicate (comparison, equality, etc.).

source
PDDL.is_funcFunction
is_func(term, domain)
+

Check if term is a non-Boolean fluent (i.e. function).

source
PDDL.is_global_funcFunction
is_global_func(name)
+

Return whether a symbol refers to global function.

source
is_global_func(term)
+

Check if term is a global function, including global predicates.

source
PDDL.is_fluentFunction
is_fluent(term, domain)
+

Check if term is a (non-external) domain fluent.

source
PDDL.is_literalFunction
is_literal(term)
+

Check if term is a literal (an atomic formula or its negation.)

source

The following utilities determine properties of a Term or any of its nested subterms.

PDDL.has_funcFunction
has_func(term, domain)
+

Check if term contains a non-Boolean fluent (i.e. function).

source
PDDL.has_typeFunction
has_type(term, domain)
+

Check if term contains a type predicate.

source

The PDDL.constituents function can be used to decompose a formula into a list of its constituent fluent terms:

diff --git a/dev/search/index.html b/dev/search/index.html index 0ca3c74..94a5d7c 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · PDDL.jl
+Search · PDDL.jl
diff --git a/dev/tutorials/getting_started/index.html b/dev/tutorials/getting_started/index.html index 939590e..2326a19 100644 --- a/dev/tutorials/getting_started/index.html +++ b/dev/tutorials/getting_started/index.html @@ -134,4 +134,4 @@ GenericState julia> length(traj) -5

You've now learned how to load PDDL domains and problems, construct and inspect states, and execute (sequences of) actions – congratulations! In the next tutorial, you can learn how to write your very own planning algorithms using the functions introduced here.

+5

You've now learned how to load PDDL domains and problems, construct and inspect states, and execute (sequences of) actions – congratulations! In the next tutorial, you can learn how to write your very own planning algorithms using the functions introduced here.

diff --git a/dev/tutorials/speeding_up/index.html b/dev/tutorials/speeding_up/index.html index 9872b99..e75cd16 100644 --- a/dev/tutorials/speeding_up/index.html +++ b/dev/tutorials/speeding_up/index.html @@ -70,4 +70,4 @@ state.holding[x_idx] = false state.on[x_idx, y_idx] = true return state -end

All of the above code is compiled from PDDL to Julia, which in turn gets compiled to high performance machine code by Julia's own compiler. By directly modifying the state representation, the compiled implementation can achieve median runtimes up to 60 times faster than the interpreted version of execute.

Compiler Limitations

While domain compilation leads to significant performant benefits, the compiler also has several limitations in the current version of PDDL.jl:

Due to these limitations, it may sometimes be preferable to use the PDDL.jl interpreter instead of the compiler, especially when generality is more important than speed. However, most of these limitations are planned to be removed in future versions of PDDL.jl.

+end

All of the above code is compiled from PDDL to Julia, which in turn gets compiled to high performance machine code by Julia's own compiler. By directly modifying the state representation, the compiled implementation can achieve median runtimes up to 60 times faster than the interpreted version of execute.

Compiler Limitations

While domain compilation leads to significant performant benefits, the compiler also has several limitations in the current version of PDDL.jl:

Due to these limitations, it may sometimes be preferable to use the PDDL.jl interpreter instead of the compiler, especially when generality is more important than speed. However, most of these limitations are planned to be removed in future versions of PDDL.jl.

diff --git a/dev/tutorials/writing_planners/index.html b/dev/tutorials/writing_planners/index.html index ea857f0..6d55b32 100644 --- a/dev/tutorials/writing_planners/index.html +++ b/dev/tutorials/writing_planners/index.html @@ -76,4 +76,4 @@ stack(d, c) julia> satisfy(domain, sol.trajectory[end], goal) -true

For more information about the planners and heuristics provided by SymbolicPlanners.jl, consult the README.

+true

For more information about the planners and heuristics provided by SymbolicPlanners.jl, consult the README.