Skip to main content

Loki: PDDL Parsing and Translation in C++ and Python

Loki is a C++20 library with Python bindings for parsing and translation of PDDL files. Loki separates the parsing and translation of domain and problem files, allowing users to effectively work with collection of problems.

The parser is based on the canonical parser structure proposed in the Boost Spirit X3 library.

The translator is based on the method presented in section four of the paper "Concise finite-domain representations for PDDL planning tasks by Malte Helmert (AIJ 2009)".

Supported PDDL Requirements

  • :strips
  • :typing
  • :negative-preconditions
  • :disjunctive-preconditions
  • :equality
  • :existential-preconditions
  • :universal-preconditions
  • :quantified-preconditions
  • :conditional-effects
  • :numeric-fluents
  • :adl
  • :derived-predicates
  • :action-costs
  • :non-deterministic (unsupported in the translator)
  • :probabilistic-effects (unsupported in the translator)

Dependencies

Loki depends on a fraction of Boost's header-only libraries (Fusion, Spirit x3, Container), its performance benchmarking framework depends on GoogleBenchmark, and its testing framework depends on GoogleTest.

Loki consumes native dependencies from Python packages:

  • pyyggdrasil == 0.0.21 for shared third-party native dependencies.

The shared workspace layout, layered install order, and the common build-from-source and CMake-integration patterns are documented in the Planning and Learning build instructions; the sections below cover loki/pypddl-specific details.

For offline/local development, install pyyggdrasil from the sibling source checkout instead:

cd ../yggdrasil
uv pip install --python ../loki/.venv/bin/python .

Build C++

Install Loki's native dependency providers into the active Python environment, then configure CMake with their native prefixes:

python -m pip install 'pyyggdrasil==0.0.21'

cmake -S . -B build

CMake discovers the installed pyyggdrasil automatically through cmake/bootstrap_pyyggdrasil.cmake (which locates the package and adds its native prefix to CMAKE_PREFIX_PATH, after which find_package(yggdrasil) provides the shared helper functions) and links against the yggdrasil::yggdrasil target. To point at a different prefix explicitly:

cmake -S . -B build \
  -DCMAKE_PREFIX_PATH="$(python -m pyyggdrasil --prefix)"

cmake --build build -j4

CMake options:

Option Default Description
LOKI_BUILD_TESTS OFF Build Loki tests.
LOKI_BUILD_EXECUTABLES OFF Build Loki executables.
LOKI_BUILD_PROFILING OFF Build Loki profiling targets.
LOKI_BUILD_PYPDDL OFF Build Loki for the pypddl Python wheel.

Run tests from a build configured with -DLOKI_BUILD_TESTS=ON:

ctest --test-dir build --output-on-failure

Install Loki from a configured build directory with:

cmake --install build --prefix=<path/to/installation-directory>

Build Python

python -m pip install .

Python API

The Python package exposes the semantic parser, translator, and reparseable PDDL formatter through pypddl.formalism:

from pypddl import formalism as pddl

parser = pddl.Parser("""
(define (domain ready-domain)
  (:predicates (ready))
)
""")

translation = pddl.translate_domain(parser.domain())
domain_text = pddl.format_domain(translation.translated_domain)
reparsed = pddl.Parser(domain_text)
assert reparsed.domain().get_name() == "ready-domain"

With default options the parser completes :action-costs artifacts and the translator compiles typing and materializes equality; see Parser and Translator Options to override.

C++ API

The umbrella header exposes the semantic parser, translator, and reparseable PDDL formatter through the top-level loki namespace:

#include <loki/loki.hpp>

#include <string>

int main()
{
    auto parser = loki::Parser(std::string { "(define (domain ready-domain) (:predicates (ready)))" });
    const auto translation = loki::translate_domain(parser.get_domain());
    const auto domain_text = loki::format_domain(translation.get_translated_domain());
    auto reparsed = loki::Parser(domain_text);
    return reparsed.get_domain().get_name() == "ready-domain" ? 0 : 1;
}

Parser and Translator Options

Both APIs accept options at construction/translation time. The library defaults are normalization-friendly for downstream consumers; every option can be turned off individually.

ParserOptions (second argument of Parser):

Option Default Description
strict false Strict semantic validation for requirements, arity, and type compatibility. Numeric-fluents violations error even in permissive mode: reads require :fluents/:numeric-fluents/:action-costs, and writes other than (increase (total-cost) ...) require :fluents/:numeric-fluents.
add_action_costs true Complete missing :action-costs artifacts (total-cost function, initial value, minimize metric) instead of erroring. If the domain declares neither :action-costs nor :fluents/:numeric-fluents, additionally injects the requirement and a unit-cost effect (increase (total-cost) 1) into every action that does not already write total-cost. Genuine numeric domains are left untouched: an absent metric means unit costs.

TranslatorOptions (second argument of translate_domain/translate_task):

Option Default Description
compile_typing true Compile typing away into type predicates and remove type annotations.
compile_conditional_effects false Multiply conditional effects out into unconditional actions; the normalization phases re-run afterwards so preconditions stay conjunctive (quantified when-conditions become derived predicates). Worst case exponential in the number of conditional effects per action.
materialize_equality true Add the = predicate and (= o o) initial literals. Turn off for consumers with native equality handling.

Pass the same TranslatorOptions to the domain and the task translation; mismatched options between the two can fail (e.g. equality materialization requires the = predicate added during domain translation).

options = pddl.TranslatorOptions()
options.materialize_equality = False
translation = pddl.translate_domain(parser.domain(), options)

The loki executable exposes the same options as opt-in flags (all off by default): --strict, --add-action-costs, --compile-typing, --compile-conditional-effects, and --materialize-equality.

CMake Integration

This section covers pypddl-specific paths and targets; the general pattern for consuming the native prefixes from CMake is in the common CMake integration instructions.

The Python package pypddl installs Loki's native headers, shared library, and CMake package config under pypddl.native_prefix(). It depends on pyyggdrasil==0.0.21 for third-party native dependencies:

import pypddl
import pyyggdrasil

print(pypddl.cmake_prefix())       # prefix to put on CMAKE_PREFIX_PATH
print(pypddl.cmake_dir())          # directory containing lokiConfig.cmake
print(pyyggdrasil.cmake_prefix())

The same paths are available from the shell via python -m pypddl --prefix, --cmake-dir, --include-dir, and --version.

Downstream CMake projects should include the native prefixes of pypddl and its native package dependencies in CMAKE_PREFIX_PATH:

cmake -S . -B build \
  -DCMAKE_PREFIX_PATH="$(python -m pypddl --prefix);$(python -m pyyggdrasil --prefix)"

Loki exports the loki::parsers target.

Running the Executables

The executable illustrates how to use Loki. It is disabled by default and can be enabled with -DLOKI_BUILD_EXECUTABLES=ON. Example PDDL inputs are available from the benchmark submodule:

git submodule update --init --recursive data/planning-benchmarks
./build/exe/loki \
  data/planning-benchmarks/tests/classical/gripper/domain.pddl \
  data/planning-benchmarks/tests/classical/gripper/test-1.pddl

Use --out-domain/--out-problem to write the translated PDDL to files, and see ./build/exe/loki --help for the parser and translator flags (--strict, --add-action-costs, --compile-typing, --compile-conditional-effects, --materialize-equality).

Citing Loki

If you use Loki in your research, please cite it as follows:

@misc{drexler-zenodo2026,
  author =       "Dominik Drexler",
  title =        "{Loki}: A {PDDL} Parser and Normalizer",
  publisher =    "Zenodo",
  year =         "2026",
  doi =          "10.5281/zenodo.20081136",
  url =          "https://doi.org/10.5281/zenodo.20081136",
}

Acknowledgements

This work was partially supported by the Wallenberg AI, Autonomous Systems and Software Program (WASP) funded by the Knut and Alice Wallenberg Foundation.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypddl-1.0.20.tar.gz (3.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pypddl-1.0.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypddl-1.0.20-cp313-cp313-macosx_11_0_arm64.whl (921.4 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pypddl-1.0.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypddl-1.0.20-cp312-cp312-macosx_11_0_arm64.whl (921.4 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypddl-1.0.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypddl-1.0.20-cp311-cp311-macosx_11_0_arm64.whl (898.5 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypddl-1.0.20-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypddl-1.0.20-cp310-cp310-macosx_11_0_arm64.whl (921.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypddl-1.0.20-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pypddl-1.0.20-cp39-cp39-macosx_11_0_arm64.whl (921.5 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file pypddl-1.0.20.tar.gz.

File metadata

  • Download URL: pypddl-1.0.20.tar.gz
  • Upload date:
  • Size: 3.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypddl-1.0.20.tar.gz
Algorithm Hash digest
SHA256 d5810d67635fdd302012acf272037ad3b7b7487f3c981ab9dfb2b3136761b0c5
MD5 03ec5a5f492c447dc3f2df8ad6da3188
BLAKE2b-256 2fb1bdc67129e05182751adb74a13865b0c0f8c963496967f8c057073da8288b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20.tar.gz:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 429e793f7d329b5950b07da81fae15dd86b8bd943fb630623d886693b32d7f24
MD5 cca60565cc9e832ef1fd7601d59361fd
BLAKE2b-256 c7d21eb29f03d308696930970eb8ed2227da0481d26017d3611457b57a08ac36

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3fa154eb411d3d4f84f6cd940f504a9dcf766c604a3260190a21faf4cc880508
MD5 cbfca4a4912f891515853739fc98d9cc
BLAKE2b-256 fb3fa37cd2dd65a98734ce46ce5619795fcf098a876ae97351fd3191fe8c1400

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5d5d0a3184b4b537ad19c5f5264f94a8d5d2c4e79b8ae9b9430a283c9ca4c17e
MD5 995a7331ea0c1efea3524975bac35c41
BLAKE2b-256 d5ea3845ed9941c66cbf0f9913bb09655867fee2b7900f426bb9f2f2167be6e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aed85914d7d2e1321786ea66209b32af61422fb31ce28431cf5e68d865632e2d
MD5 5427d2a8cff401c2da4280df5fa49479
BLAKE2b-256 3475316f0b9a01ed401f04fbd418f54a71ab5328e17e2cd6cc890e6f64f5ec4e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3d7696c20c2f4615367b5e2190782e8f35bf922e485d786ac61cde71e82b56cc
MD5 ee17701b7a2aa406bae94357ba95a504
BLAKE2b-256 5bde09cae2fc35ca8de850960ef39d2aa85688a073362592655498ba365c9311

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 78731e24a16f545cc0d3851a7b067a968d284d8de4038bbd0d326242a90420c2
MD5 8ee21e6c78d64760f92a1feb6975c1b4
BLAKE2b-256 ccd985671b272ae7a48fcba6d6c3f931c99b733297309466fabe22828ca2b1e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1afb386c21e952734da5b468ec59aa05d735c2ce9e1bdeb1eed0934d99b3d88e
MD5 48f3a576f672d170d61819eb2ddd69d3
BLAKE2b-256 ec406fbde0b77ae68e84e8479da7f70d20b8c4e1e78ffa8ab5e96007724135bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e5ffdcf5eb20590c3686ef4fb28d439b29b5b9803a0cacd62953d0cc110b6049
MD5 61b80b3dc1579f6c2c44ad977802f071
BLAKE2b-256 9dff54313ec6467a5ba2d14210fb4a8e1c19ea6682d55c42c957e2e3d037d2fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4124b35de70488e9a9aff4550d474ea242b7670507bdabe66c11d13d873c5223
MD5 cf1ef82d28d82eda33007b0aa2fa04e7
BLAKE2b-256 1d10963e4bd57e2ea02a8658db557155e2fc6c0f7e87328a56c83dd825889fbc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypddl-1.0.20-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.20-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 764f22e18d49d46b40aeb1ef7fc8c115f5b34cadb302dd29bf91ac13afa98b6b
MD5 7dc934ee918a0e6f3eeeb3c6652c3360
BLAKE2b-256 15ed589e6e8f3757e8c132894e1d0cbf999cde91aa1bd8b7b68a394b6c06e170

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.20-cp39-cp39-macosx_11_0_arm64.whl:

Publisher: release.yml on planning-and-learning/loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page