Source code for networkx.algorithms.approximation.distance_measures
"""距离度量近似于度量标准。"""
import networkx as nx
from networkx.utils.decorators import py_random_state
__all__ = ["diameter"]
[docs]
@py_random_state(1)
@nx._dispatchable(name="approximate_diameter")
def diameter(G, seed=None):
"""返回图 G 的直径下界。
该函数计算有向图或无向图 G 的直径(即最大偏心距)的下界。所使用的过程根据图是否为有向图而有所不同。
如果 G 是无向图,则函数使用 `2-sweep` 算法 [1]。其主要思想是从一个随机节点选择最远的节点并返回其偏心距。
否则,如果 G 是有向图,函数使用 `2-dSweep` 算法 [2]。该过程首先从随机选择的源节点 $s$ 开始,执行前向和后向 BFS。设 $a_1$ 和 $a_2$ 分别为前向和后向情况下的最远节点。然后,它使用后向 BFS 计算 $a_1$ 的后向偏心距,并使用前向 BFS 计算 $a_2$ 的前向偏心距。最后,返回两者之间的最佳下界。
在这两种情况下,时间复杂度与 G 的大小成线性关系。
Parameters
----------
G : NetworkX 图
seed : 整数, random_state, 或 None (默认)
随机数生成状态的指示器。
参见 :ref:`Randomness<randomness>` 。
Returns
-------
d : 整数
G 的直径下界
Examples
--------
>>> G = nx.path_graph(10) # 无向图
>>> nx.diameter(G)
9
>>> G = nx.cycle_graph(3, create_using=nx.DiGraph) # 有向图
>>> nx.diameter(G)
2
Raises
------
NetworkXError
如果图是空的,
或者图是无向图且不连通,
或者图是有向图且不强连通。
See Also
--------
networkx.algorithms.distance_measures.diameter
References
----------
.. [1] Magnien, Clémence, Matthieu Latapy, and Michel Habib.
*Fast computation of empirically tight bounds for the diameter of massive graphs.*
Journal of Experimental Algorithmics (JEA), 2009.
https://arxiv.org/pdf/0904.2728.pdf
.. [2] Crescenzi, Pierluigi, Roberto Grossi, Leonardo Lanzi, and Andrea Marino.
*On computing the diameter of real-world directed (weighted) graphs.*
International Symposium on Experimental Algorithms. Springer, Berlin, Heidelberg, 2012.
https://courses.cs.ut.ee/MTAT.03.238/2014_fall/uploads/Main/diameter.pdf
"""
# if G is empty
if not G:
raise nx.NetworkXError("Expected non-empty NetworkX graph!")
# if there's only a node
if G.number_of_nodes() == 1:
return 0
# if G is directed
if G.is_directed():
return _two_sweep_directed(G, seed)
# else if G is undirected
return _two_sweep_undirected(G, seed)
def _two_sweep_undirected(G, seed):
"""辅助函数,用于寻找无向图直径的下界。
思路是从一个随机节点出发,找到距离最远的节点,并返回其偏心距。
``G`` 是一个 NetworkX 无向图。
.. note::
``seed`` 是一个 random.Random 或 numpy.random.RandomState 实例
"""
# select a random source node
source = seed.choice(list(G))
# get the distances to the other nodes
distances = nx.shortest_path_length(G, source)
# if some nodes have not been visited, then the graph is not connected
if len(distances) != len(G):
raise nx.NetworkXError("Graph not connected.")
# take a node that is (one of) the farthest nodes from the source
*_, node = distances
# return the eccentricity of the node
return nx.eccentricity(G, node)
def _two_sweep_directed(G, seed):
"""用于寻找有向图中直径下界的辅助函数。
它实现了2-dSweep,即2-sweep算法的有向版本。该算法遵循以下步骤:
1. 随机选择一个源节点 $s$。
2. 从 $s$ 开始进行前向BFS,选择距离源节点最远的节点 $a_1$,并计算 $LB_1$,即 $a_1$ 的后向偏心距。
3. 从 $s$ 开始进行后向BFS,选择距离源节点最远的节点 $a_2$,并计算 $LB_2$,即 $a_2$ 的前向偏心距。
4. 返回 $LB_1$ 和 $LB_2$ 中的最大值。
`G` 是一个 NetworkX 有向图。
.. note::
`seed` 是一个 random.Random 或 numpy.random.RandomState 实例
"""
# get a new digraph G' with the edges reversed in the opposite direction
G_reversed = G.reverse()
# select a random source node
source = seed.choice(list(G))
# compute forward distances from source
forward_distances = nx.shortest_path_length(G, source)
# compute backward distances from source
backward_distances = nx.shortest_path_length(G_reversed, source)
# if either the source can't reach every node or not every node
# can reach the source, then the graph is not strongly connected
n = len(G)
if len(forward_distances) != n or len(backward_distances) != n:
raise nx.NetworkXError("DiGraph not strongly connected.")
# take a node a_1 at the maximum distance from the source in G
*_, a_1 = forward_distances
# take a node a_2 at the maximum distance from the source in G_reversed
*_, a_2 = backward_distances
# return the max between the backward eccentricity of a_1 and the forward eccentricity of a_2
return max(nx.eccentricity(G_reversed, a_1), nx.eccentricity(G, a_2))