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, < 0.1 for shared third-party native dependencies.
  • pypddl-datasets >= 0.0.5, < 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.21,<0.1' 'pypddl-datasets>=0.0.5,<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.

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,<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.23.tar.gz (713.7 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.23-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.23-cp313-cp313-macosx_11_0_arm64.whl (925.2 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pypddl-1.0.23-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.23-cp312-cp312-macosx_11_0_arm64.whl (925.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypddl-1.0.23-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.23-cp311-cp311-macosx_11_0_arm64.whl (925.4 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypddl-1.0.23-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.23-cp310-cp310-macosx_11_0_arm64.whl (925.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypddl-1.0.23-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.23-cp39-cp39-macosx_11_0_arm64.whl (925.3 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for pypddl-1.0.23.tar.gz
Algorithm Hash digest
SHA256 54c4f129987018699d817255b725108dea602d53457222816abed3a5e480788a
MD5 0f4cecd3390ec9e08166ff9ab4be9e6a
BLAKE2b-256 3fbf0d71ddda226f06d4bb4e2ff68c2eb3b7589e53da43881b73b536033b14a2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ec007a6d270eb1204c500f7405352d78bb1249644005791e53bfa291973824c0
MD5 2b4703dff1b2b3d9ae8cce23bbc7904b
BLAKE2b-256 e076299baf62e500dba288b5b1a83490aedac66ac25cf9e5bc1f80c18c5791fd

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0cc92ff8b9ebbfeba0b79b31c63b109a98eb098024da6fc0a0fcf5abf97e7454
MD5 465f4512ad98d2e0fa04b3e2319ae53f
BLAKE2b-256 98239bcdeff72fc239f7842bb4fd69ef7c8c643dd6c83e8e41be70d0b9bfa478

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8771f1daf4ae8e95a2ba2cce1b97abdf060d2f512ee47d5b118e56f5c32ffdf4
MD5 74621fe89e8e27d0c23309f47b30d323
BLAKE2b-256 da5f307e8095a67db2088cbd83ffcd5f554213c3e195394bf7d7aac9134667ff

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9526f8e92225ea30f748f6d12c9e03befc9f15533f420238c8c40c421d8a58dc
MD5 c82c1ccfd4177f6a93edd755084e584e
BLAKE2b-256 b8f57ac1c3b15f471df07df19e3318e1c8b5ad81714980170e97f64b167a7034

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 2da658e2a218772cef34e12ffd84e217f5f59a0630e21baf1aede575988f331d
MD5 df94e7441ffd5cdb8df924ee08b5977b
BLAKE2b-256 5009c47793f3bd0ed9b1a5bb433983db5449aab72e274425fc11daf61697bbdc

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 188098dbbd8429ad54034faf7fd66092e610f38f9af6d9642382950b1c6c701e
MD5 c7152b8b695a2344e91dede992775323
BLAKE2b-256 c75b17f80dbf568c45f3bce693caab9e02eacf06935babbb5dcade1a70ca9b98

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b2436e700b288dd121cb40e82a95d9fb85f35172785cc19d33037b7414784a5b
MD5 35a44416a52bd503db99c0a8ddaa3624
BLAKE2b-256 086ef9130dd3121dd93276d3ce5ab4280fd719e2451634d85b1ce4c92f736f7f

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bfcd7bf36e2bdae364f9938784faaf41f55b011e17f1882eb81b2b57d912c8e6
MD5 07e8d014981025907583a9dee7a974c3
BLAKE2b-256 5c1feb36071885364dd4b767104cba3fb1a634b886a5695a1fac706e2c95ef19

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 12da8c9706cc00b3efab3668f28f7428b2fb61325fc549cbad1a1ebaf3128faf
MD5 0fa5bfa50f1b810db3da07ce7b286b05
BLAKE2b-256 1caf0e7e5c7724756fe831ac6ff04385ac1b36b86431fa0bb5bde6a8a0afeac0

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.23-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d539d710a0c1a28ce7a4c9a9a0d6df6f5ad1ea865db10498c143441ee46f034f
MD5 5a7fa6d3d1002d39d4cabf9c808316e0
BLAKE2b-256 07fbcea2aaa9eca4549d53ed8bb0e70713f5cdbfa20876393d8aa1f32c531e5e

See more details on using hashes here.

Provenance

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