comparison env/lib/python3.9/site-packages/networkx/algorithms/dominance.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """
2 Dominance algorithms.
3 """
4
5 from functools import reduce
6 import networkx as nx
7 from networkx.utils import not_implemented_for
8
9 __all__ = ["immediate_dominators", "dominance_frontiers"]
10
11
12 @not_implemented_for("undirected")
13 def immediate_dominators(G, start):
14 """Returns the immediate dominators of all nodes of a directed graph.
15
16 Parameters
17 ----------
18 G : a DiGraph or MultiDiGraph
19 The graph where dominance is to be computed.
20
21 start : node
22 The start node of dominance computation.
23
24 Returns
25 -------
26 idom : dict keyed by nodes
27 A dict containing the immediate dominators of each node reachable from
28 `start`.
29
30 Raises
31 ------
32 NetworkXNotImplemented
33 If `G` is undirected.
34
35 NetworkXError
36 If `start` is not in `G`.
37
38 Notes
39 -----
40 Except for `start`, the immediate dominators are the parents of their
41 corresponding nodes in the dominator tree.
42
43 Examples
44 --------
45 >>> G = nx.DiGraph([(1, 2), (1, 3), (2, 5), (3, 4), (4, 5)])
46 >>> sorted(nx.immediate_dominators(G, 1).items())
47 [(1, 1), (2, 1), (3, 1), (4, 3), (5, 1)]
48
49 References
50 ----------
51 .. [1] K. D. Cooper, T. J. Harvey, and K. Kennedy.
52 A simple, fast dominance algorithm.
53 Software Practice & Experience, 4:110, 2001.
54 """
55 if start not in G:
56 raise nx.NetworkXError("start is not in G")
57
58 idom = {start: start}
59
60 order = list(nx.dfs_postorder_nodes(G, start))
61 dfn = {u: i for i, u in enumerate(order)}
62 order.pop()
63 order.reverse()
64
65 def intersect(u, v):
66 while u != v:
67 while dfn[u] < dfn[v]:
68 u = idom[u]
69 while dfn[u] > dfn[v]:
70 v = idom[v]
71 return u
72
73 changed = True
74 while changed:
75 changed = False
76 for u in order:
77 new_idom = reduce(intersect, (v for v in G.pred[u] if v in idom))
78 if u not in idom or idom[u] != new_idom:
79 idom[u] = new_idom
80 changed = True
81
82 return idom
83
84
85 def dominance_frontiers(G, start):
86 """Returns the dominance frontiers of all nodes of a directed graph.
87
88 Parameters
89 ----------
90 G : a DiGraph or MultiDiGraph
91 The graph where dominance is to be computed.
92
93 start : node
94 The start node of dominance computation.
95
96 Returns
97 -------
98 df : dict keyed by nodes
99 A dict containing the dominance frontiers of each node reachable from
100 `start` as lists.
101
102 Raises
103 ------
104 NetworkXNotImplemented
105 If `G` is undirected.
106
107 NetworkXError
108 If `start` is not in `G`.
109
110 Examples
111 --------
112 >>> G = nx.DiGraph([(1, 2), (1, 3), (2, 5), (3, 4), (4, 5)])
113 >>> sorted((u, sorted(df)) for u, df in nx.dominance_frontiers(G, 1).items())
114 [(1, []), (2, [5]), (3, [5]), (4, [5]), (5, [])]
115
116 References
117 ----------
118 .. [1] K. D. Cooper, T. J. Harvey, and K. Kennedy.
119 A simple, fast dominance algorithm.
120 Software Practice & Experience, 4:110, 2001.
121 """
122 idom = nx.immediate_dominators(G, start)
123
124 df = {u: set() for u in idom}
125 for u in idom:
126 if len(G.pred[u]) >= 2:
127 for v in G.pred[u]:
128 if v in idom:
129 while v != idom[u]:
130 df[v].add(u)
131 v = idom[v]
132 return df