Skip to main content

A Goal-Task-Network planning package written in Python

Project description

GTPyhop version 1.9.5

Python Version License PyPI

Doctests

GTPyhop is an HTN planning system based on Pyhop, but generalized to plan for both goals and tasks.

Dana Nau is the original author of GTPyhop.


Table of Contents

  1. Installation
  2. Testing Your Installation
  3. Quick Start Tutorial
  4. Thread-Safe Sessions
  5. Examples
  6. Documentation
  7. New Features
  8. Project Structure

The pip Branch

This pip branch is forked from Dana Nau's GTPyhop main branch and refactored for PyPI distribution, thread-safe sessions, new domain and problems file structure to facilitate LibCST parsing, new example structure to facilitate benchmarking, and documentation.

Installation

From PyPI (Recommended)

GTPyhop 1.9.5 is the latest version with cybersecurity attack planning, iterative DFS backtracking, poetry generation examples, control arena protocol examples, memory tracking, enhanced MCP orchestration examples, Opentrons Flex domains, and comprehensive style guides.

pip install gtpyhop>=1.9.5

For basic single-threaded planning, any version works:

pip install gtpyhop

uv can of course be used if you prefer:

uv pip install gtpyhop

From GitHub

Alternatively, you can directly install from GitHub:

git clone -b pip https://github.com/PCfVW/GTPyhop.git
cd GTPyhop
pip install .

Testing Your Installation

We suggest you give gtpyhop a try straight away; open a terminal and start an interactive python session:

python

.. and import gtpyhop to run the regression tests:

# Import the main GTPyhop planning system
import gtpyhop

The following should be printed in your terminal:

Imported GTPyhop version 1.9.5
Messages from find_plan will be prefixed with 'FP>'.
Messages from run_lazy_lookahead will be prefixed with 'RLL>'.
Using session-based architecture with structured logging.

Now import the regression tests module:

from gtpyhop.examples import regression_tests

Be prepared to see a lot of information on the screen about the examples and how to solve them, with different levels of verbosity; with this in mind, run the regression tests:

# Run legacy regression tests (backward compatible)
regression_tests.main()

# Or run session-based regression tests (recommended for 1.3.0+)
regression_tests.main_session()

The last line printed in your terminal should be:

Finished without error.

For GTPyhop 1.3.0+: You can also run regression tests from the command line:

# Legacy mode
python -m gtpyhop.examples.regression_tests

# Session mode (thread-safe)
python -m gtpyhop.examples.regression_tests --session

Happy Planning!

Let's HTN Start!

You have successfully installed and tested gtpyhop; it's time to declare your own planning problems in gtpyhop.

Very First HTN Example

The key pattern is: create a Domain -> define actions/methods -> declare them -> define initial state -> use gtpyhop.find_plan() to solve problems.

1. Create a Domain

import gtpyhop

# Create a Domain
gtpyhop.Domain('my_domain')

2. Define Actions

Actions are atomic operations that directly modify a state. They are Python functions where the first argument is the current state, and the others are the action's arguments.

def my_action(state, arg1, arg2):
    # Check preconditions
    if state.pos[arg1] == arg2:
        # Modify state
        state.pos[arg1] = 'new_location'
        state.status[arg2] = 'updated'
        return state  # Success
    return False  # Failure

# Declare actions
gtpyhop.declare_actions(my_action, another_action)

3. Define Task Methods

Task methods decompose compound tasks into subtasks and actions.

def method_for_task(state, arg1, arg2):
    # Check if this method is applicable
    if some_condition:
        # Return list of subtasks/actions
        return [('subtask1', arg1), ('action1', arg2)]
    return False  # Method not applicable

# Declare task methods
gtpyhop.declare_task_methods('task_name', method_for_task, alternative_method)

4. Define Initial State

initial_state = gtpyhop.State('initial_state')
initial_state.pos = {'obj1': 'loc1', 'obj2': 'loc2'}

5. Complete Example

import gtpyhop

# Domain creation
gtpyhop.Domain('my_domain')

# Actions
def move(state, obj, target):
    if obj in state.pos:
        state.pos[obj] = target
        return state
    return False

gtpyhop.declare_actions(move)

# Task methods
def transport(state, obj, destination):
    current = state.pos[obj]
    if current != destination:
        return [('move', obj, destination)]
    return []

gtpyhop.declare_task_methods('transport', transport)

# Define initial state
initial_state = gtpyhop.State('initial_state')
initial_state.pos = {'obj1': 'loc1', 'obj2': 'loc2'}

# Find plan
gtpyhop.set_verbose_level(1)
plan = gtpyhop.find_plan(initial_state, [('transport', 'obj1', 'loc2')])
print(plan)

Put this code in a file, say my_very_first_htn_example.py, and run it:

python my_very_first_htn_example.py

Increase the verbosity level to 2 or 3 to see more information about the planning process.

Session-Based Version (Recommended for 1.3.0+)

For better isolation and thread safety:

import gtpyhop

# Domain creation
my_domain = gtpyhop.Domain('my_domain')
state = gtpyhop.State('initial_state')
state.pos = {'obj1': 'loc1', 'obj2': 'loc2'}

# Define actions and methods (same as above)
def move(state, obj, target):
    if obj in state.pos:
        state.pos[obj] = target
        return state
    return False

gtpyhop.declare_actions(move)

def transport(state, obj, destination):
    current = state.pos[obj]
    if current != destination:
        return [('move', obj, destination)]
    return []

gtpyhop.declare_task_methods('transport', transport)

# Use session-based planning
with gtpyhop.PlannerSession(domain=my_domain, verbose=1) as session:
    with session.isolated_execution():
        result = session.find_plan(state, [('transport', 'obj1', 'loc2')])
        if result.success:
            print("Plan found:", result.plan)
            print("Planning stats:", result.stats)

Additional Resources

Please read Dana's additional information for detailed explanations of:

Thread-Safe Sessions (1.3.0+)

GTPyhop 1.3.0 introduces session-based, thread-safe planning that enables reliable concurrent execution and isolated planning contexts. This is a major architectural enhancement while maintaining 100% backward compatibility.

Key Benefits

  • Thread-safe concurrent planning: Multiple planners can run simultaneously
  • Isolated execution contexts: Each session has its own configuration, logs, and statistics
  • Structured logging system: Programmatic access to planning traces
  • Timeout management: Built-in timeout enforcement and resource management
  • Session persistence: Save and restore planning sessions

Quick Start with Sessions

import gtpyhop

my_domain = gtpyhop.Domain('my_domain')
# ... define actions and methods ...

with gtpyhop.PlannerSession(domain=my_domain, verbose=1) as session:
    with session.isolated_execution():
        result = session.find_plan(state, [('transport', 'obj1', 'loc2')])
        if result.success:
            print(result.plan)

For detailed documentation, see Thread-Safe Sessions Guide

Migration from Pre-1.3.0

Existing code continues to work unchanged - 100% backward compatible.

# Before (still works)
plan = gtpyhop.find_plan(state, tasks)

# After (recommended)
with gtpyhop.PlannerSession(domain=my_domain) as session:
    with session.isolated_execution():
        result = session.find_plan(state, tasks)
        plan = result.plan if result.success else None

Version Selection Guide

Use Case Recommended Version
New projects 1.9.0+
Backtracking with iterative planner 1.9.0+
Memory tracking & benchmarking 1.8.0+
MCP integration 1.5.0+
Concurrent/parallel planning 1.3.0+
Educational/simple scripts Any version

Examples

GTPyhop includes comprehensive examples demonstrating various planning techniques. All examples support both legacy and session modes.

Quick Example Run

# Legacy mode (backward compatible)
python -m gtpyhop.examples.simple_htn

# Session mode (thread-safe, recommended)
python -m gtpyhop.examples.simple_htn --session

For comprehensive example documentation, see All Examples Guide

Documentation

GTPyhop 1.9.5 includes comprehensive documentation organized in the docs/ folder:

Core Documentation

Style Guides

Example-Specific Documentation

IPC 2020 Total Order Domains (1.4.0+)

MCP Orchestration Examples (1.5.0+)

Memory Tracking Examples (1.8.0+)

Poetry Examples (1.9.0+)

Control Arena Protocol Examples (1.9.4+)

Cybersecurity Attack Planning Example (1.9.5+)

  • Cybersecurity Attack Planning - BAMS-based insider threat planning: physical, network, DMS, and malware attacks with 5 backtracking points (9 scenarios)

External Resources

New Features

Planning Strategies

GTPyhop supports three planning strategies, selectable via set_recursive_planning or the PlannerSession(strategy=...) parameter:

Strategy Backtracking? Stack Activation
Iterative greedy (default) No Explicit stack set_recursive_planning(False)
Recursive DFS Yes Python call stack set_recursive_planning(True)
Iterative DFS BT (1.9.0+) Yes Explicit stack set_recursive_planning("iterative_dfs_backtracking")

The iterative greedy strategy (default since 1.2.0) commits to the first applicable method and never reconsiders that choice. The recursive DFS strategy backtracks across methods via the Python call stack. The iterative DFS backtracking strategy (new in 1.9.0) combines the iterative planner's explicit stack with the recursive planner's ability to backtrack — it pushes all applicable method continuations onto the stack, so if one path fails, alternatives remain.

# Global API
gtpyhop.set_recursive_planning(False)                        # iterative greedy (default)
gtpyhop.set_recursive_planning(True)                         # recursive DFS
gtpyhop.set_recursive_planning("iterative_dfs_backtracking") # iterative DFS with backtracking

# Session API (1.9.0+)
with gtpyhop.PlannerSession(domain=d, strategy="iterative_dfs_backtracking") as s:
    result = s.find_plan(state, tasks)

All existing True/False callers continue to work identically. See the changelog for full details.

New Functions by Version

1.9.0 (Iterative DFS Backtracking)

  • seek_plan_iterative_backtracking - Iterative DFS with full backtracking via explicit stack
  • _refine_task_and_continue_iterative_bt - Multi-continuation task refinement
  • _refine_unigoal_and_continue_iterative_bt - Multi-continuation unigoal refinement
  • _refine_multigoal_and_continue_iterative_bt - Multi-continuation multigoal refinement
  • PlannerSession(strategy=...) - Strategy selection parameter ("recursive_dfs", "iterative_greedy", "iterative_dfs_backtracking")

1.4.0 (Robustness & Benchmarking)

  • validate_plan_from_goal - Plan validation from initial to goal state
  • PlannerBenchmark - Comprehensive benchmarking with resource tracking

1.3.0 (Thread-Safe Sessions)

  • PlannerSession - Isolated, thread-safe planning context
  • create_session, get_session, destroy_session, list_sessions
  • SessionSerializer, restore_session - Session persistence

1.2.1 (Iterative Planning)

  • set_recursive_planning, get_recursive_planning
  • seek_plan_iterative and related iterative functions

Project Structure

GTPyhop/
├── LICENSE.txt
├── pyproject.toml
├── README.md
├── docs/
│   ├── all_examples.md
│   ├── changelog.md
│   ├── gtpyhop_domain_style_guide.md
│   ├── gtpyhop_example_style_guide.md
│   ├── gtpyhop_problems_style_guide.md
│   ├── logging.md
│   ├── running_examples.md
│   └── thread_safe_sessions.md
└── src/gtpyhop/
    ├── __init__.py
    ├── main.py
    ├── logging_system.py
    ├── memory_tracking/
    │   ├── __init__.py
    │   ├── monitor.py
    │   └── tracker.py
    ├── examples/
    │   ├── __init__.py
    │   ├── regression_tests.py
    │   ├── simple_htn.py, simple_hgn.py, ...
    │   ├── blocks_htn/, blocks_hgn/, blocks_gtn/, blocks_goal_splitting/
    │   ├── ipc-2020-total-order/
    │   │   └── Blocksworld-GTOHP/, Childsnack/
    │   ├── mcp-orchestration/
    │   │   └── bio_opentrons/, cross_server/, drug_target_discovery/, omega_hdq_dna_bacteria_flex_96_channel/, tnf_cancer_modelling/
    │   ├── memory_tracking/
    │   │   └── scalable_data_processing/, scalable_recursive_decomposition/
    │   ├── poetry/
    │   │   └── structured_poetry/, backtracking_poetry/, candidate_planning_poetry/, bidirectional_planning_poetry/, replanning_poetry/, formal_mechanism_poetry/, feature_space_poetry/
    │   └── cybersecurity_attack_planning/
    └── test_harness/

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gtpyhop-1.9.5.tar.gz (402.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gtpyhop-1.9.5-py3-none-any.whl (456.4 kB view details)

Uploaded Python 3

File details

Details for the file gtpyhop-1.9.5.tar.gz.

File metadata

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

File hashes

Hashes for gtpyhop-1.9.5.tar.gz
Algorithm Hash digest
SHA256 42c9468ea01b58a018099e2128a82b50d9000c9233d69915410574fb4e530daf
MD5 69d627024502ad8818303eca80cadec4
BLAKE2b-256 67333971afb552b0a629bedd858a9a9051651eb0a1c690ab4f19426885ac94ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for gtpyhop-1.9.5.tar.gz:

Publisher: publish-new-GTPyhop-to-pypi.yml on PCfVW/GTPyhop

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gtpyhop-1.9.5-py3-none-any.whl.

File metadata

  • Download URL: gtpyhop-1.9.5-py3-none-any.whl
  • Upload date:
  • Size: 456.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gtpyhop-1.9.5-py3-none-any.whl
Algorithm Hash digest
SHA256 bd9937796ef783284e197c184a9d63eb7dcdbf86809c44d01db7e935747c0292
MD5 40253ebfece5fcf0dc707f32354da1da
BLAKE2b-256 1d8f3e71e45e5d1eb3c55ba9a6fbb16e9a749d1d46351eabbc4fa0c8d69a1e0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for gtpyhop-1.9.5-py3-none-any.whl:

Publisher: publish-new-GTPyhop-to-pypi.yml on PCfVW/GTPyhop

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