Пример #1
0
def new_rule(atomspace, action_str, pre_str, post_str):
    action_l = action_str.split()
    action = actions[action_l[0]]

    vars = {}
    for v_str in action_l[1:]:
        vars[v_str] = atomspace.add(t.VariableNode, v_str)

    preconditions = parse_conditions_list(vars, pre_str)
    preconditions.append(actionDone_template(atomspace, action_template(action, parse_params(vars, action_l))))

    postconditions = parse_conditions_list(vars, post_str)

    pil = T('PredictiveImplicationLink',
        T('SimultaneousAndLink',
            preconditions
        ),
        T('SimultaneousAndLink',
            postconditions
        )
    )
    atom_from_tree(pil, atomspace).tv = TruthValue(1, confidence_to_count(1))

    print pil
    return pil
Пример #2
0
def crispModusPonensFormula(tvs):
    (sAB, nAB), (sA, nA) = tv_seq_to_tv_tuple_seq(tvs)

    true = 0.5
    if all(x >= true for x in [sAB, nAB, sA, nA]):
        return [TruthValue(1, confidence_to_count(0.99))]
    else:
        return [TruthValue(0, 0)]
Пример #3
0
def crispModusPonensFormula(tvs):
    (sAB, nAB), (sA, nA) = tv_seq_to_tv_tuple_seq(tvs)

    true = 0.5
    if all(x >= true for x in [sAB, nAB, sA, nA]):
        return [TruthValue(1, confidence_to_count(0.99))]
    else:
        return [TruthValue(0, 0)]
Пример #4
0
def crispModusPonensFormula(tvs, U):
    (sAB, nAB), (sA, nA) = tvs

    true = 0.1
    if all(x > true for x in [sAB, nAB, sA, nA]):
        return (1, confidence_to_count(1))
    else:
        return (0, 0)
Пример #5
0
def planning_rules(atomspace):
    '''A bunch of dubious hacks for using PLN as a STRIPS-style planner. Which isn't a great idea anyway'''
    rules = []
    # Used by planning. An ExecutionLink indicates an action being performed, so we can
    # assume that the action will be performed as part of the plan (i.e. if any action
    # occurs in the plan, set the TV to full probability and confidence).
    #r = Rule(T('ExecutionLink', 1, 2),
    #                   [],
    #                   name = 'PerformAction',
    #                   tv = TruthValue(1.0,confidence_to_count(1.0)))
    #rules.append(r)
    # TOdo this should be actionSuccess not just actionDone
    r = Rule(actionDone_template(atomspace),
                [],
                name = 'PerformAction',
                tv = TruthValue(1.0,confidence_to_count(1.0)))
    rules.append(r)
    
    # If something is true at the current time, you can use it as the start of the plan.
    # First find the latest time (hack)
    current_time = 0
    for time in atomspace.get_atoms_by_type(t.TimeNode):
        timestamp = int(time.name)
        if timestamp > current_time:
            current_time = timestamp
    current_time_node = atomspace.add(t.TimeNode, str(current_time))
    # Then create the Rule
    # It's essential to store the template so it will have the same variables in both
    # the head and the goal
    template = evaluation_link_template()
    r = Rule(template,
                [T('AtTimeLink', current_time_node, template)],
                name = 'AtCurrentTime'
                )
    rules.append(r)
    
    # A hacky rule for determining SequentialAndLinks. It doesn't check that the things
    # happen after each other. It's just intended to find results from the PerformAction
    # or AtCurrentTime rules.
    type = 'SequentialAndLink'
    for size in xrange(10):
        args = [new_var() for i in xrange(size+1)]
        rules.append(Rule(T(type, args),
                           args,
                           type[:-4], 
                           formula = formulas.andSymmetricFormula))

    # A hacky rule for determining SimultaneousAndlinks.
    type = 'SimultaneousAndLink'
    for size in xrange(11):
        args = [new_var() for i in xrange(size+1)]
        rules.append(Rule(T(type, args),
            args,
            type[:-4],
            formula = formulas.andSymmetricFormula))


    return rules
Пример #6
0
def andSymmetricFormula(tvs, U):
    total_strength = 1.0
    total_confidence = 1.0
    
    for (s, n) in tvs:
        total_strength *= s
        total_confidence *= count_to_confidence(n)
    
    return (total_strength, confidence_to_count(total_confidence))
Пример #7
0
def andSymmetricFormula(tvs):
    total_strength = 1.0
    total_confidence = 1.0
    
    for tv in tvs:
        total_strength *= tv.mean
        total_confidence *= count_to_confidence(tv.count)
    
    return [TruthValue(total_strength, confidence_to_count(total_confidence))]
Пример #8
0
def andSymmetricFormula(tvs):
    total_strength = 1.0
    total_confidence = 1.0

    for tv in tvs:
        total_strength *= tv.mean
        total_confidence *= count_to_confidence(tv.count)

    return [TruthValue(total_strength, confidence_to_count(total_confidence))]
Пример #9
0
def do_planning(space, target):
    a = space

    rl = T('ReferenceLink',
           a.add_node(t.ConceptNode, 'plan_selected_demand_goal'), target)
    atom_from_tree(rl, a)

    # hack
    print 'target'
    target_a = atom_from_tree(target, a)
    print target_a
    print target_a.tv
    target_a.tv = TruthValue(0, 0)
    print target_a

    chainer = Chainer(a, planning_mode=True)

    result_atoms = chainer.bc(target, 2000)

    print "planning result: ", result_atoms

    if result_atoms:
        res_Handle = result_atoms[0]
        res = tree_from_atom(Atom(res_Handle, a))

        trail = chainer.trail(res)
        actions = chainer.extract_plan(trail)

        # set plan_success
        ps = T('EvaluationLink', a.add_node(t.PredicateNode, 'plan_success'),
               T('ListLink'))
        # set plan_action_list
        pal = T('ReferenceLink', a.add_node(t.ConceptNode, 'plan_action_list'),
                T('ListLink', actions))

        ps_a = atom_from_tree(ps, a)
        pal_a = atom_from_tree(pal, a)

        print ps
        print pal
        ps_a.tv = TruthValue(1.0, confidence_to_count(1.0))

        print ps_a.tv

    return result_atoms
Пример #10
0
    def create_ASSOC(concept):
        # ASSOC(x, concept) = [Subset x concept - Subset(Not x, concept)]+

        assoc_name = 'ASSOC(%s)' % (concept.op.name,)
        assoc_node = space.add_node(t.ConceptNode, assoc_name)

        template = T('SubsetLink', new_var(), concept)
        trees_tvs = match_wrapper(space, template, match_axiom)

        # for each x that is a subset of concept
        has_any_members = False
        for (tr, tv) in trees_tvs:
            #print tr, tv
            x = tr.args[0]
            if x.get_type() != t.ConceptNode:
                continue
            # Now find Subset(Not x, concept)
            template_not = T('SubsetLink',
                T('NotLink', x),
                concept
            )
            not_candidates = match_wrapper(space, template_not, match_axiom)
            #print not_candidates
            assert len(not_candidates) < 2
            if len(not_candidates) == 0:
                print 'missing link',template_not
                continue

            (_, tv_not) = not_candidates[0]
            assoc_strength = tv.mean - tv_not.mean

            # TODO obviously we're fudging the confidence values here
            if assoc_strength > 0:
                mem_tr = T('MemberLink',
                    x,
                    assoc_node
                )
                mem_link = atom_from_tree(mem_tr, space)
                mem_link.tv = TruthValue(assoc_strength, confidence_to_count(1.0))
                print mem_link
                has_any_members = True

        #assert has_any_members

        return T(assoc_node)
Пример #11
0
def do_planning(space, target):
    a = space

    rl = T('ReferenceLink', a.add_node(t.ConceptNode, 'plan_selected_demand_goal'), target)
    atom_from_tree(rl, a)
    
    # hack
    print 'target'
    target_a = atom_from_tree(target, a)
    print target_a
    print target_a.tv
    target_a.tv = TruthValue(0,  0)
    print target_a
    
    chainer = Chainer(a, planning_mode = True)        

    result_atoms = chainer.bc(target, 2000)
    
    print "planning result: ",  result_atoms
    
    if result_atoms:
        res_Handle = result_atoms[0]
        res = tree_from_atom(Atom(res_Handle, a))
        
        trail = chainer.trail(res)
        actions = chainer.extract_plan(trail)
        
        # set plan_success
        ps = T('EvaluationLink', a.add_node(t.PredicateNode, 'plan_success'), T('ListLink'))
        # set plan_action_list
        pal = T('ReferenceLink',
                    a.add_node(t.ConceptNode, 'plan_action_list'),
                    T('ListLink', actions))
        
        ps_a  = atom_from_tree(ps, a)
        pal_a = atom_from_tree(pal, a)
        
        print ps
        print pal
        ps_a.tv = TruthValue(1.0, confidence_to_count(1.0))
        
        print ps_a.tv
    
    return result_atoms
Пример #12
0
def do_planning(space, target, chainer=None):
    a = space

    rl = T('ReferenceLink',
           a.add_node(t.ConceptNode, 'plan_selected_demand_goal'), target)
    atom_from_tree(rl, a)

    # hack
    print 'target'
    target_a = atom_from_tree(target, a)
    print target_a
    print target_a.tv
    target_a.tv = TruthValue(0, 0)
    print target_a

    if chainer is None:
        chainer = Chainer(a, planning_mode=True)

    result_atoms = chainer.bc(target, 5000)

    print "inference result: ", result_atoms

    for res in chainer.results:
        trail = chainer.trail(res)
        actions = chainer.extract_plan(trail)
        print actions

        # set plan_success
        ps = T('EvaluationLink', a.add_node(t.PredicateNode, 'plan_success'),
               T('ListLink'))
        # set plan_action_list (but you should also delete the previous one! or is that done in C++?)
        pal = T('ReferenceLink', a.add_node(t.ConceptNode, 'plan_action_list'),
                T('ListLink', actions))

        ps_a = atom_from_tree(ps, a)
        pal_a = atom_from_tree(pal, a)

        print ps
        print pal
        ps_a.tv = TruthValue(1.0, confidence_to_count(1.0))

        print ps_a.tv

    return result_atoms
Пример #13
0
def do_planning(space, target, chainer = None):
    a = space

    rl = T('ReferenceLink', a.add_node(t.ConceptNode, 'plan_selected_demand_goal'), target)
    atom_from_tree(rl, a)
    
    # hack
    print 'target'
    target_a = atom_from_tree(target, a)
    print target_a
    print target_a.tv
    target_a.tv = TruthValue(0,  0)
    print target_a
    
    if chainer is None:
        chainer = Chainer(a, planning_mode = True)

    result_atoms = chainer.bc(target, 5000)
    
    print "inference result: ",  result_atoms
    
    
    for res in chainer.results:
        trail = chainer.trail(res)
        actions = chainer.extract_plan(trail)
        print actions

        # set plan_success
        ps = T('EvaluationLink', a.add_node(t.PredicateNode, 'plan_success'), T('ListLink'))
        # set plan_action_list (but you should also delete the previous one! or is that done in C++?)
        pal = T('ReferenceLink',
                    a.add_node(t.ConceptNode, 'plan_action_list'),
                    T('ListLink', actions))
        
        ps_a  = atom_from_tree(ps, a)
        pal_a = atom_from_tree(pal, a)
        
        print ps
        print pal
        ps_a.tv = TruthValue(1.0, confidence_to_count(1.0))
        
        print ps_a.tv
    
    return result_atoms
Пример #14
0
def match_neighbors(space,target):
    print 'match_neighbors',target
    template = T('EvaluationLink',
                space.add(t.PredicateNode,'neighbor'),
                T('ListLink',
                    Var(1),
                    Var(2)
                )
     )
    s = unify(template, target, {})
    cube1 = s[Var(1)]
    
    #template = T('ImplicationLink',
    #    Var(2),
    #    Var(1)
    #)
    #s = unify(template, target, {})
    #cube1 = s[Var(1)]
    
    def get_coords(expr):
        name = expr.op.name
        tuple_str = name[3:]
        coords = tuple(map(int, tuple_str[1:-1].split(',')))
        return coords

    if cube1.is_variable() or not isinstance(cube1.op, Atom):
        return []
    (x,y,z) = get_coords(cube1)
    
    ns = [(x-1,y,z),(x+1,y,z),(x,y-1,z),(x,y+1,z)]
    # jumping onto a block
    ns += [(x,y,z+1) for n in ns]
    
    tv = TruthValue(1,confidence_to_count(1.0))
    candidates = []
    for n in ns:
        cube2 = Tree(space.add(t.ConceptNode, 'at %s' % str(n)))
        s = {Var(1):cube1, Var(2):cube2}
        cand = subst(s, template)
        candidates.append((cand,tv))

    return candidates
Пример #15
0
def match_neighbors(space,target):
    print 'match_neighbors',target
    template = T('EvaluationLink',
                space.add(t.PredicateNode,'neighbor'),
                T('ListLink',
                    Var(1),
                    Var(2)
                )
     )
    s = unify(template, target, {})
    cube1 = s[Var(1)]
    
    #template = T('ImplicationLink',
    #    Var(2),
    #    Var(1)
    #)
    #s = unify(template, target, {})
    #cube1 = s[Var(1)]
    
    def get_coords(expr):
        name = expr.op.name
        tuple_str = name[3:]
        coords = tuple(map(int, tuple_str[1:-1].split(',')))
        return coords

    if cube1.is_variable() or not isinstance(cube1.op, Atom):
        return []
    (x,y,z) = get_coords(cube1)
    
    ns = [(x-1,y,z),(x+1,y,z),(x,y-1,z),(x,y+1,z)]
    # jumping onto a block
    ns += [(x,y,z+1) for n in ns]
    
    tv = TruthValue(1,confidence_to_count(1.0))
    candidates = []
    for n in ns:
        cube2 = Tree(space.add(t.ConceptNode, 'at %s' % str(n)))
        s = {Var(1):cube1, Var(2):cube2}
        cand = subst(s, template)
        candidates.append((cand,tv))

    return candidates
Пример #16
0
def match_predicate(space,target):
    # Actually it would be much better to use the standard target for this rule
    # + unify to find the places
    #print 'match_predicate',target
    ll = target.args[1]
    #print ll
    (n1,n2,n3) = ll.args
    
    candidates = []
    if (n1.get_type() == t.NumberNode and n2.get_type() == t.NumberNode):
        if (n3.get_type() == t.NumberNode):
            if int(n1.op.name) + int(n2.op.name) == int(n3.op.name):
                candidates.append((target, TruthValue(1.0,confidence_to_count(1.0))))
        elif (n3.is_variable()):
            addition = int(n1.op.name) + int(n2.op.name)
            s = {n3: Tree(space.add(t.NumberNode,str(addition)))}
            c = subst(s, target)
            print '>>>match_predicate:c',c
            candidates.append((c, None))
    
    return candidates
Пример #17
0
def match_predicate(space,target):
    # Actually it would be much better to use the standard target for this rule
    # + unify to find the places
    #print 'match_predicate',target
    ll = target.args[1]
    #print ll
    (n1,n2,n3) = ll.args
    
    candidates = []
    if (n1.get_type() == t.NumberNode and n2.get_type() == t.NumberNode):
        if (n3.get_type() == t.NumberNode):
            if int(n1.op.name) + int(n2.op.name) == int(n3.op.name):
                candidates.append((target, TruthValue(1.0,confidence_to_count(1.0))))
        elif (n3.is_variable()):
            addition = int(n1.op.name) + int(n2.op.name)
            s = {n3: Tree(space.add(t.NumberNode,str(addition)))}
            c = subst(s, target)
            print '>>>match_predicate:c',c
            candidates.append((c, None))
    
    return candidates
Пример #18
0
def new_rule(atomspace, action_str, pre_str, post_str):
    action_l = action_str.split()
    action = actions[action_l[0]]

    vars = {}
    for v_str in action_l[1:]:
        vars[v_str] = atomspace.add(t.VariableNode, v_str)

    preconditions = parse_conditions_list(vars, pre_str)
    preconditions.append(
        actionDone_template(
            atomspace, action_template(action, parse_params(vars, action_l))))

    postconditions = parse_conditions_list(vars, post_str)

    pil = T('PredictiveImplicationLink', T('SimultaneousAndLink',
                                           preconditions),
            T('SimultaneousAndLink', postconditions))
    atom_from_tree(pil, atomspace).tv = TruthValue(1, confidence_to_count(1))

    print pil
    return pil
Пример #19
0
def blocksworld_rules(atomspace):
    for letter in 'ABC':
        blocks[letter] = atomspace.add(t.ObjectNode, 'movable_block_' + letter)

    for action_name in 'unstack stack pickup putdown start end'.split(' '):
        actions[action_name] = atomspace.add(t.SchemaNode, action_name)

    for predicate_name in 'clear on ontable handempty holding'.split(' '):
        predicates[predicate_name] = atomspace.add(t.PredicateNode,
                                                   predicate_name)


#    top = new_var()
#    bottom = new_var()
#
#    preconditions = [
#        evaluation_link_template(predicates['clear'],[top]),
#        evaluation_link_template(predicates['on'],[top, bottom]),
#        evaluation_link_template(predicates['handempty'],[])
#    ]
#    postconditions = [
#        evaluation_link_template(predicates['holding'],[top]),
#        evaluation_link_template(predicates['clear'],[bottom]),
#        # what?
#        not_template(evaluation_link_template(predicates['clear'],[top])),
#        not_template(evaluation_link_template(predicates['on'],[top, bottom])),
#        not_template(evaluation_link_template(predicates['handempty'],[]))
#    ]
#
#    pil = T('PredictiveImplicationLink',
#        T('SimultaneousAndLink',
#            preconditions,
#            actionDone_template(atomspace, action_template(actions['unstack'], [top, bottom]))
#        ),
#        T('SimultaneousAndLink',
#            postconditions
#        )
#    )
#    atom_from_tree(pil, atomspace)

#    new_rule([('clear',top), ('on',top, bottom), ('handempty')],
#             [('holding', top), ('clear', bottom), ('~clear', top), ('~on', top, bottom), ('~handempty')],
#             ('unstack', top, bottom)
#    )
#

#    new_rule([('holding',top), ('clear', bottom)],
#    [('on',top,bottom),('clear',top),('handempty'),('~holding',top),('~clear, bottom')],
#    ('stack',top, bottom)
#    )
    new_rule(
        atomspace, 'unstack top bottom',
        'clear top | on top bottom | handempty',
        'holding top | clear bottom | ~clear top | ~on top bottom | ~handempty'
    )

    new_rule(
        atomspace, 'stack top bottom', 'holding top | clear bottom',
        'on top bottom | clear top | handempty | ~holding top | ~clear bottom')

    new_rule(atomspace, 'pickup block',
             'ontable block | clear block | handempty',
             'holding block | ~ontable block | ~clear block | ~handempty')

    new_rule(atomspace, 'putdown block', 'holding block',
             'ontable block | clear block | handempty | ~holding block')

    initial_conditions_and = T(
        'SimultaneousAndLink',
        #parse_conditions_list(blocks, 'on C A | handempty | ontable A | ontable B | clear B | clear C')
        parse_conditions_list(
            blocks,
            'ontable C | handempty | ontable A | ontable B | clear B | clear C'
        ))
    atom = atom_from_tree(initial_conditions_and, atomspace)
    atom.tv = TruthValue(1, confidence_to_count(1))
Пример #20
0
def load_scm_file(a, filename):
    log.info("loading...")
    tree = Viz_Graph()
    ident_stack = []
    atom_stack = []
    root = None
    define_dict = { }
    try:
        f = open(filename, "r")
        for line_no, line in enumerate(f.readlines()):
            # code...
            ## parase scheme file line by line
            ## parase "define" 
            temp = line.strip('\n ()')
            if temp.startswith('define'):
                temp = temp.split(' ')
                define_dict[temp[1]] = temp[2]
                continue
                ##
            if line.startswith('('):
                if tree.number_of_nodes() > 0:
                # deal with previous segment
                    add_tree_to_atomspace(a, tree, root)
                    tree.clear()
                    #
                ident_stack[:] = []
                atom_stack[:] = []
                ## parase a new segment
            name = ""
            t = ""
            stv = None
            av = {}
            ident = line.find("(")
            if ident != -1:
                #log.debug(line.strip('\n'))
                ident_stack.append(ident)
                # the first: type name
                # the second: stv or av
                # the third: stv or av
                l = line
                line = line.strip(' ')
                line = line.strip('\n')
                elms = line.split('(')
                first = elms[1]
                try:
                    second = elms[2]
                    second = second.split(')')[0]
                    second = dict_sub(second, define_dict)
                except Exception:
                    second = None


                try:
                    third = elms[3]
                    third = third.split(')')[0]
                    third = dict_sub(third, define_dict)
                except Exception:
                    third = None
                    #log.debug("********************" )
                #log.debug("first:%s*"%first)
                #log.debug("second:%s*"%second)
                #log.debug("third:%s*"%third)
                #log.debug("********************" )
                if second:
                    second = second.strip()
                    if second.find("av") != -1:
                        temp = second.split(" ")
                        av['sti'] = float(temp[1])
                        av['lti'] = float(temp[2])
                        av['vlti'] = float(temp[3])
                    elif second.find("stv") != -1:
                        temp = second.split(" ")
                        mean = float(temp[1])
                        confidence = float(temp[2])
                        # the value to stv!
                        stv = TruthValue(mean,confidence_to_count(confidence))

                if third:
                    third = third.strip()
                    if third.find("av") != -1:
                        temp = third.split(" ")
                        av['sti'] = float(temp[1])
                        av['lti'] = float(temp[2])
                        av['vlti'] = float(temp[3])
                    elif third.find("stv") != -1:
                        temp = third.split(" ")
                        mean = float(temp[1])
                        confidence = float(temp[2])
                        # the value to stv!
                        stv = TruthValue(mean,confidence_to_count(confidence))
                try:
                    t = first[0:first.index(' ')]
                    name = first[first.index(' ') + 1: -1].strip('"')
                    #log.debug("**********atom**************" )
                    #log.debug("type: %s"%t+"*" )
                    #log.debug("name: %s"%name+"*")
                    #log.debug("stv: %s"%stv)
                    #log.debug("av: %s"%av)
                    #log.debug("*****************************" )
                except Exception:
                    t = first.strip(' ')
                    ## add nodes to segment tree
                is_node = True if name else False
                if is_node:
                    # node
                    try:
                        node = FakeAtom(name_type_dict[t], name, stv, av)
                    except KeyError:
                        log.error("Unknown Atom type '%s' in line %s, pls add related type infomation to file 'types_inheritance.py' and OpenCog"% (t,line_no))
                        raise KeyError
                    uni_node_id = tree.unique_id(name)
                    tree.add_node(uni_node_id, atom = node)
                    atom_stack.append(node)
                    if l.startswith('('):
                        root = uni_node_id
                else:
                    # link
                    uni_link_id = tree.unique_id(t)
                    #print "link:%s**"%t
                    try:
                        link = FakeAtom(name_type_dict[t], uni_link_id, stv, av)
                    except KeyError:
                        log.error("Unknown Atom type '%s' in line %s"% (t,line_no))
                        raise KeyError
                    atom_stack.append(link)
                    tree.add_node( uni_link_id, atom = link)
                    if l.startswith('('):
                        root = uni_link_id

                ## add an edge(between link and node, or link to sub_link) to the segment tree
                now = ident_stack[-1]
                for i, prev_ident in reversed(list(enumerate(ident_stack))):
                    if now > prev_ident:
                        ## the ith is parent, the link
                        if is_node:
                            log.debug("%s -> %s"%(atom_stack[i].name, uni_node_id))
                            tree.add_edge(atom_stack[i].name, uni_node_id)
                        else:
                            log.debug("%s -> %s"%(atom_stack[i].name, uni_link_id))
                            tree.add_edge(atom_stack[i].name, uni_link_id)
                            ## set the 'order' attribute
                        tree.get_node_attr(atom_stack[i].name).setdefault('order',-1)
                        tree.get_node_attr(atom_stack[i].name)['order'] += 1
                        order = tree.get_node_attr(atom_stack[i].name)['order']
                        if is_node:
                            tree.set_edge_attr(atom_stack[i].name, uni_node_id, order = order)
                        else:
                            tree.set_edge_attr(atom_stack[i].name, uni_link_id, order = order)
                        break

        ## deal with the last segment
        if tree.number_of_nodes() > 0:
            add_tree_to_atomspace(a, tree, root)
            tree.clear()
        log.info("loaded scm file sucessfully!" )
    except IOError:
        log.error("failed to read file %s "%filename )
        raise IOError
    else:
        f.close()
Пример #21
0
def blocksworld_rules(atomspace):
    for letter in 'ABC':
        blocks[letter] = atomspace.add(t.ObjectNode, 'movable_block_'+letter)

    for action_name in 'unstack stack pickup putdown start end'.split(' '):
        actions[action_name] = atomspace.add(t.SchemaNode, action_name)

    for predicate_name in 'clear on ontable handempty holding'.split(' '):
        predicates[predicate_name] = atomspace.add(t.PredicateNode,predicate_name)

#    top = new_var()
#    bottom = new_var()
#
#    preconditions = [
#        evaluation_link_template(predicates['clear'],[top]),
#        evaluation_link_template(predicates['on'],[top, bottom]),
#        evaluation_link_template(predicates['handempty'],[])
#    ]
#    postconditions = [
#        evaluation_link_template(predicates['holding'],[top]),
#        evaluation_link_template(predicates['clear'],[bottom]),
#        # what?
#        not_template(evaluation_link_template(predicates['clear'],[top])),
#        not_template(evaluation_link_template(predicates['on'],[top, bottom])),
#        not_template(evaluation_link_template(predicates['handempty'],[]))
#    ]
#
#    pil = T('PredictiveImplicationLink',
#        T('SimultaneousAndLink',
#            preconditions,
#            actionDone_template(atomspace, action_template(actions['unstack'], [top, bottom]))
#        ),
#        T('SimultaneousAndLink',
#            postconditions
#        )
#    )
#    atom_from_tree(pil, atomspace)

#    new_rule([('clear',top), ('on',top, bottom), ('handempty')],
#             [('holding', top), ('clear', bottom), ('~clear', top), ('~on', top, bottom), ('~handempty')],
#             ('unstack', top, bottom)
#    )
#

#    new_rule([('holding',top), ('clear', bottom)],
#    [('on',top,bottom),('clear',top),('handempty'),('~holding',top),('~clear, bottom')],
#    ('stack',top, bottom)
#    )
    new_rule(atomspace,
        'unstack top bottom',
        'clear top | on top bottom | handempty',
        'holding top | clear bottom | ~clear top | ~on top bottom | ~handempty'
    )

    new_rule(atomspace,
        'stack top bottom',
        'holding top | clear bottom',
        'on top bottom | clear top | handempty | ~holding top | ~clear bottom'
    )

    new_rule(atomspace,
        'pickup block',
        'ontable block | clear block | handempty',
        'holding block | ~ontable block | ~clear block | ~handempty'
    )

    new_rule(atomspace,
        'putdown block',
        'holding block',
        'ontable block | clear block | handempty | ~holding block'
    )

    initial_conditions_and = T('SimultaneousAndLink',
        #parse_conditions_list(blocks, 'on C A | handempty | ontable A | ontable B | clear B | clear C')
        parse_conditions_list(blocks, 'ontable C | handempty | ontable A | ontable B | clear B | clear C')
    )
    atom = atom_from_tree(initial_conditions_and, atomspace)
    atom.tv = TruthValue(1,confidence_to_count(1))
Пример #22
0
def load_scm_file(a, filename):
    log.info("loading...")
    tree = Viz_Graph()
    ident_stack = []
    atom_stack = []
    root = None
    define_dict = {}
    try:
        f = open(filename, "r")
        for line_no, line in enumerate(f.readlines()):
            # code...
            ## parase scheme file line by line
            ## parase "define"
            temp = line.strip('\n ()')
            if temp.startswith('define'):
                temp = temp.split(' ')
                define_dict[temp[1]] = temp[2]
                continue
                ##
            if line.startswith('('):
                if tree.number_of_nodes() > 0:
                    # deal with previous segment
                    add_tree_to_atomspace(a, tree, root)
                    tree.clear()
                    #
                ident_stack[:] = []
                atom_stack[:] = []
                ## parase a new segment
            name = ""
            t = ""
            stv = None
            av = {}
            ident = line.find("(")
            if ident != -1:
                #log.debug(line.strip('\n'))
                ident_stack.append(ident)
                # the first: type name
                # the second: stv or av
                # the third: stv or av
                l = line
                line = line.strip(' ')
                line = line.strip('\n')
                elms = line.split('(')
                first = elms[1]
                try:
                    second = elms[2]
                    second = second.split(')')[0]
                    second = dict_sub(second, define_dict)
                except Exception:
                    second = None

                try:
                    third = elms[3]
                    third = third.split(')')[0]
                    third = dict_sub(third, define_dict)
                except Exception:
                    third = None
                    #log.debug("********************" )
                #log.debug("first:%s*"%first)
                #log.debug("second:%s*"%second)
                #log.debug("third:%s*"%third)
                #log.debug("********************" )
                if second:
                    second = second.strip()
                    if second.find("av") != -1:
                        temp = second.split(" ")
                        av['sti'] = float(temp[1])
                        av['lti'] = float(temp[2])
                        av['vlti'] = float(temp[3])
                    elif second.find("stv") != -1:
                        temp = second.split(" ")
                        mean = float(temp[1])
                        confidence = float(temp[2])
                        # the value to stv!
                        stv = TruthValue(mean, confidence_to_count(confidence))

                if third:
                    third = third.strip()
                    if third.find("av") != -1:
                        temp = third.split(" ")
                        av['sti'] = float(temp[1])
                        av['lti'] = float(temp[2])
                        av['vlti'] = float(temp[3])
                    elif third.find("stv") != -1:
                        temp = third.split(" ")
                        mean = float(temp[1])
                        confidence = float(temp[2])
                        # the value to stv!
                        stv = TruthValue(mean, confidence_to_count(confidence))
                try:
                    t = first[0:first.index(' ')]
                    name = first[first.index(' ') + 1:-1].strip('"')
                    #log.debug("**********atom**************" )
                    #log.debug("type: %s"%t+"*" )
                    #log.debug("name: %s"%name+"*")
                    #log.debug("stv: %s"%stv)
                    #log.debug("av: %s"%av)
                    #log.debug("*****************************" )
                except Exception:
                    t = first.strip(' ')
                    ## add nodes to segment tree
                is_node = True if name else False
                if is_node:
                    # node
                    try:
                        node = FakeAtom(name_type_dict[t], name, stv, av)
                    except KeyError:
                        log.error(
                            "Unknown Atom type '%s' in line %s, pls add related type infomation to file 'types_inheritance.py' and OpenCog"
                            % (t, line_no))
                        raise KeyError
                    uni_node_id = tree.unique_id(name)
                    tree.add_node(uni_node_id, atom=node)
                    atom_stack.append(node)
                    if l.startswith('('):
                        root = uni_node_id
                else:
                    # link
                    uni_link_id = tree.unique_id(t)
                    #print "link:%s**"%t
                    try:
                        link = FakeAtom(name_type_dict[t], uni_link_id, stv,
                                        av)
                    except KeyError:
                        log.error("Unknown Atom type '%s' in line %s" %
                                  (t, line_no))
                        raise KeyError
                    atom_stack.append(link)
                    tree.add_node(uni_link_id, atom=link)
                    if l.startswith('('):
                        root = uni_link_id

                ## add an edge(between link and node, or link to sub_link) to the segment tree
                now = ident_stack[-1]
                for i, prev_ident in reversed(list(enumerate(ident_stack))):
                    if now > prev_ident:
                        ## the ith is parent, the link
                        if is_node:
                            log.debug("%s -> %s" %
                                      (atom_stack[i].name, uni_node_id))
                            tree.add_edge(atom_stack[i].name, uni_node_id)
                        else:
                            log.debug("%s -> %s" %
                                      (atom_stack[i].name, uni_link_id))
                            tree.add_edge(atom_stack[i].name, uni_link_id)
                            ## set the 'order' attribute
                        tree.get_node_attr(atom_stack[i].name).setdefault(
                            'order', -1)
                        tree.get_node_attr(atom_stack[i].name)['order'] += 1
                        order = tree.get_node_attr(atom_stack[i].name)['order']
                        if is_node:
                            tree.set_edge_attr(atom_stack[i].name,
                                               uni_node_id,
                                               order=order)
                        else:
                            tree.set_edge_attr(atom_stack[i].name,
                                               uni_link_id,
                                               order=order)
                        break

        ## deal with the last segment
        if tree.number_of_nodes() > 0:
            add_tree_to_atomspace(a, tree, root)
            tree.clear()
        log.info("loaded scm file sucessfully!")
    except IOError:
        log.error("failed to read file %s " % filename)
        raise IOError
    else:
        f.close()
Пример #23
0
def match_subset(space, target):

    A, B = target.args
    #compatible = ((A.get_type() == t.ConceptNode and B.get_type() == t.ConceptNode) or
    #             (A.get_type() == t.PredicateNode and B.get_type() == t.PredicateNode))
    #if not compatible:
    #    return []
    if A.is_variable() or B.is_variable():
        return []

    print A, B

    def members(concept):
        '''For each member of concept, return the node and the strength of membership'''
        template = T('MemberLink', new_var(), concept)
        trees_tvs = match_wrapper(space, template, match_axiom)

        mems = [(tr.args[0], tv.mean) for (tr, tv) in trees_tvs]
        assert not (mems is None)
        return mems

    def all_member_links():
        '''Find all ObjectNodes (or other nodes) that are members of any concept.
        Returns a set of nodes (each node is wrapped in the Tree class)'''
        template = T('MemberLink', new_var(), new_var())
        trees_tvs = match_wrapper(space, template, match_axiom)

        mems = set(tr.args[0] for (tr, tv) in trees_tvs)
        return mems

    def non_members(concept):
        # Find the members of Not(A).
        # For example if A is 'the set of cats', then Not(A) is 'the set of things that aren't cats'.
        # So for every entity E in the world, (MemberLink E Not(cat)).tv.mean == 1 - (MemberLink E cat).tv.mean.
        # If the latter is not recorded in the AtomSpace, just assume it is 0.

        # Find all objects/etc that are members of anything
        # type: set(Tree)
        everything = all_member_links()

        # the type of members_of_concept is [(concept,frequency)]
        members_of_concept = members(concept)
        membershipStrengths = {
            member: strength
            for (member, strength) in members_of_concept
        }

        result = []
        for object in everything:
            membershipStrength = 0
            if object in membershipStrengths:
                membershipStrength = membershipStrengths[object]
            nonMembershipStrength = 1 - membershipStrength
            result.append((object, nonMembershipStrength))

        return result

    def evals(concept):
        template = T('EvaluationLink', concept, T('ListLink', new_var()))
        trees_tvs = match_wrapper(space, template, match_axiom)

        mems = [(tr.args[1].args[0], tv.mean) for (tr, tv) in trees_tvs]
        return mems

    # Find the members of each concept
    # For single-argument predicates, this is the same as EvaluationLinks.
    # TODO: can't handle negated predicates in EvaluationLinks...
    # This means PredicateNodes can't be in IntensionalInheritanceLinks
    if A.get_type() == t.NotLink:
        # Members of Not(A)
        assert B.get_type() == t.ConceptNode
        memA = non_members(A)
        memB = members(B)
    else:
        # Members of A
        memA = members(A) + evals(A)
        memB = members(B) + evals(B)


#    memA = evals(A)
#    memB = evals(B)

    print memA
    print
    print memB

    # calculate P(x in B | x in A) = P(A^B) / P(A)
    # based on the fuzzy-weighted average
    #nodes_in_B = [m for (m,s) in memB]
    assert not (memB is None)
    nodesB = {member: strength for (member, strength) in memB}

    N_AB = 0
    for (mA, sA) in memA:
        if mA in nodesB:
            sB = nodesB[mA]

            # min is the definition of fuzzy-AND
            N_AB += min(sA, sB)

    #N_AB = sum(s for (m, s) in memA if m in nodes_in_B)
    N_A = sum(s for (m, s) in memA)
    if N_A > 0:
        P = N_AB * 1.0 / N_A
        tv = TruthValue(P, confidence_to_count(1.0))
    else:
        # If there are no items in A then conditional probability is not defined, so give a zero confidence
        tv = TruthValue(0, 0)

    return [(target, tv)]
Пример #24
0
def rules(a, deduction_types):
    '''This function sets up all the Rules available in PLN. The concept of a Rule is the same as
    in higher-order logic. For example, Modus Ponens requires an ImplicationLink $1->$2 as well as the
    premise of the ImplicationLink ($1) and will produce $2. Every Rule comes with its own formula
    for calculating TruthValues. PLN works by applying a series of Rules to some Atoms to create new
    ones.'''

    # This function creates a list of Rules using the Rule constructor.
    # See the Rule class for more explanation of the arguments used.
    # In every step of chaining, the backward chainer has a target Atom (usually with some variables)
    # it is trying to find. It will apply any Rule whose head unifies with the target.
    # The function is called every time a Chainer is constructed.
    rules = []

    #path_rules(a)

    # PLN is able to do pathfinding (experimental). In the Minecraft world, there is a 3D grid
    # similar to that used by A*. This Rule determines the grid squares (or rather grid cubes)
    # that are next to a specified grid cube (i.e. the neighborhood, in the A* sense).
    # You can represent the grid as a network of OpenCog links, which is more suitable for PLN
    # than having an array (and more versatile in general).
    # This version of the Rule calculates the neighborhood dynamically. The function path_rules()
    # uses the simpler but much slower approach of adding thousands of links to the AtomSpace in advance.
    r = Rule(
        T(
            'EvaluationLink',
            a.add(t.PredicateNode, 'neighbor'),
            T(
                'ListLink',
                Var(
                    1
                ),  # a ConceptNode representing the coordinates in a tacky format
                Var(2))),
        [],
        name='Neighbors',
        match=match_neighbors)
    rules.append(r)
    #r = Rule(T('ImplicationLink',
    #            Var(1),
    #            Var(2)
    #            ),
    #         [],
    #         name='Neighbors',
    #         match=match_neighbors)
    #rules.append(r)

    # You can add a separate Rule for every axiom (i.e. every Atom which has a TruthValue when PLN starts).
    # It won't add a new Rule for atoms that are created during the inference, rather they will be added to
    # the Proof DAG. It's simple to have a separate Rule for each axiom, but it's slow because the chainer
    # will try to unify a target against every axiom Rule.
    #for obj in a.get_atoms_by_type(t.Atom):
    #    # POLICY: Ignore all false things. This means you can never disprove something! But much more useful for planning!
    #    if obj.tv.count > 0 and obj.tv.mean > 0:
    #        tr = tree_from_atom(obj)
    #        # A variable with a TV could just prove anything; that's evil!
    #        if not tr.is_variable():
    #
    #            # tacky filter
    #            if 'CHUNK' in str(tr):
    #                continue
    #
    #            r = Rule(tr, [], '[axiom]', tv = obj.tv)
    #            rules.append(r)

    # Just lookup the rule rather than having separate rules. Would be faster
    # with a large number of atoms (i.e. more scalable). Some examples will break if
    # you use it due to bugs in the backward chainer.
    r = Rule(Var(123), [], name='Lookup', match=match_axiom_slow)
    rules.append(r)

    # A simple example Rule to test the mechanism. You're allowed to add a Rule which calls
    # any Python function to decide one of the Atoms. This one does the plus calculation.
    # The first two variables are the numbers to be added, and the third variable is the result.
    # i.e. the last variable is the return-value for the '+' function. This is a common pattern in
    # Prolog.
    r = Rule(T('EvaluationLink', a.add(t.PredicateNode, '+'),
               T('ListLink', Var(1), Var(2), Var(3))), [],
             name='PredicateEvaluation',
             match=match_predicate)
    rules.append(r)

    # The three main logical rules in PLN. The code creates different versions of the Rule
    # for different kinds of Links.
    # The classic Modus Ponens rule, used (and over-emphasized) in classical logic everywhere.
    for ty in ['ImplicationLink', 'PredictiveImplicationLink']:
        rules.append(
            Rule(Var(2), [T(ty, 1, 2), Var(1)],
                 name='ModusPonens ' + ty,
                 formula=formulas.modusPonensFormula))

    # The PLN DeductionRule. Not to be confused with ModusPonens.
    for type in deduction_types:
        rules.append(
            Rule(T(type, 1, 3),
                 [T(type, 1, 2),
                  T(type, 2, 3),
                  Var(1), Var(2),
                  Var(3)],
                 name='Deduction',
                 formula=formulas.deductionSimpleFormula))

    # PLN InversionRule, which reverses an ImplicationLink. It's based on Bayes' Theorem.
    for type in deduction_types:
        rules.append(
            Rule(T(type, 2, 1),
                 [T(type, 1, 2), Var(1), Var(2)],
                 name='Inversion',
                 formula=formulas.inversionFormula))

    # Calculating logical And/Or/Not. These have probabilities attached,
    # but they work similarly to the Boolean versions.
    type = 'AndLink'
    for size in xrange(5):
        args = [new_var() for i in xrange(size + 1)]
        rules.append(
            Rule(T(type, args),
                 args,
                 type[:-4],
                 formula=formulas.andSymmetricFormula))

    type = 'OrLink'
    for size in xrange(1, 2):
        args = [new_var() for i in xrange(size + 1)]
        rules.append(
            Rule(T(type, args), args, type[:-4], formula=formulas.orFormula))

    # Calculate (NotLink A) using A. There's currently no Rule to find A using (NotLink A)
    rules.append(
        Rule(T('NotLink', 1), [Var(1)],
             name='Not',
             formula=formulas.notFormula))

    # PLN's heuristic Rules to convert one kind of link to another. There are other
    # variations on this Rule defined in the PLN book, but not implemented yet.
    rules.append(
        Rule(T('InheritanceLink', 1, 2), [T('SubsetLink', 1, 2)],
             name='SubsetLink=>InheritanceLink',
             formula=formulas.ext2InhFormula))

    # Used by planning. An ExecutionLink indicates an action being performed, so we can
    # assume that the action will be performed as part of the plan (i.e. if any action
    # occurs in the plan, set the TV to full probability and confidence).
    #r = Rule(T('ExecutionLink', 1, 2),
    #                   [],
    #                   name = 'PerformAction',
    #                   tv = TruthValue(1.0,confidence_to_count(1.0)))
    #rules.append(r)
    # TOdo this should be actionSuccess not just actionDone
    r = Rule(actionDone_template(a), [],
             name='PerformAction',
             tv=TruthValue(1.0, confidence_to_count(1.0)))
    rules.append(r)

    # If something is true at the current time, you can use it as the start of the plan.
    # First find the latest time (hack)
    current_time = 0
    for time in a.get_atoms_by_type(t.TimeNode):
        timestamp = int(time.name)
        if timestamp > current_time:
            current_time = timestamp
    current_time_node = a.add(t.TimeNode, str(current_time))
    # Then create the Rule
    # It's essential to store the template so it will have the same variables in both
    # the head and the goal
    template = evaluation_link_template()
    r = Rule(template, [T('AtTimeLink', current_time_node, template)],
             name='AtCurrentTime')
    rules.append(r)

    #        # Producing ForAll/Bind/AverageLinks.
    #        for type in ['ForAllLink', 'BindLink', 'AverageLink']:
    #            rules.append(Rule(T(type, 1, 2),
    #                               [ Var(2) ],
    #                               name = type+' abstraction',
    #                               formula = formulas.identityFormula))

    # This may cause weirdness with things matching too eagerly...
    #       # Both of these rely on the policy that tree_from_atom replaces VariableNodes in the AtomSpace with the variables the tree class uses.
    #        fact = new_var()
    #        list_link = new_var()
    #        r = Rule(
    #                        fact,
    #                        [T('ForAllLink', list_link, fact )],
    #                        name = 'ForAll'
    #                    )
    #        r.tv = True
    #        rules.append(r)

    # If an Atom is available in an Average/ForAll quantifier, you want to be
    # able to produce the Atom itself and send it through the other steps of the
    # inference.
    for atom in a.get_atoms_by_type(t.AverageLink):
        # out[0] is the ListLink of VariableNodes, out[1] is the expression
        tr = tree_from_atom(atom.out[1])
        r = Rule(tr, [], name='Average')
        r.tv = atom.tv
        rules.append(r)

    for atom in a.get_atoms_by_type(t.ForAllLink):
        # out[0] is the ListLink of VariableNodes, out[1] is the expression
        tr = tree_from_atom(atom.out[1])
        r = Rule(tr, [], name='ForAll')
        r.tv = atom.tv
        rules.append(r)

    rules += temporal_rules(a)

    # Return every Rule specified above.
    return rules
Пример #25
0
def match_subset(space,target):

    A, B = target.args
    #compatible = ((A.get_type() == t.ConceptNode and B.get_type() == t.ConceptNode) or
    #             (A.get_type() == t.PredicateNode and B.get_type() == t.PredicateNode))
    #if not compatible:
    #    return []
    if A.is_variable() or B.is_variable():
        return []

    print A, B

    def members(concept):
        '''For each member of concept, return the node and the strength of membership'''
        template = T('MemberLink', new_var(), concept)
        trees_tvs = match_wrapper(space, template, match_axiom)

        mems = [(tr.args[0], tv.mean) for (tr, tv) in trees_tvs]
        assert not (mems is None)
        return mems

    def all_member_links():
        '''Find all ObjectNodes (or other nodes) that are members of any concept.
        Returns a set of nodes (each node is wrapped in the Tree class)'''
        template = T('MemberLink', new_var(), new_var())
        trees_tvs = match_wrapper(space, template, match_axiom)

        mems = set(tr.args[0] for (tr, tv) in trees_tvs)
        return mems

    def non_members(concept):
        # Find the members of Not(A).
        # For example if A is 'the set of cats', then Not(A) is 'the set of things that aren't cats'.
        # So for every entity E in the world, (MemberLink E Not(cat)).tv.mean == 1 - (MemberLink E cat).tv.mean.
        # If the latter is not recorded in the AtomSpace, just assume it is 0.

        # Find all objects/etc that are members of anything
        # type: set(Tree)
        everything = all_member_links()

        # the type of members_of_concept is [(concept,frequency)]
        members_of_concept = members(concept)
        membershipStrengths = {member:strength for (member, strength) in members_of_concept}

        result = []
        for object in everything:
            membershipStrength = 0
            if object in membershipStrengths:
                membershipStrength = membershipStrengths[object]
            nonMembershipStrength = 1 - membershipStrength
            result.append( (object,nonMembershipStrength) )

        return result

    def evals(concept):
        template = T(
            'EvaluationLink',
                concept,
                T('ListLink', new_var())
        )
        trees_tvs = match_wrapper(space, template, match_axiom)

        mems = [(tr.args[1].args[0], tv.mean) for (tr, tv) in trees_tvs]
        return mems

    # Find the members of each concept
    # For single-argument predicates, this is the same as EvaluationLinks.
    # TODO: can't handle negated predicates in EvaluationLinks...
    # This means PredicateNodes can't be in IntensionalInheritanceLinks
    if A.get_type() == t.NotLink:
        # Members of Not(A)
        assert B.get_type() == t.ConceptNode
        memA = non_members(A)
        memB = members(B)
    else:
        # Members of A
        memA = members(A) + evals(A)
        memB = members(B) + evals(B)
#    memA = evals(A)
#    memB = evals(B)

    print memA
    print
    print memB

    # calculate P(x in B | x in A) = P(A^B) / P(A)
    # based on the fuzzy-weighted average
    #nodes_in_B = [m for (m,s) in memB]
    assert not (memB is None)
    nodesB = {member:strength for (member,strength) in memB}

    N_AB = 0
    for (mA, sA) in memA:
        if mA in nodesB:
            sB = nodesB[mA]

            # min is the definition of fuzzy-AND
            N_AB += min(sA,sB)
    
    #N_AB = sum(s for (m, s) in memA if m in nodes_in_B)
    N_A = sum(s for (m, s) in memA)
    if N_A > 0:
        P = N_AB*1.0 / N_A
        tv = TruthValue(P, confidence_to_count(1.0))
    else:
        # If there are no items in A then conditional probability is not defined, so give a zero confidence
        tv = TruthValue(0,0)

    return [(target, tv)]
Пример #26
0
def rules(a, deduction_types):
    '''This function sets up all the Rules available in PLN. The concept of a Rule is the same as
    in higher-order logic. For example, Modus Ponens requires an ImplicationLink $1->$2 as well as the
    premise of the ImplicationLink ($1) and will produce $2. Every Rule comes with its own formula
    for calculating TruthValues. PLN works by applying a series of Rules to some Atoms to create new
    ones.'''
    
    # This function creates a list of Rules using the Rule constructor.
    # See the Rule class for more explanation of the arguments used.
    # In every step of chaining, the backward chainer has a target Atom (usually with some variables)
    # it is trying to find. It will apply any Rule whose head unifies with the target.
    # The function is called every time a Chainer is constructed.
    rules = []

    #path_rules(a)

    # PLN is able to do pathfinding (experimental). In the Minecraft world, there is a 3D grid
    # similar to that used by A*. This Rule determines the grid squares (or rather grid cubes)
    # that are next to a specified grid cube (i.e. the neighborhood, in the A* sense).
    # You can represent the grid as a network of OpenCog links, which is more suitable for PLN
    # than having an array (and more versatile in general).
    # This version of the Rule calculates the neighborhood dynamically. The function path_rules()
    # uses the simpler but much slower approach of adding thousands of links to the AtomSpace in advance.
    r = Rule(T('EvaluationLink',
                a.add(t.PredicateNode,'neighbor'),
                T('ListLink',
                    Var(1), # a ConceptNode representing the coordinates in a tacky format
                    Var(2)
                )),
             [],
             name='Neighbors',
             match=match_neighbors)
    rules.append(r)
    #r = Rule(T('ImplicationLink',
    #            Var(1),
    #            Var(2)
    #            ),
    #         [],
    #         name='Neighbors',
    #         match=match_neighbors)
    #rules.append(r)

    # You can add a separate Rule for every axiom (i.e. every Atom which has a TruthValue when PLN starts).
    # It won't add a new Rule for atoms that are created during the inference, rather they will be added to
    # the Proof DAG. It's simple to have a separate Rule for each axiom, but it's slow because the chainer
    # will try to unify a target against every axiom Rule.
    #for obj in a.get_atoms_by_type(t.Atom):
    #    # POLICY: Ignore all false things. This means you can never disprove something! But much more useful for planning!
    #    if obj.tv.count > 0 and obj.tv.mean > 0:
    #        tr = tree_from_atom(obj)
    #        # A variable with a TV could just prove anything; that's evil!
    #        if not tr.is_variable():
    #            
    #            # tacky filter
    #            if 'CHUNK' in str(tr):
    #                continue
    #            
    #            r = Rule(tr, [], '[axiom]', tv = obj.tv)
    #            rules.append(r)

    # Just lookup the rule rather than having separate rules. Would be faster
    # with a large number of atoms (i.e. more scalable). Some examples will break if
    # you use it due to bugs in the backward chainer.
    r = Rule(Var(123),[],
                      name='Lookup',
                      match=match_axiom_slow)
    rules.append(r)

    # A simple example Rule to test the mechanism. You're allowed to add a Rule which calls
    # any Python function to decide one of the Atoms. This one does the plus calculation.
    # The first two variables are the numbers to be added, and the third variable is the result.
    # i.e. the last variable is the return-value for the '+' function. This is a common pattern in
    # Prolog.
    r = Rule(T('EvaluationLink',
               a.add(t.PredicateNode,'+'),
               T('ListLink',
                 Var(1),
                 Var(2),
                 Var(3))),
             [],
             name='PredicateEvaluation',
             match=match_predicate)
    rules.append(r)

    # The three main logical rules in PLN. The code creates different versions of the Rule
    # for different kinds of Links.
    # The classic Modus Ponens rule, used (and over-emphasized) in classical logic everywhere.
    for ty in ['ImplicationLink', 'PredictiveImplicationLink']:
        rules.append(Rule(Var(2), 
                                     [T(ty, 1, 2),
                                      Var(1) ], 
                                      name='ModusPonens '+ty,
                                      formula = formulas.modusPonensFormula))
    
    # The PLN DeductionRule. Not to be confused with ModusPonens.
    for type in deduction_types:
        rules.append(Rule(T(type, 1,3), 
                                     [T(type, 1, 2),
                                      T(type, 2, 3), 
                                      Var(1),
                                      Var(2), 
                                      Var(3)],
                                    name='Deduction', 
                                    formula = formulas.deductionSimpleFormula))
    
    # PLN InversionRule, which reverses an ImplicationLink. It's based on Bayes' Theorem.
    for type in deduction_types:
        rules.append(Rule( T(type, 2, 1), 
                                     [T(type, 1, 2),
                                      Var(1),
                                      Var(2)], 
                                     name='Inversion', 
                                     formula = formulas.inversionFormula))

    # Calculating logical And/Or/Not. These have probabilities attached,
    # but they work similarly to the Boolean versions.
    type = 'AndLink'
    for size in xrange(5):                
        args = [new_var() for i in xrange(size+1)]
        rules.append(Rule(T(type, args),
                           args,
                           type[:-4], 
                           formula = formulas.andSymmetricFormula))
    
    type = 'OrLink'
    for size in xrange(1,2):
        args = [new_var() for i in xrange(size+1)]
        rules.append(Rule(T(type, args),
                           args,
                           type[:-4], 
                           formula = formulas.orFormula))
    
    # Calculate (NotLink A) using A. There's currently no Rule to find A using (NotLink A)
    rules.append(Rule(T('NotLink', 1),
                       [ Var(1) ],
                       name = 'Not', 
                       formula = formulas.notFormula))
    
    # PLN's heuristic Rules to convert one kind of link to another. There are other
    # variations on this Rule defined in the PLN book, but not implemented yet.
    rules.append(Rule(T('InheritanceLink', 1, 2),
                       [ T('SubsetLink', 1, 2) ],
                       name = 'SubsetLink=>InheritanceLink', 
                       formula = formulas.ext2InhFormula))

    # Used by planning. An ExecutionLink indicates an action being performed, so we can
    # assume that the action will be performed as part of the plan (i.e. if any action
    # occurs in the plan, set the TV to full probability and confidence).
    #r = Rule(T('ExecutionLink', 1, 2),
    #                   [],
    #                   name = 'PerformAction',
    #                   tv = TruthValue(1.0,confidence_to_count(1.0)))
    #rules.append(r)
    # TOdo this should be actionSuccess not just actionDone
    r = Rule(actionDone_template(a),
                [],
                name = 'PerformAction',
                tv = TruthValue(1.0,confidence_to_count(1.0)))
    rules.append(r)
    
    # If something is true at the current time, you can use it as the start of the plan.
    # First find the latest time (hack)
    current_time = 0
    for time in a.get_atoms_by_type(t.TimeNode):
        timestamp = int(time.name)
        if timestamp > current_time:
            current_time = timestamp
    current_time_node = a.add(t.TimeNode, str(current_time))
    # Then create the Rule
    # It's essential to store the template so it will have the same variables in both
    # the head and the goal
    template = evaluation_link_template()
    r = Rule(template,
                [T('AtTimeLink', current_time_node, template)],
                name = 'AtCurrentTime'
                )
    rules.append(r)

#        # Producing ForAll/Bind/AverageLinks.
#        for type in ['ForAllLink', 'BindLink', 'AverageLink']:
#            rules.append(Rule(T(type, 1, 2),
#                               [ Var(2) ],
#                               name = type+' abstraction', 
#                               formula = formulas.identityFormula))

    # This may cause weirdness with things matching too eagerly...
#       # Both of these rely on the policy that tree_from_atom replaces VariableNodes in the AtomSpace with the variables the tree class uses.
#        fact = new_var()
#        list_link = new_var()
#        r = Rule(
#                        fact,
#                        [T('ForAllLink', list_link, fact )], 
#                        name = 'ForAll'     
#                    )
#        r.tv = True
#        rules.append(r)

    # If an Atom is available in an Average/ForAll quantifier, you want to be
    # able to produce the Atom itself and send it through the other steps of the
    # inference.
    for atom in a.get_atoms_by_type(t.AverageLink):
        # out[0] is the ListLink of VariableNodes, out[1] is the expression
        tr = tree_from_atom(atom.out[1])
        r = Rule(tr, [], name='Average')
        r.tv = atom.tv
        rules.append(r)

    for atom in a.get_atoms_by_type(t.ForAllLink):
        # out[0] is the ListLink of VariableNodes, out[1] is the expression
        tr = tree_from_atom(atom.out[1])
        r = Rule(tr, [], name='ForAll')
        r.tv = atom.tv
        rules.append(r)

    rules += temporal_rules(a)

    # Return every Rule specified above.
    return rules