Skip to content

Commit

Permalink
Merge branch 'master' into approach-wrapper-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
tomsilver authored Nov 21, 2023
2 parents d06191e + 8f16303 commit 17cfc09
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 25 deletions.
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ omit =
predicators/envs/kitchen.py
predicators/perception/kitchen_perceiver.py
predicators/ground_truth_models/kitchen/**
# Currently disabled due to flakiness in the SME dependency.
predicators/approaches/sme_pg3_analogy_approach.py

[report]
# Regexes for lines to exclude from consideration
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Repository Description

This codebase implements a framework for *bilevel planning with learned neuro-symbolic relational abstractions*, as described in [this paper](https://arxiv.org/abs/2203.09634). Several features are concurrently under active development. **Please contact <[email protected]> and <ronuchit@mit.edu> before attempting to use it for your own research.** In particular, this codebase aims to ultimately provide an integrated system for learning the ingredients of search-then-sample bilevel planning with learned abstractions. That includes: options, predicates, operators, and samplers.
This codebase implements a framework for *bilevel planning with learned neuro-symbolic relational abstractions*, as described in [this paper](https://arxiv.org/abs/2203.09634). Several features are concurrently under active development. **Please contact <[email protected]> or <njk@mit.edu> before attempting to use it for your own research.** In particular, this codebase aims to ultimately provide an integrated system for learning the ingredients of search-then-sample bilevel planning with learned abstractions. That includes: options, predicates, operators, and samplers.

### Code Structure

Expand Down
48 changes: 29 additions & 19 deletions predicators/explorers/active_sampler_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ def __init__(self, predicates: Set[Predicate],
self._last_executed_nsrt: Optional[_GroundNSRT] = None
self._nsrt_to_explorer_sampler = nsrt_to_explorer_sampler
self._seen_train_task_idxs = seen_train_task_idxs
self._task_plan_cache: Dict[_TaskID, List[_GroundSTRIPSOperator]] = {}
# If the plan is None, that means none can be found, e.g., due to
# timeouts or dead-ends.
self._task_plan_cache: Dict[
_TaskID, Optional[List[_GroundSTRIPSOperator]]] = {}
self._task_plan_calls_since_replan: Dict[_TaskID, int] = {}
self._sorted_options = sorted(options, key=lambda o: o.name)

Expand Down Expand Up @@ -410,17 +413,20 @@ def _score_ground_op_planning_progress(
replan_task_ids = [("replan", i) for i in range(len(num_replan_tasks))]
for task_id in train_task_ids + replan_task_ids:
plan = self._get_task_plan_for_task(task_id, ground_op_costs)
task_plan_costs = []
for op in plan:
op_cost = ground_op_costs.get(op, self._default_cost)
task_plan_costs.append(op_cost)
plan_costs.append(sum(task_plan_costs))
# If no plan can be found for a task, the task is just ignored.
if plan is not None:
task_plan_costs = []
for op in plan:
op_cost = ground_op_costs.get(op, self._default_cost)
task_plan_costs.append(op_cost)
plan_costs.append(sum(task_plan_costs))
return -sum(plan_costs) # higher scores are better

def _get_task_plan_for_task(
self, task_id: _TaskID, ground_op_costs: Dict[_GroundSTRIPSOperator,
float]
) -> List[_GroundSTRIPSOperator]:
) -> Optional[List[_GroundSTRIPSOperator]]:
"""Returns None if no task plan can be found."""
# Optimization: only re-plan at a certain frequency.
replan_freq = CFG.active_sampler_explorer_replan_frequency
if task_id not in self._task_plan_calls_since_replan or \
Expand All @@ -433,18 +439,22 @@ def _get_task_plan_for_task(
"train": self._train_tasks,
"replan": self._replanning_tasks,
}[task_type][task_idx]
plan, _, _ = run_task_plan_once(
task,
self._nsrts,
self._predicates,
self._types,
timeout,
self._seed,
task_planning_heuristic=task_planning_heuristic,
ground_op_costs=ground_op_costs,
default_cost=self._default_cost,
max_horizon=np.inf)
self._task_plan_cache[task_id] = [n.op for n in plan]
try:
plan, _, _ = run_task_plan_once(
task,
self._nsrts,
self._predicates,
self._types,
timeout,
self._seed,
task_planning_heuristic=task_planning_heuristic,
ground_op_costs=ground_op_costs,
default_cost=self._default_cost,
max_horizon=np.inf)
self._task_plan_cache[task_id] = [n.op for n in plan]
except (PlanningFailure, PlanningTimeout): # pragma: no cover
logging.info("WARNING: task planning failed in the explorer.")
self._task_plan_cache[task_id] = None

self._task_plan_calls_since_replan[task_id] += 1
return self._task_plan_cache[task_id]
Expand Down
3 changes: 2 additions & 1 deletion predicators/planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,8 @@ def fd_plan_from_sas_file(
metrics: Metrics = defaultdict(float)
num_nodes_expanded = re.findall(r"Expanded (\d+) state", output)
num_nodes_created = re.findall(r"Evaluated (\d+) state", output)
assert len(num_nodes_expanded) == 1
if len(num_nodes_expanded) != 1:
raise PlanningFailure(f"Plan not found with FD! Error: {output}")
assert len(num_nodes_created) == 1
metrics["num_nodes_expanded"] = float(num_nodes_expanded[0])
metrics["num_nodes_created"] = float(num_nodes_created[0])
Expand Down
1 change: 1 addition & 0 deletions tests/approaches/test_oracle_approach.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ def simulate(self, state, action):
return self._transition_stack(state, x, y, z)

env = _ExternalBlocksEnv()
assert env.get_name() == "external_blocks"

# Create external options by modifying blocks options.
options = set()
Expand Down
10 changes: 8 additions & 2 deletions tests/approaches/test_pg3_analogy_approach.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,14 @@ def test_pg3_analogy_approach():
)"""


def test_find_env_analogies():
"""Tests for _find_env_analogies()."""
def _disabled_test_find_env_analogies(): # pragma: no cover
"""Tests for _find_env_analogies().
NOTE: this test is currently disabled because of sudden flakiness in the
SME depedency, despite no changes for months. Since we're not actively
using this code, we're just disabling it, but leaving it here in case we
do want to resurrect the code in the future.
"""
# Test for gripper -> ferry.
base_env = create_new_env("pddl_gripper_procedural_tasks")
base_nsrts = get_gt_nsrts(base_env.get_name(), base_env.predicates,
Expand Down
8 changes: 6 additions & 2 deletions tests/envs/test_pybullet_cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,12 @@ def test_pybullet_cover_step(env):
assert abs(state.get(block, "pose") - 0.75) < 0.01


def test_pybullet_cover_pick_workspace_bounds(env):
"""Tests for picking at workspace bounds in PyBulletCoverEnv."""
def _disabled_test_pybullet_cover_pick_workspace_bounds(
env): # pragma: no cover
"""Tests for picking at workspace bounds in PyBulletCoverEnv.
This is currently disabled due to nondeterminism issues in IK.
"""
block = Object("block0", env.block_type)
robot = env.robot
workspace_x, workspace_z = env.workspace_dimensions
Expand Down

0 comments on commit 17cfc09

Please sign in to comment.