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.19.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.19-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.19-cp313-cp313-macosx_11_0_arm64.whl (915.6 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pypddl-1.0.19-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.19-cp312-cp312-macosx_11_0_arm64.whl (893.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypddl-1.0.19-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.19-cp311-cp311-macosx_11_0_arm64.whl (915.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypddl-1.0.19-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.19-cp310-cp310-macosx_11_0_arm64.whl (915.6 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypddl-1.0.19-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.19-cp39-cp39-macosx_11_0_arm64.whl (893.7 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: pypddl-1.0.19.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.19.tar.gz
Algorithm Hash digest
SHA256 5f6cfc5fa5fc936ba302443108351fccdda37b6de243d2d46f6055034623866a
MD5 44de713076430b016742132b644073c1
BLAKE2b-256 aee2ddc396d7223422430b48153e2be7fc439a8ad921adaa5007ec085759b556

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e143dc7f4e33ae1b3d62731fbbbb40831af1fda773043a3b7a19ca6a91a52b93
MD5 33d31cc773988e4a0ead0df92b27d806
BLAKE2b-256 f7806e51377c5c3e4e5ff15268230859ce4a16a02c84a680932b48962279e5e3

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a813b78029543b786c859eefcb1e2288ae5a01bd8961bed17f56fb3067265aec
MD5 0c7dbc806eade1f1815e2332d4433eea
BLAKE2b-256 225e17c5e907d502907aa6990091cc5c5a800955b46327eb05619df81da151e1

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b213dd01b4e9c837d64b57516c9722fc1d5b963f76cefce1e7b5704193adfdbf
MD5 95c610ee55b94fb770e3f44c1ae49e96
BLAKE2b-256 1cbb9587dd216de9ef5f7d25fb6dc86f596aebdc24f1c6b313c18b77cd3a5c44

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a17b12e4a19c17dbce564891303cda57bc1e9710b3f05d6a4fb44ceb536490c4
MD5 106772b2b514823f1f9b612eb0fd611e
BLAKE2b-256 1406e53a79db859f8a22b29bd26f991042b5bf8e6f70bc63d2e7bd23238bdc04

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1dc83d9682a868d9863be6cd4b76cc68ffd7219bfafe88faaa20596e0bf262c4
MD5 28e3b7a7f3fed4146214ff8251c02e70
BLAKE2b-256 d674c7bf553f3c7b2830818346e9ecd0a618ba00b45af17249240e7dc93471eb

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bb17c0ab5910cbb77e530811903326088464dd98d2fa273fab8c2ec481e355f3
MD5 873dcb2d1c55dc88c2feaf9a50f359bf
BLAKE2b-256 1eb19d47247b126739c7a511bf35aa0727835a5d17df6204dbe258514563c9c1

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4cbacc916ed1e1129ac103753aefc99c01186842c0b96b1aca17fa5cc0263ec8
MD5 0a52d622b7c8e3e6cd247f9f7b3b1bfb
BLAKE2b-256 70aaa6594d913dcb626cf49e9c904967e8d42d9f88573342b2ff0e0cba573534

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 982ab4ad9628d2f5d0f2bd1846af22b355a27a91fc58545eb216257ced9aa3bc
MD5 495dbdacf17e479b7e97b6167f4fa3c0
BLAKE2b-256 ed9b7d1c1df9497e6751b0d03b1e28bedbe6e5af4f8c0bfdadda8350056a3b7b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 57ab935c700a34dc038d53860bbadcbbfa704b0e2895b9aa9b9d44b3cbe06f63
MD5 dfceee7ba9a7f59ab0c2d650221de2a9
BLAKE2b-256 614bafe5f7580f1bd6e53422759c09dcdc158ca7acda38060ebadce05861b253

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.19-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0ac29df41ab8ef41ee5ef4314d4f97afd7013898929ea6b61f3c95c1b6373922
MD5 bdf38b68e2f475ed74d8135a374ff6df
BLAKE2b-256 fe8c05f79f32d08019488f91e17287981de546ebdb1dd12681009fbbc61d5cb8

See more details on using hashes here.

Provenance

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