Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

BFS layout implementation #5179

Merged
merged 12 commits into from
Feb 15, 2024
52 changes: 52 additions & 0 deletions networkx/drawing/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"fruchterman_reingold_layout",
"spiral_layout",
"multipartite_layout",
"bfs_layout",
"arf_layout",
]

Expand Down Expand Up @@ -1295,3 +1296,54 @@ def rescale_layout_dict(pos, scale=1):
pos_v = np.array(list(pos.values()))
pos_v = rescale_layout(pos_v, scale=scale)
return dict(zip(pos, pos_v))


def bfs_layout(G, start, center=None, **kwargs):
dschult marked this conversation as resolved.
Show resolved Hide resolved
"""Position nodes according to breadth-first search algorithm.

Parameters
----------
G : NetworkX graph or list of nodes
dschult marked this conversation as resolved.
Show resolved Hide resolved
A position will be assigned to every node in G.

start : string
Starting point.
dschult marked this conversation as resolved.
Show resolved Hide resolved

center : array-like or None
Coordinate pair around which to center the layout.

Returns
-------
pos : dict
A dictionary of positions keyed by node.
dschult marked this conversation as resolved.
Show resolved Hide resolved

Examples
--------
>>> G = nx.path_graph(4)
>>> pos = nx.bfs_layout(G, 0)

Notes
-----
This algorithm currently only works in two dimensions and does not
try to minimize edge crossings.

"""
from collections import deque

G, center = _process_params(G, center, 2)
H = G.copy() # So original graph remains unmodified

# Compute layers with BFS
visited = set()
queue = deque([(start, 0)])
while queue:
current_vertex, current_depth = queue.pop()
if current_vertex in visited:
continue
for nbr in H.neighbors(current_vertex):
queue.appendleft((nbr, current_depth + 1))
visited.add(current_vertex)
H.nodes[current_vertex]["layer"] = current_depth
dschult marked this conversation as resolved.
Show resolved Hide resolved

# Compute node positions with multipartite_layout
return multipartite_layout(H, subset_key="layer", **kwargs)
dschult marked this conversation as resolved.
Show resolved Hide resolved