def __init__(self, initial, goal, actions, axioms): self.index_from_var = {} self.var_order = [] self.index_from_var_val = {} self.val_order_from_var = {} self.mutexes = [] self.initial = apply(initial, defaultdict(lambda: self.default)) self.fluent_heads = set() for op in (actions + axioms): for literal in op.effects: if isinstance(literal, Literal) and ( literal.value != self.initial[literal.head]): self.fluent_heads.add(literal.head) self.condition_heads = set() for op in (actions + axioms + [Goal(goal)]): for literal in op.preconditions: assert isinstance(literal, Literal) if literal.head not in self.fluent_heads: continue self.condition_heads.add(literal.head) self.goal = self._get_conditions(goal) self.actions = list(self._get_actions(actions)) self.axioms = list(self._get_axioms(axioms)) self.derived_vars = {axiom.effect.var for axiom in self.axioms}
def is_solution(evals, plan, goal): state = defaultdict(bool) instances = [Initial(evals) ] + [action.instantiate(args) for action, args in plan] + [Goal(goal)] for instance in instances: if not instance.applicable(state): return False state = instance.apply(state) return True
def predicate_uses(self): predicate_to_signs = defaultdict(set) for op in (self.actions + [Goal(self.goal)]): for pre in op.preconditions: if isinstance(pre.head.function, Predicate): predicate_to_signs[pre.head.function].add(pre.value) for ax in self.axioms: for sign in predicate_to_signs[ax.effect.head.function]: for pre in ax.preconditions: if isinstance(pre.head.function, Predicate): predicate_to_signs[pre.head.function].add( sign == pre.value) return predicate_to_signs
def is_solution(self, plan): plan_instances = [action.instantiate(args) for action, args in plan ] + [Goal(self.problem.goal)] axiom_instances = [ axiom.instantiate(args) for axiom, args in self.axiom_instances() ] state = apply(self.evaluations, defaultdict(bool)) for instance in plan_instances: reset_derived(self.axioms_from_derived, state) apply_axioms(axiom_instances, state) if not instance.applicable(state): return False state = instance.apply(state) return True
def negative_axioms(universe, plan): negative_atoms = set() if plan is None: return negative_atoms action_instances = [action.instantiate(args) for action, args in plan ] + [Goal(universe.problem.goal)] states = list( state_sequence(universe.evaluations, action_instances, default=bool)) for state, action in zip(states, action_instances): atoms_from_predicate = defaultdict(list) for head, val in state.items(): if (val is True) and (head.function in universe.fluents): atoms_from_predicate[head.function].append(Atom(head)) for pre in action.preconditions: if not isinstance(pre, NegatedAtom) or not universe.is_derived(pre): continue for axiom in universe.axioms_from_derived[pre.head.function]: assert not any( universe.is_derived(a) for a in axiom.preconditions) external = filter( lambda a: a.head.function.is_defined() and (a.head.function.bound is False), axiom.preconditions) if not external: continue fluents = filter(universe.is_fluent, axiom.preconditions) values = [ atoms_from_predicate.get(a.head.function, []) for a in fluents ] initial_mapping = dict( zip(axiom.effect.head.args, pre.head.args)) for combo in product(*values): mapping = get_mapping(fluents, combo, initial=initial_mapping) if mapping is None: continue assert all(p in mapping for p in axiom.parameters) if all( pre.substitute(mapping).holds(state) for pre in (set(axiom.preconditions) - set(external))): negative_atoms.update(~pre.substitute(mapping) for pre in external) return filter(lambda a: not a.head.computed(), negative_atoms)
def plan_preimage(universe, evaluations, plan): action_instances = [action.instantiate(args) for action, args in plan] lazy_states = list(literal_sequence(universe.evaluations, action_instances)) real_states = list(literal_sequence(evaluations, action_instances)) axiom_instances = [ axiom.instantiate(args) for axiom, args in universe.axiom_instances() ] preimage = set() remapped_axioms = [] for rs, ls, action in reversed( zip(real_states, lazy_states, action_instances + [Goal(universe.problem.goal)])): preimage -= set(action.effects) derived = filter( lambda a: isinstance(a, Atom) and (a.head.function in universe.axioms_from_derived), action.preconditions) preimage |= (set(action.preconditions) - set(derived)) if derived: derived_map = { f: f.__class__(f.inputs) for f in universe.axioms_from_derived } remap_fn = lambda a: a.__class__( Head(derived_map[a.head.function], a.head.args)) preimage.update(map(remap_fn, derived)) for ax in axiom_instances: preconditions = [] for atom in ax.preconditions: if atom.head.function in derived_map: preconditions.append(remap_fn(atom)) elif ls.get(atom.head, False) != atom.value: break elif (atom.head not in rs) and (not atom.head.function.is_defined()): preconditions.append(atom) else: remapped_axioms.append( Axiom([], preconditions, remap_fn(ax.effect))) return preimage, remapped_axioms
def functions(self): return { f for op in (self.actions + self.axioms + [Goal(self.goal)]) for f in op.functions() }
def plan_supporting_axioms(evaluations, plan_instances, axiom_instances, goal): states = state_sequence(evaluations, plan_instances, default=bool) for state, action in zip(states, plan_instances + [Goal(goal)]): yield supporting_axioms(state, action.preconditions, axiom_instances)