def bipartiteGraph(g, rL, cL): gb = [[] for n in range(rL + cL)] for edges in g: for e in edges: gb[e.src].append(Edge(e.src, e.dst + rL)) gb[e.dst + rL].append(Edge(e.dst + rL, e.src)) return gb
def bipartiteMatching(g, L, matching): n = len(g) matchTo = [-1 for n in range(n)] match = 0 for u in range(L): visited = [False] * n if augment(g, u, matchTo, visited): match += 1 for u in range(L): if matchTo[u] >= 0: matching.append(Edge(u, matchTo[u])) return match
def construct_gb(self): # construct graph of dm-decomped blocks' dependency nb = len(self.rss) self.endossb = [set() for n in range(nb)] for k in range(nb): for e in self.rss[k]: self.endossb[k] |= { self.find_css_block(v.dst) for v in self.g[e] } self.gb = [[] for n in range(nb)] for k in range(nb): for v in self.endossb[k]: self.gb[k].append(Edge(k, v))
def DulmageMendelsohnDecomposition(g, rs, cs): rL = len(g) cL = max([e.dst for edges in g for e in edges]) + 1 # step0: generate bipartite graph gb = bipartiteGraph(g, rL, cL) # step1: find bipartiteMatching matching = [] bipartiteMatching(gb, rL, matching) # step2: modify graph i.e. birateral M and R -> C edges gb[rL:] = [[] for n in range(cL)] for m in matching: r = min(m.src, m.dst) c = max(m.src, m.dst) gb[c].append(Edge(c, r)) # step3: find V0 and Vinf matched = [m.src for m in matching] matched += [m.dst for m in matching] rsrc = [n for n in range(rL) if not n in matched] cdst = [n for n in range(rL, rL + cL) if not n in matched] Vinf = getDst(gb, rsrc) V0 = getDst(reverse(gb), cdst) # step4: find scc of g without V0 and Vinf # Kosaraju's algorithm to preserve topological order of scc V = V0 + Vinf gb[:] = [[e for e in edges if not (e.dst in V or e.src in V)] for edges in gb] scc = [] stronglyConnectedComponents(gb, scc) scc[:] = [c for c in scc if not c[0] in V] # remove V0 and Vinf scc[:] = [V0] + scc + [Vinf] rs[:] = [[n for n in c if n < rL] for c in scc] cs[:] = [[n - rL for n in c if n >= rL] for c in scc]
return False # g: bipartite graph # L: size of the left side def bipartiteMatching(g, L, matching): n = len(g) matchTo = [-1 for n in range(n)] match = 0 for u in range(L): visited = [False] * n if augment(g, u, matchTo, visited): match += 1 for u in range(L): if matchTo[u] >= 0: matching.append(Edge(u, matchTo[u])) return match # -*- sample code -*- if __name__ == '__main__': from algorithm.graph import Edge matching = [] L = 3 g = [[Edge(0, 3), Edge(0, 4)], [Edge(1, 4), Edge(1, 5)], [Edge(2, 5)], [Edge(3, 0)], [Edge(4, 0), Edge(4, 1)], [Edge(5, 1), Edge(5, 2)]] bipartiteMatching(g, L, matching) for e in matching: print(e)
if v == w: break # Tarjan's algorithm def stronglyConnectedComponents(g, scc): n = len(g) num = [0] * n low = [0] * n inS = [False] * n S = [] del scc[:] time = 0 for u in range(n): if num[u] == 0: visit(g, u, scc, S, inS, low, num, time) # -*- sample code -*- if __name__ == '__main__': scc = [] g = [[Edge(0, 6)], [Edge(1, 0)], [Edge(2, 6)], [Edge(3, 4)], [Edge(4, 3)], [Edge(5, 0), Edge(5, 4)], [Edge(6, 1), Edge(6, 3), Edge(6, 4), Edge(6, 5)]] stronglyConnectedComponents(g, scc) print(scc) #-> [[4, 3], [5, 1, 6, 0], [2]]
def construct_g(self): # construct graph of endogenous vars' dependency self.g = [[] for n in range(len(self.d))] for e in range(len(self.endoss)): for v in sorted(self.endoss[e]): self.g[e].append(Edge(e, self.d[v]))