Exemplo n.º 1
0
    def attachBetaNodes(self,patternIterator,lastBetaNodePattern=None):
        """
        The second 'pass' in the Rete network compilation algorithm:
        Attaches Beta nodes to the alpha nodes associated with all the patterns
        in a rule's LHS recursively towards a 'root' Beta node - the terminal node
        for the rule.  This root / terminal node is returned
        """
        try:
            nextPattern = patternIterator.next()
        except StopIteration:
            assert lastBetaNodePattern
            if lastBetaNodePattern:
                return self.nodes[lastBetaNodePattern]
            else:
                assert len(self.universalTruths),"should be empty LHSs"
                terminalNode = BetaNode(None,None,aPassThru=True)
                self.nodes[HashablePatternList([None])] = terminalNode
                return terminalNode#raise Exception("Ehh. Why are we here?")
        if lastBetaNodePattern:
            firstNode = self.nodes[lastBetaNodePattern]
            secondNode = self.nodes[nextPattern]
            newBNodePattern = lastBetaNodePattern + nextPattern
            newBetaNode = BetaNode(firstNode,secondNode)
            self.nodes[newBNodePattern] = newBetaNode
        else:
            firstNode  = self.nodes[nextPattern]
            oldAnchor = self.nodes.get(HashablePatternList([None])+nextPattern)
            if not oldAnchor:
                if isinstance(firstNode,AlphaNode):
                    newfirstNode = BetaNode(None,firstNode,aPassThru=True)
                    newfirstNode.connectIncomingNodes(None,firstNode)
                    self.nodes[HashablePatternList([None])+nextPattern] = newfirstNode
                else:
                    newfirstNode = firstNode
            else:
                newfirstNode = oldAnchor
            firstNode = newfirstNode
            secondPattern = patternIterator.next()
            secondNode = self.nodes[secondPattern]
            newBetaNode = BetaNode(firstNode,secondNode)
            newBNodePattern = HashablePatternList([None]) + nextPattern + secondPattern
            self.nodes[newBNodePattern] = newBetaNode

        newBetaNode.connectIncomingNodes(firstNode,secondNode)
        return self.attachBetaNodes(patternIterator,newBNodePattern)
Exemplo n.º 2
0
    def attachBetaNodes(self,patternIterator,lastBetaNodePattern=None):
        """
        The second 'pass' in the Rete network compilation algorithm:
        Attaches Beta nodes to the alpha nodes associated with all the patterns
        in a rule's LHS recursively towards a 'root' Beta node - the terminal node
        for the rule.  This root / terminal node is returned
        """
        try:
            nextPattern = patternIterator.next()
        except StopIteration:
            assert lastBetaNodePattern
            if lastBetaNodePattern:
                return self.nodes[lastBetaNodePattern]
            else:
                assert len(self.universalTruths),"should be empty LHSs"
                terminalNode = BetaNode(None,None,aPassThru=True)
                self.nodes[HashablePatternList([None])] = terminalNode                
                return terminalNode#raise Exception("Ehh. Why are we here?")
        if lastBetaNodePattern:
            firstNode = self.nodes[lastBetaNodePattern]
            secondNode = self.nodes[nextPattern]
            newBNodePattern = lastBetaNodePattern + nextPattern
            newBetaNode = BetaNode(firstNode,secondNode)        
            self.nodes[newBNodePattern] = newBetaNode            
        else:            
            firstNode  = self.nodes[nextPattern]
            oldAnchor = self.nodes.get(HashablePatternList([None])+nextPattern)
            if not oldAnchor: 
                if isinstance(firstNode,AlphaNode):
                    newfirstNode = BetaNode(None,firstNode,aPassThru=True) 
                    newfirstNode.connectIncomingNodes(None,firstNode)
                    self.nodes[HashablePatternList([None])+nextPattern] = newfirstNode
                else:
                    newfirstNode = firstNode
            else:                
                newfirstNode = oldAnchor
            firstNode = newfirstNode
            secondPattern = patternIterator.next()
            secondNode = self.nodes[secondPattern]
            newBetaNode = BetaNode(firstNode,secondNode)                         
            newBNodePattern = HashablePatternList([None]) + nextPattern + secondPattern                    
            self.nodes[newBNodePattern] = newBetaNode

        newBetaNode.connectIncomingNodes(firstNode,secondNode)
        return self.attachBetaNodes(patternIterator,newBNodePattern)
Exemplo n.º 3
0
    def buildNetwork(self,lhsIterator,rhsIterator,rule,aFilter=False):
        """
        Takes an iterator of triples in the LHS of an N3 rule and an iterator of the RHS and extends
        the Rete network, building / reusing Alpha
        and Beta nodes along the way (via a dictionary mapping of patterns to the built nodes)
        """
        matchedPatterns   = HashablePatternList()
        attachedPatterns = []
        # hasBuiltin = False
        LHS = []
        while True:
            try:
                currentPattern = lhsIterator.next()
                #The LHS isn't done yet, stow away the current pattern
                #We need to convert the Uniterm into a triple
                if isinstance(currentPattern,Uniterm):
                    currentPattern = currentPattern.toRDFTuple()
                LHS.append(currentPattern)
            except StopIteration:
                #The LHS is done, need to initiate second pass to recursively build join / beta
                #nodes towards a terminal node

                #We need to convert the Uniterm into a triple
                consequents = [isinstance(fact,Uniterm) and fact.toRDFTuple() or fact for fact in rhsIterator]
                if matchedPatterns and matchedPatterns in self.nodes:
                    attachedPatterns.append(matchedPatterns)
                elif matchedPatterns:
                    rt = self._findPatterns(matchedPatterns)
                    attachedPatterns.extend(rt)
                if len(attachedPatterns) == 1:
                    node = self.nodes[attachedPatterns[0]]
                    if isinstance(node,BetaNode):
                        terminalNode = node
                    else:
                        paddedLHSPattern = HashablePatternList([None])+attachedPatterns[0]
                        terminalNode = self.nodes.get(paddedLHSPattern)
                        if terminalNode is None:
                            #New terminal node
                            terminalNode = BetaNode(None,node,aPassThru=True)
                            self.nodes[paddedLHSPattern] = terminalNode
                            node.connectToBetaNode(terminalNode,RIGHT_MEMORY)
                    terminalNode.consequent.update(consequents)
                    terminalNode.rules.add(rule)
                    terminalNode.antecedent = rule.formula.body
                    terminalNode.network    = self
                    terminalNode.headAtoms.update(rule.formula.head)
                    terminalNode.filter = aFilter
                    self.terminalNodes.add(terminalNode)
                else:
                    moveToEnd = []
                    # endIdx = len(attachedPatterns) - 1
                    finalPatternList = []
                    for idx,pattern in enumerate(attachedPatterns):
                        assert isinstance(pattern,HashablePatternList),repr(pattern)
                        currNode = self.nodes[pattern]
                        if (isinstance(currNode,BuiltInAlphaNode) or
                            isinstance(currNode,BetaNode) and currNode.fedByBuiltin):
                            moveToEnd.append(pattern)
                        else:
                            finalPatternList.append(pattern)
                    terminalNode = self.attachBetaNodes(chain(finalPatternList,moveToEnd))
                    terminalNode.consequent.update(consequents)
                    terminalNode.rules.add(rule)
                    terminalNode.antecedent = rule.formula.body
                    terminalNode.network    = self
                    terminalNode.headAtoms.update(rule.formula.head)
                    terminalNode.filter = aFilter
                    self.terminalNodes.add(terminalNode)
                    self._resetinstantiationStats()
                #self.checkDuplicateRules()
                return terminalNode
            if HashablePatternList([currentPattern]) in self.nodes:
                #Current pattern matches an existing alpha node
                matchedPatterns.append(currentPattern)
            elif matchedPatterns in self.nodes:
                #preceding patterns match an existing join/beta node
                newNode = self.createAlphaNode(currentPattern)
                if len(matchedPatterns) == 1 and HashablePatternList([None])+matchedPatterns in self.nodes:
                    existingNode = self.nodes[HashablePatternList([None])+matchedPatterns]
                    newBetaNode = BetaNode(existingNode,newNode)
                    self.nodes[HashablePatternList([None])+matchedPatterns+HashablePatternList([currentPattern])] = newBetaNode
                    matchedPatterns = HashablePatternList([None])+matchedPatterns+HashablePatternList([currentPattern])
                else:
                    existingNode = self.nodes[matchedPatterns]
                    newBetaNode = BetaNode(existingNode,newNode)
                    self.nodes[matchedPatterns+HashablePatternList([currentPattern])] = newBetaNode
                    matchedPatterns.append(currentPattern)

                self.nodes[HashablePatternList([currentPattern])] = newNode
                newBetaNode.connectIncomingNodes(existingNode,newNode)
                #Extend the match list with the current pattern and add it
                #to the list of attached patterns for the second pass
                attachedPatterns.append(matchedPatterns)
                matchedPatterns = HashablePatternList()
            else:
                #The current pattern is not in the network and the match list isn't
                #either.  Add an alpha node
                newNode = self.createAlphaNode(currentPattern)
                self.nodes[HashablePatternList([currentPattern])] = newNode
                #Add to list of attached patterns for the second pass
                attachedPatterns.append(HashablePatternList([currentPattern]))
Exemplo n.º 4
0
 def buildNetwork(self,lhsIterator,rhsIterator,rule,aFilter=False):
     """
     Takes an iterator of triples in the LHS of an N3 rule and an iterator of the RHS and extends
     the Rete network, building / reusing Alpha 
     and Beta nodes along the way (via a dictionary mapping of patterns to the built nodes)
     """
     matchedPatterns   = HashablePatternList()
     attachedPatterns = []
     hasBuiltin = False
     LHS = []
     while True:
         try:
             currentPattern = lhsIterator.next()
             #The LHS isn't done yet, stow away the current pattern
             #We need to convert the Uniterm into a triple
             if isinstance(currentPattern,Uniterm):
                 currentPattern = currentPattern.toRDFTuple()
             LHS.append(currentPattern)
         except StopIteration:                
             #The LHS is done, need to initiate second pass to recursively build join / beta
             #nodes towards a terminal node                
             
             #We need to convert the Uniterm into a triple
             consequents = [isinstance(fact,Uniterm) and fact.toRDFTuple() or fact for fact in rhsIterator]
             if matchedPatterns and matchedPatterns in self.nodes:
                 attachedPatterns.append(matchedPatterns)
             elif matchedPatterns:
                 rt = self._findPatterns(matchedPatterns)
                 attachedPatterns.extend(rt)
             if len(attachedPatterns) == 1:
                 node = self.nodes[attachedPatterns[0]]
                 if isinstance(node,BetaNode):
                     terminalNode = node
                 else:
                     paddedLHSPattern = HashablePatternList([None])+attachedPatterns[0]                    
                     terminalNode = self.nodes.get(paddedLHSPattern)
                     if terminalNode is None:
                         #New terminal node
                         terminalNode = BetaNode(None,node,aPassThru=True)
                         self.nodes[paddedLHSPattern] = terminalNode    
                         node.connectToBetaNode(terminalNode,RIGHT_MEMORY)                            
                 terminalNode.consequent.update(consequents)
                 terminalNode.rules.add(rule)
                 terminalNode.antecedent = rule.formula.body
                 terminalNode.network    = self
                 terminalNode.headAtoms.update(rule.formula.head)
                 terminalNode.filter = aFilter
                 self.terminalNodes.add(terminalNode)                    
             else:              
                 moveToEnd = []
                 endIdx = len(attachedPatterns) - 1
                 finalPatternList = []
                 for idx,pattern in enumerate(attachedPatterns):
                     assert isinstance(pattern,HashablePatternList),repr(pattern)                    
                     currNode = self.nodes[pattern]
                     if (isinstance(currNode,BuiltInAlphaNode) or 
                         isinstance(currNode,BetaNode) and currNode.fedByBuiltin):
                         moveToEnd.append(pattern)
                     else:
                         finalPatternList.append(pattern)
                 terminalNode = self.attachBetaNodes(chain(finalPatternList,moveToEnd))
                 terminalNode.consequent.update(consequents)
                 terminalNode.rules.add(rule)
                 terminalNode.antecedent = rule.formula.body                    
                 terminalNode.network    = self
                 terminalNode.headAtoms.update(rule.formula.head)
                 terminalNode.filter = aFilter
                 self.terminalNodes.add(terminalNode)
                 self._resetinstanciationStats()                        
             #self.checkDuplicateRules()
             return terminalNode
         if HashablePatternList([currentPattern]) in self.nodes:
             #Current pattern matches an existing alpha node
             matchedPatterns.append(currentPattern)
         elif matchedPatterns in self.nodes:
             #preceding patterns match an existing join/beta node
             newNode = self.createAlphaNode(currentPattern)
             if len(matchedPatterns) == 1 and HashablePatternList([None])+matchedPatterns in self.nodes:
                 existingNode = self.nodes[HashablePatternList([None])+matchedPatterns]
                 newBetaNode = BetaNode(existingNode,newNode)     
                 self.nodes[HashablePatternList([None])+matchedPatterns+HashablePatternList([currentPattern])] = newBetaNode
                 matchedPatterns = HashablePatternList([None])+matchedPatterns+HashablePatternList([currentPattern])
             else:
                 existingNode = self.nodes[matchedPatterns]                
                 newBetaNode = BetaNode(existingNode,newNode)     
                 self.nodes[matchedPatterns+HashablePatternList([currentPattern])] = newBetaNode
                 matchedPatterns.append(currentPattern)
             
             self.nodes[HashablePatternList([currentPattern])] = newNode
             newBetaNode.connectIncomingNodes(existingNode,newNode)
             #Extend the match list with the current pattern and add it
             #to the list of attached patterns for the second pass                
             attachedPatterns.append(matchedPatterns)
             matchedPatterns = HashablePatternList()
         else:
             #The current pattern is not in the network and the match list isn't
             #either.  Add an alpha node 
             newNode = self.createAlphaNode(currentPattern)
             self.nodes[HashablePatternList([currentPattern])] = newNode
             #Add to list of attached patterns for the second pass
             attachedPatterns.append(HashablePatternList([currentPattern]))