Exemplo n.º 1
0
def recover_negative_axioms(real_task, opt_task, axiom_plans, action_plan,
                            negative_from_name):
    action_plan = reinstantiate_action_instances(
        opt_task, action_plan, negative_from_name=negative_from_name)
    # https://github.com/caelan/pddlstream/commit/18b303e19bbab9f8e0016fbb2656f461067e1e94#diff-55454a85485551f9139e20a446b56a83L53
    #simplify_conditional_effects(opt_task, action_plan, negative_from_name)
    axiom_plans = list(map(reinstantiate_axiom_instances, axiom_plans))
    axioms_from_name = get_derived_predicates(opt_task.axioms)

    # TODO: could instead just accumulate difference between real and opt
    opt_task.init = set(opt_task.init)
    real_states = [set(real_task.init)]
    preimage_plan = []
    for axiom_plan, action_instance in safe_zip(axiom_plans, action_plan):
        preimage = [
            l for l in plan_preimage(axiom_plan + [action_instance])
            if (l.predicate in axioms_from_name)
        ]
        #assert conditions_hold(opt_task.init, conditions)
        # TODO: only add derived facts and negative facts to fluent state to make normalizing easier
        negative_axiom_plan = extract_axiom_plan(opt_task,
                                                 preimage,
                                                 negative_from_name,
                                                 static_state=opt_task.init)
        #static_state=real_states[-1])
        assert negative_axiom_plan is not None
        preimage_plan.extend(negative_axiom_plan + axiom_plan +
                             [action_instance])
        if action_instance.name != GOAL_NAME:
            apply_action(opt_task.init, action_instance)
            real_states.append(set(real_states[-1]))
            apply_action(real_states[-1], action_instance)
    return real_states, preimage_plan
Exemplo n.º 2
0
    def __init__(self, instantiated, action_instances=[]):
        derived_predicates = get_derived_predicates(instantiated.task.axioms)
        conditions = {
            literal.positive()
            for axiom in instantiated.axioms for literal in axiom.condition
        }
        state = set(instantiated.task.init)
        fluents = get_fluents(state, action_instances) & conditions
        self.fluent_order = list(fluents)

        applicable_axioms = []
        axiom_from_literal = defaultdict(list)
        # TODO: could also just use get_achieving_axioms
        self.root = SuccessorNode()
        for axiom in instantiated.axioms:
            if all((l.predicate in derived_predicates) or (
                    l.positive() in fluents) or literal_holds(state, l)
                   for l in axiom.condition):
                applicable_axioms.append(axiom)
                for literal in axiom.condition:
                    if literal in fluents:
                        axiom_from_literal[literal].append(axiom)

                fluent_conds = {
                    l.positive(): not l.negated
                    for l in axiom.condition
                }
                node = self.root
                for atom in self.fluent_order:
                    value = fluent_conds.get(atom, None)
                    node = node.get_child(value)
                node.instances.append(axiom)
Exemplo n.º 3
0
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
Exemplo n.º 4
0
def get_necessary_axioms(conditions, axioms, negative_from_name):
    if not conditions or not axioms:
        return {}
    axioms_from_name = get_derived_predicates(axioms)
    atom_queue = []
    processed_atoms = set()

    def add_literals(literals):
        for lit in literals:
            atom = lit.positive()
            if atom not in processed_atoms:
                atom_queue.append(
                    atom)  # Previously was lit.positive() for some reason?
                processed_atoms.add(atom)

    add_literals(conditions)
    axiom_from_action = {}
    partial_instantiations = set()
    while atom_queue:
        literal = atom_queue.pop()
        for axiom in axioms_from_name[literal.predicate]:
            derived_parameters = axiom.parameters[:axiom.
                                                  num_external_parameters]
            var_mapping = {
                p.name: a
                for p, a in zip(derived_parameters, literal.args)
                if not is_parameter(a)
            }
            key = (axiom, frozenset(var_mapping.items()))
            if key in partial_instantiations:
                continue
            partial_instantiations.add(key)
            parts = [
                l.rename_variables(var_mapping)
                for l in get_literals(axiom.condition)
                if l.predicate not in negative_from_name
            ]  # Assumes a conjunction?
            # new_condition = axiom.condition.uniquify_variables(None, var_mapping)
            effect_args = [
                var_mapping.get(a.name, a.name) for a in derived_parameters
            ]
            effect = pddl.Effect([], pddl.Truth(),
                                 pddl.conditions.Atom(axiom.name, effect_args))
            free_parameters = [
                p for p in axiom.parameters if p.name not in var_mapping
            ]
            new_action = pddl.Action(axiom.name, free_parameters,
                                     len(free_parameters),
                                     pddl.Conjunction(parts), [effect], None)
            # Creating actions so I can partially instantiate (impossible with axioms)
            axiom_from_action[new_action] = (axiom, var_mapping)
            add_literals(parts)
    return axiom_from_action
Exemplo n.º 5
0
def extract_axiom_plan(task, goals, negative_from_name, static_state=set()):
    import pddl_to_prolog
    import build_model
    import instantiate
    # TODO: only reinstantiate the negative axioms
    if not negative_from_name:
        return []
    axioms_from_name = get_derived_predicates(task.axioms)
    derived_goals = {l for l in goals if l.predicate in axioms_from_name}
    assert all(
        literal_holds(task.init, l)  # or (l.predicate in negative_from_name)
        for l in set(goals) - derived_goals)
    axiom_from_action = get_necessary_axioms(derived_goals, task.axioms,
                                             negative_from_name)
    if not axiom_from_action:
        return []
    conditions_from_predicate = defaultdict(set)
    for axiom, mapping in axiom_from_action.values():
        for literal in get_literals(axiom.condition):
            conditions_from_predicate[literal.predicate].add(
                literal.rename_variables(mapping))

    original_init = task.init
    original_actions = task.actions
    original_axioms = task.axioms
    # TODO: retrieve initial state based on if helpful
    task.init = {
        atom
        for atom in task.init
        if is_useful_atom(atom, conditions_from_predicate)
    }
    # TODO: store map from predicate to atom
    task.actions = axiom_from_action.keys()
    task.axioms = []
    # TODO: maybe it would just be better to drop the negative throughout this process until this end
    with Verbose(verbose=False):
        model = build_model.compute_model(
            pddl_to_prolog.translate(task))  # Changes based on init
    opt_facts = instantiate.get_fluent_facts(
        task, model) | (task.init - static_state)
    mock_fluent = MockSet(lambda item: (item.predicate in negative_from_name)
                          or (item in opt_facts))
    instantiated_axioms = instantiate_necessary_axioms(model, static_state,
                                                       mock_fluent,
                                                       axiom_from_action)
    axiom_plan = extraction_helper(task.init, instantiated_axioms,
                                   derived_goals, negative_from_name)
    task.init = original_init
    task.actions = original_actions
    task.axioms = original_axioms
    return axiom_plan