Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/dominance.py: 21%
42 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""
2Dominance algorithms.
3"""
5from functools import reduce
7import networkx as nx
8from networkx.utils import not_implemented_for
10__all__ = ["immediate_dominators", "dominance_frontiers"]
13@not_implemented_for("undirected")
14@nx._dispatch
15def immediate_dominators(G, start):
16 """Returns the immediate dominators of all nodes of a directed graph.
18 Parameters
19 ----------
20 G : a DiGraph or MultiDiGraph
21 The graph where dominance is to be computed.
23 start : node
24 The start node of dominance computation.
26 Returns
27 -------
28 idom : dict keyed by nodes
29 A dict containing the immediate dominators of each node reachable from
30 `start`.
32 Raises
33 ------
34 NetworkXNotImplemented
35 If `G` is undirected.
37 NetworkXError
38 If `start` is not in `G`.
40 Notes
41 -----
42 Except for `start`, the immediate dominators are the parents of their
43 corresponding nodes in the dominator tree.
45 Examples
46 --------
47 >>> G = nx.DiGraph([(1, 2), (1, 3), (2, 5), (3, 4), (4, 5)])
48 >>> sorted(nx.immediate_dominators(G, 1).items())
49 [(1, 1), (2, 1), (3, 1), (4, 3), (5, 1)]
51 References
52 ----------
53 .. [1] K. D. Cooper, T. J. Harvey, and K. Kennedy.
54 A simple, fast dominance algorithm.
55 Software Practice & Experience, 4:110, 2001.
56 """
57 if start not in G:
58 raise nx.NetworkXError("start is not in G")
60 idom = {start: start}
62 order = list(nx.dfs_postorder_nodes(G, start))
63 dfn = {u: i for i, u in enumerate(order)}
64 order.pop()
65 order.reverse()
67 def intersect(u, v):
68 while u != v:
69 while dfn[u] < dfn[v]:
70 u = idom[u]
71 while dfn[u] > dfn[v]:
72 v = idom[v]
73 return u
75 changed = True
76 while changed:
77 changed = False
78 for u in order:
79 new_idom = reduce(intersect, (v for v in G.pred[u] if v in idom))
80 if u not in idom or idom[u] != new_idom:
81 idom[u] = new_idom
82 changed = True
84 return idom
87@nx._dispatch
88def dominance_frontiers(G, start):
89 """Returns the dominance frontiers of all nodes of a directed graph.
91 Parameters
92 ----------
93 G : a DiGraph or MultiDiGraph
94 The graph where dominance is to be computed.
96 start : node
97 The start node of dominance computation.
99 Returns
100 -------
101 df : dict keyed by nodes
102 A dict containing the dominance frontiers of each node reachable from
103 `start` as lists.
105 Raises
106 ------
107 NetworkXNotImplemented
108 If `G` is undirected.
110 NetworkXError
111 If `start` is not in `G`.
113 Examples
114 --------
115 >>> G = nx.DiGraph([(1, 2), (1, 3), (2, 5), (3, 4), (4, 5)])
116 >>> sorted((u, sorted(df)) for u, df in nx.dominance_frontiers(G, 1).items())
117 [(1, []), (2, [5]), (3, [5]), (4, [5]), (5, [])]
119 References
120 ----------
121 .. [1] K. D. Cooper, T. J. Harvey, and K. Kennedy.
122 A simple, fast dominance algorithm.
123 Software Practice & Experience, 4:110, 2001.
124 """
125 idom = nx.immediate_dominators(G, start)
127 df = {u: set() for u in idom}
128 for u in idom:
129 if len(G.pred[u]) >= 2:
130 for v in G.pred[u]:
131 if v in idom:
132 while v != idom[u]:
133 df[v].add(u)
134 v = idom[v]
135 return df