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 provided by the pypddl-datasets package (also used by the C++ test suite; materialize them once into data/benchmarks):

pip install pypddl-datasets
python -c "import pypddl_datasets as pb; [pb.export_suite(s, 'data/benchmarks') for s in ('tests-classical', 'tests-numeric')]"
./build/exe/loki \
  data/benchmarks/classical/tests/gripper/domain.pddl \
  data/benchmarks/classical/tests/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.22.tar.gz (713.8 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.22-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.22-cp313-cp313-macosx_11_0_arm64.whl (924.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pypddl-1.0.22-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.22-cp312-cp312-macosx_11_0_arm64.whl (901.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pypddl-1.0.22-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.22-cp311-cp311-macosx_11_0_arm64.whl (924.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pypddl-1.0.22-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.22-cp310-cp310-macosx_11_0_arm64.whl (924.9 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

pypddl-1.0.22-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.22-cp39-cp39-macosx_11_0_arm64.whl (925.0 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: pypddl-1.0.22.tar.gz
  • Upload date:
  • Size: 713.8 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.22.tar.gz
Algorithm Hash digest
SHA256 1d9ae9f11b6d2e122b517a27ab024a8910ae608f2dc9f4f006af78464b89a43b
MD5 6623c9636db0277d55dcf3b636fb59ab
BLAKE2b-256 4bd7106f553f23a89a6edbdfc7e51545dfab1f29094644bf49adbe8a3dff0abc

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e2cbef152fa222e98991e517beffc77e9e27998cb93cfa043958478d06362d44
MD5 ba283f38ca2671840238ffceb8e20ddc
BLAKE2b-256 21a394cfacf7614e4700621b71f4e4194daf17d742f68470136aa812f2f4933f

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c2c510fccc8c76b37fed6d398ef7fcee77b46d70e2caf272d18cdcd138f9ff5c
MD5 2bced683f0f839972ec113a5c438ef4c
BLAKE2b-256 7c8682895a25f0a4e6cacabef68b16a8154f2e239095f11008f95fd30e8a5883

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 55cb4e17e9bfc3dec3e11b1cf17d599d79347f59d015add2d1de069f4e18657e
MD5 fc730dc9f1680de90e36065739e322a1
BLAKE2b-256 3122d1b86ca441a205687645451458af83cd5b5fb467714211d2965183c6022d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3ec1d37ad64e5e76712a1c668444e9a205cc715b4680383d5944f537eefe6856
MD5 801fdb78134a94be265e295e52e60a21
BLAKE2b-256 d571ed626d5e28cabd62127e2c536c9455eccfe05846f633ae8c1429e25b9499

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c0913ba5b20ffa8cb4c91afe09ca45382a1c76dd4cedc46d2b1bfb1b0a3806ea
MD5 31f9be6463b4ee0678c8558024b47a45
BLAKE2b-256 847dc920c8160b22b00c12b6461cf6596afcd564f85d68556491581802cd70f9

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9c5dac0679fdc8820017a0baf8b555442c263eb78a6769fabe924cba321cefc7
MD5 505bec3b02d2cd64c9c58beb15ab662b
BLAKE2b-256 e452d15334dddb11c3380e0b7feb5350c73345b9ed4a29658e21eff782fc8e99

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a672572fa61ca3fc28e2bbea92c00f9296ebaa1fa1a1ed4f027f34a75afc8651
MD5 e0b75df0654227e23901dd8c65dafc4b
BLAKE2b-256 661bf8209c2cf000388d9f825eff9d5259fdfaa4c06fa8822f897958968cf9ed

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6d100ae8177f6336347b51e77c439266ad24be89dae3e5ba7fe511bd6699f36d
MD5 aecd0effa258c07b9d718d778de2cf4f
BLAKE2b-256 f80e619494729eb174d8890f4c78dc1638fe82775a56121f511669c97c1c8e38

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 79047f77298a7e0823cc421b57e68500af22404e9a44c3716b1905785aef001f
MD5 9260124e61cc7e4caa168c23c5a4fb36
BLAKE2b-256 9a32d21270227c704e0a8eeef70701360549c629f3f9003dcada0a77b0c00247

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for pypddl-1.0.22-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1c56bc32b53ad8427aa253b4c6b3e696a9d92274a7871b36095c961cd7a921f8
MD5 fd9f4e55f72f4ae0c5a0d5e1aadea56a
BLAKE2b-256 36161163a06ada468288d8cd9c3bb8c10d7824c613ec6581573e0e36a92b5bc3

See more details on using hashes here.

Provenance

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