Repository: networkx/networkx

Issue:
`nx.find_cliques_recursive`: nonsensical output for some directed graphs
<!-- If you have a general question about NetworkX, please use the discussions tab to create a new discussion -->

<!--- Provide a general summary of the issue in the Title above -->

### Current Behavior

<!--- Tell us what happens instead of the expected behavior -->
When computing the cliques in a directed graph with `find_cliques_recursive`, the results can sometimes be nonsensical:
```python-console
>>> import networkx as nx
>>> G = nx.path_graph(4, create_using=nx.DiGraph)
>>> list(nx.find_cliques_recursive(G))
[[0, 1], [2, 3], [3]]
```

### Expected Behavior

<!--- Tell us what should happen -->
It probably makes the most sense to exclude directed graphs (as is mentioned in the comment above the function definition):
https://github.com/networkx/networkx/blob/cbc117da86247dc5c15ced7d48f378cd5ab10d35/networkx/algorithms/clique.py#L300-L302

This is also what is the other clique functions do:
```python-console
>>> list(nx.find_cliques(G))
Traceback (most recent call last):
  File "<python-input-3>", line 1, in <module>
    list(nx.find_cliques(G))
         ~~~~~~~~~~~~~~~^^^
  File "/Users/gillespeiffer/Documents/foss/networkx/networkx/utils/decorators.py", line 784, in func
    return argmap._lazy_compile(__wrapper)(*args, **kwargs)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "<class 'networkx.utils.decorators.argmap'> compilation 25", line 3, in argmap_find_cliques_21
    import gzip
         ^^^^^^
  File "/Users/gillespeiffer/Documents/foss/networkx/networkx/utils/decorators.py", line 87, in _not_implemented_for
    raise nx.NetworkXNotImplemented(errmsg)
networkx.exception.NetworkXNotImplemented: not implemented for directed type
>>>
>>> list(nx.enumerate_all_cliques(G))
Traceback (most recent call last):
  File "<python-input-4>", line 1, in <module>
    list(nx.enumerate_all_cliques(G))
         ~~~~~~~~~~~~~~~~~~~~~~~~^^^
  File "/Users/gillespeiffer/Documents/foss/networkx/networkx/utils/decorators.py", line 784, in func
    return argmap._lazy_compile(__wrapper)(*args, **kwargs)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "<class 'networkx.utils.decorators.argmap'> compilation 30", line 3, in argmap_enumerate_all_cliques_26
    import gzip
         ^^^^^^
  File "/Users/gillespeiffer/Documents/foss/networkx/networkx/utils/decorators.py", line 87, in _not_implemented_for
    raise nx.NetworkXNotImplemented(errmsg)
networkx.exception.NetworkXNotImplemented: not implemented for directed type
```

Another possibility is to search for sets of nodes such that there are bidirectional edges between each pair of them, but that would not be consistent with the other clique functions as mentioned above.

### Steps to Reproduce

<!--- Provide a minimal example that reproduces the bug -->
See above.

### Environment

<!--- Please provide details about your local environment -->

Python version: 3.13.7
NetworkX version: 3.5.1rc0.dev0

### Additional context

<!--- Add any other context about the problem here, screenshots, etc. -->



Discussion:
Yes -- Thanks for the example of it not working reliably.
This function should treat directed graphs in the same way that the `find_cliques` function treats them.
I think simply adding the decorator and a line in the doc_string is sufficient. Maybe a test? (for both if there isn't one for find_cliques).



Patch:
diff --git a/networkx/algorithms/clique.py b/networkx/algorithms/clique.py
index 741baa4d714..a562c37f0e8 100644
--- a/networkx/algorithms/clique.py
+++ b/networkx/algorithms/clique.py
@@ -297,7 +297,7 @@ def find_cliques(G, nodes=None):
         pass
 
 
-# TODO Should this also be not implemented for directed graphs?
+@not_implemented_for("directed")
 @nx._dispatchable
 def find_cliques_recursive(G, nodes=None):
     """Returns all maximal cliques in a graph.
@@ -318,6 +318,7 @@ def find_cliques_recursive(G, nodes=None):
     Parameters
     ----------
     G : NetworkX graph
+        An undirected graph.
 
     nodes : list, optional (default=None)
         If provided, only yield *maximal cliques* containing all nodes in `nodes`.
@@ -333,6 +334,9 @@ def find_cliques_recursive(G, nodes=None):
 
     Raises
     ------
+    NetworkXNotImplemented
+        If `G` is directed.
+
     ValueError
         If `nodes` is not a clique.
 


Test patch:
diff --git a/networkx/algorithms/tests/test_clique.py b/networkx/algorithms/tests/test_clique.py
index 3bee2109828..118b3093cf3 100644
--- a/networkx/algorithms/tests/test_clique.py
+++ b/networkx/algorithms/tests/test_clique.py
@@ -67,6 +67,15 @@ def test_find_cliques3(self):
         with pytest.raises(ValueError):
             list(nx.find_cliques_recursive(self.G, [2, 6, 4, 1]))
 
+    def test_find_cliques_directed(self):
+        G = nx.path_graph(4, create_using=nx.DiGraph)
+        msg = "not implemented for directed"
+        with pytest.raises(nx.NetworkXNotImplemented, match=msg):
+            list(nx.find_cliques(G))
+
+        with pytest.raises(nx.NetworkXNotImplemented, match=msg):
+            list(nx.find_cliques_recursive(G))
+
     def test_number_of_cliques(self):
         G = self.G
         assert nx.number_of_cliques(G, 1) == 1