Skip to content

Commit

Permalink
test: run compilation tests also for ADLCompiler
Browse files Browse the repository at this point in the history
  • Loading branch information
marcofavorito committed Oct 3, 2023
1 parent ce48e1e commit ca7cfc7
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 53 deletions.
92 changes: 87 additions & 5 deletions tests/test_compiler/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,21 @@

"""Base test module for testing the compiler module."""
from abc import abstractmethod
from functools import partial
from pathlib import Path
from typing import Tuple
from typing import Callable, Dict, Optional, Sequence, Tuple, cast

import pytest
from pddl.core import Domain, Problem
from pddl.logic import Predicate
from pddl.parser.domain import DomainParser
from pddl.parser.problem import ProblemParser
from pylogics.parsers import parse_pltl
from pylogics.syntax.base import Formula
from pylogics.syntax.pltl import Atomic as PLTLAtomic

from plan4past.compiler import Compiler
from plan4past.compiler import ADLCompiler, Compiler
from plan4past.constants import ACHIEVE_GOAL_ACTION, EVALUATE_PNF_ACTION
from tests.helpers.misc import check_compilation
from tests.helpers.planutils.base import BasePlannerWrapper
from tests.helpers.planutils.val import VALWrapper
Expand Down Expand Up @@ -60,8 +66,82 @@ def get_domain_file(self, _instance_id: int) -> Path:
"""Get the domain file for the given instance."""
return self.PATH_TO_DOMAINS_DIR / "domain.pddl"

def _get_compiler(
self,
domain: Domain,
problem: Problem,
formula: Formula,
from_atoms_to_fluent: Optional[Dict[PLTLAtomic, Predicate]] = None,
adl: bool = False,
evaluate_pnf: bool = False,
simplify_disj_goal: bool = False,
) -> Compiler:
"""Get the compiler."""
if adl:
return ADLCompiler(
domain,
problem,
formula,
from_atoms_to_fluent=from_atoms_to_fluent,
evaluate_pnf=evaluate_pnf,
simplify_disj_goal=simplify_disj_goal,
)
return Compiler(
domain, problem, formula, from_atoms_to_fluent=from_atoms_to_fluent
)

def _insert_evaluate_pnf_actions(self, actions: Sequence[str]) -> Tuple[str, ...]:
"""Insert the evaluate-pnf actions."""
result = []
for action in actions:
if ACHIEVE_GOAL_ACTION not in action:
result.append(f"({EVALUATE_PNF_ACTION} )")
result.append(action)
return tuple(result)

def _compute_expected_plan(
self, instance_id: int, compiler: Compiler | ADLCompiler
) -> Tuple[str, ...]:
"""Return a wrapper to get_expected_plan to handle achieve-actions and evaluate-pnf actions."""
is_adl_compiler = isinstance(compiler, ADLCompiler)
expected_plan = self.get_expected_plan(instance_id)
if is_adl_compiler:
compiler = cast(ADLCompiler, compiler)
simplify_disj_goal = compiler.simplify_disj_goal
if simplify_disj_goal:
pytest.skip("disjunctive goal simplification not supported yet")
expected_plan = expected_plan + ("(achieve-goal )",)
if compiler.evaluate_pnf:
expected_plan = self._insert_evaluate_pnf_actions(expected_plan)
return expected_plan

@classmethod
def parametrize_compiler(cls):
"""Get the parametrization for the P4P compiler."""
return pytest.mark.parametrize(
"compiler_builder",
[
partial(
cls._get_compiler,
adl=False,
evaluate_pnf=False,
simplify_disj_goal=False,
),
partial(
cls._get_compiler,
adl=True,
evaluate_pnf=False,
simplify_disj_goal=False,
),
],
)

def _test_instance(
self, instance_id: int, val: VALWrapper, planner: BasePlannerWrapper
self,
instance_id: int,
compiler_builder: Callable,
val: VALWrapper,
planner: BasePlannerWrapper,
) -> None:
"""Test the instance with the given id."""
domain_parser = DomainParser()
Expand All @@ -78,14 +158,16 @@ def _test_instance(
problem = problem_parser(problem_path.read_text(encoding="utf-8"))
goal = parse_pltl(self.make_formula(instance_id, domain_path, problem_path))

compiler = Compiler(domain, problem, goal)
compiler = compiler_builder(self, domain, problem, goal)
compiler.compile()
compiled_domain, compiled_problem = compiler.result

expected_plan = self._compute_expected_plan(instance_id, compiler)

check_compilation(
compiled_domain,
compiled_problem,
val,
planner,
self.get_expected_plan(instance_id),
expected_plan,
)
9 changes: 6 additions & 3 deletions tests/test_compiler/test_blocksworld_det.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class TestBlocksworldDetSimpleSequence(BaseCompilerTest):
PATH_TO_DOMAINS_DIR = BLOCKSWORLD_DIR
PATH_TO_INSTANCES_DIR = BLOCKSWORLD_DIR
MIN_INSTANCE_ID = 10
MAX_INSTANCE_ID = 15
MAX_INSTANCE_ID = 10

def make_formula(self, instance_id: int, domain: Path, problem: Path) -> str:
"""
Expand Down Expand Up @@ -70,6 +70,9 @@ def get_expected_plan(self, instance_id: int) -> Tuple[str, ...]:
@pytest.mark.parametrize(
"instance_id", list(range(MIN_INSTANCE_ID, MAX_INSTANCE_ID + 1))
)
def test_run(self, instance_id, val, default_planner):
@BaseCompilerTest.parametrize_compiler()
def test_run(self, instance_id, compiler_builder, val, default_planner):
"""Test the instance with the given id."""
self._test_instance(instance_id, val=val, planner=default_planner)
self._test_instance(
instance_id, compiler_builder, val=val, planner=default_planner
)
49 changes: 6 additions & 43 deletions tests/test_compiler/test_elevators_det.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class TestElevatorsDet(BaseCompilerTest):
PATH_TO_INSTANCES_DIR = ELEVATORS_DIR
TEGS = ELEVATORS_DIR / "elevators_teg.json"
MIN_INSTANCE_ID = 2
MAX_INSTANCE_ID = 10
MAX_INSTANCE_ID = 9
EXPECTED_PLANS = {
"s2-0": (
"(up f0 f1)",
Expand Down Expand Up @@ -224,46 +224,6 @@ class TestElevatorsDet(BaseCompilerTest):
"(down f14 f7)",
"(depart f7 p6)",
),
"s10-0": (
"(up f0 f9)",
"(board f9 p4)",
"(down f9 f1)",
"(depart f1 p4)",
"(up f1 f13)",
"(board f13 p2)",
"(up f13 f15)",
"(depart f15 p2)",
"(up f15 f17)",
"(board f17 p1)",
"(down f17 f15)",
"(depart f15 p1)",
"(down f15 f3)",
"(board f3 p0)",
"(up f3 f6)",
"(depart f6 p0)",
"(board f6 p3)",
"(up f6 f12)",
"(board f12 p9)",
"(depart f12 p3)",
"(down f12 f2)",
"(board f2 p5)",
"(up f2 f16)",
"(depart f16 p9)",
"(down f16 f7)",
"(depart f7 p5)",
"(up f7 f10)",
"(board f10 p6)",
"(up f10 f19)",
"(depart f19 p6)",
"(down f19 f0)",
"(board f0 p8)",
"(up f0 f6)",
"(depart f6 p8)",
"(down f6 f3)",
"(board f3 p7)",
"(up f3 f6)",
"(depart f6 p7)",
),
}

def make_formula(self, instance_id: int, domain: Path, problem: Path) -> str:
Expand All @@ -282,6 +242,9 @@ def get_expected_plan(self, instance_id: int) -> Tuple[str, ...]:
@pytest.mark.parametrize(
"instance_id", list(range(MIN_INSTANCE_ID, MAX_INSTANCE_ID + 1))
)
def test_run(self, instance_id, val, default_planner):
@BaseCompilerTest.parametrize_compiler()
def test_run(self, instance_id, compiler_builder, val, default_planner):
"""Test the instance with the given id."""
self._test_instance(instance_id, val=val, planner=default_planner)
self._test_instance(
instance_id, compiler_builder, val=val, planner=default_planner
)
7 changes: 5 additions & 2 deletions tests/test_compiler/test_openstacks_det.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ def get_expected_plan(self, instance_id: int) -> Tuple[str, ...]:
@pytest.mark.parametrize(
"instance_id", list(range(MIN_INSTANCE_ID, MAX_INSTANCE_ID + 1))
)
def test_run(self, instance_id, val, default_planner):
@BaseCompilerTest.parametrize_compiler()
def test_run(self, instance_id, compiler_builder, val, default_planner):
"""Test the instance with the given id."""
self._test_instance(instance_id, val=val, planner=default_planner)
self._test_instance(
instance_id, compiler_builder, val=val, planner=default_planner
)

0 comments on commit ca7cfc7

Please sign in to comment.