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 Actions and axiom Clauses 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 CachedDomains:
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.