diff --git a/src/sage/graphs/base/boost_graph.pyx b/src/sage/graphs/base/boost_graph.pyx index 41a41a2eaac..d51a8832d29 100644 --- a/src/sage/graphs/base/boost_graph.pyx +++ b/src/sage/graphs/base/boost_graph.pyx @@ -49,7 +49,6 @@ Functions # http://www.gnu.org/licenses/ # **************************************************************************** -cimport cython from cysignals.signals cimport sig_check, sig_on, sig_off from libcpp.set cimport set as cset from libcpp.pair cimport pair @@ -744,7 +743,7 @@ cpdef min_spanning_tree(g, return [(u, v, g.edge_label(u, v)) for u, v in edges] -cpdef blocks_and_cut_vertices(g): +cpdef blocks_and_cut_vertices(g, forbidden_vertices=None): r""" Compute the blocks and cut vertices of the graph. @@ -755,6 +754,9 @@ cpdef blocks_and_cut_vertices(g): - ``g`` -- the input Sage graph + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search + OUTPUT: A 2-dimensional vector with m+1 rows (m is the number of biconnected @@ -772,10 +774,29 @@ cpdef blocks_and_cut_vertices(g): sage: blocks_and_cut_vertices(g) ([[8, 9], [7, 8], [0, 1, 2, 3, 5, 4, 6, 7]], [8, 7]) - sage: G = Graph([(0,1,{'name':'a','weight':1}), (0,2,{'name':'b','weight':3}), (1,2,{'name':'b','weight':1})]) + sage: G = Graph([(0,1,{'name':'a','weight':1}), + ....: (0,2,{'name':'b','weight':3}), + ....: (1,2,{'name':'b','weight':1})]) sage: blocks_and_cut_vertices(G) ([[0, 1, 2]], []) + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.WindmillGraph(4, 3) + sage: blocks_and_cut_vertices(G) + ([[0, 1, 2, 3], [0, 4, 5, 6], [0, 7, 8, 9]], [0]) + sage: blocks_and_cut_vertices(G, forbidden_vertices=[0]) + ([[1, 2, 3], [4, 5, 6], [7, 8, 9]], []) + sage: blocks_and_cut_vertices(G, forbidden_vertices=[1]) + ([[0, 2, 3], [0, 4, 5, 6], [0, 7, 8, 9]], [0]) + sage: G = graphs.PathGraph(3) + sage: blocks_and_cut_vertices(G) + ([[1, 2], [0, 1]], [1]) + sage: blocks_and_cut_vertices(G, forbidden_vertices=[0]) + ([[1, 2]], []) + sage: blocks_and_cut_vertices(G, forbidden_vertices=[1]) + ([[0], [2]], []) + TESTS: Given an input which is not a graph:: @@ -790,8 +811,17 @@ cpdef blocks_and_cut_vertices(g): if not isinstance(g, GenericGraph): raise TypeError("the input must be a Sage graph") - if g.allows_loops() or g.allows_multiple_edges() or g.is_directed(): - g = g.to_simple() + cdef set forbidden = set() if forbidden_vertices is None else set(forbidden_vertices) + + if (g.allows_loops() or g.allows_multiple_edges() + or g.is_directed() or forbidden): + # Build the underlying undirected graph without loops or multiple edges, + # and without the forbidden vertices + V = [v for v in g if v not in forbidden] + E = [(u, v) for u, v in g.edge_iterator(vertices=V, labels=False, sort_vertices=False) + if u != v and u not in forbidden and v not in forbidden] + from sage.graphs.graph import Graph + g = Graph([V, E], format='vertices_and_edges') cdef BoostVecGraph g_boost cdef vector[vector[v_index]] result diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index b1f6db2b54f..ca895a27f60 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -22,7 +22,10 @@ Here is what the module can do: :meth:`connected_components_sizes` | Return the sizes of the connected components as a list. :meth:`blocks_and_cut_vertices` | Return the blocks and cut vertices of the graph. :meth:`blocks_and_cuts_tree` | Return the blocks-and-cuts tree of the graph. + :meth:`is_biconnected` | Check whether the graph is biconnected. + :meth:`biconnected_components` | Return the list of biconnected components. :meth:`biconnected_components_subgraphs` | Return a list of biconnected components as graph objects. + :meth:`number_of_biconnected_components` | Return the number of biconnected components. :meth:`is_cut_edge` | Check whether the input edge is a cut-edge or a bridge. :meth:`is_edge_cut` | Check whether the input edges form an edge cut. :meth:`is_cut_vertex` | Check whether the input vertex is a cut-vertex. @@ -90,7 +93,7 @@ def is_connected(G, forbidden_vertices=None): .. SEEALSO:: - - :meth:`~Graph.is_biconnected` + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected` EXAMPLES:: @@ -462,7 +465,8 @@ def connected_components_sizes(G, forbidden_vertices=None): forbidden_vertices=forbidden_vertices)] -def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): +def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None, + forbidden_vertices=None): """ Return the blocks and cut vertices of the graph. @@ -492,6 +496,9 @@ def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): vertex as its one argument and returns a value that can be used for comparisons in the sorting algorithm (we must have ``sort=True``) + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search + OUTPUT: ``(B, C)``, where ``B`` is a list of blocks - each is a list of vertices and the blocks are the corresponding induced subgraphs - and ``C`` is a list of cut vertices. @@ -551,6 +558,29 @@ def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): sage: blocks_and_cut_vertices(rings, algorithm='Tarjan_Boost') ([[0, 1, 4, 2, 3], [0, 6, 9, 7, 8]], [0]) + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.WindmillGraph(4, 3) + sage: G.blocks_and_cut_vertices(sort=True) + ([[0, 1, 2, 3], [0, 4, 5, 6], [0, 7, 8, 9]], [0]) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Boost', forbidden_vertices=[0]) + ([[1, 2, 3], [4, 5, 6], [7, 8, 9]], []) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Sage', forbidden_vertices=[0]) + ([[1, 2, 3], [4, 5, 6], [7, 8, 9]], []) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Boost', forbidden_vertices=[1]) + ([[0, 2, 3], [0, 4, 5, 6], [0, 7, 8, 9]], [0]) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Sage', forbidden_vertices=[1]) + ([[0, 2, 3], [0, 4, 5, 6], [0, 7, 8, 9]], [0]) + sage: G = graphs.PathGraph(3) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Sage') + ([[1, 2], [0, 1]], [1]) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Sage', forbidden_vertices=[0]) + ([[1, 2]], []) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Sage', forbidden_vertices=[1]) + ([[0], [2]], []) + sage: G.blocks_and_cut_vertices(sort=True, algorithm='Tarjan_Boost', forbidden_vertices=[1]) + ([[0], [2]], []) + TESTS:: sage: blocks_and_cut_vertices(Graph(0)) @@ -572,9 +602,10 @@ def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): if not isinstance(G, GenericGraph): raise TypeError("the input must be a Sage graph") + if algorithm == "Tarjan_Boost": from sage.graphs.base.boost_graph import blocks_and_cut_vertices - return blocks_and_cut_vertices(G) + return blocks_and_cut_vertices(G, forbidden_vertices=forbidden_vertices) if algorithm != "Tarjan_Sage": raise NotImplementedError("blocks and cut vertices algorithm '%s' is not implemented" % algorithm) @@ -588,13 +619,16 @@ def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): # We iterate over all vertices to ensure that we visit each connected # component of the graph - seen = set() + cdef set forbidden = set() if forbidden_vertices is None else set(forbidden_vertices) + cdef set seen = set(forbidden) for start in G.vertex_iterator(): if start in seen: continue # Special case of an isolated vertex - if not G.degree(start): + if (not G.degree(start) or + (forbidden and + len(set(G.neighbors(start, closed=True)) - forbidden) == 1)): blocks.append([start]) seen.add(start) continue @@ -634,6 +668,10 @@ def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): # We consider the next of its neighbors w = next(neighbors[v]) + if w in forbidden: + # We skip that neighbor + continue + # If we never met w before, we remember the direction of # edge vw, and add w to the stack. if w not in number: @@ -694,7 +732,7 @@ def blocks_and_cut_vertices(G, algorithm='Tarjan_Boost', sort=False, key=None): return blocks, list(cut_vertices) -def blocks_and_cuts_tree(G): +def blocks_and_cuts_tree(G, forbidden_vertices=None): """ Return the blocks-and-cuts tree of ``self``. @@ -713,10 +751,18 @@ def blocks_and_cuts_tree(G): We referred to [HarPri]_ and [Gallai]_ for blocks and cuts tree. + INPUT: + + - ``G`` -- a Sage graph + + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search. This is equilavent to get the blocks-and-cut tree + of a graph in which the forbidden vertices have been removed. + .. SEEALSO:: - :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices` - - :meth:`~Graph.is_biconnected` + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected` EXAMPLES:: @@ -744,6 +790,18 @@ def blocks_and_cuts_tree(G): sage: T.vertices(sort=True) [('B', (0, 1, 4, 5, 2, 6, 3, 7, 8, 9))] + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.CycleGraph(5) + sage: G.blocks_and_cut_vertices() + ([[0, 1, 4, 2, 3]], []) + sage: G.blocks_and_cuts_tree() + Graph on 1 vertex + sage: G.blocks_and_cut_vertices(forbidden_vertices=[0]) + ([[3, 4], [2, 3], [1, 2]], [2, 3]) + sage: G.blocks_and_cuts_tree(forbidden_vertices=[0]) + Graph on 5 vertices + TESTS: When ``self`` is not connected, the resulting graph is a forest @@ -766,7 +824,7 @@ def blocks_and_cuts_tree(G): raise TypeError("the input must be a Sage graph") from sage.graphs.graph import Graph - B, C = G.blocks_and_cut_vertices() + B, C = G.blocks_and_cut_vertices(forbidden_vertices=forbidden_vertices) B = map(tuple, B) set_C = set(C) g = Graph() @@ -778,17 +836,128 @@ def blocks_and_cuts_tree(G): return g -def biconnected_components_subgraphs(G): +def is_biconnected(G, forbidden_vertices=None): + r""" + Check whether the graph is biconnected. + + A biconnected graph is a connected graph on two or more vertices that is not + broken into disconnected pieces by deleting any single vertex. + + INPUT: + + - ``G`` -- a Sage graph + + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search. This is equilavent to check whether the graph in + which the forbidden vertices have been removed is biconnected. + + .. SEEALSO:: + + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_connected` + - :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices` + - :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cuts_tree` + - :wikipedia:`Biconnected_graph` + + EXAMPLES:: + + sage: G = graphs.PetersenGraph() + sage: G.is_biconnected() + True + sage: G.add_path([0,'a','b']) + sage: G.is_biconnected() + False + sage: G.add_edge('b', 1) + sage: G.is_biconnected() + True + + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.CycleGraph(5) + sage: G.is_biconnected() + True + sage: G.is_biconnected(forbidden_vertices=[0]) + False + + TESTS:: + + sage: Graph().is_biconnected() + False + sage: Graph(1).is_biconnected() + False + sage: graphs.CompleteGraph(2).is_biconnected() + True + """ + if G.order() < 2 or not G.is_connected(): + return False + return not G.blocks_and_cut_vertices(forbidden_vertices=forbidden_vertices)[1] + + +def biconnected_components(G, forbidden_vertices=None): + r""" + Return the list of biconnected components. + + A biconnected component is a maximal subgraph on two or more vertices that + is biconnected, i.e., removing any vertex does not disconnect it. + + INPUT: + + - ``G`` -- the input graph + + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search. This is equilavent to get the biconnected + components of the graph after the removal of the forbidden vertices. + + EXAMPLES:: + + sage: from sage.graphs.connectivity import biconnected_components + sage: G = Graph({0: [1, 2], 1: [0, 2], 2: [0, 1, 3], 3: [2]}) + sage: sorted(len(b) for b in biconnected_components(G)) + [2, 3] + sage: sorted(len(b) for b in biconnected_components(2 * G)) + [2, 2, 3, 3] + + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.CycleGraph(5) + sage: len(G.biconnected_components()) + 1 + sage: len(G.biconnected_components(forbidden_vertices=[0])) + 3 + + TESTS: + + If ``G`` is not a Sage graph, an error is raised:: + + sage: from sage.graphs.connectivity import biconnected_components + sage: biconnected_components('I am not a graph') + Traceback (most recent call last): + ... + TypeError: the input must be a Sage graph + """ + from sage.graphs.generic_graph import GenericGraph + if not isinstance(G, GenericGraph): + raise TypeError("the input must be a Sage graph") + + B = blocks_and_cut_vertices(G, forbidden_vertices=forbidden_vertices)[0] + return [b for b in B if len(b) > 1] + + +def biconnected_components_subgraphs(G, forbidden_vertices=None): r""" Return a list of biconnected components as graph objects. - A biconnected component is a maximal subgraph that is biconnected, i.e., - removing any vertex does not disconnect it. + A biconnected component is a maximal subgraph on two or more vertices that + is biconnected, i.e., removing any vertex does not disconnect it. INPUT: - ``G`` -- the input graph + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search. This is equilavent to get the biconnected + components subgraphs of the graph after the removal of the forbidden + vertices. + EXAMPLES:: sage: from sage.graphs.connectivity import biconnected_components_subgraphs @@ -801,6 +970,14 @@ def biconnected_components_subgraphs(G): sage: L[1].edges() [(0, 1, None), (0, 2, None), (1, 2, None)] + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.CycleGraph(5) + sage: len(G.biconnected_components_subgraphs()) + 1 + sage: len(G.biconnected_components_subgraphs(forbidden_vertices=[0])) + 3 + TESTS: If ``G`` is not a Sage graph, an error is raised:: @@ -815,7 +992,89 @@ def biconnected_components_subgraphs(G): if not isinstance(G, GenericGraph): raise TypeError("the input must be a Sage graph") - return [G.subgraph(c) for c in blocks_and_cut_vertices(G)[0]] + B = G.biconnected_components(forbidden_vertices=forbidden_vertices) + return [G.subgraph(c) for c in B] + + +def number_of_biconnected_components(G, forbidden_vertices=None): + r""" + Return the number of biconnected components. + + A biconnected component is a maximal subgraph on two or more vertices that + is biconnected, i.e., removing any vertex does not disconnect it. + + INPUT: + + - ``G`` -- the input graph + + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search. This is equilavent to get the number of + biconnected components of the graph after the removal of the forbidden + vertices. + + .. SEEALSO:: + + - :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices` + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected` + + EXAMPLES: + + The disjoint union of cycles has as many biconnected components as the + number of cycles:: + + sage: G = graphs.CycleGraph(5) + sage: G.number_of_biconnected_components() + 1 + sage: (3 * G).number_of_biconnected_components() + 3 + + A block graph is a connected graph in which every biconnected component + (block) is a clique. Hence its number of biconnected components is its + number of blocks:: + + sage: number_of_blocks = randint(4, 10) + sage: G = graphs.RandomBlockGraph(number_of_blocks, 5) + sage: G.number_of_biconnected_components() == number_of_blocks + True + + By definition, an edge is a biconnected component. Hence, the number of + biconnected components of a tree is its number of edges:: + + sage: T = graphs.RandomTree(randint(0, 10)) + sage: T.number_of_biconnected_components() == T.size() + True + + An isolated vertex is a block but not a biconnected component:: + + sage: G = Graph(3) + sage: len(G.blocks_and_cut_vertices()[0]) + 3 + sage: G.number_of_biconnected_components() + 0 + + Check the behavior of parameter ``forbidden_vertices``:: + + sage: G = graphs.CycleGraph(5) + sage: G.number_of_biconnected_components() + 1 + sage: G.number_of_biconnected_components(forbidden_vertices=[0]) + 3 + + TESTS: + + An error is raised if the input is not a Sage graph:: + + sage: from sage.graphs.connectivity import number_of_biconnected_components + sage: number_of_biconnected_components('I am not a graph') + Traceback (most recent call last): + ... + TypeError: the input must be a Sage graph + """ + from sage.graphs.generic_graph import GenericGraph + if not isinstance(G, GenericGraph): + raise TypeError("the input must be a Sage graph") + + return len(G.biconnected_components(forbidden_vertices=forbidden_vertices)) def is_edge_cut(G, edges): @@ -3363,7 +3622,7 @@ cdef class TriconnectivitySPQR: .. SEEALSO:: - :meth:`sage.graphs.connectivity.spqr_tree` - - :meth:`~Graph.is_biconnected` + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected` - :wikipedia:`SPQR_tree` EXAMPLES: @@ -4789,7 +5048,7 @@ def is_triconnected(G): .. SEEALSO:: - :meth:`~sage.graphs.generic_graph.GenericGraph.is_connected` - - :meth:`~Graph.is_biconnected` + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected` - :meth:`~sage.graphs.connectivity.spqr_tree` - :wikipedia:`SPQR_tree` diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 847ce71bf05..9292b2d30ae 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -236,7 +236,7 @@ :widths: 30, 70 :delim: | - :meth:`~GenericGraph.is_connected` | Test whether the (di)graph is connected. + :meth:`~GenericGraph.is_connected` | Check whether the (di)graph is connected. :meth:`~GenericGraph.connected_components` | Return the list of connected components :meth:`~GenericGraph.connected_components_number` | Return the number of connected components. :meth:`~GenericGraph.connected_components_subgraphs` | Return a list of connected components as graph objects. @@ -244,7 +244,10 @@ :meth:`~GenericGraph.connected_components_sizes` | Return the sizes of the connected components as a list. :meth:`~GenericGraph.blocks_and_cut_vertices` | Compute the blocks and cut vertices of the graph. :meth:`~GenericGraph.blocks_and_cuts_tree` | Compute the blocks-and-cuts tree of the graph. + :meth:`~GenericGraph.is_biconnected` | Check whether the graph is biconnected. + :meth:`~GenericGraph.biconnected_components` | Return the list of biconnected components. :meth:`~GenericGraph.biconnected_components_subgraphs` | Return a list of biconnected components as graph objects. + :meth:`~GenericGraph.number_of_biconnected_components` | Return the number of biconnected components. :meth:`~GenericGraph.is_cut_edge` | Check whether the input edge is a cut-edge or a bridge. :meth:`~GenericGraph.is_edge_cut` | Check whether the input edges form an edge cut. :meth:`~GenericGraph.is_cut_vertex` | Check whether the input vertex is a cut-vertex. @@ -25991,6 +25994,7 @@ def is_self_complementary(self): from sage.graphs.base.static_dense_graph import connected_subgraph_iterator from sage.graphs.base.static_sparse_graph import spectral_radius from sage.graphs.connectivity import ( + biconnected_components, biconnected_components_subgraphs, blocks_and_cut_vertices, blocks_and_cuts_tree, @@ -26000,11 +26004,13 @@ def is_self_complementary(self): connected_components_sizes, connected_components_subgraphs, edge_connectivity, + is_biconnected, is_connected, is_cut_edge, is_cut_vertex, is_edge_cut, is_vertex_cut, + number_of_biconnected_components, vertex_connectivity, ) from sage.graphs.distances_all_pairs import distances_distribution, szeged_index diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 248fd65d12f..c5e36ce9c6d 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -1754,46 +1754,6 @@ def is_cactus(self): B = self.blocks_and_cut_vertices()[0] return len(self.faces()) == sum(1 for b in B if len(b) > 2) + 1 - @doc_index("Graph properties") - def is_biconnected(self): - """ - Test if the graph is biconnected. - - A biconnected graph is a connected graph on two or more vertices that is - not broken into disconnected pieces by deleting any single vertex. - - .. SEEALSO:: - - - :meth:`~sage.graphs.generic_graph.GenericGraph.is_connected` - - :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices` - - :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cuts_tree` - - :wikipedia:`Biconnected_graph` - - EXAMPLES:: - - sage: G = graphs.PetersenGraph() - sage: G.is_biconnected() - True - sage: G.add_path([0,'a','b']) - sage: G.is_biconnected() - False - sage: G.add_edge('b', 1) - sage: G.is_biconnected() - True - - TESTS:: - - sage: Graph().is_biconnected() - False - sage: Graph(1).is_biconnected() - False - sage: graphs.CompleteGraph(2).is_biconnected() - True - """ - if self.order() < 2 or not self.is_connected(): - return False - return not self.blocks_and_cut_vertices()[1] - @doc_index("Graph properties") def is_block_graph(self): r""" diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index 5efedd77616..d00bb9597e7 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -144,7 +144,7 @@ * - Biconnected - - :meth:`~sage.graphs.graph.Graph.is_biconnected`, + - :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected`, :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cut_vertices`, :meth:`~sage.graphs.generic_graph.GenericGraph.blocks_and_cuts_tree` diff --git a/src/sage/graphs/matching_covered_graph.py b/src/sage/graphs/matching_covered_graph.py index 5d7e2ba49b8..48756e1e389 100644 --- a/src/sage/graphs/matching_covered_graph.py +++ b/src/sage/graphs/matching_covered_graph.py @@ -2387,8 +2387,8 @@ def is_biconnected(self): .. NOTE:: This method overwrites the - :meth:`~sage.graphs.graph.Graph.is_biconnected` method - in order to return ``True`` as matching covered graphs are + :meth:`~sage.graphs.generic_graph.GenericGraph.is_biconnected` + method in order to return ``True`` as matching covered graphs are biconnected. EXAMPLES: