diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index 0dcab74e90c..7f631fcfe28 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -17,6 +17,7 @@ :meth:`~is_redundant` | Check whether a set of vertices has redundant vertices (with respect to domination). :meth:`~private_neighbors` | Return the private neighbors of a vertex with respect to other vertices. :meth:`~greedy_dominating_set` | Return a greedy distance-`k` dominating set of the graph. + :meth:`~maximum_leaf_number` | Return the maximum leaf number of the graph. EXAMPLES: @@ -1284,3 +1285,81 @@ def greedy_dominating_set(G, k=1, vertices=None, ordering=None, return_sets=Fals return dom else: return list(dom) + + +def maximum_leaf_number(G, solver=None, verbose=0, integrality_tolerance=1e-3): + r""" + Return the maximum leaf number of the graph. + + The maximum leaf number is the maximum possible number of leaves of a + spanning tree of `G`. This is also the cardinality of the complement of a + minimum connected dominating set. + See the :wikipedia:`Connected_dominating_set`. + + The MLN of a graph with less than 2 vertices is 0, while the MLN of a connected + graph with 2 or 3 vertices is 1 or 2 respectively. + + INPUT: + + - ``G`` -- a Graph + + - ``solver`` -- string (default: ``None``); specify a Mixed Integer Linear + Programming (MILP) solver to be used. If set to ``None``, the default one + is used. For more information on MILP solvers and which default solver is + used, see the method :meth:`solve + ` of the class + :class:`MixedIntegerLinearProgram + `. + + - ``verbose`` -- integer (default: ``0``); sets the level of verbosity. Set + to 0 by default, which means quiet. + + - ``integrality_tolerance`` -- float; parameter for use with MILP solvers + over an inexact base ring; see + :meth:`MixedIntegerLinearProgram.get_values`. + + EXAMPLES: + + Empty graph:: + + sage: G = Graph() + sage: G.maximum_leaf_number() + 0 + + Petersen graph:: + + sage: G = graphs.PetersenGraph() + sage: G.maximum_leaf_number() + 6 + + TESTS: + + One vertex:: + + sage: G = Graph(1) + sage: G.maximum_leaf_number() + 0 + + Two vertices:: + + sage: G = graphs.PathGraph(2) + sage: G.maximum_leaf_number() + 1 + + Unconnected graph:: + + sage: G = Graph(2) + sage: G.maximum_leaf_number() + Traceback (most recent call last): + ... + ValueError: the graph must be connected + """ + if G.order() <= 1: + return 0 + if not G.is_connected(): + raise ValueError('the graph must be connected') + if G.order() <= 3: + return G.order() - 1 + return G.order() - dominating_set(G, connected=True, value_only=True, + solver=solver, verbose=verbose, + integrality_tolerance=integrality_tolerance) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index a99aa1d5a64..a9129a62e7d 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -315,6 +315,7 @@ :meth:`~GenericGraph.disjoint_routed_paths` | Return a set of disjoint routed paths. :meth:`~GenericGraph.dominating_set` | Return a minimum dominating set of the graph :meth:`~GenericGraph.greedy_dominating_set` | Return a greedy distance-`k` dominating set of the graph. + :meth:`~GenericGraph.maximum_leaf_number` | Return the maximum leaf number of the graph. :meth:`~GenericGraph.subgraph_search` | Return a copy of ``G`` in ``self``. :meth:`~GenericGraph.subgraph_search_count` | Return the number of labelled occurrences of ``G`` in ``self``. :meth:`~GenericGraph.subgraph_search_iterator` | Return an iterator over the labelled copies of ``G`` in ``self``. @@ -24407,6 +24408,7 @@ def is_self_complementary(self): from sage.graphs.domination import dominating_sets from sage.graphs.domination import dominating_set from sage.graphs.domination import greedy_dominating_set + from sage.graphs.domination import maximum_leaf_number from sage.graphs.base.static_dense_graph import connected_subgraph_iterator rooted_product = LazyImport('sage.graphs.graph_decompositions.graph_products', 'rooted_product') from sage.graphs.path_enumeration import shortest_simple_paths