예제 #1
0
 def goal_test(self, node, goal):
     index = build_index(node.state)
     for m in pattern_match(goal.state, index, {}):
         for v in m:
             goal.action[1][v] = m[v]
         return True
     return False
예제 #2
0
def generate_del_constraints(del_effects, positive_goals):
    # print(del_effects, list(positive_goals))
    return [
        or_constraints([(ne, match[v], v) for v in match])
        for e in positive_goals
        for match in pattern_match([e], build_index(del_effects), {})
    ]
예제 #3
0
def test_partial_match():
    kb = [('Number', '5')]
    q = [
        ('Number', '5'),
        # ('Number', '?y')
    ]

    print(list(pattern_match(q, build_index(kb), partial=True)))
예제 #4
0
 def __init__(self, state, goals, operators):
     state = frozenset(state)
     self.operators = operators
     self.goal = GoalNode(frozenset(goals))
     self.initial = Node(state, parent=None, action=None, node_cost=0)
     achievable = set(e for o in self.operators for e in o.add_effects)
     achievable.update(e for e in state)
     self.achievable = build_index(achievable)
예제 #5
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)
예제 #6
0
        conditions = set(subst(sub, c) for c in self.conditions)
        effects = set(subst(sub, e) for e in self.effects)

        return Operator(self.name, conditions, effects, self.cost, reverse_sub)

    def __str__(self):
        s = "Name: %s" % self.name + "\n"
        s += "Cost: %0.2f" % self.cost + "\n"
        s += "Conditions: %s" % self.conditions + "\n"
        s += "Effects: %s" % self.effects + "\n"
        return s

    def __repr__(self):
        return str(self.name)


if __name__ == "__main__":

    from py_plan.pattern_matching import build_index

    kb = [('A'), ('B'), ('C')]
    q = [('A'), ('B')]

    index = build_index(kb)

    o = Operator("test", q, [])
    print(o)
    for m in o.match(index):
        print("MATCH FOUND", m)
예제 #7
0
def generate_add_constraints(add_effects, negative_goals):
    return [
        or_constraints([(ne, match[v], v) for v in match])
        for e in negative_goals
        for match in pattern_match([e], build_index(add_effects), {})
    ]
예제 #8
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)
예제 #9
0
 def goal_test(self, node, goal):
     index = build_index(node.state)
     for m in pattern_match(goal.state, index, {}):
         return True
     return False
예제 #10
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)