-
Notifications
You must be signed in to change notification settings - Fork 1
/
normalizer.py
84 lines (65 loc) · 2.35 KB
/
normalizer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from pddl.action import Action
from pddl.logic.base import OneOf, Not
from pddl.logic.effects import When, AndEffect
from pddl.logic.predicates import Predicate
from itertools import product, chain
DEBUG = False
def normalize(op):
effs = flatten(op.effect)
if len(effs) == 1:
eff = effs[0]
else:
# Normalize to wrap every operand of an OneOf in an AndEffect
for i in range(len(effs)):
if not isinstance(effs[i], AndEffect):
effs[i] = AndEffect(effs[i])
# As an optimization, compress one level of nested AndEffects on the outcomes
new_outcomes = []
for outcome in effs:
if isinstance(outcome, AndEffect):
new_operands = []
for operand in outcome.operands:
if isinstance(operand, AndEffect):
new_operands.extend(operand.operands)
else:
new_operands.append(operand)
new_outcomes.append(AndEffect(*new_operands))
else:
new_outcomes.append(outcome)
eff = OneOf(*new_outcomes)
return Action(
name=op.name,
parameters=op.parameters,
precondition=op.precondition,
effect=eff)
def flatten(eff):
return _flatten(eff)
def combine(eff_lists):
combos = list(product(*eff_lists))
combined_oneofs = [AndEffect(*[x for x in choice if x != AndEffect([])]) for choice in combos]
if DEBUG:
print ("\nCombining:\n%s" % '\n'.join(map(str, eff_lists)))
print ("Result: %s\n" % combined_oneofs)
return combined_oneofs
def _flatten(eff):
if DEBUG:
print ("Flattening %s" % str(eff))
if isinstance(eff, AndEffect):
if 0 == len(eff.operands):
return [eff]
else:
return combine(list(map(_flatten, eff.operands)))
elif isinstance(eff, OneOf):
return list(chain(*(list(map(_flatten, eff.operands)))))
elif isinstance(eff, When):
return [When(eff.condition, res) for res in _flatten(eff.effect)]
# Default cases
elif isinstance(eff, Not):
return [eff]
elif isinstance(eff, Predicate):
return [eff]
else:
if DEBUG:
print ("Base: %s" % str(eff))
raise ValueError("Unexpected effect type: %s" % type(eff))
# return [eff]