Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement unambiguous mapping for deterministic compiler #265

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
76 changes: 45 additions & 31 deletions plan4past/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
from pddl.logic.predicates import DerivedPredicate, Predicate
from pylogics.syntax.base import Formula, Logic
from pylogics.syntax.pltl import Atomic as PLTLAtomic
from pylogics.syntax.pltl import FalseFormula
from pylogics.utils.to_string import to_string
from pylogics.syntax.pltl import Before, FalseFormula

from plan4past.constants import (
ACHIEVE_GOAL_ACTION,
Expand All @@ -45,23 +44,21 @@
TRUE_PREDICATE,
)
from plan4past.exceptions import ProblemUnsolvableException
from plan4past.helpers.compilation_helper import CompilationManager, YesterdayAtom
from plan4past.helpers.utils import (
add_val_prefix,
check_,
default_mapping,
remove_yesterday_prefix,
replace_symbols,
from plan4past.helpers.compilation_helper import (
CompilationManager,
PredicateMapping,
YesterdayAtom,
)
from plan4past.helpers.utils import add_val_prefix, check_, default_mapping
from plan4past.helpers.yesterday_atom_helper import QUOTED_ATOM
from plan4past.utils.atoms_visitor import find_atoms
from plan4past.utils.derived_visitor import derived_predicates
from plan4past.utils.derived_visitor import DerivedPredicatesVisitor
from plan4past.utils.dnf_visitor import dnf
from plan4past.utils.nnf_visitor import nnf
from plan4past.utils.predicates_visitor import predicates
from plan4past.utils.predicates_visitor import PredicatesVisitor
from plan4past.utils.pylogics2pddl import Pylogics2PddlTranslator
from plan4past.utils.rewrite_formula_visitor import rewrite
from plan4past.utils.val_predicates_visitor import val_predicates
from plan4past.utils.val_predicates_visitor import ValPredicatesVisitor


class Compiler:
Expand Down Expand Up @@ -93,6 +90,7 @@ def __init__(

check_(self.formula.logic == Logic.PLTL, "only PPLTL is supported!")

self._predicate_mapping = PredicateMapping()
self._executed: bool = False
self._result_domain: Optional[Domain] = None
self._result_problem: Optional[Problem] = None
Expand Down Expand Up @@ -134,18 +132,27 @@ def result(self) -> Tuple[Domain, Problem]:

def compile(self):
"""Compute the new domain and the new problem."""
if not self._executed:
self._compile_domain()
self._compile_problem()
self._executed = True
if self._executed:
return

self._compile_domain()
self._compile_problem()

self._executed = True

def _compile_domain(self):
"""Compute the new domain."""
new_predicates = predicates(self.formula).union(val_predicates(self.formula))
new_derived_predicates = derived_predicates(
self.formula, self.from_atoms_to_fluent
subformula_predicates_set = PredicatesVisitor(self._predicate_mapping).visit(
self.formula
)
val_predicates_set = ValPredicatesVisitor(self._predicate_mapping).visit(
self.formula
)
new_whens = _compute_whens(self.formula)
new_predicates = subformula_predicates_set.union(val_predicates_set)
new_derived_predicates = DerivedPredicatesVisitor(
self._predicate_mapping, self.from_atoms_to_fluent
).visit(self.formula)
new_whens = _compute_whens(subformula_predicates_set, self._predicate_mapping)
domain_actions = _update_domain_actions_det(self.domain.actions, new_whens)

self._result_domain = Domain(
Expand Down Expand Up @@ -174,27 +181,34 @@ def _compile_problem(self):
else set(self.problem.init)
)

goal_predicate = self._predicate_mapping.get_predicate(self.formula)
self._result_problem = Problem(
name=self.problem.name,
domain_name=self.domain.name,
requirements=self.problem.requirements,
objects=[*self.problem.objects],
init=new_init,
goal=And(
Predicate(add_val_prefix(replace_symbols(to_string(self.formula))))
),
goal=And(Predicate(add_val_prefix(goal_predicate.name))),
)


def _compute_whens(formula: Formula) -> Set[When]:
def _compute_whens(predicates: Set[Predicate], mapping: PredicateMapping) -> Set[When]:
"""Compute conditional effects for formula progression."""
return {
When(Predicate(add_val_prefix(remove_yesterday_prefix(p.name))), p)
for p in predicates(formula)
}.union(
When(Not(Predicate(add_val_prefix(remove_yesterday_prefix(p.name)))), Not(p))
for p in predicates(formula)
)
result: Set[When] = set()
for p in predicates:
formula = mapping.inverse_mapping[p]
if isinstance(formula, Before):
arg_predicate = mapping.mapping[formula.argument]
present_predicate = Predicate(add_val_prefix(arg_predicate.name))
past_predicate = p
else:
present_predicate = Predicate(add_val_prefix(p.name))
past_predicate = p

positive_when = When(present_predicate, past_predicate)
negative_when = When(Not(present_predicate), Not(past_predicate))
result.update({positive_when, negative_when})
return result


def _update_domain_actions_det(
Expand Down
48 changes: 46 additions & 2 deletions plan4past/helpers/compilation_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
# along with Plan4Past. If not, see <https://www.gnu.org/licenses/>.
#
"""This module contains the class that manages the compilation of a PPLTL formula."""
from typing import List, Tuple
from typing import Dict, List, Tuple

from pddl.logic import Predicate
from pylogics.syntax.base import Formula, Not
from pylogics.syntax.pltl import (
Atomic,
Expand All @@ -33,7 +34,7 @@
)

from plan4past.helpers.utils import check_
from plan4past.helpers.yesterday_atom_helper import YesterdayAtom
from plan4past.helpers.yesterday_atom_helper import QUOTED_ATOM, YesterdayAtom
from plan4past.utils.ppnf_visitor import ppnf
from plan4past.utils.yesterday_generator_visitor import get_quoted_dictionary

Expand Down Expand Up @@ -108,3 +109,46 @@ def get_problem_extension(self) -> Tuple[List[Formula], List, Formula]:
conditional_effects.append((ppnf(yesterday_atom.formula), yesterday_atom))

return fresh_atoms, conditional_effects, goal


class PredicateMapping:
"""Class that manages the mapping of the predicates."""

def __init__(self):
"""Initialize the predicate mapping."""
self.mapping: Dict[Formula, Predicate] = {}
self.inverse_mapping: Dict[Predicate, Formula] = {}
self.id = 0

def add_predicate(self, formula: Formula) -> None:
"""
Add a predicate to the mapping.

:param formula: the formula to be added
"""
if self.mapping.get(formula) is None:
self.mapping[formula] = Predicate(f"{QUOTED_ATOM}_{self.id}")
self.inverse_mapping[self.mapping[formula]] = formula
self.id += 1

def get_predicate(self, formula: Formula) -> Predicate:
"""
Get the predicate from the mapping.

:param formula: the formula to be added
:return: the predicate
"""
result = self.mapping.get(formula)
if result is None:
self.add_predicate(formula)
return self.mapping[formula]

def get_formula(self, predicate: Predicate) -> Formula:
"""
Get the formula from the inverse mapping.

:param predicate: the predicate to be added
:return: the formula
"""
check_(predicate in self.inverse_mapping, f"predicate {predicate} not found")
return self.inverse_mapping[predicate]
11 changes: 0 additions & 11 deletions plan4past/helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,6 @@ def add_val_prefix(name: str):
return "val-" + name.replace('"', "")


def remove_yesterday_prefix(name: str):
"""Remove the 'Y' prefix."""
return (
name.replace("Y-", "")
if name.startswith("Y-")
else name.replace("Y", "", 1)
if name.startswith("Y")
else name
)


def remove_val_prefix(name: str):
"""Remove the 'prime' prefix."""
return name.replace("val-", "") if name.startswith("val-") else name
Expand Down
Loading