Repository: networkx/networkx

Issue:
`global_efficiency` is inefficient
See https://stackoverflow.com/a/57032282/2966723

Currently the code takes every single pair of nodes (in both directions), and finds the length of the path between those two.  

An obvious factor of 2 speedup is to change the denominator by a factor of 2 and use `combinations` rather than `permutations` to do the calculation, so that the path is only considered once.  (presumably would need to check that the graph is undirected first)

Alternately, another option is to use this code that I provided in my answer.

    def my_global_efficiency(G):
        '''author Joel C Miller
           https://stackoverflow.com/a/57032282/2966723
        '''

        n = len(G)
        denom = n*(n-1)
        if denom>0:
            efficiency = 0
            for path_collection in nx.all_pairs_shortest_path_length(G):
                source = path_collection[0]
                for target in path_collection[1]:
                    if target != source:
                        efficiency += 1./path_collection[1][target]    
                return efficiency/denom
        else:
            return 0



Discussion:
This looks good to me.

Resolving patch:
diff --git a/networkx/algorithms/__init__.py b/networkx/algorithms/__init__.py
--- a/networkx/algorithms/__init__.py
+++ b/networkx/algorithms/__init__.py
@@ -19,7 +19,7 @@
 from networkx.algorithms.distance_regular import *
 from networkx.algorithms.dominance import *
 from networkx.algorithms.dominating import *
-from networkx.algorithms.efficiency import *
+from networkx.algorithms.efficiency_measures import *
 from networkx.algorithms.euler import *
 from networkx.algorithms.graphical import *
 from networkx.algorithms.hierarchy import *
diff --git a/networkx/algorithms/efficiency.py b/networkx/algorithms/efficiency_measures.py
similarity index 91%
rename from networkx/algorithms/efficiency.py
rename to networkx/algorithms/efficiency_measures.py
--- a/networkx/algorithms/efficiency.py
+++ b/networkx/algorithms/efficiency_measures.py
@@ -99,16 +99,21 @@ def global_efficiency(G):
     n = len(G)
     denom = n * (n - 1)
     if denom != 0:
-        g_eff = sum(efficiency(G, u, v) for u, v in permutations(G, 2)) / denom
+        lengths = nx.all_pairs_shortest_path_length(G)
+        g_eff = 0
+        for source, targets in lengths:
+            for target, distance in targets.items():
+                if distance > 0:
+                    g_eff += 1 / distance
+        g_eff /= denom
+        # g_eff = sum(1 / d for s, tgts in lengths
+        #                   for t, d in tgts.items() if d > 0) / denom
     else:
         g_eff = 0
     # TODO This can be made more efficient by computing all pairs shortest
     # path lengths in parallel.
-    #
-    # TODO This summation can be trivially parallelized.
     return g_eff
 
-
 @not_implemented_for('directed')
 def local_efficiency(G):
     """Returns the average local efficiency of the graph.


Test patch:
diff --git a/networkx/generators/tests/test_degree_seq.py b/networkx/generators/tests/test_degree_seq.py
--- a/networkx/generators/tests/test_degree_seq.py
+++ b/networkx/generators/tests/test_degree_seq.py
@@ -200,8 +200,6 @@ def test_random_degree_sequence_graph():
     d = [1, 2, 2, 3]
     G = nx.random_degree_sequence_graph(d, seed=42)
     assert_equal(d, sorted(d for n, d in G.degree()))
-    G = nx.random_degree_sequence_graph(d)
-    assert_equal(d, sorted(d for n, d in G.degree()))
 
 
 def test_random_degree_sequence_graph_raise():
@@ -210,7 +208,7 @@ def test_random_degree_sequence_graph_raise():
 
 
 def test_random_degree_sequence_large():
-    G1 = nx.fast_gnp_random_graph(100, 0.1)
+    G1 = nx.fast_gnp_random_graph(100, 0.1, seed=42)
     d1 = (d for n, d in G1.degree())
     G2 = nx.random_degree_sequence_graph(d1, seed=42)
     d2 = (d for n, d in G2.degree())