Mercurial > codeOptimizer
view DepGraph.py @ 10:09b39021c4af
Make filename an attribute of file.
| author | Tom Fredrik Blenning Klaussen <bfg@blenning.no> |
|---|---|
| date | Wed, 14 Nov 2012 21:44:53 +0100 |
| parents | 2263a283203c |
| children |
line wrap: on
line source
import copy from types import * class DepGraph: def __init__(self): self.deps = [] self.values = [] def add(self, value): if value in self.values: raise ValueError self.values.append(value) def rightSize(self): vl = len(self.values) dl = len(self.deps) if dl != vl: full = [] for i in range(0, vl): full.append(False) exp = [] for i in range(dl, vl): exp.append(False) self.deps.append(full[:]) for i in range(0, dl): self.deps[i].append(exp[:]) def addDependency(self, src, dst): if not type(dst) is ListType: dst = [ dst ] self.rightSize() si = self.values.index(src) for d in dst: if d in self.values: di = self.values.index(d) self.deps[si][di] = True @staticmethod def identifyStronglyConnectedComponents(deps): """Tarjan's algorithm""" S=[] vindex={} lowlink={} retVal=[] for v in range(len(deps)): if not v in vindex: retVal.extend(DepGraph.strongconnect(deps, v, 0, vindex, lowlink, S)) return retVal @staticmethod def successors(deps, v): retVal = [] for w in range(len(deps)): if deps[w][v]: retVal.append(w) return retVal @staticmethod def strongconnect(deps, v, index, vindex, lowlink, S): retVal = [] # Set the depth index for v to the smallest unused index vindex[v] = index lowlink[v] = index S.append(v) # Consider successors of v for w in DepGraph.successors(deps, v): if not w in vindex: # Successor w has not yet been visited; recurse on it res = DepGraph.strongconnect(deps, w, index + 1, vindex, lowlink, S) retVal.extend(res) lowlink[v] = min(lowlink[v], lowlink[w]) elif w in S: # Successor w is in stack S and hence in the current SCC lowlink[v] = min(lowlink[v], vindex[w]) # If v is a root node, pop the stack and generate an SCC if lowlink[v] == vindex[v]: #start a new strongly connected component component = [] w = None while w != v: w = S.pop() #add w to current strongly connected component component.append(w) retVal.append(component) return retVal @staticmethod def dissolveStronglyConnectedComponents(deps): dissolved = True while dissolved: dissolved = False strong = DepGraph.identifyStronglyConnectedComponents(deps) for s in strong: if len(s) > 1: #We remove the first dependency, and see how it goes. #FIXME: This may not be the best strategy to achieve this v = s[0] for w in s[1:]: if deps[w][v]: #print "Remove link %d -> %d" % (w, v) deps[w][v] = False dissolved = True break return deps @staticmethod def directedGraphInternal(deps): dl = len(deps) startPoints = [] for i in range(dl): if not max(deps[i]): startPoints.append(i) for i in startPoints: for j in range(dl): deps[j][i] = False retVal = startPoints if len(deps) != len(startPoints): subVals = DepGraph.directedGraphInternal(deps) for val in startPoints: if val in subVals: ind = subVals.index(val) del subVals[ind] if subVals: retVal.extend(subVals) return retVal @staticmethod def printableDepgraph(deps): res='' for i in range(len(deps)): if res: res += '\n' s = '' for j in range(len(deps[i])): if deps[i][j]: s += '1' else: s += '0' res += s return res def depGraphRepr(self): return self.printableDepgraph(self.deps) def directedGraph(self, force = True): deps = copy.deepcopy(self.deps) if force: deps = self.dissolveStronglyConnectedComponents(deps) vals = self.directedGraphInternal(deps) retVal = [] for i in vals: retVal.append(self.values[i]) return retVal def toplevelDependencies(self): dl = len(self.deps) retVal = [] for i in range(dl): if not max(self.deps[i]): print max(self.deps[i]) retVal.append(self.values[i]) return retVal
