Exemple #1
0
def get_fluents(init, action_instances):
    fluents = set()
    for action in action_instances:  # TODO: just actions if no action_instances
        for cond, eff in action.add_effects:
            assert not cond
            if not literal_holds(init, eff):
                fluents.add(eff)
        for cond, eff in action.del_effects:
            assert not cond
            if not literal_holds(init, eff.negate()):
                fluents.add(eff)
    return fluents
Exemple #2
0
def recover_axioms_plans2(instantiated, action_instances):
    #import axiom_rules
    #with Verbose(False):
    #    normalized_axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms(
    #        [], instantiated.axioms, instantiated.goal_list)
    #state = set(instantiated.task.init + axiom_init)
    normalized_axioms = instantiated.axioms  # TODO: ignoring negated because cannot reinstantiate correctly
    state = set(instantiated.task.init)
    fluents = get_fluents(state, action_instances)

    unprocessed_from_atom = defaultdict(list)
    fluents_from_axiom = {}
    remaining_from_axiom = {}
    for axiom in normalized_axioms:
        fluent_conditions = []
        for literal in axiom.condition:
            if literal.positive() in fluents:
                fluent_conditions.append(literal)
            elif not literal_holds(state, literal):
                fluent_conditions = None
                break
        if fluent_conditions is None:
            continue
        for literal in fluent_conditions:
            unprocessed_from_atom[literal].append(axiom)
        fluents_from_axiom[id(axiom)] = len(fluent_conditions)
        remaining_from_axiom[id(axiom)] = fluents_from_axiom[id(axiom)]
    static_axioms = [
        axiom for axiom, num in fluents_from_axiom.items() if num == 0
    ]

    axiom_plans = []
    for action in action_instances + [
            get_goal_instance(instantiated.task.goal)
    ]:
        axiom_from_atom = mark_iteration(state, unprocessed_from_atom,
                                         fluents_from_axiom,
                                         remaining_from_axiom, static_axioms)
        preimage = []
        for literal in action.precondition:
            if not literal_holds(state, literal):
                preimage.append(literal)
                assert literal in axiom_from_atom
        for cond, eff in (action.add_effects + action.del_effects):
            # TODO: add conditional effects that must hold here
            assert not cond
        axiom_plans.append([])
        assert extract_axioms(axiom_from_atom, preimage, axiom_plans[-1])
        apply_action(state, action)
    return axiom_plans
Exemple #3
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)
Exemple #4
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
Exemple #5
0
 def get_successors(self, atom_order, state):
     if len(atom_order) <= self.depth:
         return self.instances
     atom = atom_order[self.depth]
     instances = []
     for value, node in self.children.items():
         if (value is None) or (literal_holds(state, atom) is value):
             instances.extend(node.get_successors(atom_order, state))
     return instances
Exemple #6
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
Exemple #7
0
def extract_axioms(state, axiom_from_atom, conditions, axiom_plan, negated_from_name={}):
    success = True
    for fact in filter_negated(conditions, negated_from_name):
        if literal_holds(state, fact):
            continue
        if fact not in axiom_from_atom:
            print('Fact is not achievable:', fact)
            success = False
            continue
        axiom = axiom_from_atom[fact]
        if (axiom is None) or (axiom in axiom_plan):
            continue
        extract_axioms(state, axiom_from_atom, axiom.condition, axiom_plan, negated_from_name=negated_from_name)
        axiom_plan.append(axiom)
    return success
Exemple #8
0
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
Exemple #9
0
def recover_axioms_plans(instantiated, action_instances):
    task = instantiated.task
    derived_predicates = get_derived_predicates(task.axioms)
    state = set(task.init)
    axiom_plans = []
    for action_instance in action_instances + [get_goal_instance(task.goal)]:
        # TODO: apply all axiom_instances unaffected by negative conditions
        preimage = list(plan_preimage([action_instance], []))
        axiom_instances = filter(
            lambda ax: all(l.predicate in derived_predicates or literal_holds(
                state, l) for l in ax.condition), instantiated.axioms)
        # Only instantiate if preimage has goal
        axiom_plan = extraction_helper(state, axiom_instances, preimage)
        assert axiom_plan is not None
        axiom_plans.append(axiom_plan)
        apply_action(state, action_instance)
    return axiom_plans
Exemple #10
0
def mark_iteration(state, axioms_from_literal, fluents_from_axiom,
                   remaining_from_axiom, static_axioms):
    axioms_from_atom = defaultdict(list)
    for literal in axioms_from_literal:
        if literal_holds(state, literal):
            axioms_from_atom[literal].append(None)
    queue = deque(axioms_from_atom.keys())
    for axiom in static_axioms:
        mark_axiom(queue, remaining_from_axiom, axiom, axioms_from_atom)
    while queue:
        literal = queue.popleft()
        for axiom in axioms_from_literal[literal]:
            remaining_from_axiom[id(axiom)] -= 1
            mark_axiom(queue, remaining_from_axiom, axiom, axioms_from_atom)
    for literal, axioms in axioms_from_atom.items():
        for axiom in axioms:
            if axiom is not None:
                remaining_from_axiom[id(axiom)] = fluents_from_axiom[id(axiom)]
    # TODO: still some overhead here
    # TODO: could process these layer by layer instead
    return {atom: axioms[0] for atom, axioms in axioms_from_atom.items()}
Exemple #11
0
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
    ]
Exemple #12
0
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