Skip to content

Commit

Permalink
Allow adding SAS+ files to FastDownwardExperiment (#90)
Browse files Browse the repository at this point in the history
Co-authored-by: ClemensBuechner <clemens.buechner@unibas.ch>
  • Loading branch information
jendrikseipp and ClemensBuechner committed Sep 22, 2020
1 parent 90ef939 commit 3291e15
Show file tree
Hide file tree
Showing 7 changed files with 959 additions and 66 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name: Ubuntu

# see https://github.community/t5/GitHub-Actions/How-to-trigger-an-action-on-push-or-pull-request-but-not-both/m-p/35805
on:
push:
branches:
- master
pull_request:
branches:
- master
# and https://github.community/t/duplicate-checks-on-push-and-pull-request-simultaneous-event/18012/6
on: [push, pull_request]

jobs:
build:

runs-on: ubuntu-18.04

# We want to run on external PRs, but not on our own internal PRs as they'll be run
# by the push to the branch.
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository

strategy:
matrix:
python-version: [3.6, 3.7, 3.8]
Expand Down
12 changes: 12 additions & 0 deletions docs/news.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
News
====

v6.2 (unreleased)
-----------------

Lab
^^^
* No changes.

Downward Lab
^^^^^^^^^^^^
* Allow adding SAS+ files with ``FastDownwardExperiment.add_suite()`` (Jendrik Seipp).


v6.1 (2020-09-15)
-----------------

Expand Down
56 changes: 33 additions & 23 deletions downward/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,41 @@ def __init__(self, exp, algo, task):
self.algo = algo
self.task = task

self._set_properties()

# Linking to instead of copying the PDDL files makes building
# the experiment twice as fast.
self.add_resource("domain", self.task.domain_file, "domain.pddl", symlink=True)
self.add_resource(
"problem", self.task.problem_file, "problem.pddl", symlink=True
)
self.driver_options = algo.driver_options[:]

if self.task.domain_file is None:
self.add_resource("task", self.task.problem_file, "task.sas", symlink=True)
input_files = ["{task}"]
# Without PDDL input files, we can't validate the solution.
self.driver_options.remove("--validate")
else:
self.add_resource(
"domain", self.task.domain_file, "domain.pddl", symlink=True
)
self.add_resource(
"problem", self.task.problem_file, "problem.pddl", symlink=True
)
input_files = ["{domain}", "{problem}"]

self.add_command(
"planner",
[tools.get_python_executable()]
+ ["{" + _get_solver_resource_name(algo.cached_revision) + "}"]
+ algo.driver_options
+ ["{domain}", "{problem}"]
+ self.driver_options
+ input_files
+ algo.component_options,
)

self._set_properties()

def _set_properties(self):
self.set_property("algorithm", self.algo.name)
self.set_property("repo", self.algo.cached_revision.repo)
self.set_property("local_revision", self.algo.cached_revision.local_rev)
self.set_property("global_revision", self.algo.cached_revision.global_rev)
self.set_property("revision_summary", self.algo.cached_revision.summary)
self.set_property("build_options", self.algo.cached_revision.build_options)
self.set_property("driver_options", self.algo.driver_options)
self.set_property("driver_options", self.driver_options)
self.set_property("component_options", self.algo.component_options)

for key, value in self.task.properties.items():
Expand Down Expand Up @@ -182,30 +191,31 @@ def _get_tasks(self):
return tasks

def add_suite(self, benchmarks_dir, suite):
"""Add benchmarks to the experiment.
"""Add PDDL or SAS+ benchmarks to the experiment.
*benchmarks_dir* must be a path to a benchmark directory. It
must contain domain directories, which in turn hold PDDL files.
*benchmarks_dir* must be a path to a benchmark directory. It must
contain domain directories, which in turn hold PDDL or SAS+ files.
*suite* must be a list of domain or domain:task names. ::
exp.add_suite(benchmarks_dir, ["depot", "gripper"])
exp.add_suite(benchmarks_dir, ["gripper:prob01.pddl"])
>>> benchmarks_dir = os.environ["DOWNWARD_BENCHMARKS"]
>>> exp = FastDownwardExperiment()
>>> exp.add_suite(benchmarks_dir, ["depot", "gripper"])
>>> exp.add_suite(benchmarks_dir, ["gripper:prob01.pddl"])
>>> exp.add_suite(benchmarks_dir, ["rubiks-cube:p01.sas"])
One source for benchmarks is
https://github.com/aibasel/downward-benchmarks. After cloning
the repo, you can generate suites with the ``suites.py``
script. We recommend using the suite ``optimal_strips`` for
optimal planning and ``satisficing`` for satisficing planning::
https://github.com/aibasel/downward-benchmarks. After cloning the
repo, you can generate suites with the ``suites.py`` script. We
recommend using the suite ``optimal_strips`` for optimal STRIPS planners
and ``satisficing`` for satisficing planners::
# Create standard optimal planning suite.
$ path/to/downward-benchmarks/suites.py optimal_strips
['airport', ..., 'zenotravel']
You can copy the generated list into your experiment script::
Then you can copy the generated list into your experiment script::
>>> benchmarks_dir = os.environ["DOWNWARD_BENCHMARKS"]
>>> exp = FastDownwardExperiment()
>>> exp.add_suite(benchmarks_dir, ['airport', 'zenotravel'])
"""
Expand Down
70 changes: 35 additions & 35 deletions downward/suites.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@
from lab import tools


def find_domain_file(benchmarks_dir, domain, problem):
"""
Search for domain file in the directory *benchmarks_dir*/*domain*.
Check the following names: 'domain.pddl', 'pXX-domain.pddl', or the
full problem name preceeded by 'domain_'.
"""
domain_basenames = [
"domain.pddl",
problem[:3] + "-domain.pddl",
"domain_" + problem,
"domain-" + problem,
]
domain_dir = os.path.join(benchmarks_dir, domain)
return tools.find_file(domain_basenames, domain_dir)


def get_problem(benchmarks_dir, domain_name, problem_name):
problem_file = os.path.join(benchmarks_dir, domain_name, problem_name)
domain_file = None
if problem_file.endswith(".pddl"):
domain_file = find_domain_file(benchmarks_dir, domain_name, problem_name)
return Problem(
domain_name, problem_name, problem_file=problem_file, domain_file=domain_file
)


class Domain:
def __init__(self, benchmarks_dir, domain):
self.domain = domain
Expand All @@ -31,8 +57,7 @@ def __init__(self, benchmarks_dir, domain):
]
)
self.problems = [
Problem(domain, problem, benchmarks_dir=benchmarks_dir)
for problem in problem_files
get_problem(benchmarks_dir, domain, problem) for problem in problem_files
]

def __str__(self):
Expand All @@ -53,59 +78,34 @@ def __iter__(self):

class Problem:
def __init__(
self,
domain,
problem,
benchmarks_dir="",
domain_file=None,
problem_file=None,
properties=None,
self, domain, problem, problem_file, domain_file=None, properties=None
):
"""
*domain* and *problem* are the display names of the domain and
problem, *domain_file* and *problem_file* are paths to the
respective files on the disk. If the latter are not specified,
they will be automatically generated according to the following
naming conventions: both files are searched in the directory
*benchmarks_dir*/*domain*. The default filename of the problem
is *problem* and the domain file is searched for under the
names 'domain.pddl', 'pXX-domain.pddl', or the full problem
name preceeded by 'domain_'.
respective files on the disk. If *domain_file* is not given,
assume that *problem_file* is a SAS task.
*properties* may be a dictionary of entries that should be
added to the properties file of each run that uses this
problem. ::
suite = [
Problem('gripper-original', 'prob01.pddl',
domain_file='/path/to/original/domain.pddl',
problem_file='/path/to/original/problem.pddl',
domain_file='/path/to/original/domain.pddl',
properties={'relaxed': False}),
Problem('gripper-relaxed', 'prob01.pddl',
domain_file='/path/to/relaxed/domain.pddl',
problem_file='/path/to/relaxed/problem.pddl',
domain_file='/path/to/relaxed/domain.pddl',
properties={'relaxed': True}),
Problem('gripper', 'prob01.pddl',
benchmarks_dir='/path/to/benchmarks',
Problem('gripper', 'prob01.pddl', '/path/to/prob01.pddl')
]
"""
self.domain = domain
self.problem = problem

self.problem_file = problem_file
self.domain_file = domain_file
if self.domain_file is None:
domain_basenames = [
"domain.pddl",
self.problem[:3] + "-domain.pddl",
"domain_" + self.problem,
"domain-" + self.problem,
]
domain_dir = os.path.join(benchmarks_dir, self.domain)
self.domain_file = tools.find_file(domain_basenames, domain_dir)

self.problem_file = problem_file or os.path.join(
benchmarks_dir, self.domain, self.problem
)

self.properties = properties or {}
self.properties.setdefault("domain", self.domain)
Expand All @@ -129,7 +129,7 @@ def _generate_problems(benchmarks_dir, description):
yield from description
elif ":" in description:
domain_name, problem_name = description.split(":", 1)
yield Problem(domain_name, problem_name, benchmarks_dir=benchmarks_dir)
yield get_problem(benchmarks_dir, domain_name, problem_name)
else:
yield from Domain(benchmarks_dir, description)

Expand Down
4 changes: 3 additions & 1 deletion examples/showcase-options.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from collections import defaultdict
import os
import os.path
from pathlib import Path
import platform
from subprocess import call

Expand All @@ -20,7 +21,7 @@
from lab.reports.filter import FilterReport


DIR = os.path.dirname(os.path.abspath(__file__))
DIR = Path(__file__).resolve().parent
NODE = platform.node()
REMOTE = NODE.endswith(".scicore.unibas.ch") or NODE.endswith(".cluster.bc2.ch")
if REMOTE:
Expand Down Expand Up @@ -93,6 +94,7 @@ def add_quality(self, run):
exp.add_parser(exp.PLANNER_PARSER)

exp.add_suite(BENCHMARKS_DIR, ["gripper:prob01.pddl", "miconic:s1-0.pddl"])
exp.add_suite(DIR / ".." / "tests" / "benchmarks", ["blocks", "gripper:p01.sas"])
exp.add_algorithm(
"iter-hadd",
REPO,
Expand Down

0 comments on commit 3291e15

Please sign in to comment.