def hasBuiltins(self): from builtins import builtinp, funcBuiltinp """Return True if I have builtins connected to me, otherwise False. Also set a pointer to the builtins""" # If left and right are builtins, they will have the same input node (does this hold for func. builtins, too?) if builtinp(self.lnode): self.builtinInput = self.lnode.getInputNode() if builtinp(self.rnode): self.builtinInput = self.rnode.getInputNode() return bool(self.builtinInput)
def makeBetaNetwork(self, rule, betaNode, alphaNodeList): """I have more than 2 alpha nodes and so I make a network""" length = len(alphaNodeList) if length == 0: betaNode.rule = self.makeRuleNode(rule) betaNode.rule.betaNode = betaNode else: alpha = alphaNodeList[0] betaChild = self.makeBetaNode(betaNode, alpha) # connect our newly created BetaNode to its parent BetaNode, # and connect the parent to its child betaChild.parents = [betaNode] betaNode.children = [betaChild] sharedJoinVars = self.getSharedVars(betaNode, alpha) sortVars(sharedJoinVars) if not builtinp(alpha): # adjust our beta node shared variables betaNode.svars = sharedJoinVars # Our betanode has children, and so set up our # pattern in an order that is conducive to the children JOINs betaNode.pattern = removedups(sharedJoinVars + betaNode.pattern) # connect our AlphaNode to its relevant BetaNode alpha.betaNodes = [betaChild] self.rete.betaNodeStore.addNode(betaNode) self.rete.betaNodeStore.addNode(betaChild) alphaNodeList = alphaNodeList[1:] return self.makeBetaNetwork(rule, betaChild, alphaNodeList)
def __init__(self, lnode, rnode): from builtins import builtinp self.lnode = lnode self.rnode = rnode #####Make this opaque if isinstance(lnode, BetaNode): self.lvars = lnode.pattern elif isinstance(lnode, AlphaNode): self.lvars = lnode.vars self.rvars = rnode.vars # Detect builtins if isinstance(rnode, AlphaNode): if builtinp(self.rnode): self.svars = lnode.svars else: # store svars in lexical order self.svars = [v for v in self.lvars if v in self.rvars] else: self.svars = [v for v in self.lvars if v in self.rvars] sortVars(self.svars) #destructively sort vars self.parents = list() self.children = list() self.pattern = removedups(self.svars + self.lvars + self.rvars) # Redundant var, will be refactored out self.vars = self.pattern self.builtinInput = None self.ind = Memory() self.inferredFacts = Set() # a pointer to the rule node (which contains the rhs) self.rule = None
def addNode(self, node): from builtins import builtinp if node not in self.nodes: self.nodes.append(node) # Only index the non-builtins for sorting (since we want to make sure # builtins appear at the end if not builtinp(node) and not isListVarNode(node): for v in node.vars: if v not in self.sharedIndex: self.sharedIndex[v] = [node] else: self.sharedIndex[v].append(node)
def sort(self): self.generateDependencies() from builtins import builtinp builtins = list() for node in self.nodes: if builtinp(node): builtins.append(node) builtins = removedups(builtins) # for nodes with pattern like (_:exivar FIRST ?x) we want to make sure ?x's are bound when joining, #so add them at the end (like builtins) listVarNodes = [ node for node in self.nodes if node.pattern.p in [FIRST, REST, INCLUDES, TYPE, SEMANTICS] ] listVarNodes = removedups(listVarNodes) nonBuiltins = [x for x in self.nodes if x not in builtins] nonBuiltins = [x for x in nonBuiltins if x not in listVarNodes] # Sort the non-builtin alphas so that nodes that share variables (if any) # are adjacent sortedNonBuiltins = list() for nb in nonBuiltins: for v in nb.vars: nodesThatShare = self.sharedIndex.get(v) if nodesThatShare: sortedNonBuiltins.extend(nodesThatShare) sortedNonBuiltins.append(nb) # If there were any nodes that shared variables, use the sorted list of nodes if sortedNonBuiltins: nonBuiltins = removedups(sortedNonBuiltins) #only sort builtins and list nodes (rdf:first, rest, etc.) #the other nodes should come first unsortedNodes = removedups(builtins + listVarNodes) # make full topological sort self.nodes = removedups(nonBuiltins + self.topSort(unsortedNodes, [])) """
def sort(self): self.generateDependencies() from builtins import builtinp builtins = list() for node in self.nodes: if builtinp(node): builtins.append(node) builtins = removedups(builtins) # for nodes with pattern like (_:exivar FIRST ?x) we want to make sure ?x's are bound when joining, #so add them at the end (like builtins) listVarNodes = [node for node in self.nodes if node.pattern.p in [FIRST, REST, INCLUDES, TYPE, SEMANTICS]] listVarNodes = removedups(listVarNodes) nonBuiltins = [x for x in self.nodes if x not in builtins] nonBuiltins = [x for x in nonBuiltins if x not in listVarNodes] # Sort the non-builtin alphas so that nodes that share variables (if any) # are adjacent sortedNonBuiltins = list() for nb in nonBuiltins: for v in nb.vars: nodesThatShare = self.sharedIndex.get(v) if nodesThatShare: sortedNonBuiltins.extend(nodesThatShare) sortedNonBuiltins.append(nb) # If there were any nodes that shared variables, use the sorted list of nodes if sortedNonBuiltins: nonBuiltins = removedups(sortedNonBuiltins) #only sort builtins and list nodes (rdf:first, rest, etc.) #the other nodes should come first unsortedNodes = removedups(builtins + listVarNodes) # make full topological sort self.nodes = removedups(nonBuiltins + self.topSort(unsortedNodes, [])) """
def join(self, useBindings=False): """ print "\n\n" print "self key:", self.getkey() print "join left:", self.lnode.pattern #for row in keysToList(self.lnode.ind): # print "left row",row[0] print "memory size of left node:", len(keysToList(self.lnode.ind)) print "left key:", self.lnode.getkey() print "" print "join right:", self.rnode.pattern # for row in keysToList(self.rnode.ind): # print "right row",row[0] print "memory size of right node:", len(keysToList(self.rnode.ind)) print "right key:", self.rnode.getkey() switched = False t = time.time() if len(keysToList(self.rnode.ind)) < len(keysToList(self.lnode.ind)): print "switched" switched = True print "keysToList time:", time.time() - t """ from builtins import builtinp if self.lnode == self.rnode: from builtins import builtinp, funcBuiltinp if builtinp(self.lnode): self.builtinInput = self.lnode.getInputNode() #problem is, here builtin input is empty return self.evalBuiltins(returnBindings=useBindings) else: self.pattern = self.lnode.vars if self.lnode.ind: return keysToList(self.lnode.ind) else: return [] elif self.hasBuiltins(): return self.evalBuiltins(returnBindings=useBindings) else: #right node is always an alpha node, #left one is an alphanode in the first join, beta node aftewards #compare the memory of both nodes, we want the smaller one to the left # if isListVarNode(self.rnode): rows = keysToList(self.lnode.ind) for row in rows: row = row[0] #print "rows:", row #print "left node key:", self.lnode.getkey() #left node key does not correspond to the bindings #bindings = self.lnode.getbindings(row) #get the bindings according to its own key, above line didnt work bindings = dict() key = self.getkey() try: for i, v in enumerate(key): bindings[v] = row[i] except: print "bindings=%s" % bindings print "row=%s" % row print "v=%s" % v print "i=%s" % i raise #copy the values for the variable in pattern.o if self.rnode.pattern.o in bindings: #copy it back to the original node - easiest way is to add it as a fact #also add bindings for the bnodes in subj for var in self.rnode.vars: if isinstance(var, Exivar): self.rnode.add( Fact(convertBNodeToFact(var), self.rnode.pattern.p, bindings[self.rnode.pattern.o])) #print "fact added:",convertBNodeToFact(var), self.rnode.pattern.p, bindings[self.rnode.pattern.o] elif isinstance(self.rnode.pattern.s, Exivar): print "something wrong happened - %s was supposed to be bound", self.rnode.pattern.s if isinstance(self.lnode, AlphaNode): key = self.lnode.svars elif isinstance(self.lnode, BetaNode): if not Set(self.lnode.vars).intersection(Set(self.rnode.vars)): key = list() else: #regenerate key here? was using self.svars before but was buggy key = self.getSharedVars(self.lnode, self.rnode) joinResults = list() if not key: #no shared variables and no matched values, so store and return the union #of the two memories """if switched: leftMemory = keysToList(self.rnode.ind) rightMemory = keysToList(self.lnode.ind) else:""" leftMemory = keysToList(self.lnode.ind) rightMemory = keysToList(self.rnode.ind) for lm, ljust in leftMemory: for rm, rjust in rightMemory: """if switched: row = rm + lm else:""" row = lm + rm joinResults.append([row, []]) ####NOTE -- Need to add justification (proof tracing) for this case self.add(row, []) else: t = time.time() """if switched: joinResults = self.joinhelper(self.rnode.ind, self.lnode.ind, key, [], [], switched) else:""" joinResults = self.joinhelper(self.lnode.ind, self.rnode.ind, key, [], []) print "joinhelper time:", time.time() - t return joinResults
def evalBuiltins(self, returnBindings=False): t = time.time() """I evaluate my attached builtins nodes.""" from builtins import builtinp, funcBuiltinp #Three cases to handle: left is a builtin and right is a plain anode, #left is a plain anode and right is a builtin, or both the left #and right are builtins evaldRows = list() builtinNodes = list() if builtinp(self.lnode): builtinNodes.append(self.lnode) if builtinp(self.rnode): builtinNodes.append(self.rnode) for bi in builtinNodes: inputNode = bi.getInputNode() builtinInput = keysToList(inputNode.ind) for row in builtinInput: row = row[0] #Needed since row[1] is the justification set #print row #print bi.pattern bindings = inputNode.getbindings(row, useBuiltin=bi) #need to check and substitute bi.pattern.s and bi.pattern.o for possible bindings here #check and substitute if subj or obj are lists, they also might have variables in the lists subjInput = convertBNodeToFact(bi.pattern.s) objInput = convertBNodeToFact(bi.pattern.o) if isinstance(bi.pattern.s, Variable): if bi.pattern.s in bindings: subjInput = convertBNodeToFact(bindings[bi.pattern.s]) if isinstance(bi.pattern.o, Variable): if bi.pattern.o in bindings: objInput = convertBNodeToFact(bindings[bi.pattern.o]) if subjInput in py_lists: subjInput = [ self.bindPossibleVar(x, bindings) for x in py_lists[subjInput] ] if objInput in py_lists: objInput = [ self.bindPossibleVar(x, bindings) for x in py_lists[objInput] ] # print "builtin", bi, subjInput, objInput result = bi.evaluate(subjInput, objInput) if result: #hack: append the bindings if it's log:includes if bi.pattern.p == INCLUDES: bindings[bi.pattern.s] = subjInput bindings[bi.pattern.o] = objInput row.append(subjInput) row.append(objInput) #a bit inefficient if returnBindings: evaldRows.append(bindings) else: evaldRows.append([row, []]) #Empty justification for now #add to memory -- ##NOTE: Need to add justification (proof tracing) for data resulting ##from builtins #print "row after bindings", row #if it's a functional builtin, it's different - need to return result and store in memory if funcBuiltinp(self.lnode) or funcBuiltinp(self.rnode): #have no idea why it works row.append(result) #print "row added in evalbuiltins:", row #add this fact self.add(row) #print "___row:", row else: #print "___row:", row self.add(row) #print "evaldRows:", evaldRows print "evalBultins time:", time.time() - t return evaldRows
def join(self, useBindings=False): """ print "\n\n" print "self key:", self.getkey() print "join left:", self.lnode.pattern #for row in keysToList(self.lnode.ind): # print "left row",row[0] print "memory size of left node:", len(keysToList(self.lnode.ind)) print "left key:", self.lnode.getkey() print "" print "join right:", self.rnode.pattern # for row in keysToList(self.rnode.ind): # print "right row",row[0] print "memory size of right node:", len(keysToList(self.rnode.ind)) print "right key:", self.rnode.getkey() switched = False t = time.time() if len(keysToList(self.rnode.ind)) < len(keysToList(self.lnode.ind)): print "switched" switched = True print "keysToList time:", time.time() - t """ from builtins import builtinp if self.lnode == self.rnode: from builtins import builtinp, funcBuiltinp if builtinp(self.lnode): self.builtinInput = self.lnode.getInputNode() #problem is, here builtin input is empty return self.evalBuiltins(returnBindings=useBindings) else: self.pattern = self.lnode.vars if self.lnode.ind: return keysToList(self.lnode.ind) else: return [] elif self.hasBuiltins(): return self.evalBuiltins(returnBindings=useBindings) else: #right node is always an alpha node, #left one is an alphanode in the first join, beta node aftewards #compare the memory of both nodes, we want the smaller one to the left # if isListVarNode(self.rnode): rows = keysToList(self.lnode.ind) for row in rows: row = row[0] #print "rows:", row #print "left node key:", self.lnode.getkey() #left node key does not correspond to the bindings #bindings = self.lnode.getbindings(row) #get the bindings according to its own key, above line didnt work bindings = dict() key = self.getkey() try: for i, v in enumerate(key): bindings[v] = row[i] except: print "bindings=%s" % bindings print "row=%s" % row print "v=%s" % v print "i=%s" % i raise #copy the values for the variable in pattern.o if self.rnode.pattern.o in bindings: #copy it back to the original node - easiest way is to add it as a fact #also add bindings for the bnodes in subj for var in self.rnode.vars: if isinstance(var, Exivar): self.rnode.add(Fact(convertBNodeToFact(var), self.rnode.pattern.p, bindings[self.rnode.pattern.o])) #print "fact added:",convertBNodeToFact(var), self.rnode.pattern.p, bindings[self.rnode.pattern.o] elif isinstance(self.rnode.pattern.s, Exivar): print "something wrong happened - %s was supposed to be bound", self.rnode.pattern.s if isinstance(self.lnode, AlphaNode): key = self.lnode.svars elif isinstance(self.lnode, BetaNode): if not Set(self.lnode.vars).intersection(Set(self.rnode.vars)): key = list() else: #regenerate key here? was using self.svars before but was buggy key = self.getSharedVars(self.lnode, self.rnode) joinResults = list() if not key: #no shared variables and no matched values, so store and return the union #of the two memories """if switched: leftMemory = keysToList(self.rnode.ind) rightMemory = keysToList(self.lnode.ind) else:""" leftMemory = keysToList(self.lnode.ind) rightMemory = keysToList(self.rnode.ind) for lm, ljust in leftMemory: for rm, rjust in rightMemory: """if switched: row = rm + lm else:""" row = lm + rm joinResults.append([row, []]) ####NOTE -- Need to add justification (proof tracing) for this case self.add(row, []) else: t = time.time() """if switched: joinResults = self.joinhelper(self.rnode.ind, self.lnode.ind, key, [], [], switched) else:""" joinResults = self.joinhelper(self.lnode.ind, self.rnode.ind, key, [], []) print "joinhelper time:", time.time() - t return joinResults
def evalBuiltins(self, returnBindings=False): t = time.time() """I evaluate my attached builtins nodes.""" from builtins import builtinp, funcBuiltinp #Three cases to handle: left is a builtin and right is a plain anode, #left is a plain anode and right is a builtin, or both the left #and right are builtins evaldRows = list() builtinNodes = list() if builtinp(self.lnode): builtinNodes.append(self.lnode) if builtinp(self.rnode): builtinNodes.append(self.rnode) for bi in builtinNodes: inputNode = bi.getInputNode() builtinInput = keysToList(inputNode.ind) for row in builtinInput: row = row[0] #Needed since row[1] is the justification set #print row #print bi.pattern bindings = inputNode.getbindings(row, useBuiltin=bi) #need to check and substitute bi.pattern.s and bi.pattern.o for possible bindings here #check and substitute if subj or obj are lists, they also might have variables in the lists subjInput = convertBNodeToFact(bi.pattern.s) objInput = convertBNodeToFact(bi.pattern.o) if isinstance(bi.pattern.s, Variable): if bi.pattern.s in bindings: subjInput = convertBNodeToFact(bindings[bi.pattern.s]) if isinstance(bi.pattern.o, Variable): if bi.pattern.o in bindings: objInput = convertBNodeToFact(bindings[bi.pattern.o]) if subjInput in py_lists: subjInput = [self.bindPossibleVar(x, bindings) for x in py_lists[subjInput]] if objInput in py_lists: objInput = [self.bindPossibleVar(x, bindings) for x in py_lists[objInput]] # print "builtin", bi, subjInput, objInput result = bi.evaluate(subjInput, objInput) if result: #hack: append the bindings if it's log:includes if bi.pattern.p == INCLUDES: bindings[bi.pattern.s]= subjInput bindings[bi.pattern.o]= objInput row.append(subjInput) row.append(objInput) #a bit inefficient if returnBindings: evaldRows.append(bindings) else: evaldRows.append([row, []]) #Empty justification for now #add to memory -- ##NOTE: Need to add justification (proof tracing) for data resulting ##from builtins #print "row after bindings", row #if it's a functional builtin, it's different - need to return result and store in memory if funcBuiltinp(self.lnode) or funcBuiltinp(self.rnode): #have no idea why it works row.append(result) #print "row added in evalbuiltins:", row #add this fact self.add(row) #print "___row:", row else: #print "___row:", row self.add(row) #print "evaldRows:", evaldRows print "evalBultins time:", time.time() - t return evaldRows