def instantiate_condition(action, is_static, args_from_predicate): parameters = {p.name for p in action.parameters} #if not parameters: # yield {} # return static_conditions = list( filter(is_static, get_literals(get_precondition(action)))) static_parameters = set( filter(is_parameter, flatten(atom.args for atom in static_conditions))) if not (parameters <= static_parameters): raise NotImplementedError( 'Could not instantiate action {} due to parameters: {}'.format( action.name, str_from_object(parameters - static_parameters))) atoms_from_cond = { condition: args_from_predicate[condition.predicate, get_constants(condition)] for condition in static_conditions } conditions, atoms = zip(*atoms_from_cond.items()) relations = [ Relation(conditions[index].args, atoms[index]) for index in compute_order(conditions, atoms) ] solution = solve_satisfaction(relations) for element in solution.body: yield solution.get_mapping(element)
def recover_axioms_plans(instantiated, action_instances): #axioms, axiom_init, _ = axiom_rules.handle_axioms( # instantiated.actions, instantiated.axioms, instantiated.goal_list) new_action_instances = [ copy.deepcopy(instance) for instance in action_instances ] axioms, axiom_init = instantiated.axioms, [ ] # TODO: bug when needing to reachieve negated axioms_from_effect = defaultdict(list) for axiom in axioms: axioms_from_effect[axiom.effect].append(axiom) axioms_from_name = get_derived_predicates(instantiated.task.axioms) state = set(instantiated.task.init) | set(axiom_init) axiom_plans = [] for action in new_action_instances + [ get_goal_instance(instantiated.task.goal) ]: all_conditions = list(get_precondition(action)) + list( flatten(cond for cond, _ in action.add_effects + action.del_effects)) axioms = backtrack_axioms(all_conditions, axioms_from_effect, set()) axiom_from_atom, _ = get_achieving_axioms(state, axioms) action.applied_effects = [] for effects in [action.add_effects, action.del_effects]: negate = (effects is action.del_effects) for i, (conditions, effect) in reversed(list(enumerate(effects))): if all( literal_holds(state, literal) or ( literal in axiom_from_atom) for literal in conditions): action.precondition.extend(conditions) effects[i] = ([], effect) action.applied_effects.append( effect.negate() if negate else effect) else: effects.pop(i) # RuntimeError: Preimage fact ('new-axiom@0',) is not achievable! #precondition = action.precondition # TODO: strange bug if this applies precondition = [ literal for literal in action.precondition if literal.predicate in axioms_from_name ] axiom_plans.append([]) success = extract_axioms(state, axiom_from_atom, precondition, axiom_plans[-1]) if not success: print(all_conditions) print(action) print(axioms) raise RuntimeError('Could not extract axioms') apply_action(state, action) return new_action_instances, axiom_plans
def instantiate_domain(task, prune_static=True): fluent_predicates = get_fluents(task) is_static = lambda a: isinstance(a, pddl.Atom) and (a.predicate not in fluent_predicates) fluent_facts = MockSet(lambda a: not prune_static or not is_static(a)) init_facts = set(task.init) function_assignments = get_function_assignments(task) type_to_objects = instantiate.get_objects_by_type(task.objects, task.types) constants_from_predicate = defaultdict(set) for action in task.actions + task.axioms: for atom in filter(is_static, get_literals(get_precondition(action))): constants = tuple((i, a) for i, a in enumerate(atom.args) if not is_parameter(a)) constants_from_predicate[atom.predicate].add(constants) predicate_to_atoms = defaultdict(set) args_from_predicate = defaultdict(set) for atom in filter(is_static, task.init): # TODO: compute which predicates might involve constants predicate_to_atoms[atom.predicate].add(atom) args_from_predicate[atom.predicate].add(atom.args) for constants in constants_from_predicate[atom.predicate]: if all(atom.args[i] == o for i, o in constants): args_from_predicate[atom.predicate, constants].add(atom.args) instantiated_actions = [] for action in task.actions: for variable_mapping in instantiate_condition(action, is_static, args_from_predicate): inst_action = action.instantiate(variable_mapping, init_facts, fluent_facts, type_to_objects, task.use_min_cost_metric, function_assignments, predicate_to_atoms) if inst_action: instantiated_actions.append(inst_action) instantiated_axioms = [] for axiom in task.axioms: for variable_mapping in instantiate_condition(axiom, is_static, args_from_predicate): inst_axiom = axiom.instantiate(variable_mapping, init_facts, fluent_facts) if inst_axiom: instantiated_axioms.append(inst_axiom) reachable_facts, reachable_operators = get_achieving_axioms(init_facts, instantiated_actions + instantiated_axioms) atoms = {atom for atom in (init_facts | set(reachable_facts)) if isinstance(atom, pddl.Atom)} relaxed_reachable = all(literal_holds(init_facts, goal) or goal in reachable_facts for goal in instantiate_goal(task.goal)) reachable_actions = [action for action in reachable_operators if isinstance(action, pddl.PropositionalAction)] reachable_axioms = [axiom for axiom in reachable_operators if isinstance(axiom, pddl.PropositionalAxiom)] return relaxed_reachable, atoms, reachable_actions, reachable_axioms
def get_achieving_axioms(state, operators, negated_from_name={}): # TODO: order by stream effort # marking algorithm for propositional Horn logic unprocessed_from_literal = defaultdict(list) operator_from_literal = {} remaining_from_stream = {} reachable_operators = set() # TODO: only keep facts queue = deque() def process_axiom(op, effect): reachable_operators.add(id(op)) if effect not in operator_from_literal: operator_from_literal[effect] = op queue.append(effect) # TODO: could produce a list of all derived conditions for op in operators: preconditions = get_precondition(op) for cond, effect in get_conditional_effects(op): conditions = cond + preconditions remaining_from_stream[id(op), effect] = 0 for literal in filter_negated(conditions, negated_from_name): if literal_holds(state, literal): operator_from_literal[literal] = None else: remaining_from_stream[id(op), effect] += 1 unprocessed_from_literal[literal].append((op, effect)) if remaining_from_stream[id(op), effect] == 0: process_axiom(op, effect) while queue: literal = queue.popleft() for op, effect in unprocessed_from_literal[literal]: remaining_from_stream[id(op), effect] -= 1 if remaining_from_stream[id(op), effect] == 0: process_axiom(op, effect) return operator_from_literal, [ op for op in operators if id(op) in reachable_operators ]
def recover_axioms_plans(instantiated, action_instances): #axioms, axiom_init, _ = axiom_rules.handle_axioms( # instantiated.actions, instantiated.axioms, instantiated.goal_list) axioms, axiom_init = instantiated.axioms, [ ] # TODO: bug when needing to reachieve negated axioms_from_effect = defaultdict(list) for axiom in axioms: axioms_from_effect[axiom.effect].append(axiom) state = set(instantiated.task.init) | set(axiom_init) axiom_plans = [] for action in action_instances + [ get_goal_instance(instantiated.task.goal) ]: all_conditions = list(get_precondition(action)) + list( flatten(cond for cond, _ in action.add_effects + action.del_effects)) axioms = backtrack_axioms(all_conditions, axioms_from_effect, set()) axiom_from_atom, _ = get_achieving_axioms(state, axioms) action.applied_effects = [] for effects in [action.add_effects, action.del_effects]: negate = effects is action.del_effects for i, (conditions, effect) in reversed(list(enumerate(effects))): if all( literal_holds(state, literal) or ( literal in axiom_from_atom) for literal in conditions): action.precondition.extend(conditions) effects[i] = ([], effect) action.applied_effects.append( effect.negate() if negate else effect) else: effects.pop(i) axiom_plans.append([]) assert extract_axioms(state, axiom_from_atom, action.precondition, axiom_plans[-1]) apply_action(state, action) return axiom_plans