Пример #1
0
def listRange2ListPrefix(listRange,fieldRange):
    '''
    Convert a range list to prefix list.
    
    Algorithm: generate a prefix rule list based on the range list, and convert
    it to PMTree, and fetch the entries in the range list from the
    tree.
    
    Examples:
    >>> listPrefix=listRange2ListPrefix([(0,4),(10,12)],(0,15))
    >>> print listPrefix
    ['00**', '0100', '101*', '1100']
    >>> print listRange2ListPrefix([(8,8),(10,11)],(0,15))
    ['1000', '101*']
    '''
    
    #sanity check range
    l,h=fieldRange
    assert(l==0)
    nBit=int(math.log(h+1,2))
    assert(2**nBit-1==h)    

    #generate prefix rule list
    listFat=[]
    for r in listRange:
        appendRuleToRangeRuleList(listFat,r,'y')
    appendRuleToRangeRuleList(listFat,fieldRange,'n')    
    #generate tree
    tree=PMTree(listFat,True,fieldRange)
    #saveSvgFile(tree.getDotCode(),'../output/tree.svg',True)
    
    #get node with 'y' label
    ly= tree.fetch('y')

    #fill in last bits by '*' in ly
    lz=[]
    for y in ly:
        lz.append(y+(nBit-len(y))*'*')
    
    return lz
Пример #2
0
    def generatePrefixRuleListND(self,listDecision,dictFieldRange,
                                 fmt,dictCost=None,getCode=False,
                                 listNodeOfInterest=None):
        '''
        Generate multi-dimensional prefix rule list from the subtree starting
        from this node.
        
        fmt (format): 
        prefix_overlap - predicates can overlap (calling the DP algorithm)
        prefix_nonoverlap - the predicates in the rules will be disjoint;
        range - predicate is in range format
        
        dictCost (optional):
        Dictionary to store the cost at each node.
        Key: the node (ADNode) of the tree. 
        Value: the weight of the node times number of rules associated 
        with the node.
        
        getCode (optional):
        If True, code returned is the dot code for visualizing the tree
        If False, code returned is ''
        
        listNodeOfInterest (optional):
        Only the rule list associated with the list of interested nodes
        are output to lnd.
        If None, all nodes in the subtree are of interest.
        
        Returns: 
        -- A weight
        -- A list of dictionary, with each entry including the fields and
        decision.
        -- Code for plot the resulting dot file
        '''
        '-----------code------------'
        code=''
        '-----------code------------'
        if self.hasChild():

            #add children to dictionary
            dictNode=_generateDictNode(self.children)
            fieldRange=dictFieldRange[self.label]

            #sanity check range
            l,h=fieldRange
            assert(l==0)
            nBit=int(math.log(h+1,2))
            assert(2**nBit-1==h)
            
            #iterate dictionary
            listRangeRule=[]
            listChildren=[]
            dictWeight={}
            dictLnd={}
            dictNewCode={}
            for c,rs in sorted(dictNode.items(), key=lambda x: x[1]):
                        #sorted(dictNode.items(), key=lambda x: x[1]) 
                        #make sure sorting in order of values                        
                #print 'rs:'
                #print rs
                w,lnd,newCode=c.generatePrefixRuleListND(listDecision,
                                dictFieldRange,fmt,dictCost=dictCost,
                                getCode=getCode,
                                listNodeOfInterest=listNodeOfInterest)
                listChildren.append(c)
                dictWeight[c]=w
                dictLnd[c]=lnd
                dictNewCode[c]=newCode
                for r in rs:
                    appendRuleToRangeRuleList(listRangeRule,r,c)
            
            listCurrRule=[]            
            if fmt=='prefix_overlap':#rules can overlap: use DP                                        
                tree=PMTree(listRangeRule,listIsRange=True,fieldRange=fieldRange)
                #print listRangeRule
                #saveSvgFile(tree.getDotCode(),'../output/tree.svg',True)

                res=generateShortestPrefixRuleListFromTree(tree,nBit,
                                                listChildren,dictWeight)
            
                listCurrRule=res[1][0]
            elif fmt=='prefix_nonoverlap':
                for c,rs in sorted(dictNode.items(), key=lambda x: x[1]):
                            #sorted(dictNode.items(), key=lambda x: x[1]) 
                            #make sure sorting in order of values                        
                    ps=listRange2ListPrefix(rs,fieldRange)
                    for p in ps:
                        appendRuleToPrefixRuleList(listCurrRule,p,c)
            elif fmt=='range':
                for c,rs in sorted(dictNode.items(), key=lambda x: x[1]):
                            #sorted(dictNode.items(), key=lambda x: x[1]) 
                            #make sure sorting in order of values                        
                    for r in rs:
                        appendRuleToPrefixRuleList(listCurrRule,r,c)
                
                
            # #sort the list, such that more specific rules (less *) are in front
            #20131008 result still correct if not used
            #listCurrRule=sorted(listCurrRule,key=lambda x: x['prefix'].count('*'))

            #count num rules for each child
            dictNRule={}#dict of decision (i.e. child) -> number of rules
            for rule in listCurrRule:
                c=rule['decision']                
                dictNRule.setdefault(c,0)
                dictNRule[c]+=1
                
            #generate the new n-dim rule list via 'cross product'
            lnd=[]
            for rule in listCurrRule:
                c=rule['decision']             
                currLnd=dictLnd[c]
                for rule2 in currLnd:
                    newRule=rule2.copy()
                    ###newRule[self.label]=(prio,rule['prefix']) #20131008 remove redundant prio
                    newRule[self.label]=rule['prefix']
                    if listNodeOfInterest is None:
                        lnd.append(newRule)
                    else:
                        for n in listNodeOfInterest:
                            if c==n or c.label!=n.label:
                                lnd.append(newRule)

            
            #the weight of this node is the sum of child weight x child rules
            w=sum([dictWeight[c]*dictNRule[c] for c in listChildren])            
            #NOTE: above not particularly better than belows. do more test            
            #w=sum([dictNRule[c] for c in listChildren])
            #w=sum([dictWeight[c] for c in listChildren])
            #w=1
            
            if dictCost is not None:
                dictCost[self]=w
                #also update all the subtree nodes' cost by times the #rules
                for c in listChildren:
                    c.propagateCostGain(dictNRule[c],dictCost)
            
            '-----------code------------'
            if getCode:
                code+=repr(self)+' [label="'+self.label+'",shape=oval];\n'
                #code+=repr(self)+' [label="'+self.label+' %d' % w+'",shape=oval];\n'
            '-----------code------------'
            
               
            '-----------code------------'
            if getCode:

                #record the rules (for generate dot code only)
                ###for iRule,rule in zip(range(len(listCurrRule)),listCurrRule): #20131008 remove redundant prio
                dictPrefixs={}#dict of decision (i.e. child) -> list of (priority,prefix)
                for rule in listCurrRule:
                    c=rule['decision']                
                    ###prio=nCurrRule-iRule-1 #20131008 remove redundant prio
                    lr=dictPrefixs.setdefault(c,[])
                    ###lr.append((prio,rule['prefix'])) #20131008 remove redundant prio
                    lr.append(rule['prefix'])
                           
                for c,rs in sorted(dictNode.items(), key=lambda x: x[1]):
                            #sorted(dictNode.items(), key=lambda x: x[1]) 
                            #make sure sorting in order of values
                    code+=repr(c)+' [label="'+c.label+'"];\n'
                    code+=repr(self)+' -> '+repr(c)+' [label="'
                    
                    nP=0
                    for res in dictPrefixs[c]:
                        ###prio,prefix=res #20131008 remove redundant prio
                        #prefix=res
                        nP+=1
                        if nP<=2:
                            if fmt=='range':
                                code+='(%d-%d)' % (res[0],res[1])
                            else:
                                ###code+='(%d:%s)' % (prio,prefix) #20131008 remove redundant prio
                                #code+='(%s)' % prefix
                                code+='(%s)' % res
                        else:
                            code+=' ...'
                            break
                    code+='"];\n'
                    code+=dictNewCode[c]
            '-----------code------------'
            
            #print 'weight (non-terminal): %d' % w
            return (w,lnd,code)
            
        else:#is terminal node.
            assert(self.label in listDecision)                        
            
            w=1

            if dictCost is not None:
                dictCost[self]=w
            
            #lnd=[{'decision':self.label}]#list n-dim
            lnd=[({'decision':self.label})]#list n-dim

            '-----------code------------'
            if getCode:
                code+=repr(self)+' [label="'+self.label+'",shape=box];\n'
                #code+=repr(self)+' [label="'+self.label+' %d' % w+'",shape=box];\n'
            '-----------code------------'
                        
            #print 'weight (terminal): %d' % w
            return (w,lnd,code)