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.25, < 0.1 for shared third-party native dependencies.
  • pypddl-datasets >= 0.0.9, < 0.1 for the PDDL benchmark data used by the C++ test suite and the example executables (resolved from its cache at CMake configure time).

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.25,<0.1' 'pypddl-datasets>=0.0.9,<0.1'

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.
LOKI_USE_LLD ON Use LLVM lld with Clang when available.
LOKI_ENABLE_LTO ON Enable link-time optimization for Release builds.

Single-config CMake builds default to Release. On GCC and Clang, Debug builds use -Og with debug symbols, RelWithDebInfo keeps frame pointers and disables LTO, and Release LTO uses GCC LTO or Clang ThinLTO. Editable installs and wheels disable LOKI_USE_LLD and LOKI_ENABLE_LTO by default for build reliability.

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.25,<0.1 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 come straight from the pypddl-datasets cache:

./build/exe/loki $(python -c "import pypddl_datasets as pb; t = pb.fetch_task('classical/tests/gripper/test-1.pddl'); print(t.domain_path, t.task_path)")

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.25.tar.gz (867.2 kB 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.25-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.25-cp313-cp313-macosx_11_0_arm64.whl (877.3 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pypddl-1.0.25-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.25-cp312-cp312-macosx_11_0_arm64.whl (877.3 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypddl-1.0.25-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.25-cp311-cp311-macosx_11_0_arm64.whl (877.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypddl-1.0.25-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.25-cp310-cp310-macosx_11_0_arm64.whl (877.2 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypddl-1.0.25-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.25-cp39-cp39-macosx_11_0_arm64.whl (877.2 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: pypddl-1.0.25.tar.gz
  • Upload date:
  • Size: 867.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pypddl-1.0.25.tar.gz
Algorithm Hash digest
SHA256 1f5fb530a4d9da73ae028377ed20b831b87144426231465ba83f2582ca52bbdd
MD5 372c239823a0ad6eef378ecf8dc046ec
BLAKE2b-256 47da9ae1d8ae3f8032daf9d0f60d77c8d662967df46fae5dced438f15d2c8677

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25.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.25-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 eaff35397ad6f4e2c9fd495295fffa4a54ba5b79ed9e2e2e69a5b6224c995ba9
MD5 b10e7f8d3469dcc8a010ec874d0330a6
BLAKE2b-256 27a1710afc2ea16888d7359f59f42550208e19ede9d6be8ca69b2dedceb065be

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 51ebb0e7cf497882af5425f7f2ae45d32bdef57b6fc874abc5cda2b7220a58f4
MD5 980cfa4a28a81085f439340d55eacd29
BLAKE2b-256 8d17b86437e46adf1d62d09ac105b2d976fa53e5bc2c5d80ed920b528516d996

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 440230a37796202af41050f6419ba269b081006accd5913e11c6ed038b5326c2
MD5 7173616e545233d5094cef104f2512be
BLAKE2b-256 3add8e347e7e5a3e1b866c45bfd30218571b797acbafeb2d94782588ebea0bb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e9954446e3f9c5312b99092bc7dcc1167268ce2f28825c272e300e8632c74bca
MD5 3adcab39205954966d3720036f130341
BLAKE2b-256 df002e1f22e0cbee2f1a084d3ac0a84314615bd7fc88906db9708b36306c4321

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d438693b542df6955dd340cafde70cbb74c7a486d3ff5b84827edcbb1d8e465f
MD5 c96ef6ae31a8f0c9df0016528b6fb63e
BLAKE2b-256 bd43888ec7fb180418c67108e02ed3779d0094ab36a10d5c11fdc11ef7c85fc9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f4017f67ec5abfba58d8aa44ac7151a2a74f98698efd38e9447dccdb7ba9b7e2
MD5 ae014a85ea4756a8039ec2aa77060db2
BLAKE2b-256 babb7e9d1a5ebb91f2a8197c8069ff85a1b4d8de05a1ec253225a2d59ff1ee94

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d0833c84b63a58e0aaaf72c7d79e2aee0b15eb9e3749dcfd85cd7f3f2d785f28
MD5 18aada1163b3cf4091c1d2ca3099f086
BLAKE2b-256 30b81388fe7b419994ff78714333c32678d5d2919b6d51c87cbe5711b1494aef

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e21176228b255a833e3c29567d2d87a59a4a3aa36568daf5e41988eba4b26cac
MD5 204122f47d94f61330091cd35761c3b6
BLAKE2b-256 f888837ceedf6481100de598958626cd0bb7594360e5ed6e9d5281b1c9b2a13d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e2b7050b0c943f1e3522f719e8ea37b5d38e3b7bbcc3b03626e119f9db4eef55
MD5 a55265be3126135703b1a5f8eda875f6
BLAKE2b-256 5977537c787dc925b372d7f68ba88096b990e520dce49ceb724ae1498bbc66ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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.25-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pypddl-1.0.25-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 48cb4ff3f251f0a8cbfb0d8155428c731e4db8530988dd73fefa7ce0e678750b
MD5 59d260e4090546f2a79880c444cf5466
BLAKE2b-256 578df97ef54f258b91454d090d8aa53bc42f4cec1ec6aefc20c236d1e92c3ac5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypddl-1.0.25-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