Example #1
0
    def __init__(self):
        ## nltk stemmer
        self.stemmer  = PorterStemmer()

        self.state_stack = []
        self.stack = []

        ## local variables
        self.Grounds = Groundings()
        self.Groundings = {}
        self.Types = {}
Example #2
0
class rule_engine:
    def __init__(self):
        ## nltk stemmer
        self.stemmer  = PorterStemmer()

        self.state_stack = []
        self.stack = []

        ## local variables
        self.Grounds = Groundings()
        self.Groundings = {}
        self.Types = {}
        
    def initialize(self, univ_sentence):
        self.tag_stack  = univ_sentence.features
        self.hypergraph = univ_sentence.hypergraph
        
    def interpreter(self, FileList):
        vm = VM('r5rs')
        
        primitive_procedures = [
            ["match-rule?", self.matchRule],
            ["rule-applied", self.rule_applied],
            ["lemma", self.lemma],
            ["in-sentence?", self.inSentence],
            ["make-link", self.addLink],
            ["reset-scope", self.Grounds.variableScope],
            ["ground", self.Grounds.groundVariable],
            ["set-link-type", self.setType],
            ["make-phrase", self.makePhrase],
            ["output-phrase", self.Output],
            ["get-groundings", self.getGroundings],
            ["has-feature?", self.hasFeature],
            ["has-flag?", self.hasFlag],
        ]
        for name, procedure in primitive_procedures:
            vm.define(name, vm.toscheme(procedure))

        for File in FileList:
            vm.load(File)
        
    def run_rules(self):
        files = ['analysis/prep-rules.scm', 'analysis/triple-rules.scm']
        self.interpreter(files)

    def getGroundings(self):
        #debug(self.Groundings)
        pass
        
    def Output(self, Ground1, Ground2, Ground3):
        #self.Groundings = self.output
        ground_1 = None
        ground_2 = None
        ground_3 = None
        
        if self.Grounds.isGround(Ground1) and self.isVariable(Ground1):
            ground_1 = self.Grounds.getGrounding(Ground1)
        elif not self.isVariable(Ground1):
            ground_1 = Ground1
            
        if self.Grounds.isGround(Ground2) and self.isVariable(Ground2):
            ground_2 = self.Grounds.getGrounding(Ground2)
        elif not self.isVariable(Ground2):
            ground_2 = Ground2
            
        if self.Grounds.isGround(Ground3) and self.isVariable(Ground3):
            ground_3 = self.Grounds.getGrounding(Ground3)
        elif not self.isVariable(Ground3):
            ground_3 = Ground3

        
        if ground_1 and ground_2 and ground_3:
            debug([ground_1, ground_2, ground_3], prefix="triple")
            
            self.hypergraph.add_edge(ground_2, ground_3,\
            edge_data=[ground_1], edge_type='triple', with_merge=False)
            
    def rule_applied(self, rule):
        #debug(rule, prefix="rule applied from scheme")
        #if hasattr(self, "output"):
        #    debug(self.output, prefix="Groundings")
        pass
    
    def hasFlag(self, flag, variable):
        ## do we have a given flag
        for x in self.hypergraph.edge_by_type('feature'):            
            head, cur_tag, tail = x
            if cur_tag[0] == flag:
                if self.isVariable(variable) and self.Grounds.isGround(variable):
                    value = self.Grounds.getGrounding(variable)
                else:
                    value = variable
                    
                if head == value:
                    return True

        return False
    
    def hasFeature(self, feature):
        for x in self.hypergraph.edge_by_type('feature'):
            head, cur_tag, tail = x
            if cur_tag == feature:
                return True

        return False
    
    def makePhrase(self, Ground1, Ground2):
        if self.Grounds.isGround(Ground1) and self.Grounds.isGround(Ground2):
            ground_1 = self.Grounds.getGrounding(Ground1)
            ground_2 = self.Grounds.getGrounding(Ground2)
            phrase = '_'.join([ground_1, ground_2])
            self.Grounds.groundVariable('$phrase', phrase)

    def inSentence(self, word):
        pass
    
    def isVariable(self, text):
        ## is it a variable?
        if text.startswith('$'):
            return True
        else:
            return False

    ## Type specifics
    def isType(self, variable):
        if self.Types.has_key(variable):
            return True
        else:
            return False
    
    def getType(self, variable):
        if self.isType(variable):
            return self.Types[variable]
        else:
            return False
    
    def setType(self, variable, Type):
        self.Types[variable] = Type

    ## Grounding specifics
    def compareGround(self, ground, idx):
        if self.Grounds.getGrounding(ground) != self.current[idx]:
            return False
        else:
            return True

    def addLink(self, ground_1, ground_2, type, data=None):
        if self.Grounds.isGround(ground_1) and self.Grounds.isGround(ground_2):
            ground_1 = self.Grounds.getGrounding(ground_1)
            ground_2 = self.Grounds.getGrounding(ground_2)
            
            self.hypergraph.add_edge(ground_1, ground_2, edge_data=[data], edge_type=type, with_merge=False)


    def matchRule(self, rule_set):
        results = []
        state   = None
        stack   = []
        
        for matches in self.match_rule_generator(rule_set):
            ## match to list then append the output
            ## find and match is a generator
            results.append(matches[0])
            state = matches[1]
            
        ## match it outright
        if rule_set == results:
            self.output = matches[1]
            return True

        return False
    
    def replaceOutput(self, ruleOutput, rule):
        if not ruleOutput:
            return False
        
        output = []
        
        for tag_set in rule:            
            replaced = self.replaceVariable(tag_set, self.output)
            output.append(replaced)

        return output
            
    def replaceVariable(self, tag_frame, groundings):
        output = tag_frame
        for x in xrange(len(tag_frame)):
            if self.isVariable(tag_frame[x]):
                if tag_frame[x] in groundings.keys():
                    output[x] = groundings[tag_frame[x]]

        return output
    
    def matchTemplate(self, rule_set, callback):
        output_stack = []
        for key, value in rule_set.items():
            match_rule = callback(value)
            if match_rule[0]:
                output = self.replaceOutput(match_rule, value)
                output_stack.append((key, output))
                
            self.reset()
                
        return output_stack
        
    def matchRuleSet(self, ruleSet):
        output_stack = []
        for key, value in ruleSet.items():
            match_list = self.matchRule(value)
            if match_list:
                output = self.replaceOutput(match_list, value)
                output_stack.append((key, output))
                
            self.reset()
            
        return output_stack
    
    def lemma(self, word, grounding):
        if self.isVariable(word) and self.Grounds.isGround(word):
            groundedWord = self.Grounds.getGrounding(word)
            stemmed = self.stemmer.stem_word(groundedWord)
            self.Grounds.groundVariable(grounding, stemmed)
            
        elif not self.isVariable(word):
            stemmed = self.stemmer.stem_word(word)
            self.Grounds.groundVariable(grounding, stemmed)

    def compareRule(self, tag, var_1, var_2):
        ## check to see if we are ground and it is a var
        if self.isVariable(var_1) and self.Grounds.isGround(var_1):
            out = self.compareGround(var_1, 0)
            if not out:
                return False
            
        ## otherwise we need to ground it
        elif self.isVariable(var_1) and not self.Grounds.isGround(var_1):
            self.Grounds.groundVariable(var_1, self.current[0])
     
        if self.isVariable(var_2) and self.Grounds.isGround(var_2):
            out = self.compareGround(var_2, 2)
            if not out:
                return False
            
        elif self.isVariable(var_2) and not self.Grounds.isGround(var_2):
            self.Grounds.groundVariable(var_2, self.current[2])
            
        if tag == '$prep':
            ## XXX: bad way of doing this
            return True
        
        if self.isVariable(tag) and self.Grounds.isGround(tag):
            self.compareGround(tag, 1)
                
        elif self.isVariable(tag) and not self.Grounds.isGround(tag):
            self.Grounds.groundVariable(tag, self.current[1])
        
        return True
    
    def find_next(self, tag):
        if self.isType(tag):
            tagType = self.getType(tag)
            ## dont play with a loaded gun
            if self.hypergraph.has_edge_type(tagType):
                for x in self.hypergraph.edge_by_type(tagType):
                    head, cur_tag, tail = x
                    edge_data = cur_tag[0]
                    self.Grounds.groundVariable(tag, edge_data)
                    self.current = (head, edge_data, tail)
                    yield (head, edge_data, tail)
            else:
                yield False            
                return
                        
        
        for x in self.hypergraph.edge_by_type('feature'):
            if not isinstance(tag, list):        
                if tag.startswith('$'):
                    head, tag, tail = x
                    self.current = (head, tag[0], tail)
                    yield self.current
                    
                elif x[1][0] == tag:
                    head, tag, tail = x
                    self.current = (head, tag[0], tail)
                    yield self.current
                    
    def match_rule_generator(self, rule_set):
        ## tag list is the list we match to
        ## it is the rule
        rule_set = deque(rule_set)
        
        ## has to be a deque with something in it
        if rule_set:
            popped = rule_set.popleft()
            self.stack.append(popped)
            ## pop off the tag list onto the stack
            tag, var_1, var_2 = self.stack[-1]

            ## find the next matching tag
            for x in self.find_next(tag):
                if x:
                    ## find our matching tag
                    match = self.compareRule(tag, var_1, var_2)
                    if match:
                        ## self.match_stack.append(self.groundings)
                        yield ([tag, var_1, var_2], self.Grounds.getGroundings())

                        ## run with recursion after yield
                        for x in self.match_rule_generator(rule_set):
                            ## check for sanity's sake
                            if len(rule_set) > 0:
                                tag, var_1, var_2 = rule_set.popleft()
                            else:
                                return
                            
                            #debug((tag, var_1, var_2))
                            match = self.compareRule(tag, var_1, var_2)
                            #debug(match)
                            if match:
                            ## dump on the stack
                                self.stack.append((tag, var_1, var_2))
                                ## self.match_stack.append(self.groundings)
                                yield ([tag, var_1, var_2], self.Grounds.getGroundings())

                            else:
                                ## reset the groundings
                                self.Grounds.variableScope()
                    else:
                        self.Grounds.variableScope()