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.
- Installation
- Testing Your Installation
- Quick Start Tutorial
- Thread-Safe Sessions
- Examples
- Documentation
- New Features
- Project Structure
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.
GTPyhop 1.9.0 is the latest version with iterative DFS backtracking, poetry generation examples, memory tracking, enhanced MCP orchestration examples, Opentrons Flex domains, and comprehensive style guides.
pip install gtpyhop>=1.9.0For basic single-threaded planning, any version works:
pip install gtpyhopuv can of course be used if you prefer:
uv pip install gtpyhopAlternatively, you can directly install from GitHub:
git clone -b pip https://github.com/PCfVW/GTPyhop.git
cd GTPyhop
pip install .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 gtpyhopThe following should be printed in your terminal:
Imported GTPyhop version 1.9.0
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_testsBe 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 --sessionHappy Planning!
You have successfully installed and tested gtpyhop; it's time to declare your own planning problems in gtpyhop.
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.pyIncrease the verbosity level to 2 or 3 to see more information about the planning process.
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)Please read Dana's additional information for detailed explanations of:
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.
- 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
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
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| 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 |
GTPyhop includes comprehensive examples demonstrating various planning techniques. All examples support both legacy and session modes.
# Legacy mode (backward compatible)
python -m gtpyhop.examples.simple_htn
# Session mode (thread-safe, recommended)
python -m gtpyhop.examples.simple_htn --sessionFor comprehensive example documentation, see All Examples Guide
GTPyhop 1.9.0 includes comprehensive documentation organized in the docs/ folder:
- All Examples Guide - Pedagogical details about all HTN planning examples
- Running Examples - Detailed instructions for executing examples
- Structured Logging - Comprehensive logging system documentation
- Thread-Safe Sessions - Complete guide to session-based architecture
- Version History - Complete changelog
- Example Style Guide - How to write GTPyhop examples (folder structure, required files)
- Domain Style Guide - Conventions for writing domain files (actions and methods)
- Problems Style Guide - Conventions for writing problem files
- Memory Tracking Overview - Memory tracking capabilities with psutil
- Scalable Data Processing - Memory scaling via data size (10K-1M items)
- Scalable Recursive Decomposition - Memory scaling via recursion depth (2^k tasks)
- Memory Benchmarking Quickstart - How to run memory benchmarks
- Poetry Overview - HTN-planned poetry generation with MCP delegation
- Structured Poetry - Baseline: couplet, limerick, haiku, sonnet (6 scenarios)
- Backtracking Poetry - Strict/relaxed rhyme methods with backtracking (3 scenarios)
- Candidate Planning Poetry - Multi-candidate rhyme selection pipeline (3 scenarios)
- Bidirectional Planning Poetry - Decomposed backward line construction (3 scenarios)
- Replanning Poetry - Post-generation evaluation and steering/revision (3 scenarios)
- Benchmarking Quickstart - Performance benchmarking guide
- Blocksworld-GTOHP - IPC 2020 Blocksworld domain
- Childsnack - IPC 2020 Childsnack domain
- MCP Benchmarking - MCP orchestration benchmarking guide
- Bio-Opentrons PCR Workflow - PCR workflow automation (6 scenarios)
- Cross-Server Orchestration - Multi-server coordination (2 scenarios)
- Drug Target Discovery - OpenTargets platform integration (3 scenarios)
- Omega HDQ DNA Extraction - DNA extraction workflow (3 scenarios)
- TNF Cancer Modelling - Multiscale cancer modeling (1 scenario)
- Dana's Additional Information - Core GTPyhop concepts
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.
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 refinementPlannerSession(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 statePlannerBenchmark- Comprehensive benchmarking with resource tracking
1.3.0 (Thread-Safe Sessions)
PlannerSession- Isolated, thread-safe planning contextcreate_session,get_session,destroy_session,list_sessionsSessionSerializer,restore_session- Session persistence
1.2.1 (Iterative Planning)
set_recursive_planning,get_recursive_planningseek_plan_iterativeand related iterative functions
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/
└── test_harness/