Skip to main content

A Goal-Task-Network planning package written in Python

Project description

GTPyhop version 1.2.1

Python Version License

GTPyhop is a task-planning system based on Pyhop, but generalized to plan for both goals and tasks.

Dana Nau is the original author of GTPyhop.

The pip Branch

This pip branch is forked from Dana Nau's GTPyhop main branch and refactored for PyPI distribution.

The file tree structure of this pip branch, produced with the help of _GithubTree, is the following:

๐Ÿ“„ LICENSE.txt
๐Ÿ“„ pyproject.toml
๐Ÿ“„ README.md
๐Ÿ“ src/
    โ””โ”€โ”€ ๐Ÿ“ gtpyhop/
        โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
        โ”œโ”€โ”€ ๐Ÿ“ examples/
            โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
            โ”œโ”€โ”€ ๐Ÿ“„ backtracking_htn.py
            โ”œโ”€โ”€ ๐Ÿ“ blocks_goal_splitting/
                โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
                โ”œโ”€โ”€ ๐Ÿ“„ actions.py
                โ”œโ”€โ”€ ๐Ÿ“„ examples.py
                โ”œโ”€โ”€ ๐Ÿ“„ methods.py
                โ””โ”€โ”€ ๐Ÿ“„ README.txt
            โ”œโ”€โ”€ ๐Ÿ“ blocks_gtn/
                โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
                โ”œโ”€โ”€ ๐Ÿ“„ actions.py
                โ”œโ”€โ”€ ๐Ÿ“„ examples.py
                โ”œโ”€โ”€ ๐Ÿ“„ methods.py
                โ””โ”€โ”€ ๐Ÿ“„ README.txt
            โ”œโ”€โ”€ ๐Ÿ“ blocks_hgn/
                โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
                โ”œโ”€โ”€ ๐Ÿ“„ actions.py
                โ”œโ”€โ”€ ๐Ÿ“„ examples.py
                โ””โ”€โ”€ ๐Ÿ“„ methods.py
            โ”œโ”€โ”€ ๐Ÿ“ blocks_htn/
                โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
                โ”œโ”€โ”€ ๐Ÿ“„ actions.py
                โ”œโ”€โ”€ ๐Ÿ“„ examples.py
                โ””โ”€โ”€ ๐Ÿ“„ methods.py
            โ”œโ”€โ”€ ๐Ÿ“„ logistics_hgn.py
            โ”œโ”€โ”€ ๐Ÿ“„ pyhop_simple_travel_example.py
            โ”œโ”€โ”€ ๐Ÿ“„ regression_tests.py
            โ”œโ”€โ”€ ๐Ÿ“„ simple_hgn.py
            โ”œโ”€โ”€ ๐Ÿ“„ simple_htn_acting_error.py
            โ””โ”€โ”€ ๐Ÿ“„ simple_htn.py
        โ”œโ”€โ”€ ๐Ÿ“„ main.py
        โ””โ”€โ”€ ๐Ÿ“ test_harness/
            โ”œโ”€โ”€ ๐Ÿ“„ __init__.py
            โ””โ”€โ”€ ๐Ÿ“„ test_harness.py

Installation from PyPI is available since version 1.2.0

Open a terminal and type the following:

pip install gtpyhop

uv can of course be used if you prefer:

uv pip install gtpyhop

Installation 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.2.1
Messages from find_plan will be prefixed with 'FP>'.
Messages from run_lazy_lookahead will be prefixed with 'RLL>'.
Using iterative seek_plan.

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:

regression_tests.main()

The last lines printed in your terminal should be:

-----------------------------------------------------------------------
Created the domain 'gtpyhop.examples.simple_htn_acting_error'. To run the examples, type this:
gtpyhop.examples.simple_htn_acting_error.main()

Finished without error.

Happy Planning!

Usage

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 domain โ†’ define actions/methods โ†’ declare them โ†’ use gtpyhop.find_plan() to solve problems.

In the first three steps, we give simple illustrations on domain creation, action and task method definition, and how to declare them; in step 4 below, you'll find the code for a complete example.

1. First, create a Domain to hold your definitions

import gtpyhop

# Create domain
gtpyhop.Domain('my_domain')

2. Define Actions

Actions are atomic operations that directly modify a state: actions are Python functions where the first argument is the current state, and the others are the action's arguments telling what changes the action shall bring to the state.

For example, the function my_action(state, arg1, arg2) below implements the action ('my_action', arg1, arg2). In the following code, arg1 is used as an object key to check and modify its position, while arg2 is used both as a condition to check against and as a key to update the status:

def my_action(state, arg1, arg2):
    # Check preconditions using arg1 and arg2
    if state.pos[arg1] == arg2:
        # Modify state using arg1 and arg2
        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

During planning, Task methods decompose compound tasks into subtasks (which shall be further decomposed) and actions (whose Python functions will be executed).

Task methods are also Python functions where the first argument is the current state, and the others can be passed to the subtasks and actions.

In the following code, arg1 is used as an argument to the subtasks (perhaps specifying what object to work with), while arg2 is used as an argument to the action (perhaps specifying a target location or condition):

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. Here is a complete example:

import gtpyhop

# Create domain
gtpyhop.Domain('my_domain')

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

# 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)

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

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

python my_very_first_htn_example.py

Does it run correctly? Increase the verbosity level to 2 or 3 and run it again to see more information about the planning process.

Additional Information

Please read Dana's additional information of how to implement:

New Features

Iterative Planning Strategy

This pip branch introduces a new iterative planning strategy that enhances the planner's capabilities for large planning scenarios; it is the default strategy.

  • How it works: Uses an explicit stack data structure
  • Memory usage: More memory-efficient, no call stack buildup
  • Limitations: No recursion limit constraints
  • Backtracking: Explicit stack management for exploring alternatives
  • Use cases:
    • Large planning problems that might exceed recursion limits
    • Memory-constrained environments
    • Production systems requiring reliability

Once gtpyhop is imported, Dana Nau's original recursive strategy can be set by calling:

set_recursive_planning(True)  # Planning strategy now is recursive

Recursive Planning Strategy:

  • How it works: Uses Python's call stack with recursive function calls
  • Memory usage: Each recursive call adds a frame to the call stack
  • Limitations: Limited by Python's recursion limit (default 1000)
  • Backtracking: Natural backtracking through function returns
  • Use cases:
    • Small to medium planning problems
    • When you need to see traditional backtracking behavior
    • Educational purposes or debugging

Of course you can get back to the iterative planning strategy by calling:

set_recursive_planning(False)  # Planning strategy now is iterative

New Functions

The following functions have been added to Dana's original code:

  • print_domain_names
  • find_domain_by_name, is_domain_created
  • set_current_domain, get_current_domain
  • set_recursive_planning, get_recursive_planning, reset_planning_strategy
  • set_verbose_level, get_verbose_level
  • seek_plan_iterative,
    • refine_multigoal_and_continue_iterative
    • refine_unigoal_and_continue_iterative
    • refine_task_and_continue_iterative
    • apply_action_and_continue_iterative

Renaming

_recursive has been added at the end of the identifiers of the original functions involved in seeking for a plan:

  • seek_plan โ†’ seek_plan_recursive
  • _apply_action_and_continue โ†’ apply_action_and_continue_recursive
  • _refine_multigoal_and_continue โ†’ refine_multigoal_and_continue_recursive
  • _refine_unigoal_and_continue โ†’ refine_unigoal_and_continue_recursive
  • _refine_task_and_continue โ†’ refine_task_and_continue_recursive

Version History

1.2.1 -- Cosmetics Uploaded to PyPI: https://pypi.org/project/gtpyhop/1.2.1/

  • Fix: set_recursive_strategy() replaced by set_recursive_planning() in README.md
  • Added Python and License badges to this README.md
  • Added summary of trivial differences between recursive and iterative planning strategies
  • Added very first HTN example
  • Added "open a terminal and" in the first paragraph of Testing your installation
  • Removed (soon available) after Installation from PyPI
  • Added how to get back to iterative planning strategy
  • Removed unnecessary imports in main.py
  • Fix: various typos and inconsistencies in README.md

1.2.0 -- Uploaded to PyPI: https://pypi.org/project/gtpyhop/

1.2.0rc1 -- Uploaded to Test PyPI: https://test.pypi.org/project/gtpyhop/1.2.0rc1/

1.2.0b2 -- This tested refactored version will soon be ready to be indexed on TestPyPI as 1.2.0rc1

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.2.1.tar.gz (85.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.2.1-py3-none-any.whl (65.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: gtpyhop-1.2.1.tar.gz
  • Upload date:
  • Size: 85.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for gtpyhop-1.2.1.tar.gz
Algorithm Hash digest
SHA256 ccb47fce15e6fc5b72ed5882575e18cb1a763e17879ef5c8a7fa2655af1d77dd
MD5 fa20cc5e90c4b9d92442ac343ae1b74d
BLAKE2b-256 bfb4a50c4f35a9dcdb783f2e1652a14bb1ab6ee664b83ab5d6c5faad4e5bb73e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: gtpyhop-1.2.1-py3-none-any.whl
  • Upload date:
  • Size: 65.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.2

File hashes

Hashes for gtpyhop-1.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c07de815506d9d23dbffafd01ee55a8b6f3989176caf0a1bb55e4cd12b0893b4
MD5 f5fe552c37e91a3bd30299bd2ef7cc8e
BLAKE2b-256 29e89b7a85d3d0bfc30622d593df51989cbf8f15bbbace29380fc23a481cba21

See more details on using hashes here.

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