Repository: networkx/networkx

Issue:
Possible bug in dominance package
While working with ```dominance_frontiers``` algorithm I have noticed some strange line of code, which I think leads to incorrect results.

My question is: why try to discard element ```u```?
```
p.discard(u)
```

Given the following example it produces wrong results.
```
import networkx as nx
from networkx.algorithms.dominance import *

g = nx.DiGraph()
g.add_edges_from([
('b0','b1'), 
('b1', 'b2'),
('b2', 'b3'),
('b3','b1'), 
('b1','b5'), 
('b5', 'b6'), 
('b5', 'b8'), 
('b6', 'b7'), 
('b8', 'b7'), 
('b7', 'b3'), 
('b3', 'b4')
]

df = dominance_frontiers(g, 'b0')

print df
```

It yields:
```
{'b0': [],
 'b1': [],
 'b2': ['b3'],
 'b3': ['b1'],
 'b4': [],
 'b5': ['b3'],
 'b6': ['b7'],
 'b7': ['b3'],
 'b8': ['b7']}
```
However, I expect to see ```b1``` in ```df[b1]```, as if I use general algorithm for ```b1```, while parsing its predecessors, ```b1``` itself will be passed before its immediate dominator ```b0```, so it should be added to ```df[b1]```.


Discussion:

Patch:
diff --git a/doc/source/reference/algorithms.rst b/doc/source/reference/algorithms.rst
index e9a3b1f99..dd3958cfe 100644
--- a/doc/source/reference/algorithms.rst
+++ b/doc/source/reference/algorithms.rst
@@ -30,7 +30,6 @@ Algorithms
    algorithms.distance_regular
    algorithms.dominance
    algorithms.dominating
-   algorithms.efficiency
    algorithms.euler
    algorithms.flow
    algorithms.graphical
diff --git a/networkx/algorithms/assortativity/correlation.py b/networkx/algorithms/assortativity/correlation.py
index d6b34f3dc..6c56678e1 100644
--- a/networkx/algorithms/assortativity/correlation.py
+++ b/networkx/algorithms/assortativity/correlation.py
@@ -190,15 +190,13 @@ def numeric_assortativity_coefficient(G, attribute, nodes=None):
 
     Assortativity measures the similarity of connections
     in the graph with respect to the given numeric attribute.
-    The numeric attribute must be an integer.
-
+    
     Parameters
     ----------
     G : NetworkX graph
 
     attribute : string 
-        Node attribute key.  The corresponding attribute value must be an
-        integer.
+        Node attribute key
 
     nodes: list or iterable (optional)
         Compute numeric assortativity only for attributes of nodes in 
diff --git a/networkx/algorithms/assortativity/mixing.py b/networkx/algorithms/assortativity/mixing.py
index 09886c749..2c0e4f02b 100644
--- a/networkx/algorithms/assortativity/mixing.py
+++ b/networkx/algorithms/assortativity/mixing.py
@@ -166,15 +166,13 @@ def degree_mixing_matrix(G, x='out', y='in', weight=None,
 def numeric_mixing_matrix(G,attribute,nodes=None,normalized=True):
     """Return numeric mixing matrix for attribute.
 
-    The attribute must be an integer.
-
     Parameters
     ----------
     G : graph 
        NetworkX graph object.
 
     attribute : string 
-       Node attribute key.  The corresponding attribute must be an integer.
+       Node attribute key.
 
     nodes: list or iterable (optional)
         Build the matrix only with nodes in container. The default is all nodes.
diff --git a/networkx/algorithms/community/__init__.py b/networkx/algorithms/community/__init__.py
index 1d0fbbdf1..aa9a9b1a4 100644
--- a/networkx/algorithms/community/__init__.py
+++ b/networkx/algorithms/community/__init__.py
@@ -1,6 +1,6 @@
 from networkx.algorithms.community.asyn_lpa import *
 from networkx.algorithms.community.centrality import *
-from networkx.algorithms.community.community_generators import *
+from networkx.algorithms.community.generators import *
 from networkx.algorithms.community.kclique import *
 from networkx.algorithms.community.kernighan_lin import *
 from networkx.algorithms.community.quality import *
diff --git a/networkx/algorithms/community/community_generators.py b/networkx/algorithms/community/generators.py
similarity index 100%
rename from networkx/algorithms/community/community_generators.py
rename to networkx/algorithms/community/generators.py
diff --git a/networkx/algorithms/components/attracting.py b/networkx/algorithms/components/attracting.py
index ae805903a..aa7971b7c 100644
--- a/networkx/algorithms/components/attracting.py
+++ b/networkx/algorithms/components/attracting.py
@@ -1,23 +1,22 @@
 # -*- coding: utf-8 -*-
+"""
+Attracting components.
+"""
 #    Copyright (C) 2004-2016 by
 #    Aric Hagberg <hagberg@lanl.gov>
 #    Dan Schult <dschult@colgate.edu>
 #    Pieter Swart <swart@lanl.gov>
 #    All rights reserved.
 #    BSD license.
-#
-# Authors: Christopher Ellison
-"""Attracting components."""
 import networkx as nx
 from networkx.utils.decorators import not_implemented_for
-
-__all__ = ['number_attracting_components',
+__authors__ = "\n".join(['Christopher Ellison'])
+__all__ = ['number_attracting_components', 
            'attracting_components',
-           'is_attracting_component',
+           'is_attracting_component', 
            'attracting_component_subgraphs',
            ]
 
-
 @not_implemented_for('undirected')
 def attracting_components(G):
     """Generates a list of attracting components in `G`.
@@ -40,15 +39,10 @@ def attracting_components(G):
     attractors : generator of sets
         A generator of sets of nodes, one for each attracting component of G.
 
-    Raises
-    ------
-    NetworkXNotImplemented :
-        If the input graph is undirected.
-
     See Also
     --------
     number_attracting_components
-    is_attracting_component
+    is_attracting_component 
     attracting_component_subgraphs
 
     """
@@ -58,7 +52,6 @@ def attracting_components(G):
         if cG.out_degree(n) == 0:
             yield scc[n]
 
-
 @not_implemented_for('undirected')
 def number_attracting_components(G):
     """Returns the number of attracting components in `G`.
@@ -73,11 +66,6 @@ def number_attracting_components(G):
     n : int
         The number of attracting components in G.
 
-    Raises
-    ------
-    NetworkXNotImplemented :
-        If the input graph is undirected.
-
     See Also
     --------
     attracting_components
@@ -103,11 +91,6 @@ def is_attracting_component(G):
     attracting : bool
         True if `G` has a single attracting component. Otherwise, False.
 
-    Raises
-    ------
-    NetworkXNotImplemented :
-        If the input graph is undirected.
-
     See Also
     --------
     attracting_components
@@ -138,14 +121,9 @@ def attracting_component_subgraphs(G, copy=True):
         A list of node-induced subgraphs of the attracting components of `G`.
 
     copy : bool
-        If copy is True, graph, node, and edge attributes are copied to the
+        If copy is True, graph, node, and edge attributes are copied to the 
         subgraphs.
 
-    Raises
-    ------
-    NetworkXNotImplemented :
-        If the input graph is undirected.
-
     See Also
     --------
     attracting_components
diff --git a/networkx/algorithms/components/biconnected.py b/networkx/algorithms/components/biconnected.py
index 53a96cafc..762e10b60 100644
--- a/networkx/algorithms/components/biconnected.py
+++ b/networkx/algorithms/components/biconnected.py
@@ -1,19 +1,21 @@
 # -*- coding: utf-8 -*-
-#    Copyright (C) 2011-2016 by
+"""
+Biconnected components and articulation points.
+"""
+#    Copyright (C) 2011-2013 by
 #    Aric Hagberg <hagberg@lanl.gov>
 #    Dan Schult <dschult@colgate.edu>
 #    Pieter Swart <swart@lanl.gov>
 #    All rights reserved.
 #    BSD license.
-#
-# Authors: Jordi Torrents (jtorrents@milnou.net)
-#          Dan Schult (dschult@colgate.edu)
-#          Aric Hagberg (aric.hagberg@gmail.com)
-"""Biconnected components and articulation points."""
 from itertools import chain
 import networkx as nx
 from networkx.utils.decorators import not_implemented_for
 
+__author__ = '\n'.join(['Jordi Torrents <jtorrents@milnou.net>',
+                        'Dan Schult <dschult@colgate.edu>',
+                        'Aric Hagberg <aric.hagberg@gmail.com>'])
+
 __all__ = [
     'biconnected_components',
     'biconnected_component_edges',
@@ -28,7 +30,7 @@ def is_biconnected(G):
     """Return True if the graph is biconnected, False otherwise.
 
     A graph is biconnected if, and only if, it cannot be disconnected by
-    removing only one node (and all edges incident on that node).  If
+    removing only one node (and all edges incident on that node). If
     removing a node increases the number of disconnected components
     in the graph, that node is called an articulation point, or cut
     vertex.  A biconnected graph has no articulation points.
@@ -63,20 +65,16 @@ def is_biconnected(G):
     articulation_points
     biconnected_component_edges
     biconnected_component_subgraphs
-    components.is_strongly_connected
-    components.is_weakly_connected
-    components.is_connected
-    components.is_semiconnected
 
     Notes
     -----
     The algorithm to find articulation points and biconnected
     components is implemented using a non-recursive depth-first-search
     (DFS) that keeps track of the highest level that back edges reach
-    in the DFS tree.  A node `n` is an articulation point if, and only
+    in the DFS tree. A node `n` is an articulation point if, and only
     if, there exists a subtree rooted at `n` such that there is no
     back edge from any successor of `n` that links to a predecessor of
-    `n` in the DFS tree.  By keeping track of all the edges traversed
+    `n` in the DFS tree. By keeping track of all the edges traversed
     by the DFS we can obtain the biconnected components because all
     edges of a bicomponent will be traversed consecutively between
     articulation points.
@@ -89,7 +87,7 @@ def is_biconnected(G):
 
     """
     bcc = list(biconnected_components(G))
-    if not bcc:  # No bicomponents (it could be an empty graph)
+    if not bcc: # No bicomponents (it could be an empty graph)
         return False
     return len(bcc[0]) == len(G)
 
@@ -101,9 +99,9 @@ def biconnected_component_edges(G):
 
     Biconnected components are maximal subgraphs such that the removal of a
     node (and all edges incident on that node) will not disconnect the
-    subgraph.  Note that nodes may be part of more than one biconnected
-    component.  Those nodes are articulation points, or cut vertices.
-    However, each edge belongs to one, and only one, biconnected component.
+    subgraph. Note that nodes may be part of more than one biconnected
+    component. Those nodes are articulation points, or cut vertices. However,
+    each edge belongs to one, and only one, biconnected component.
 
     Notice that by convention a dyad is considered a biconnected component.
 
@@ -149,10 +147,10 @@ def biconnected_component_edges(G):
     The algorithm to find articulation points and biconnected
     components is implemented using a non-recursive depth-first-search
     (DFS) that keeps track of the highest level that back edges reach
-    in the DFS tree.  A node `n` is an articulation point if, and only
+    in the DFS tree. A node `n` is an articulation point if, and only
     if, there exists a subtree rooted at `n` such that there is no
     back edge from any successor of `n` that links to a predecessor of
-    `n` in the DFS tree.  By keeping track of all the edges traversed
+    `n` in the DFS tree. By keeping track of all the edges traversed
     by the DFS we can obtain the biconnected components because all
     edges of a bicomponent will be traversed consecutively between
     articulation points.
@@ -176,7 +174,7 @@ def biconnected_components(G):
     Biconnected components are maximal subgraphs such that the removal of a
     node (and all edges incident on that node) will not disconnect the
     subgraph. Note that nodes may be part of more than one biconnected
-    component.  Those nodes are articulation points, or cut vertices.  The
+    component. Those nodes are articulation points, or cut vertices. The
     removal of articulation points will increase the number of connected
     components of the graph.
 
@@ -226,9 +224,9 @@ def biconnected_components(G):
 
     See Also
     --------
-    is_biconnected
-    articulation_points
-    biconnected_component_edges
+    is_biconnected,
+    articulation_points,
+    biconnected_component_edges,
     biconnected_component_subgraphs
 
     Notes
@@ -236,10 +234,10 @@ def biconnected_components(G):
     The algorithm to find articulation points and biconnected
     components is implemented using a non-recursive depth-first-search
     (DFS) that keeps track of the highest level that back edges reach
-    in the DFS tree.  A node `n` is an articulation point if, and only
+    in the DFS tree. A node `n` is an articulation point if, and only
     if, there exists a subtree rooted at `n` such that there is no
     back edge from any successor of `n` that links to a predecessor of
-    `n` in the DFS tree.  By keeping track of all the edges traversed
+    `n` in the DFS tree. By keeping track of all the edges traversed
     by the DFS we can obtain the biconnected components because all
     edges of a bicomponent will be traversed consecutively between
     articulation points.
@@ -254,7 +252,6 @@ def biconnected_components(G):
     for comp in _biconnected_dfs(G, components=True):
         yield set(chain.from_iterable(comp))
 
-
 @not_implemented_for('directed')
 def biconnected_component_subgraphs(G, copy=True):
     """Return a generator of graphs, one graph for each biconnected component
@@ -262,8 +259,8 @@ def biconnected_component_subgraphs(G, copy=True):
 
     Biconnected components are maximal subgraphs such that the removal of a
     node (and all edges incident on that node) will not disconnect the
-    subgraph.  Note that nodes may be part of more than one biconnected
-    component.  Those nodes are articulation points, or cut vertices.  The
+    subgraph. Note that nodes may be part of more than one biconnected
+    component. Those nodes are articulation points, or cut vertices. The
     removal of articulation points will increase the number of connected
     components of the graph.
 
@@ -315,9 +312,9 @@ def biconnected_component_subgraphs(G, copy=True):
 
     See Also
     --------
-    is_biconnected
-    articulation_points
-    biconnected_component_edges
+    is_biconnected,
+    articulation_points,
+    biconnected_component_edges,
     biconnected_components
 
     Notes
@@ -325,10 +322,10 @@ def biconnected_component_subgraphs(G, copy=True):
     The algorithm to find articulation points and biconnected
     components is implemented using a non-recursive depth-first-search
     (DFS) that keeps track of the highest level that back edges reach
-    in the DFS tree.  A node `n` is an articulation point if, and only
+    in the DFS tree. A node `n` is an articulation point if, and only
     if, there exists a subtree rooted at `n` such that there is no
     back edge from any successor of `n` that links to a predecessor of
-    `n` in the DFS tree.  By keeping track of all the edges traversed
+    `n` in the DFS tree. By keeping track of all the edges traversed
     by the DFS we can obtain the biconnected components because all
     edges of a bicomponent will be traversed consecutively between
     articulation points.
@@ -355,7 +352,7 @@ def articulation_points(G):
 
     An articulation point or cut vertex is any node whose removal (along with
     all its incident edges) increases the number of connected components of
-    a graph.  An undirected connected graph without articulation points is
+    a graph. An undirected connected graph without articulation points is
     biconnected. Articulation points belong to more than one biconnected
     component of a graph.
 
@@ -392,9 +389,9 @@ def articulation_points(G):
 
     See Also
     --------
-    is_biconnected
-    biconnected_components
-    biconnected_component_edges
+    is_biconnected,
+    biconnected_components,
+    biconnected_component_edges,
     biconnected_component_subgraphs
 
     Notes
@@ -402,10 +399,10 @@ def articulation_points(G):
     The algorithm to find articulation points and biconnected
     components is implemented using a non-recursive depth-first-search
     (DFS) that keeps track of the highest level that back edges reach
-    in the DFS tree.  A node `n` is an articulation point if, and only
+    in the DFS tree. A node `n` is an articulation point if, and only
     if, there exists a subtree rooted at `n` such that there is no
     back edge from any successor of `n` that links to a predecessor of
-    `n` in the DFS tree.  By keeping track of all the edges traversed
+    `n` in the DFS tree. By keeping track of all the edges traversed
     by the DFS we can obtain the biconnected components because all
     edges of a bicomponent will be traversed consecutively between
     articulation points.
@@ -428,8 +425,8 @@ def _biconnected_dfs(G, components=True):
     for start in G:
         if start in visited:
             continue
-        discovery = {start: 0}  # time of first discovery of node during search
-        low = {start: 0}
+        discovery = {start:0} # "time" of first discovery of node during search
+        low = {start:0}
         root_children = 0
         visited.add(start)
         edge_stack = []
@@ -441,31 +438,31 @@ def _biconnected_dfs(G, components=True):
                 if grandparent == child:
                     continue
                 if child in visited:
-                    if discovery[child] <= discovery[parent]:  # back edge
-                        low[parent] = min(low[parent], discovery[child])
+                    if discovery[child] <= discovery[parent]: # back edge
+                        low[parent] = min(low[parent],discovery[child])
                         if components:
-                            edge_stack.append((parent, child))
+                            edge_stack.append((parent,child))
                 else:
                     low[child] = discovery[child] = len(discovery)
                     visited.add(child)
                     stack.append((parent, child, iter(G[child])))
                     if components:
-                        edge_stack.append((parent, child))
+                        edge_stack.append((parent,child))
             except StopIteration:
                 stack.pop()
                 if len(stack) > 1:
                     if low[parent] >= discovery[grandparent]:
                         if components:
-                            ind = edge_stack.index((grandparent, parent))
+                            ind = edge_stack.index((grandparent,parent))
                             yield edge_stack[ind:]
-                            edge_stack = edge_stack[:ind]
+                            edge_stack=edge_stack[:ind]
                         else:
                             yield grandparent
                     low[grandparent] = min(low[parent], low[grandparent])
-                elif stack:  # length 1 so grandparent is root
+                elif stack: # length 1 so grandparent is root
                     root_children += 1
                     if components:
-                        ind = edge_stack.index((grandparent, parent))
+                        ind = edge_stack.index((grandparent,parent))
                         yield edge_stack[ind:]
         if not components:
             # root node is articulation point if it has more than 1 child
diff --git a/networkx/algorithms/components/connected.py b/networkx/algorithms/components/connected.py
index 5e90da716..dc17d34da 100644
--- a/networkx/algorithms/components/connected.py
+++ b/networkx/algorithms/components/connected.py
@@ -1,19 +1,20 @@
 # -*- coding: utf-8 -*-
-#    Copyright (C) 2004-2016 by
+"""
+Connected components.
+"""
+#    Copyright (C) 2004-2013 by
 #    Aric Hagberg <hagberg@lanl.gov>
 #    Dan Schult <dschult@colgate.edu>
 #    Pieter Swart <swart@lanl.gov>
 #    All rights reserved.
 #    BSD license.
-#
-# Authors: Eben Kenah
-#          Aric Hagberg (hagberg@lanl.gov)
-#          Christopher Ellison
-"""Connected components."""
 import networkx as nx
 from networkx.utils.decorators import not_implemented_for
 from ...utils import arbitrary_element
 
+__authors__ = "\n".join(['Eben Kenah',
+                         'Aric Hagberg <aric.hagberg@gmail.com>'
+                         'Christopher Ellison'])
 __all__ = [
     'number_connected_components',
     'connected_components',
@@ -37,11 +38,6 @@ def connected_components(G):
     comp : generator of sets
        A generator of sets of nodes, one for each component of G.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     Examples
     --------
     Generate a sorted list of connected components, largest first.
@@ -58,8 +54,7 @@ def connected_components(G):
 
     See Also
     --------
-    components.strongly_connected_components
-    components.weakly_connected_components
+    strongly_connected_components
 
     Notes
     -----
@@ -91,11 +86,6 @@ def connected_component_subgraphs(G, copy=True):
     comp : generator
       A generator of graphs, one for each connected component of G.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     Examples
     --------
     >>> G = nx.path_graph(4)
@@ -103,15 +93,13 @@ def connected_component_subgraphs(G, copy=True):
     >>> graphs = list(nx.connected_component_subgraphs(G))
 
     If you only want the largest connected component, it's more
-    efficient to use max instead of sort:
+    efficient to use max than sort.
 
     >>> Gc = max(nx.connected_component_subgraphs(G), key=len)
 
     See Also
     --------
     connected_components
-    components.strongly_connected_component_subgraphs
-    components.weakly_connected_component_subgraphs
 
     Notes
     -----
@@ -142,8 +130,6 @@ def number_connected_components(G):
     See Also
     --------
     connected_components
-    components.number_weakly_connected_components
-    components.number_strongly_connected_components
 
     Notes
     -----
@@ -167,11 +153,6 @@ def is_connected(G):
     connected : bool
       True if the graph is connected, false otherwise.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     Examples
     --------
     >>> G = nx.path_graph(4)
@@ -180,10 +161,6 @@ def is_connected(G):
 
     See Also
     --------
-    components.is_strongly_connected
-    components.is_weakly_connected
-    components.is_semiconnected
-    components.is_biconnected
     connected_components
 
     Notes
@@ -214,11 +191,6 @@ def node_connected_component(G, n):
     comp : set
        A set of nodes in the component of G containing node n.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     See Also
     --------
     connected_components
diff --git a/networkx/algorithms/components/semiconnected.py b/networkx/algorithms/components/semiconnected.py
index a9766024a..07cc05dd5 100644
--- a/networkx/algorithms/components/semiconnected.py
+++ b/networkx/algorithms/components/semiconnected.py
@@ -1,19 +1,18 @@
 # -*- coding: utf-8 -*-
-#    Copyright (C) 2004-2016 by
-#    Aric Hagberg <hagberg@lanl.gov>
-#    Dan Schult <dschult@colgate.edu>
-#    Pieter Swart <swart@lanl.gov>
-#    All rights reserved.
-#    BSD license.
-#
-# Authors: ysitu (ysitu@users.noreply.github.com)
-"""Semiconnectedness."""
+"""
+Semiconnectedness.
+"""
+
+__author__ = """ysitu <ysitu@users.noreply.github.com>"""
+# Copyright (C) 2014 ysitu <ysitu@users.noreply.github.com>
+# All rights reserved.
+# BSD license.
+
 import networkx as nx
 from networkx.utils import not_implemented_for, pairwise
 
 __all__ = ['is_semiconnected']
 
-
 @not_implemented_for('undirected')
 def is_semiconnected(G):
     """Return True if the graph is semiconnected, False otherwise.
@@ -34,7 +33,7 @@ def is_semiconnected(G):
     Raises
     ------
     NetworkXNotImplemented :
-        If the input graph is undirected.
+        If the input graph is not directed.
 
     NetworkXPointlessConcept :
         If the graph is empty.
@@ -50,10 +49,8 @@ def is_semiconnected(G):
 
     See Also
     --------
-    components.is_strongly_connected
-    components.is_weakly_connected
-    components.is_connected
-    components.is_biconnected
+    is_strongly_connected,
+    is_weakly_connected
     """
     if len(G) == 0:
         raise nx.NetworkXPointlessConcept(
diff --git a/networkx/algorithms/components/strongly_connected.py b/networkx/algorithms/components/strongly_connected.py
index 9fcfd1de5..98e57f5de 100644
--- a/networkx/algorithms/components/strongly_connected.py
+++ b/networkx/algorithms/components/strongly_connected.py
@@ -1,19 +1,20 @@
 # -*- coding: utf-8 -*-
+"""Strongly connected components.
+"""
 #    Copyright (C) 2004-2016 by
 #    Aric Hagberg <hagberg@lanl.gov>
 #    Dan Schult <dschult@colgate.edu>
 #    Pieter Swart <swart@lanl.gov>
 #    All rights reserved.
 #    BSD license.
-#
-# Authors: Eben Kenah
-#          Aric Hagberg (hagberg@lanl.gov)
-#          Christopher Ellison
-#          Ben Edwards (bedwards@cs.unm.edu)
-"""Strongly connected components."""
 import networkx as nx
 from networkx.utils.decorators import not_implemented_for
 
+__authors__ = "\n".join(['Eben Kenah',
+                         'Aric Hagberg (hagberg@lanl.gov)'
+                         'Christopher Ellison',
+                         'Ben Edwards (bedwards@cs.unm.edu)'])
+
 __all__ = ['number_strongly_connected_components',
            'strongly_connected_components',
            'strongly_connected_component_subgraphs',
@@ -40,7 +41,7 @@ def strongly_connected_components(G):
 
     Raises
     ------
-    NetworkXNotImplemented :
+    NetworkXNotImplemented:
         If G is undirected.
 
     Examples
@@ -60,13 +61,12 @@ def strongly_connected_components(G):
 
     See Also
     --------
-    components.connected_components
-    components.weakly_connected_components
-    kosaraju_strongly_connected_components
+    connected_components,
+    weakly_connected_components
 
     Notes
     -----
-    Uses Tarjan's algorithm[1]_ with Nuutila's modifications[2]_.
+    Uses Tarjan's algorithm with Nuutila's modifications.
     Nonrecursive version of algorithm.
 
     References
@@ -157,7 +157,8 @@ def kosaraju_strongly_connected_components(G, source=None):
 
     See Also
     --------
-    strongly_connected_components
+    connected_components
+    weakly_connected_components
 
     Notes
     -----
@@ -197,8 +198,8 @@ def strongly_connected_components_recursive(G):
 
     Raises
     ------
-    NetworkXNotImplemented :
-        If G is undirected.
+    NetworkXNotImplemented:
+        If G is undirected
 
     Examples
     --------
@@ -221,7 +222,7 @@ def strongly_connected_components_recursive(G):
 
     Notes
     -----
-    Uses Tarjan's algorithm[1]_ with Nuutila's modifications[2]_.
+    Uses Tarjan's algorithm with Nuutila's modifications.
 
     References
     ----------
@@ -283,11 +284,6 @@ def strongly_connected_component_subgraphs(G, copy=True):
     comp : generator of graphs
       A generator of graphs, one for each strongly connected component of G.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     Examples
     --------
     Generate a sorted list of strongly connected components, largest first.
@@ -305,9 +301,8 @@ def strongly_connected_component_subgraphs(G, copy=True):
 
     See Also
     --------
-    strongly_connected_components
-    components.connected_component_subgraphs
-    components.weakly_connected_component_subgraphs
+    connected_component_subgraphs
+    weakly_connected_component_subgraphs
 
     """
     for comp in strongly_connected_components(G):
@@ -331,16 +326,9 @@ def number_strongly_connected_components(G):
     n : integer
        Number of strongly connected components
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     See Also
     --------
-    strongly_connected_components
-    components.number_connected_components
-    components.number_weakly_connected_components
+    connected_components
 
     Notes
     -----
@@ -363,17 +351,8 @@ def is_strongly_connected(G):
     connected : bool
       True if the graph is strongly connected, False otherwise.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     See Also
     --------
-    components.is_weakly_connected
-    components.is_semiconnected
-    components.is_connected
-    components.is_biconnected
     strongly_connected_components
 
     Notes
@@ -407,18 +386,18 @@ def condensation(G, scc=None):
     Returns
     -------
     C : NetworkX DiGraph
-       The condensation graph C of G.  The node labels are integers
+       The condensation graph C of G. The node labels are integers
        corresponding to the index of the component in the list of
-       strongly connected components of G.  C has a graph attribute named
+       strongly connected components of G. C has a graph attribute named
        'mapping' with a dictionary mapping the original nodes to the
-       nodes in C to which they belong.  Each node in C also has a node
+       nodes in C to which they belong. Each node in C also has a node
        attribute 'members' with the set of original nodes in G that
        form the SCC that the node in C represents.
 
     Raises
     ------
     NetworkXNotImplemented:
-        If G is undirected.
+        If G is not directed
 
     Notes
     -----
diff --git a/networkx/algorithms/components/weakly_connected.py b/networkx/algorithms/components/weakly_connected.py
index ff2b06421..05df0166a 100644
--- a/networkx/algorithms/components/weakly_connected.py
+++ b/networkx/algorithms/components/weakly_connected.py
@@ -1,17 +1,19 @@
 # -*- coding: utf-8 -*-
+"""Weakly connected components.
+"""
 #    Copyright (C) 2004-2016 by
 #    Aric Hagberg <hagberg@lanl.gov>
 #    Dan Schult <dschult@colgate.edu>
 #    Pieter Swart <swart@lanl.gov>
 #    All rights reserved.
 #    BSD license.
-#
-# Authors: Aric Hagberg (hagberg@lanl.gov)
-#          Christopher Ellison
-"""Weakly connected components."""
+
 import networkx as nx
 from networkx.utils.decorators import not_implemented_for
 
+__authors__ = "\n".join(['Aric Hagberg (hagberg@lanl.gov)'
+                         'Christopher Ellison'])
+
 __all__ = [
     'number_weakly_connected_components',
     'weakly_connected_components',
@@ -35,11 +37,6 @@ def weakly_connected_components(G):
         A generator of sets of nodes, one for each weakly connected
         component of G.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     Examples
     --------
     Generate a sorted list of weakly connected components, largest first.
@@ -51,14 +48,13 @@ def weakly_connected_components(G):
     [4, 3]
 
     If you only want the largest component, it's more efficient to
-    use max instead of sort:
+    use max instead of sort.
 
     >>> largest_cc = max(nx.weakly_connected_components(G), key=len)
 
     See Also
     --------
-    components.connected_components
-    components.strongly_connected_components
+    strongly_connected_components
 
     Notes
     -----
@@ -87,16 +83,9 @@ def number_weakly_connected_components(G):
     n : integer
         Number of weakly connected components
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     See Also
     --------
-    weakly_connected_components
-    components.number_connected_components
-    components.number_strongly_connected_components
+    connected_components
 
     Notes
     -----
@@ -123,11 +112,6 @@ def weakly_connected_component_subgraphs(G, copy=True):
     comp : generator
         A generator of graphs, one for each weakly connected component of G.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     Examples
     --------
     Generate a sorted list of weakly connected components, largest first.
@@ -139,15 +123,14 @@ def weakly_connected_component_subgraphs(G, copy=True):
     [4, 3]
 
     If you only want the largest component, it's more efficient to
-    use max instead of sort:
+    use max instead of sort.
 
     >>> Gc = max(nx.weakly_connected_component_subgraphs(G), key=len)
 
     See Also
     --------
-    weakly_connected_components
-    components.strongly_connected_component_subgraphs
-    components.connected_component_subgraphs
+    strongly_connected_components
+    connected_components
 
     Notes
     -----
@@ -179,18 +162,11 @@ def is_weakly_connected(G):
     connected : bool
         True if the graph is weakly connected, False otherwise.
 
-    Raises
-    ------
-    NetworkXNotImplemented:
-        If G is undirected.
-
     See Also
     --------
-    components.is_strongly_connected
-    components.is_semiconnected
-    components.is_connected
-    components.is_biconnected
-    weakly_connected_components
+    is_strongly_connected
+    is_semiconnected
+    is_connected
 
     Notes
     -----
diff --git a/networkx/algorithms/dominance.py b/networkx/algorithms/dominance.py
index 0f0901e21..9d3b84375 100644
--- a/networkx/algorithms/dominance.py
+++ b/networkx/algorithms/dominance.py
@@ -126,17 +126,12 @@ def dominance_frontiers(G, start):
     """
     idom = nx.immediate_dominators(G, start)
 
-    df = {u: [] for u in idom}
-
+    df = {u: set() for u in idom}
     for u in idom:
-        if len(G.pred[u]) - int(u in G.pred[u]) >= 2:
-            p = set()
+        if len(G.pred[u]) >= 2:
             for v in G.pred[u]:
-                while v != idom[u] and v not in p:
-                    p.add(v)
-                    v = idom[v]
-            p.discard(u)
-            for v in p:
-                df[v].append(u)
-
+                if v in idom:
+                    while v != idom[u]:
+                        df[v].add(u)
+                        v = idom[v]
     return df
diff --git a/networkx/generators/geometric.py b/networkx/generators/geometric.py
index 02b3740fb..516fb4f4d 100644
--- a/networkx/generators/geometric.py
+++ b/networkx/generators/geometric.py
@@ -60,9 +60,9 @@ def random_geometric_graph(n, radius, dim=2, pos=None, metric=None):
         A metric on vectors of numbers (represented as lists or
         tuples). This must be a function that accepts two lists (or
         tuples) as input and yields a number as output. The function
-        must also satisfy the four requirements of a `metric`_.
-        Specifically, if *d* is the function and *x*, *y*,
-        and *z* are vectors in the graph, then *d* must satisfy
+        must also satisfy the four requirements of a
+        `metric`_. Specifically, if *d* is the function and *x*, *y*,
+        and *x* are vectors in the graph, then *d* must satisfy
 
         1. *d*(*x*, *y*) ≥ 0,
         2. *d*(*x*, *y*) = 0 if and only if *x* = *y*,
@@ -72,7 +72,7 @@ def random_geometric_graph(n, radius, dim=2, pos=None, metric=None):
         If this argument is not specified, the Euclidean distance metric is
         used.
 
-        .. _metric: https://en.wikipedia.org/wiki/Metric_%28mathematics%29
+    .. _metric: https://en.wikipedia.org/wiki/Metric_%28mathematics%29
 
     Returns
     -------
@@ -193,9 +193,9 @@ def geographical_threshold_graph(n, theta, alpha=2, dim=2, pos=None,
         A metric on vectors of numbers (represented as lists or
         tuples). This must be a function that accepts two lists (or
         tuples) as input and yields a number as output. The function
-        must also satisfy the four requirements of a `metric`_.
-        Specifically, if *d* is the function and *x*, *y*,
-        and *z* are vectors in the graph, then *d* must satisfy
+        must also satisfy the four requirements of a
+        `metric`_. Specifically, if *d* is the function and *x*, *y*,
+        and *x* are vectors in the graph, then *d* must satisfy
 
         1. *d*(*x*, *y*) ≥ 0,
         2. *d*(*x*, *y*) = 0 if and only if *x* = *y*,
@@ -205,7 +205,7 @@ def geographical_threshold_graph(n, theta, alpha=2, dim=2, pos=None,
         If this argument is not specified, the Euclidean distance metric is
         used.
 
-        .. _metric: https://en.wikipedia.org/wiki/Metric_%28mathematics%29
+    .. _metric: https://en.wikipedia.org/wiki/Metric_%28mathematics%29
 
     Returns
     -------
@@ -326,9 +326,9 @@ def waxman_graph(n, alpha=0.4, beta=0.1, L=None, domain=(0, 0, 1, 1),
         A metric on vectors of numbers (represented as lists or
         tuples). This must be a function that accepts two lists (or
         tuples) as input and yields a number as output. The function
-        must also satisfy the four requirements of a `metric`_.
-        Specifically, if *d* is the function and *x*, *y*,
-        and *z* are vectors in the graph, then *d* must satisfy
+        must also satisfy the four requirements of a
+        `metric`_. Specifically, if *d* is the function and *x*, *y*,
+        and *x* are vectors in the graph, then *d* must satisfy
 
         1. *d*(*x*, *y*) ≥ 0,
         2. *d*(*x*, *y*) = 0 if and only if *x* = *y*,
@@ -338,7 +338,7 @@ def waxman_graph(n, alpha=0.4, beta=0.1, L=None, domain=(0, 0, 1, 1),
         If this argument is not specified, the Euclidean distance metric is
         used.
 
-        .. _metric: https://en.wikipedia.org/wiki/Metric_%28mathematics%29
+    .. _metric: https://en.wikipedia.org/wiki/Metric_%28mathematics%29
 
     Returns
     -------


Test patch:
diff --git a/networkx/algorithms/tests/test_dominance.py b/networkx/algorithms/tests/test_dominance.py
index 94bd80468..4ce020f6c 100644
--- a/networkx/algorithms/tests/test_dominance.py
+++ b/networkx/algorithms/tests/test_dominance.py
@@ -99,28 +99,28 @@ class TestDominanceFrontiers(object):
     def test_singleton(self):
         G = nx.DiGraph()
         G.add_node(0)
-        assert_equal(nx.dominance_frontiers(G, 0), {0: []})
+        assert_equal(nx.dominance_frontiers(G, 0), {0: set()})
         G.add_edge(0, 0)
-        assert_equal(nx.dominance_frontiers(G, 0), {0: []})
+        assert_equal(nx.dominance_frontiers(G, 0), {0: set()})
 
     def test_path(self):
         n = 5
         G = nx.path_graph(n, create_using=nx.DiGraph())
         assert_equal(nx.dominance_frontiers(G, 0),
-                     {i: [] for i in range(n)})
+                     {i: set() for i in range(n)})
 
     def test_cycle(self):
         n = 5
         G = nx.cycle_graph(n, create_using=nx.DiGraph())
         assert_equal(nx.dominance_frontiers(G, 0),
-                     {i: [] for i in range(n)})
+                     {i: set() for i in range(n)})
 
     def test_unreachable(self):
         n = 5
         assert_greater(n, 1)
         G = nx.path_graph(n, create_using=nx.DiGraph())
         assert_equal(nx.dominance_frontiers(G, n // 2),
-                     {i: [] for i in range(n // 2, n)})
+                     {i: set() for i in range(n // 2, n)})
 
     def test_irreducible1(self):
         # Graph taken from Figure 2 of
@@ -129,9 +129,11 @@ class TestDominanceFrontiers(object):
         # Software Practice & Experience, 4:110, 2001.
         edges = [(1, 2), (2, 1), (3, 2), (4, 1), (5, 3), (5, 4)]
         G = nx.DiGraph(edges)
-        assert_equal({u: sorted(df)
+        assert_equal({u: df
                       for u, df in nx.dominance_frontiers(G, 5).items()},
-                     {1: [2], 2: [1], 3: [2], 4: [1], 5: []})
+                     {1: set([2]), 2: set([1]), 3: set([2]),
+                      4: set([1]), 5: set()})
+
 
     def test_irreducible2(self):
         # Graph taken from Figure 4 of
@@ -142,18 +144,21 @@ class TestDominanceFrontiers(object):
                  (6, 4), (6, 5)]
         G = nx.DiGraph(edges)
         assert_equal(nx.dominance_frontiers(G, 6),
-                     {1: [2], 2: [1, 3], 3: [2], 4: [2, 3], 5: [1], 6: []})
+                     {1: set([2]), 2: set([1, 3]), 3: set([2]), 4: set([2, 3])
+                      , 5: set([1]), 6: set([])})
 
     def test_domrel_png(self):
         # Graph taken from https://commons.wikipedia.org/wiki/File:Domrel.png
         edges = [(1, 2), (2, 3), (2, 4), (2, 6), (3, 5), (4, 5), (5, 2)]
         G = nx.DiGraph(edges)
         assert_equal(nx.dominance_frontiers(G, 1),
-                     {1: [], 2: [], 3: [5], 4: [5], 5: [2], 6: []})
+                     {1: set([]), 2: set([2]), 3: set([5]), 4: set([5]),
+                                         5: set([2]), 6: set()})
         # Test postdominance.
         with nx.utils.reversed(G):
             assert_equal(nx.dominance_frontiers(G, 6),
-                         {1: [], 2: [], 3: [2], 4: [2], 5: [2], 6: []})
+                         {1: set(), 2: set([2]), 3: set([2]), 4: set([2]),
+                          5: set([2]), 6: set()})
 
     def test_boost_example(self):
         # Graph taken from Figure 1 of
@@ -162,10 +167,97 @@ class TestDominanceFrontiers(object):
                  (5, 7), (6, 4)]
         G = nx.DiGraph(edges)
         assert_equal(nx.dominance_frontiers(G, 0),
-                     {0: [], 1: [], 2: [7], 3: [7], 4: [7], 5: [7], 6: [4],
-                      7: []})
+                     {0: set(), 1: set(), 2: set([7]), 3: set([7]),
+                      4: set([4,7]), 5: set([7]), 6: set([4]), 7: set()})
         # Test postdominance.
         with nx.utils.reversed(G):
             assert_equal(nx.dominance_frontiers(G, 7),
-                         {0: [], 1: [], 2: [1], 3: [1], 4: [1], 5: [1], 6: [4],
-                          7: []})
+                         {0: set(), 1: set(), 2: set([1]), 3: set([1]),
+                          4: set([1,4]), 5: set([1]), 6: set([4]), 7: set()})
+
+
+    def test_discard_issue(self):
+        # https://github.com/networkx/networkx/issues/2071
+        g = nx.DiGraph()
+        g.add_edges_from([
+            ('b0','b1'),
+            ('b1', 'b2'),
+            ('b2', 'b3'),
+            ('b3','b1'),
+            ('b1','b5'),
+            ('b5', 'b6'),
+            ('b5', 'b8'),
+            ('b6', 'b7'),
+            ('b8', 'b7'),
+            ('b7', 'b3'),
+            ('b3', 'b4')
+        ]
+        )
+        df = nx.dominance_frontiers(g, 'b0')
+        assert_equal(df, {'b4': set(), 'b5': set(['b3']), 'b6': set(['b7']),
+                          'b7': set(['b3']),
+                          'b0': set(), 'b1': set(['b1']), 'b2': set(['b3']),
+                          'b3': set(['b1']), 'b8': set(['b7'])})
+
+    def test_loop(self):
+        g = nx.DiGraph()
+        g.add_edges_from([('a','b'),('b','c'),('b','a')])
+        df = nx.dominance_frontiers(g, 'a')
+        assert_equal(df, {'a': set(), 'b': set(), 'c': set()})
+
+    def test_missing_immediate_doms(self):
+        # see https://github.com/networkx/networkx/issues/2070
+        g = nx.DiGraph()
+        edges = [
+            ('entry_1', 'b1'),
+            ('b1', 'b2'),
+            ('b2', 'b3'),
+            ('b3', 'exit'),
+            ('entry_2', 'b3')
+        ]
+
+        # entry_1
+        #   |
+        #   b1
+        #   |
+        #   b2  entry_2
+        #    |  /
+        #    b3
+        #    |
+        #   exit
+
+        g.add_edges_from(edges)
+        # formerly raised KeyError on entry_2 when parsing b3
+        # because entry_2 does not have immediate doms (no path)
+        nx.dominance_frontiers(g,'entry_1')
+
+    def test_loops_larger(self):
+        # from
+        # http://ecee.colorado.edu/~waite/Darmstadt/motion.html
+        g = nx.DiGraph()
+        edges = [
+            ('entry', 'exit'),
+            ('entry', '1'),
+            ('1', '2'),
+            ('2', '3'),
+            ('3', '4'),
+            ('4', '5'),
+            ('5', '6'),
+            ('6', 'exit'),
+            ('6', '2'),
+            ('5', '3'),
+            ('4', '4')
+        ]
+
+        g.add_edges_from(edges)
+        df = nx.dominance_frontiers(g,'entry')
+        answer = {'entry': set(),
+                  '1': set(['exit']),
+                  '2': set(['exit', '2']),
+                  '3': set(['exit', '3', '2']),
+                  '4': set(['exit', '4','3', '2']),
+                  '5': set(['exit', '3', '2']),
+                  '6': set(['exit', '2']),
+                  'exit': set()}
+        for n in df:
+            assert_equal(set(df[n]),set(answer[n]))