Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/traversal/beamsearch.py: 50%
10 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"""Basic algorithms for breadth-first searching the nodes of a graph."""
2import networkx as nx
4from .breadth_first_search import generic_bfs_edges
6__all__ = ["bfs_beam_edges"]
9@nx._dispatch
10def bfs_beam_edges(G, source, value, width=None):
11 """Iterates over edges in a beam search.
13 The beam search is a generalized breadth-first search in which only
14 the "best" *w* neighbors of the current node are enqueued, where *w*
15 is the beam width and "best" is an application-specific
16 heuristic. In general, a beam search with a small beam width might
17 not visit each node in the graph.
19 Parameters
20 ----------
21 G : NetworkX graph
23 source : node
24 Starting node for the breadth-first search; this function
25 iterates over only those edges in the component reachable from
26 this node.
28 value : function
29 A function that takes a node of the graph as input and returns a
30 real number indicating how "good" it is. A higher value means it
31 is more likely to be visited sooner during the search. When
32 visiting a new node, only the `width` neighbors with the highest
33 `value` are enqueued (in decreasing order of `value`).
35 width : int (default = None)
36 The beam width for the search. This is the number of neighbors
37 (ordered by `value`) to enqueue when visiting each new node.
39 Yields
40 ------
41 edge
42 Edges in the beam search starting from `source`, given as a pair
43 of nodes.
45 Examples
46 --------
47 To give nodes with, for example, a higher centrality precedence
48 during the search, set the `value` function to return the centrality
49 value of the node:
51 >>> G = nx.karate_club_graph()
52 >>> centrality = nx.eigenvector_centrality(G)
53 >>> source = 0
54 >>> width = 5
55 >>> for u, v in nx.bfs_beam_edges(G, source, centrality.get, width):
56 ... print((u, v))
57 ...
58 (0, 2)
59 (0, 1)
60 (0, 8)
61 (0, 13)
62 (0, 3)
63 (2, 32)
64 (1, 30)
65 (8, 33)
66 (3, 7)
67 (32, 31)
68 (31, 28)
69 (31, 25)
70 (25, 23)
71 (25, 24)
72 (23, 29)
73 (23, 27)
74 (29, 26)
75 """
77 if width is None:
78 width = len(G)
80 def successors(v):
81 """Returns a list of the best neighbors of a node.
83 `v` is a node in the graph `G`.
85 The "best" neighbors are chosen according to the `value`
86 function (higher is better). Only the `width` best neighbors of
87 `v` are returned.
89 The list returned by this function is in decreasing value as
90 measured by the `value` function.
92 """
93 # TODO The Python documentation states that for small values, it
94 # is better to use `heapq.nlargest`. We should determine the
95 # threshold at which its better to use `heapq.nlargest()`
96 # instead of `sorted()[:]` and apply that optimization here.
97 #
98 # If `width` is greater than the number of neighbors of `v`, all
99 # neighbors are returned by the semantics of slicing in
100 # Python. This occurs in the special case that the user did not
101 # specify a `width`: in this case all neighbors are always
102 # returned, so this is just a (slower) implementation of
103 # `bfs_edges(G, source)` but with a sorted enqueue step.
104 return iter(sorted(G.neighbors(v), key=value, reverse=True)[:width])
106 yield from generic_bfs_edges(G, source, successors)