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.Simulator
— TypeAbstract type for PDDL simulators.
PDDL.simulate
— Functionsimulate([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.
The following types of Simulator
are provided, depending on what results are desired:
PDDL.StateRecorder
— TypeStateRecorder(max_steps::Union{Int,Nothing} = nothing)
Simulator that records the state trajectory, including the start state.
PDDL.EndStateSimulator
— TypeEndStateSimulator(max_steps::Union{Int,Nothing} = nothing)
Simulator that returns the end state of simulation.
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 Action
s and axiom Clause
s into lists of grounded actions:
PDDL.GroundAction
— TypeGroundAction(name, term, preconds, effect)
Ground action definition, represented by the name
of its corresponding action schema, a term
with grounded arguments, a list of preconds
, and an effect
, represented as a PDDL.GenericDiff
or PDDL.ConditionalDiff
.
PDDL.groundactions
— Functiongroundactions(domain::Domain, state::State, action::Action)
Returns ground actions for a lifted action
in a domain
and initial state
.
groundactions(domain::Domain, state::State)
Returns all ground actions for a domain
and initial state
.
PDDL.groundaxioms
— Functiongroundaxioms(domain::Domain, state::State, axiom::Clause)
Converts a PDDL axiom to a set of ground actions.
groundaxioms(domain::Domain, state::State)
Convert all axioms into ground actions for a domain
and initial state
.
PDDL.jl also provides the ground
function, which can be used to ground specific actions:
PDDL.ground
— Methodground(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
.
PDDL.ground
— Methodground(domain::Domain, state::State, action::Action)
Grounds a lifted action
in a domain
and initial state
, returning a group of grounded actions.
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.ground
— Methodground(domain::Domain, state::State)
ground(domain::Domain, problem::Problem)
Grounds a lifted domain
with respect to a initial state
or problem
.
PDDL.GroundDomain
— TypeGroundDomain(name, source, actions)
Ground PDDL domain, constructed from a lifted source
domain, with a dictionary of ground actions
.
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 CachedDomain
s:
PDDL.CachedDomain
— TypeCachedDomain{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.
PDDL.CachedDomain
— MethodCachedDomain(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]
.
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_static_fluents
— Functioninfer_static_fluents(domain)
Infer fluents that are never modified by some action in a domain.
PDDL.infer_affected_fluents
— Functioninfer_affected_fluents(domain)
Infer fluents that are modified by some action in a domain.
PDDL.infer_relevant_fluents
— Functioninfer_relevant_fluents(domain)
Infer fluents that are relevant to some action precondition.
infer_relevant_fluents(domain, goals)
infer_relevant_fluents(domain, goals, axiom_parents)
Infer fluents that are relevant to achieving a set of goal fluents.
PDDL.infer_axiom_hierarchy
— Functioninfer_axiom_hierarchy(domain)
Infer dependency structure between axioms.
An associated set of (un-exported) utility functions are provided:
PDDL.is_static
— Functionis_static(term, domain)
is_static(term, domain, statics)
Check if term is static or composed of static subterms.
PDDL.is_affected
— Functionis_affected(term, domain)
is_affected(term, domain, affected)
Check if term is affected by some action or composed of affected subterms.
PDDL.simplify_statics
— FunctionSimplify away static fluents within a term
.
PDDL.substitute_axioms
— Functionsubstitute_axioms(term, domain; ignore)
Substitute derived predicates in a term with their axiom bodies.
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_pred
— Functionis_pred(term, domain)
Check if term is a predicate.
PDDL.is_derived
— Functionis_derived(term, domain)
Check if term is a derived predicate
PDDL.is_global_pred
— Functionis_global_pred(name)
Return whether a symbol refers to global predicate.
is_global_pred(term)
Check if term is a global predicate (comparison, equality, etc.).
PDDL.is_func
— Functionis_func(term, domain)
Check if term is a non-Boolean fluent (i.e. function).
PDDL.is_global_func
— Functionis_global_func(name)
Return whether a symbol refers to global function.
is_global_func(term)
Check if term is a global function, including global predicates.
PDDL.is_attached_func
— Functionis_attached_func(term, domain)
Check if term is an external function attached to a domain.
PDDL.is_external_func
— Functionis_external_func(term, domain)
Check if term is an external function (attached or global).
PDDL.is_fluent
— Functionis_fluent(term, domain)
Check if term is a (non-external) domain fluent.
PDDL.is_literal
— Functionis_literal(term)
Check if term is a literal (an atomic formula or its negation.)
PDDL.is_logical_op
— Functionis_logical_op(term)
Check if term is a logical operator.
PDDL.is_negation
— Functionis_negation(term)
Check if term is a negation of another term.
PDDL.is_quantifier
— Functionis_quantifier(term)
Check if term is a universal or existential quantifier.
PDDL.is_type
— Functionis_type(term, domain)
Check if term is a type predicate.
PDDL.has_subtypes
— Functionhas_subtypes(term, domain)
Check if term is a type predicate with subtypes.
The following utilities determine properties of a Term
or any of its nested subterms.
PDDL.has_name
— FunctionCheck if term
has a (sub-term with a) name in names
.
PDDL.has_pred
— Functionhas_pred(term, domain)
Check if term contains a predicate.
PDDL.has_derived
— Functionhas_derived(term, domain)
Check if term contains a derived predicate
PDDL.has_global_pred
— Functionhas_global_pred(term)
Check if term contains a global predicate.
PDDL.has_func
— Functionhas_func(term, domain)
Check if term contains a non-Boolean fluent (i.e. function).
PDDL.has_global_func
— Functionhas_global_func(term)
Check if term contains a global function.
PDDL.has_attached_func
— Functionhas_attached_func(term, domain)
Check if term contains an external function attached to a domain.
PDDL.has_fluent
— Functionhas_fluent(term, domain)
Check if term contains a fluent name.
PDDL.has_logical_op
— Functionhas_logical_op(term)
Check if term contains a logical operator.
PDDL.has_negation
— Functionhas_negation(term)
Check if term contains a negated literal.
PDDL.has_quantifier
— Functionhas_quantifier(term)
Check if term contains a universal or existential quantifier.
PDDL.has_type
— Functionhas_type(term, domain)
Check if term contains a type predicate.
The PDDL.constituents
function can be used to decompose a formula into a list of its constituent fluent terms:
PDDL.constituents
— Functionconstituents(term, domain)
Returns list of constituent fluents.