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.26, < 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.26,<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.26,<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.26.tar.gz (867.4 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.26-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.26-cp313-cp313-macosx_11_0_arm64.whl (873.8 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pypddl-1.0.26-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.26-cp312-cp312-macosx_11_0_arm64.whl (873.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypddl-1.0.26-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.26-cp311-cp311-macosx_11_0_arm64.whl (873.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypddl-1.0.26-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.26-cp310-cp310-macosx_11_0_arm64.whl (873.6 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypddl-1.0.26-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.26-cp39-cp39-macosx_11_0_arm64.whl (873.7 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: pypddl-1.0.26.tar.gz
  • Upload date:
  • Size: 867.4 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.26.tar.gz
Algorithm Hash digest
SHA256 472f9bc7264f9f11283e103c4e19312132bbe4c6cbb97efba465d499649d8304
MD5 0607ac57daa2153ae29a76bb4bba8d50
BLAKE2b-256 ebf4fca6900c7b50891201569b549493c5dc098dcc9ee0a5a4a07da59b896ad8

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b26ab251dd708e2d03a7d8bb10ae019df4a3e9d92d5d94e925edcec9e852f181
MD5 0e4730f9fa687a9efc61082cb5487da5
BLAKE2b-256 7058e48bdb9d4278f778ba0f9d2b87295c1fae641535cc7fda9f1a5fcbf50997

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b64df51d73d790306fee79540a93b2583bdda08b14f442cd33e05582a4c1b325
MD5 1e3fa82c449d70d44cc31b9d9d8f60c0
BLAKE2b-256 9f6597078cde9075d9bfb9b84649b72bcddc35867e4701b5c309f8e7cfc00816

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a81ea9172ebaa9fa791e3813f38eb95a0649535cf3dbe478e40d8bf5cedf7bbc
MD5 15a133c0773b8e6e04f7ef2deca6b692
BLAKE2b-256 17df9babe54932fff537083bf1b8f3b765147450014d1fb2a845a0b605f5d1f9

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6c3d5de5185cd48f09dccf2a1f042acf2dc2539049264c2de6dccfe5ef5a9e97
MD5 f8aee3ef2681f58ceb66a56ddbf00eea
BLAKE2b-256 9f451a55d6f48d4a23ebe97f07e71aa64064110b86327af00aa280d387e6112d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e4e6c9b0dd0d7cb576b9b653c50ae1199c10ad7d59f6bb309c7af3436db41490
MD5 7fb2ac446d35827291d4599e16e54154
BLAKE2b-256 a4315f65e388dc110959672406f8ca0f7e303f466bc19919195c924998b0d48a

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0e5a931d64ad54e73f93eb052e6ae3afc484662a7c5856171f3accc470bd795d
MD5 fed631063e6f8422a99f4ce1c59c99b1
BLAKE2b-256 49ec6169d169c08665094454a90741fa7593c488c8f474b50e135e5b80116510

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ff72863051ecb8aa1740aabddc460cba7ace72b8fc81c5245c4ad2e1473dd09d
MD5 8f0368f2007946b8d59d63abbfd8789a
BLAKE2b-256 243163c23f72ee87c5231160538df77e65e82f538c4160d499c6f49bcfc618e0

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2563989cd11985f94ae4078c0cba9df7b3643f0187955c80f30a74f92b086e78
MD5 ccac8f3c8c68e27c3a4f717c3df9192f
BLAKE2b-256 8cee018da20a040b3870fd3f7e40e761f9a3dc335f647f82048c2247e3dad0e6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4fee0a6b59ff18745f4aa9acbcbf96e68162575f54f322afc8878584a3288ac1
MD5 fdbabe79201c3373ee4f2499a5037fd5
BLAKE2b-256 78dbe3cecdea51b9ca4990a3635bd8c4936c6c8a34b3685919afa5d03ab55137

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.26-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9e4886e372e88d4551ba55d53f753eaa27e9ef899b90807b3c30a6d535629bc1
MD5 d4864d05b86a8cbc45f641db4f80cbbf
BLAKE2b-256 08b6ca907d273d3c87341c9ebd93e315a86b5522213f2954b0bfe609e3590a93

See more details on using hashes here.

Provenance

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