Skip to content
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/update-website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
cd misc/autodoc
python3 -m pip install -r requirements.txt
python3 generate-docs.py
python3 generate-translate-docs.py
cd ../../..

- name: Move website material to website repo
Expand Down
1 change: 1 addition & 0 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ This file controls the navigation below "documentation" on the website.

- [](README.md)
- [Planner usage](planner-usage.md)
- [Translator options](translator-options.md)
- [Search plugins](search/)
- [Syntax for search plugins](search-plugin-syntax.md)
- [Exit codes](exit-codes.md)
Expand Down
24 changes: 12 additions & 12 deletions docs/planner-usage.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Usage
# Planner Usage

Fast Downward is a domain-independent classical planning system that consists of two main components:

Expand All @@ -20,26 +20,26 @@ participated in IPC 2011, please also check the page on
## Translation component
To translate a PDDL input task into a SAS+ task without performing a search run the following:

./fast-downward.py --translate [<domain.pddl>] <task.pddl>
./fast-downward.py --translate [<domain.pddl>] <problem.pddl>

Note:

- Giving the domain file as input is optional.
In case no domain file is specified, the component will search for a file called `domain.pddl` located in the same directory as the task file.
- Translator component options can be specified after the input files following the `--translator-options` flag.
In case no domain file is specified for the task, the component will search for a file called `domain.pddl` located in the same directory as the problem file.
- Translator component options can be specified after the input files following the `--translator-options` flag. See [translator options](translator-options.md) for details.

## Search component
To run a search on a PDDL input task run the following:

./fast-downward.py [<domain.pddl>] <task.pddl> \
./fast-downward.py [<domain.pddl>] <problem.pddl> \
--search "<some-search-algorithm>(<algorithm-parameters>)"

Note:

- The PDDL task is translated into a SAS+ task internally without the need to explicitly call the `translate` component.
Instead of a PDDL task a SAS+ translator output file could be given as input. In this case the translation step is omitted.
- Giving the domain file as input is optional.
In case no domain file is specified, the component will search for a file called `domain.pddl` located in the same directory as the task file.
In case no domain file is specified for the task, the component will search for a file called `domain.pddl` located in the same directory as the problem file.
- `<some-search-algorithm>` can be any of the [search algorithms](search/SearchAlgorithm.md) with corresponding `<algorithm-parameters>` as input.
- Search component options can be specified anywhere after the input files.
Search component options following translator component options need to first be escaped with the `--search-options` flag.
Expand All @@ -49,11 +49,11 @@ Note:
The following example is a recommended search algorithm configuration:
[A* algorithm](search/SearchAlgorithm/#a_search_eager) with the [LM-cut heuristic](search/Evaluator/#landmark-cut_heuristic), which can be run as follows:

./fast-downward.py [<domain.pddl>] <task.pddl> --search "astar(lmcut())"
./fast-downward.py [<domain.pddl>] <problem.pddl> --search "astar(lmcut())"

As this is a common search configuration an alias (`seq-opt-lmcut`) exists that results in the same execution and can be used as follows:

./fast-downward.py --alias seq-opt-lmcut [<domain.pddl>] <task.pddl>
./fast-downward.py --alias seq-opt-lmcut [<domain.pddl>] <problem.pddl>

### Aliases

Expand All @@ -65,7 +65,7 @@ To find out which actual search options the aliases corresponds to, check the so

For example to run the "LAMA 2011 configuration" of the planner, call:

./fast-downward.py --alias seq-sat-lama-2011 [<domain.pddl>] <task.pddl>
./fast-downward.py --alias seq-sat-lama-2011 [<domain.pddl>] <problem.pddl>

Note:

Expand All @@ -79,19 +79,19 @@ The search options are built with flexibility in mind, not ease of
use. It is very easy to use option settings that look plausible, yet
introduce significant inefficiencies. For example, an invocation like

./fast-downward.py [<domain.pddl>] <task.pddl> \
./fast-downward.py [<domain.pddl>] <problem.pddl> \
--search "lazy_greedy([ff()], preferred=[ff()])"

looks plausible, yet is hugely inefficient since it will compute the FF
heuristic twice per state. To circumvent this a [`let`-expression](search-plugin-syntax.md#variables_as_parameters) could be used:

./fast-downward.py [<domain.pddl>] <task.pddl> \
./fast-downward.py [<domain.pddl>] <problem.pddl> \
--search "let(hff, ff(), lazy_greedy([hff], preferred=[hff]))"

## Validating plans
To validate a plan found by some search algorithm using [VAL](https://github.com/KCL-Planning/VAL) run the following:

./fast-downward.py --validate [<domain.pddl>] <task.pddl> \
./fast-downward.py --validate [<domain.pddl>] <problem.pddl> \
--search "<some-search-algorithm>(<algorithm-parameters>)"

Note:
Expand Down
14 changes: 7 additions & 7 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ You can run the planner as follows:

Assume you want to solve a planning task (e.g. from the [Fast Downward benchmarks](https://github.com/aibasel/downward-benchmarks)) using A* search with the LM-cut heuristic. To do so you can run the following:

./fast-downward.sif <domain.pddl> <task.pddl> --search "astar(lmcut())"
./fast-downward.sif <domain.pddl> <problem.pddl> --search "astar(lmcut())"

See more planner options at [planner usage](planner-usage.md).

Expand All @@ -58,16 +58,16 @@ Note:
Assume you want to solve a planning task (e.g. from the [Fast Downward benchmarks](https://github.com/aibasel/downward-benchmarks)) using A* search with the LM-cut heuristic. To do so you can run the following:

sudo docker run --rm -v <path-to-benchmarks>:/benchmarks aibasel/downward \
/benchmarks/<domain.pddl> /benchmarks/<task.pddl> \
/benchmarks/<domain.pddl> /benchmarks/<problem.pddl> \
--search "astar(lmcut())"

Here `<path-to-benchmarks>` refers to your local directory containing your domain and task file.
Here `<path-to-benchmarks>` refers to your local directory containing your domain and problem file.

Note:

- The Docker flag `-v` mounts the local directory `<path-to-benchmarks>` of your host
machine under the container directory `/benchmarks`, which is the
place where the containerised planner looks for the problem.
place where the containerised planner looks for the domain and problem file.
- `<path-to-benchmarks>` must be an absolute path; relative paths are only supported as of Docker Engine version 23.

See more planner options at [planner usage](planner-usage.md).
Expand Down Expand Up @@ -128,7 +128,7 @@ vagrant ssh

# Run the planner.
downward/fast-downward.py \
/vagrant/benchmarks/<domain.pddl> /vagrant/benchmarks/<task.pddl> \
/vagrant/benchmarks/<domain.pddl> /vagrant/benchmarks/<problem.pddl> \
--search "astar(lmcut())"

# Log out from the VM.
Expand All @@ -138,7 +138,7 @@ logout
vagrant halt
```

Here `<path-to-benchmarks>` refers to your local directory containing your domain and task file.
Here `<path-to-benchmarks>` refers to your local directory containing your domain and problem file.

See more planner options at [planner usage](planner-usage.md).

Expand Down Expand Up @@ -168,7 +168,7 @@ You can run the planner as follows:

Assume you want to solve a planning task (e.g. from the [Fast Downward benchmarks](https://github.com/aibasel/downward-benchmarks)) using A* search with the LM-cut heuristic. To do so you can run the following:

./fast-downward.py <domain.pddl> <task.pddl> --search "astar(lmcut())"
./fast-downward.py <domain.pddl> <problem.pddl> --search "astar(lmcut())"

See more planner options at [planner usage](planner-usage.md).

Expand Down
6 changes: 3 additions & 3 deletions docs/translator-output-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,8 @@ conditions (0) and affects var6 (6). It requires that the old value of
the variable is 1, so it is only applicable if the robot is in rooma. It
establishes the value 0, so that the robot will be in roomb afterwards.
This domain does not use explicit action_costs (as encoded in the `metric`
section), so the final line is `0`. (The search code will treat problems with
no explicit action costs as unit-cost problems though, so the action will be
section), so the final line is `0`. (The search code will treat tasks with
no explicit action costs as unit-cost tasks though, so the action will be
handled as if its cost were 1.)

The two pick-up operators are similar, so we only explain the last one.
Expand Down Expand Up @@ -554,7 +554,7 @@ generated for domains that contain derived predicates, but they can also
be generated for PDDL tasks without derived predicates if they use
non-STRIPS features such as universally quantified conditions, as some
of these are compiled away with the help of axioms. As an example, here
is an axiom rules from a Miconic-FullADL task:
is an axiom rule from a Miconic-FullADL task:

*Sample axiom section (Miconic-FullADL domain):*

Expand Down
112 changes: 112 additions & 0 deletions misc/autodoc/generate-translate-docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#! /usr/bin/env python3

import argparse
import logging
from pathlib import Path
import subprocess
import sys

SCRIPT_DIR = Path(__file__).resolve().parent
REPO_ROOT_DIR = SCRIPT_DIR.parents[1]
BUILD = "release"
FILENAME = "translator-options.md"

HEADER_TEXT = """
# Translator Options

"""

FOOTER_TEXT = """
# Examples

### Translate with disabled invariant synthesis and find a plan with A* + LM-Cut:
```
fast-downward.py domain.pddl problem.pddl --search "astar(lmcut())" --translate-options --invariant-generation-max-candidates 0
```
Note that the order of the arguments matters.


### Print the help message of the translator
```
fast-downward.py -- --translate-options --help
```
The singular `--` is used to skip passing a domain and problem file to the driver.
"""


def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--outdir", default=f"{REPO_ROOT_DIR}/docs")
return parser.parse_args()


def build_translator():
subprocess.check_call([sys.executable, "build.py", BUILD, "translate"], cwd=REPO_ROOT_DIR)


def import_argparser_from_translator():
sys.path.insert(0, str(REPO_ROOT_DIR / "builds" / BUILD / "bin"))
from translate import options
return options.get_arg_parser()


def action_to_markdown(parser: argparse.ArgumentParser, action: argparse.Action):
names = []
for opt in action.option_strings:
toc_entry = opt
if action.choices is not None:
choice_str = ",".join(map(str, action.choices))
names.append(f"`{opt} {{{choice_str}}}`")
elif action.metavar is not None:
names.append(f"`{opt} {action.metavar}`")
elif action.nargs != 0:
metavar = action.dest.upper()
names.append(f"`{opt} {metavar}`")
else:
names.append(f"`{opt}`")
name = ", ".join(names)

# Expand %(default)s, %(choices)s, etc.
help_text = action.help or ""
if help_text is not argparse.SUPPRESS:
params = {
"default": action.default,
"prog": parser.prog,
"type": action.type,
"choices": action.choices,
"metavar": action.metavar,
"dest": action.dest,
}
try:
help_text = help_text % params
except Exception:
pass

return f"### {name} {{: data-toc-label=\"{toc_entry}\"}}\n{help_text}\n"


def parser_to_markdown(parser: argparse.ArgumentParser):
lines = [HEADER_TEXT]
for action in parser._actions:
if action.option_strings:
lines.append(action_to_markdown(parser, action))
lines += [FOOTER_TEXT]
return "\n".join(lines)


def build_docs(path: Path):
parser = import_argparser_from_translator()
path.write_text(parser_to_markdown(parser))


if __name__ == '__main__':
args = parse_args()
logging.info("building translator...")
build_translator()
logging.info("building documentation...")
outdir = SCRIPT_DIR / args.outdir
outdir.mkdir(parents=True, exist_ok=True)
outpath = outdir / FILENAME
if outpath.exists():
sys.exit(f"{outpath} already exists.")
build_docs(outpath)
15 changes: 11 additions & 4 deletions misc/website/build_website.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
SCRIPT_DIR = Path(__file__).resolve().parent
REPO_ROOT_DIR = SCRIPT_DIR.parents[1]
BUILD_DIR = SCRIPT_DIR/"build"
GENERATED_DOC_DIR = BUILD_DIR/"docs"/"documentation"/"search"
GENERATED_DOC_DIR = BUILD_DIR/"docs"/"documentation"
GENERATED_SEARCH_DOC_DIR = GENERATED_DOC_DIR/"search"

if __name__ == '__main__':
try:
Expand All @@ -31,14 +32,20 @@
# we remove the search directory from the documentation (in case it is
# there) because we will re-generate its content in the next step from the
# actual code (binary).
rmtree(GENERATED_DOC_DIR, ignore_errors=True)
rmtree(GENERATED_SEARCH_DOC_DIR, ignore_errors=True)

print("Start creating documentation of search plugins")
out = subprocess.run(
subprocess.run(
[REPO_ROOT_DIR/"misc"/"autodoc"/"generate-docs.py", "--outdir",
GENERATED_DOC_DIR])
GENERATED_SEARCH_DOC_DIR])
print("Done creating documentation of search plugins")

print("Start creating documentation of translator")
subprocess.run(
[REPO_ROOT_DIR/"misc"/"autodoc"/"generate-translate-docs.py", "--outdir",
GENERATED_DOC_DIR])
print("Done creating documentation of translator")

print("\n\n", "Done. Run 'mkdocs serve' from the build directory "
"to see the website in the browser at http://localhost:8001/:\n",
"cd build && mkdocs serve -a localhost:8001")
Loading