Пример #1
0
 def successors(self, node):
     index = build_index(node.state)
     for o in self.operators:
         for m in pattern_match(o.conditions, index):
             dels = frozenset(execute_functions(e, m) if
                              is_functional_term(e) else subst(m, e) for e
                              in o.del_effects)
             adds = frozenset(execute_functions(e, m) if
                              is_functional_term(e) else subst(m, e) for e
                              in o.add_effects)
             new_state = node.state.difference(dels).union(adds)
             yield Node(new_state, node, (o, m), node.cost() + o.cost)
Пример #2
0
def replace_constants(ele, sub):
    """
    Return the element with all functionals replaced,
    at the top level. Builds up sub along the way.
    """
    if is_variable(ele):
        return ele
    if is_functional_term(ele):
        return ele
    if isinstance(ele, tuple) and ele[0] == 'not':
        return ele
    if isinstance(ele, tuple):
        new_ele = (ele[0],) + tuple(replace_constants(e, sub) for e in ele[1:])
        return new_ele
    sk = gen_skolem()
    sub[sk] = ele
    return sk
Пример #3
0
    def predecessors(self, node):
        for o in self.operators:
            # Rename variables to prevent collisions.
            # TODO figure out how to reverse this for printing plans
            o = o.standardized_copy()

            # Convert constants into equality constraints, so that goals with
            # constants can be matched in reverse.
            constant_mapping = {}
            var_state = frozenset(
                replace_constants(e, constant_mapping) for e in node.state)
            equality_constraints = set(
                (eq, e, constant_mapping[e]) for e in constant_mapping)

            # Generate constraints that prevent operator inconsistency
            # prevent delete effects that match positive goals
            del_constraints = generate_del_constraints(o.del_effects, [
                e for e in var_state
                if not is_functional_term(e) and not is_negated_term(e)
            ])
            # prevent positive effects that produce negated goals
            add_constraints = generate_add_constraints(o.add_effects, [
                e[1] for e in var_state
                if not is_functional_term(e) and is_negated_term(e)
            ])

            # TODO figure out how to add any applicable constraints to var
            # state in order to prevent variables bindings that are
            # inconsistent this requires comparing the vars in the state with
            # those in the constraints and only adds constraints that have var
            # subsets.
            var_state = var_state.union(equality_constraints)

            for m in pattern_match(var_state,
                                   build_index(o.add_effects),
                                   partial=True):

                new_state = frozenset(subst(m, e) for e in var_state)
                new_state = new_state.difference(o.add_effects)
                new_state = new_state.union(o.conditions)

                cons = set(
                    subst(m, e) for e in new_state if is_functional_term(e))
                cons.update(subst(m, e) for e in del_constraints)
                cons.update(subst(m, e) for e in add_constraints)

                new_state = frozenset(e for e in new_state
                                      if not is_functional_term(e))
                # print("Constraints", cons)

                # Check equality constraints that disagree
                invalid = False
                assignment_mapping = {}
                for c in cons:
                    if is_var_assignment(c):
                        var = c[1]
                        const = c[2]

                        if var in assignment_mapping:
                            invalid = True
                            break

                        assignment_mapping[var] = const

                if invalid:
                    continue

                # substitute assignment equality constraints
                # back in, i.e., replace all var with constants.
                cons = set(
                    subst(assignment_mapping, e) for e in cons
                    if not is_var_assignment(e))
                new_state = frozenset(
                    subst(assignment_mapping, e) for e in new_state)

                # Check for any other functional constraints.
                # Terminate branches with false functions
                # Eliminate constraints that are satisfied
                new_cons = set()
                for c in cons:
                    try:
                        if execute_functions(c, m) is False:
                            invalid = True
                            break
                    except TypeError:
                        new_cons.add(c)

                if invalid:
                    continue

                # REACHABILITY ANALYSIS, check if there are any
                # new_state elements that cannot be generated by an
                # operator and do not exist in the state
                for e in new_state:
                    if is_negated_term(e):
                        continue
                    temp_m = {}
                    new_e = replace_constants(e, temp_m)
                    p = set((eq, e, temp_m[e]) for e in temp_m)
                    p.add(new_e)
                    try:
                        next(pattern_match(p, self.achievable, partial=True))
                    except Exception:
                        invalid = True
                        break

                if invalid:
                    continue

                # Add any surviving constraints back into the state
                new_state = new_state.union(new_cons)

                yield GoalNode(new_state, node, (o, m), node.cost() + o.cost)
Пример #4
0
    def predecessors(self, node):
        # print()
        # pprint(node.state)
        # if node.parent is not None:
        #     return
        for o in self.operators:
            o = o.standardized_copy()

            # convert constants into equality constraints.
            constant_mapping = {}
            var_state = frozenset(replace_constants(e, constant_mapping) for e
                                  in node.state)
            equality_constraints = set((eq, e, constant_mapping[e]) for e in
                                       constant_mapping)
            var_state = var_state.union(equality_constraints)

            # print()
            # pprint(var_state)
            # print(o)
            for m in pattern_match(var_state,
                                   build_index(o.add_effects),
                                   partial=True):
                # pprint(m)
                new_state = frozenset(subst(m, e) for e in var_state)
                new_state = new_state.difference(o.add_effects)
                new_state = new_state.union(o.conditions)

                cons = set(subst(m, e) for e in new_state if
                           is_functional_term(e))
                new_state = frozenset(e for e in new_state if not
                                      is_functional_term(e))
                # print("Constraints", cons)

                # Check equality constraints that disagree
                invalid = False
                assignment_mapping = {}
                for c in cons:
                    if is_var_assignment(c):
                        var = c[1]
                        const = c[2]

                        if var in assignment_mapping:
                            invalid = True
                            break

                        assignment_mapping[var] = const

                if invalid:
                    continue

                # substitute assignment equality constraints
                # back in, i.e., replace all var with constants.
                cons = set(subst(assignment_mapping, e) for e in cons
                           if not is_var_assignment(e))
                new_state = frozenset(subst(assignment_mapping, e)
                                      for e in new_state)

                # check for any other functional constraints.
                new_cons = set()
                for c in cons:
                    try:
                        if execute_functions(c, m) is False:
                            invalid = True
                            break
                    except TypeError:
                        new_cons.add(c)

                if invalid:
                    continue

                # REACHABILITY ANALYSIS, check if there are any
                # new_state elements that cannot be generated by an
                # operator and do not exist in the state
                # print()
                # pprint(new_state)
                # print(build_index(self.achievable))
                for e in new_state:
                    if is_negated_term(e):
                        continue
                    temp_m = {}
                    new_e = replace_constants(e, temp_m)
                    p = set((eq, e, temp_m[e]) for e in temp_m)
                    p.add(new_e)
                    try:
                        next(pattern_match(p, self.achievable,
                                           partial=True))
                    except Exception as e:
                        # print(e)
                        # print("ACHIEVABLE")
                        # pprint(self.achievable)
                        # print("HUH?", p)
                        # print('OP', o, m)
                        # print(new_state)
                        invalid = True
                        break

                if invalid:
                    continue

                new_state = new_state.union(new_cons)
                # pprint(new_state)

                yield GoalNode(new_state, node, (o, m), node.cost() + o.cost)