Skip to content

Commit

Permalink
Support for modified floor-tile domain (#11)
Browse files Browse the repository at this point in the history
* floortile first draft

* floortile domain support and tests
  • Loading branch information
maxzuo authored Sep 10, 2024
1 parent b7d5694 commit 65086c2
Show file tree
Hide file tree
Showing 15 changed files with 3,336 additions and 1,150 deletions.
9 changes: 8 additions & 1 deletion planetarium/ASSUMPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,11 @@ Generally, since Grippers has reversible actions, essentially all problems are e
Rover has the capability of being a much more complex domain, but for the purposes of this benchmark, we work only with a single rover and a single lander.

`:init` conditions:
- No double `at_*` predicates (rover and lander can only be in one location at a time)
- No double `at_*` predicates (rover and lander can only be in one location at a time)

## Floortile

Generally, all valid problems with reachable goal states are evaluable.

`:init` conditions:
- No robot has two colors (`robot-has`)
77 changes: 77 additions & 0 deletions planetarium/domains/floor-tile.pddl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
;; Modified from: https://github.com/AI-Planning/pddl-generators/blob/main/floortile/domain.pddl

(define (domain floor-tile)
(:requirements :typing :action-costs)
(:types
robot tile color - object
)

(:predicates
(robot-at ?r - robot ?x - tile)
(up ?x - tile ?y - tile)
(right ?x - tile ?y - tile)
(painted ?x - tile ?c - color)
(robot-has ?r - robot ?c - color)
(available-color ?c - color)
)

(:action change-color
:parameters (?r - robot ?c - color ?c2 - color)
:precondition (and (robot-has ?r ?c) (available-color ?c2))
:effect (and (not (robot-has ?r ?c)) (robot-has ?r ?c2)
)
)

(:action paint-up
:parameters (?r - robot ?y - tile ?x - tile ?c - color)
:precondition (and (robot-has ?r ?c) (robot-at ?r ?x) (up ?y ?x))
:effect (painted ?y ?c)
)

(:action paint-down
:parameters (?r - robot ?y - tile ?x - tile ?c - color)
:precondition (and (robot-has ?r ?c) (robot-at ?r ?x) (up ?x ?y))
:effect (and (painted ?y ?c)
)
)

(:action paint-right
:parameters (?r - robot ?y - tile ?x - tile ?c - color)
:precondition (and (robot-has ?r ?c) (robot-at ?r ?x) (right ?y ?x))
:effect (and (painted ?y ?c)
)
)

(:action paint-left
:parameters (?r - robot ?y - tile ?x - tile ?c - color)
:precondition (and (robot-has ?r ?c) (robot-at ?r ?x) (right ?x ?y))
:effect (and (painted ?y ?c)
)
)

; Robot movements
(:action up
:parameters (?r - robot ?x - tile ?y - tile)
:precondition (and (robot-at ?r ?x) (up ?y ?x))
:effect (and (robot-at ?r ?y) (not (robot-at ?r ?x)))
)

(:action down
:parameters (?r - robot ?x - tile ?y - tile)
:precondition (and (robot-at ?r ?x) (up ?x ?y))
:effect (and (robot-at ?r ?y) (not (robot-at ?r ?x)))
)

(:action right
:parameters (?r - robot ?x - tile ?y - tile)
:precondition (and (robot-at ?r ?x) (right ?y ?x))
:effect (and (robot-at ?r ?y) (not (robot-at ?r ?x)))
)

(:action left
:parameters (?r - robot ?x - tile ?y - tile)
:precondition (and (robot-at ?r ?x) (right ?x ?y))
:effect (and (robot-at ?r ?y) (not (robot-at ?r ?x)))
)

)
3 changes: 2 additions & 1 deletion planetarium/downward.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def _get_best_plan(plan_filepath: str) -> tuple[str | None, float]:
best_cost = float("inf")
best_plan = None

for plan_fp in glob.glob(f"{plan_filepath}.*"):
for plan_fp in glob.glob(f"{plan_filepath}*"):
print(plan_fp)
with open(plan_fp, "r") as f:
*pddl_plan, cost_str = f.readlines()
match = re.search(r"cost = ([-\d\.]+)", cost_str)
Expand Down
2 changes: 1 addition & 1 deletion planetarium/evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def evaluate(
if check_solveable and isinstance(domain_str, str):
try:
plan_str = oracle.plan_to_string(oracle.plan(target_graph))
except oracle.DomainNotSupportedError:
except (oracle.DomainNotSupportedError, NotImplementedError):
try:
plan_str, _ = downward.plan(
domain_str,
Expand Down
4 changes: 1 addition & 3 deletions planetarium/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ def _edge_matching(
"""

def _getattr(obj, attr):
v = getattr(obj, attr, attributes[attr])
if v is None:
v = attributes[attr]
v = getattr(obj, attr, attributes.get(attr))
return v

return all(_getattr(source, attr) == _getattr(target, attr) for attr in attributes)
Expand Down
86 changes: 16 additions & 70 deletions planetarium/oracle.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
from typing import Callable

import jinja2 as jinja
from pddl.core import Action
import rustworkx as rx

from planetarium import graph

from .reduced_graph import ReducedSceneGraph, ReducedProblemGraph
from .oracles.blocksworld import (
_reduce_blocksworld,
_inflate_blocksworld,
_fully_specify_blocksworld,
_plan_blocksworld,
)
from .oracles.gripper import (
_reduce_gripper,
_inflate_gripper,
_fully_specify_gripper,
_plan_gripper,
)
from .oracles.rover_single import (
_reduce_rover_single,
_inflate_rover_single,
_fully_specify_rover_single,
)
from .oracles import ORACLES


plan_template = jinja.Template(
Expand Down Expand Up @@ -51,15 +36,9 @@ def reduce(
ReducedGraph: The reduced problem graph.
"""
domain = domain or graph.domain
match domain:
case "blocksworld":
return _reduce_blocksworld(graph)
case "gripper":
return _reduce_gripper(graph)
case "rover-single":
return _reduce_rover_single(graph)
case _:
raise DomainNotSupportedError(f"Domain {domain} not supported.")
if oracle := ORACLES.get(domain):
return oracle.reduce(graph)
raise DomainNotSupportedError(f"Domain {domain} not supported.")


def inflate(
Expand All @@ -77,22 +56,16 @@ def inflate(
graph.SceneGraph: The respecified, inflated scene graph.
"""
domain = domain or scene._domain
match domain:
case "blocksworld":
return _inflate_blocksworld(scene)
case "gripper":
return _inflate_gripper(scene)
case "rover-single":
return _inflate_rover_single(scene)
case _:
raise DomainNotSupportedError(f"Domain {domain} not supported.")
if oracle := ORACLES.get(domain):
return oracle.inflate(scene)
raise DomainNotSupportedError(f"Domain {domain} not supported.")


def fully_specify(
problem: graph.ProblemGraph,
domain: str | None = None,
return_reduced: bool = False,
) -> graph.ProblemGraph:
) -> graph.ProblemGraph | ReducedProblemGraph:
"""Fully specifies a goal state.
Args:
Expand All @@ -108,31 +81,9 @@ def fully_specify(
"""
domain = domain or problem.domain

match domain:
case "blocksworld":
reduced_init, reduced_goal = _reduce_blocksworld(problem).decompose()
fully_specified_goal = _fully_specify_blocksworld(reduced_goal)
case "gripper":
reduced_init, reduced_goal = _reduce_gripper(problem).decompose()
fully_specified_goal = _fully_specify_gripper(
reduced_init,
reduced_goal,
)
case "rover-single":
reduced_init, fully_specified_goal = _fully_specify_rover_single(
*problem.decompose()
)
case _:
raise DomainNotSupportedError(f"Domain {domain} not supported.")

if return_reduced:
return ReducedProblemGraph.join(reduced_init, fully_specified_goal)
else:
init, _ = problem.decompose()
return graph.ProblemGraph.join(
init,
inflate(fully_specified_goal, domain=domain),
)
if oracle := ORACLES.get(domain):
return oracle.fully_specify(problem, return_reduced=return_reduced)
raise DomainNotSupportedError(f"Domain {domain} not supported.")


def plan(problem: graph.ProblemGraph, domain: str | None = None) -> list[Action]:
Expand All @@ -145,14 +96,9 @@ def plan(problem: graph.ProblemGraph, domain: str | None = None) -> list[Action]
str: The sequence of actions to solve the problem.
"""
domain = domain or problem.domain
problem = fully_specify(problem, domain=domain, return_reduced=True)
match domain:
case "blocksworld":
return _plan_blocksworld(problem)
case "gripper":
return _plan_gripper(problem)
case _:
raise DomainNotSupportedError(f"Domain {domain} not supported.")
if oracle := ORACLES.get(domain):
return oracle.plan(problem)
raise DomainNotSupportedError(f"Domain {domain} not supported.")


def plan_to_string(actions: list[Action]) -> str:
Expand Down
15 changes: 15 additions & 0 deletions planetarium/oracles/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
__all__ = ["blocksworld", "gripper", "rover_single", "floortile"]

from . import oracle

from . import blocksworld
from . import gripper
from . import rover_single
from . import floortile

ORACLES: dict[str, oracle.Oracle] = {
"blocksworld": blocksworld.BlocksworldOracle,
"gripper": gripper.GripperOracle,
"rover-single": rover_single.RoverSingleOracle,
"floor-tile": floortile.FloorTileOracle,
}
Loading

0 comments on commit 65086c2

Please sign in to comment.