Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[flake8]
max-line-length = 100
extend-ignore = E203, W503
exclude = .venv, pddl-examples, build, dist, .git, __pycache__
40 changes: 12 additions & 28 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,24 @@ jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: [3.6, 3.7, 3.8]
exclude:
- os: macos-latest
python-version: 3.8
os: [ubuntu-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7
uses: actions/setup-python@v3
- uses: actions/checkout@v4
with:
python-version: 3.7
- uses: actions/checkout@v2.4.0
- uses: julia-actions/setup-julia@v1
submodules: recursive
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
version: '1.4.1'
- name: Install Julia dependencies
run: |
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))'
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))'
- name: Install Python dependencies
python-version: ${{ matrix.python-version }}
- name: Install package (dev extras)
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -e ".[dev]"
- name: Lint with flake8
run: |
python -m pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Checkout reposistory
uses: actions/checkout@master
- name: Checkout submodules
uses: snickerbockers/submodules-init@v4

flake8 jupyddl tests --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 jupyddl tests --count --statistics
13 changes: 6 additions & 7 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,22 @@ jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- uses: actions/checkout@v2
- name: Set up Python 3.7
uses: actions/setup-python@v3
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.7
python-version: '3.12'
- name: Install formatter dependencies
run: |
python -m pip install --upgrade pip
python -m pip install black
- name: Format with black
run: |
black .
black jupyddl tests
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v4.14.0
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: Apply formatting changes
branch: main
87 changes: 15 additions & 72 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,91 +3,34 @@ name: tests
on: [push]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
python-version: [3.6, 3.7, 3.8]
exclude:
- os: macos-latest
python-version: 3.8

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7
uses: actions/setup-python@v3
with:
python-version: 3.7
- uses: actions/checkout@v2.4.0
- uses: julia-actions/setup-julia@v1
with:
version: '1.4.1'
- name: Install Julia dependencies
run: |
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))'
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))'
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install julia
python -m pip install pycall
- name: Lint with flake8
run: |
python -m pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Checkout reposistory
uses: actions/checkout@master
- name: Checkout submodules
uses: snickerbockers/submodules-init@v4

test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: [3.6, 3.7, 3.8]
exclude:
- os: macos-latest
python-version: 3.8
os: [ubuntu-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7
uses: actions/setup-python@v3
- uses: actions/checkout@v4
with:
python-version: 3.7
- uses: actions/checkout@v2.4.0
- uses: julia-actions/setup-julia@v1
submodules: recursive
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
version: '1.4.1'
- name: Install Julia dependencies
run: |
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/JuliaPy/PyCall.jl"))'
julia --color=yes -e 'using Pkg; Pkg.add(Pkg.PackageSpec(path="https://github.com/APLA-Toolbox/PDDL.jl"))'
- name: Install Python dependencies
python-version: ${{ matrix.python-version }}
- name: Install package (dev extras)
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -e ".[dev]"
- name: Lint with flake8
run: |
python -m pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Checkout reposistory
uses: actions/checkout@master
- name: Checkout submodules
uses: snickerbockers/submodules-init@v4
flake8 jupyddl tests --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 jupyddl tests --count --statistics
- name: Test with pytest
run: |
pip install pytest
pip install pytest-cov
pytest --cov=./
pytest --cov=jupyddl --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v4
with:
name: codecov-umbrella
38 changes: 38 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# AGENTS.md

## Cursor Cloud specific instructions

`jupyddl` is a **pure-Python** PDDL planning framework (parser, grounder,
planners, heuristics, benchmarking). The Julia/`PDDL.jl`/PyCall integration has
been removed — there is no Julia, no native build step, and the core has zero
runtime dependencies.

### Environment
- Python ≥ 3.9; a `.venv` (created with `uv`, Python 3.12) with an editable
install: `uv pip install -e ".[dev]"` (add `viz` for matplotlib-based
benchmark plots). `.venv` and `pddl-examples/` contents are git-ignored.
- The `pddl-examples` git submodule supplies the domains/problems the tests use;
it must be initialised (`git submodule update --init`).

### Running / testing / linting (use the venv interpreter)
- Tests: `.venv/bin/python -m pytest` (add `--cov=jupyddl`).
- Lint (as CI): `flake8 jupyddl tests` (config in `.flake8`, max-line 100).
- CLI: `.venv/bin/python -m jupyddl.cli solve <domain> <problem> -s astar -H lmcut`
or `... benchmark pddl-examples --csv out.csv`. Installed as `jupyddl` too.

### Non-obvious notes
- **Example data quirks (external submodule, do not "fix" in this repo):**
`grid` uses numeric fluents and is intentionally unsupported (raises
`UnsupportedFeatureError`); `vehicle` has typos in its problem file
(`struck`/`truck`, `acessible`) so its goal is unreachable and it is correctly
reported unsolvable. Tests treat both as expected.
- **Conditional effects (`flip`)**: the delete-relaxation heuristics (`hadd`,
`hff`, `lmcut`, `h^m`) are *not guaranteed admissible* on domains with
conditional effects because each conditional effect is relaxed into its own
operator. For guaranteed-optimal plans there use `bfs`, `dijkstra`, or
`astar`/`idastar` with the `blind` heuristic. Optimality tests use these.
- **Matplotlib is optional**: only `jupyddl.benchmark.plot_summary` (and
`jupyddl solve/benchmark --plot`) need it; run headless with `MPLBACKEND=Agg`
if no display. The test suite does not require it.
- Extend via the registries: `jupyddl.search.PLANNERS` and
`jupyddl.heuristics.HEURISTICS`.
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Changelog

All notable changes to this project are documented in this file. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0] - 2026-07-01

Complete rewrite: **the Julia dependency is removed** and the project is now a
pure-Python planning framework.

### Added
- Hand-written PDDL tokenizer, AST and recursive-descent parser
(`jupyddl.parser`).
- Grounder (`jupyddl.grounding`) with type hierarchies, static-predicate
pruning, positive-normal-form compilation of negative preconditions/goals,
object harvesting for undeclared constants, and `forall`/`when` conditional
effect expansion.
- Grounded task representation with conditional effects (`jupyddl.task`).
- Planners (`jupyddl.search`): BFS, DFS, Iterative Deepening, Dijkstra
(uniform cost), Greedy Best-First, A*, Weighted A*, IDA*, and Enforced Hill
Climbing, plus a shared best-first engine and a planner registry.
- Heuristics (`jupyddl.heuristics`): blind, goal-count, `h_max`, `h_add`, FF,
critical-path `h^m` (`h1`/`h2`), and LM-cut, plus a heuristic registry.
- Benchmarking harness (`jupyddl.benchmark`) with CSV export and comparison
plots, and a CLI (`jupyddl solve` / `jupyddl benchmark`).
- High-level API: `solve`, `build_task`, `solve_task`, `validate_plan`.
- Comprehensive pytest suite covering parsing, grounding, search optimality,
heuristic admissibility, the API, the benchmark harness and the CLI.

### Changed
- Packaging migrated from `setup.py`/`requirements.txt` to `pyproject.toml`
(hatchling); the core has **zero runtime dependencies** (matplotlib is an
optional `viz` extra).
- CI reworked to run on modern Python without Julia.

### Removed
- The Julia / `PDDL.jl` / PyCall / pyjulia integration and the old
`AutomatedPlanner` / `DataAnalyst` API.
Loading
Loading