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
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)