Skip to content

Commit

Permalink
Improve implementation of #63 and add some further tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gfrances committed Aug 4, 2019
1 parent ea827c2 commit 6184bfa
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
20 changes: 17 additions & 3 deletions src/tarski/fstrips/representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,12 @@ def collect_effect_free_parameters(action: Action):
return parameters.difference(free)


def project_away_effect_free_variables(action: Action):
def project_away_effect_free_variables(action: Action, inplace=False):
""" Return an action schema which is equivalent to the given `action` except that all "effect-free" parameters have
been compiled away into existential variables in the precondition. Hence, an action
been compiled away into existential variables in the precondition. The value of `inplace` determines whether
the modification will be done in-place to the given action, or a new action will be created.
As an example, an action
action a(x, y, z)
PRE: p(x, y) and q(y, z)
Expand All @@ -158,12 +161,23 @@ def project_away_effect_free_variables(action: Action):
"""
free = collect_effect_free_parameters(action)
bound = [x for x in action.parameters if symref(x) not in free]
projected = copy.deepcopy(action)
projected = action if inplace else copy.deepcopy(action)
projected.parameters = VariableBinding(bound)
projected.precondition = exists(*(x.expr for x in free), action.precondition)
return projected


def project_away_effect_free_variables_from_problem(problem: Problem, inplace=False):
""" Return a new problem equivalent to the given one but where all action schemas have had their "effect-free"
parameters compiled away into existential variables in the precondition. The value of `inplace` determines whether
the modification will be done in-place to the given problem, or a new problem will be created.
"""
# If not modifying inplace, we copy the full problem (including its actions) and then modify that one inplace
projected = problem if inplace else copy.deepcopy(problem)
_ = [project_away_effect_free_variables(action, inplace=True) for action in projected.actions.values()]
return projected


def collect_effect_free_variables(eff: fs.BaseEffect):
""" Return the set of all variables that appear free in the given effect. """
free = set()
Expand Down
22 changes: 15 additions & 7 deletions tests/fstrips/test_representation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

from tarski.fstrips.representation import collect_effect_free_parameters, project_away_effect_free_variables, \
collect_effect_free_variables
collect_effect_free_variables, project_away_effect_free_variables_from_problem
from tarski.syntax import exists, land
from tarski.fstrips import representation as rep

Expand Down Expand Up @@ -100,9 +100,17 @@ def test_effect_free_variables_in_caldera():
assert names == ['?v01']

projected = project_away_effect_free_variables(act)
names = sorted(x.symbol for x in projected.parameters)
assert names == ['?v01']




names1 = sorted(x.symbol for x in act.parameters)
names2 = sorted(x.symbol for x in projected.parameters)
assert names1 == ['?v00', '?v01', '?v02'] and names2 == ['?v01']

# Check inplace argument works as expected
problem2 = project_away_effect_free_variables_from_problem(problem, inplace=False)
names1 = sorted(x.symbol for x in problem.get_action('get_domain').parameters)
names2 = sorted(x.symbol for x in problem2.get_action('get_domain').parameters)
assert names1 == ['?v00', '?v01', '?v02'] and names2 == ['?v01']

problem2 = project_away_effect_free_variables_from_problem(problem, inplace=True)
names1 = sorted(x.symbol for x in problem.get_action('get_domain').parameters)
names2 = sorted(x.symbol for x in problem2.get_action('get_domain').parameters)
assert names1 == names2 == ['?v01']

0 comments on commit 6184bfa

Please sign in to comment.