Repository: networkx/networkx
Pull request: update anceestor&descendent doc
Closes #4191

Problem statement:
ancestors & descendant documentation appears overly restrictive
I'm trying to find the out-component of a node, and it looks like I could use `nx.descendants` and just add the node to the descendants.

But the documentation of `descendants` suggests the graph needs to be a DAG, rather than just directed.  I don't see anything in the code that requires that restriction.

Hints from issue discussion:
I agree. For both descendants and ancestors the input graph does not need to be acyclic (or even directed).

Also, this code is not taking advantage of python 3 dict.keys capabilities. It should be closer to something like:
```python
if source not in G:
    raise....
return nx.shortest_path_length(G, source).keys() - {source}
```
`dfs_preorder_nodes` already serves this purpose (remove source to get descendants).

I guess the reason that  `descendants` and `ancestors` are implemented in `networkx.algorithms.dag` is because of terminology? Because those terms may only make sense for a DAG (and trees), although the same algorithms can be applied on general graphs to get "nodes reachable from u" and "nodes from which u is reachable" (they may not be disjoint for non-DAGs) If we decide to call these also "descendants" and "ancestors", then they should be moved out of `networkx.algorithms.dag`.

Another thing that I noticed is that both `dag.descendants` and `dag.ancestors` are sub-optimal complexity-wise because they use `shortest_path_length` (which will default to something like dijkstra or bellman-ford). They should be using a basic traveral algorithm (like `dfs_preorder_nodes` does) to achieve a time complexity of O(V+E).

Would the devs here be interested in a PR re-writing `descendants` and `ancestors` (and maybe moving them out of `networkx.algorithms.dag`)?

The complexity issue should be fine. If a weight is not specified `shortest_path_length` defaults to a breadth first search.

I think simply removing the restriction from the docs of ancestors and descendants is the main issue.
Moving `descendants` and `ancestors` to, e.g., the traversal subpackage would also be OK with me. 
You can chose a module name, but `relatives.py` could work I suppose... :}
There will be a bit of changes needed in docs and `__init__.py` files.
If you want to just do the doc_string that would be fine too.
Hey, I was looking into this and was trying to understand the kind of change that would be needed? I would like to take on this task.  
I think the right approach here is to remove the restriction written in the doc_string that these two functions work only for DAGs. I don't think we need to move the functions elsewhere.  Pretty straightforward I hope.
Agreed.
Right now it is :
G : NetworkX DiGraph
A directed acyclic graph (DAG)
I feel it should say:
G : NetworkX DiGraph
A directed graph

Would that be correct ? @dschult  
Yes, that seems good!  Thanks!

Commit message: update anceestor&descendent doc

Patch to review:
diff --git a/networkx/algorithms/dag.py b/networkx/algorithms/dag.py
index 4c6e0efdf78..16b503522c1 100644
--- a/networkx/algorithms/dag.py
+++ b/networkx/algorithms/dag.py
@@ -46,7 +46,7 @@ def descendants(G, source):
     Parameters
     ----------
     G : NetworkX DiGraph
-        A directed acyclic graph (DAG)
+        A directed  graph
     source : node in `G`
 
     Returns
@@ -66,7 +66,7 @@ def ancestors(G, source):
     Parameters
     ----------
     G : NetworkX DiGraph
-        A directed acyclic graph (DAG)
+        A directed graph
     source : node in `G`
 
     Returns


Code review comments:
diff_hunk: @@ -46,7 +46,7 @@ def descendants(G, source):
     Parameters
     ----------
     G : NetworkX DiGraph
-        A directed acyclic graph (DAG)
+        A directed  graph
path: networkx/algorithms/dag.py
text: @user1:
```suggestion
        A directed graph
```