Skip to content

Commit

Permalink
[issue913] fix instantiation bug with uninitialized numeric expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
roeger committed Jan 31, 2024
1 parent 2349940 commit 917a6c4
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
24 changes: 22 additions & 2 deletions src/translate/normalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import copy

import pddl
import pddl_to_prolog

class ConditionProxy:
def clone_owner(self):
Expand All @@ -23,7 +24,19 @@ def delete_owner(self, task):
def build_rules(self, rules):
action = self.owner
rule_head = get_action_predicate(action)
rule_body = condition_to_rule_body(action.parameters, self.condition)

# if the action cost is based on a primitive numeric expression,
# we need to require that it has a value defined in the initial state.
# We hand it over to condition_to_rule_body to include this in the rule
# body.
pne = None
if (isinstance(action.cost, pddl.Increase) and
isinstance(action.cost.expression,
pddl.PrimitiveNumericExpression)):
pne = action.cost.expression

rule_body = condition_to_rule_body(action.parameters, self.condition,
pne)
rules.append((rule_body, rule_head))
def get_type_map(self):
return self.owner.type_map
Expand Down Expand Up @@ -366,10 +379,13 @@ def build_exploration_rules(task):
proxy.build_rules(result)
return result

def condition_to_rule_body(parameters, condition):
def condition_to_rule_body(parameters, condition, numeric_expression=None):
result = []
# require parameters to be of the right type
for par in parameters:
result.append(par.get_atom())

# require the given condition
if not isinstance(condition, pddl.Truth):
if isinstance(condition, pddl.ExistentialCondition):
for par in condition.parameters:
Expand All @@ -388,6 +404,10 @@ def condition_to_rule_body(parameters, condition):
assert isinstance(part, pddl.Literal), "Condition not normalized: %r" % part
if not part.negated:
result.append(part)

# require the numeric expression (from the action cost) to be defined.
if numeric_expression is not None:
result.append(pddl_to_prolog.get_definition_fluent(numeric_expression))
return result

if __name__ == "__main__":
Expand Down
7 changes: 7 additions & 0 deletions src/translate/pddl_to_prolog.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ def __str__(self):
cond_str = ", ".join(map(str, self.conditions))
return "%s :- %s." % (self.effect, cond_str)

def get_definition_fluent(pne: pddl.PrimitiveNumericExpression):
return pddl.Atom(f"@def-{pne.symbol}", pne.args)

def translate_typed_object(prog, obj, type_dict):
supertypes = type_dict[obj.type_name].supertype_names
for type_name in [obj.type_name] + supertypes:
Expand All @@ -155,6 +158,10 @@ def translate_facts(prog, task):
assert isinstance(fact, pddl.Atom) or isinstance(fact, pddl.Assign)
if isinstance(fact, pddl.Atom):
prog.add_fact(fact)
else:
# Add a fact to indicate that the primitive numeric expression in
# fact.fluent has been defined.
prog.add_fact(get_definition_fluent(fact.fluent))

def translate(task):
# Note: The function requires that the task has been normalized.
Expand Down

0 comments on commit 917a6c4

Please sign in to comment.