@@ -137,7 +137,7 @@ def is_redundant(G, dom, focus=None):
137
137
False
138
138
"""
139
139
dom = list (dom )
140
- focus = list ( G ) if focus is None else list (focus )
140
+ focus = G if focus is None else set (focus )
141
141
142
142
# dominator[v] (for v in focus) will be equal to:
143
143
# - (0, None) if v has no neighbor in dom
@@ -343,6 +343,13 @@ def dominating_sets(g, k=1, independent=False, total=False,
343
343
Traceback (most recent call last):
344
344
...
345
345
ValueError: the domination distance must be a non-negative integer
346
+
347
+ The method is robust to vertices with incomparable labels::
348
+
349
+ sage: G = Graph([(1, 'A'), ('A', 2), (2, 3), (3, 1)])
350
+ sage: L = list(G.dominating_sets())
351
+ sage: len(L)
352
+ 6
346
353
"""
347
354
g ._scream_if_not_simple (allow_multiple_edges = True , allow_loops = not total )
348
355
@@ -719,8 +726,8 @@ def _aux_with_rep(H, to_dom, u_next):
719
726
720
727
# Here we use aux_with_rep twice to enumerate the minimal
721
728
# dominating sets while avoiding repeated outputs
722
- for ( X , i ) in _aux_with_rep (G , to_dom , u_next ):
723
- for ( Y , j ) in _aux_with_rep (G , to_dom , u_next ):
729
+ for X , i in _aux_with_rep (G , to_dom , u_next ):
730
+ for Y , j in _aux_with_rep (G , to_dom , u_next ):
724
731
if j >= i :
725
732
# This is the first time we meet X: we output it
726
733
yield X
@@ -730,7 +737,7 @@ def _aux_with_rep(H, to_dom, u_next):
730
737
break
731
738
732
739
733
- def minimal_dominating_sets (G , to_dominate = None , work_on_copy = False , k = 1 ):
740
+ def minimal_dominating_sets (G , to_dominate = None , work_on_copy = True , k = 1 ):
734
741
r"""
735
742
Return an iterator over the minimal dominating sets of a graph.
736
743
@@ -741,7 +748,7 @@ def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1):
741
748
- ``to_dominate`` -- vertex iterable or ``None`` (default: ``None``);
742
749
the set of vertices to be dominated.
743
750
744
- - ``work_on_copy`` -- boolean (default: ``False ``); whether or not to work on
751
+ - ``work_on_copy`` -- boolean (default: ``True ``); whether or not to work on
745
752
a copy of the input graph; if set to ``False``, the input graph will be
746
753
modified (relabeled).
747
754
@@ -889,6 +896,15 @@ def minimal_dominating_sets(G, to_dominate=None, work_on_copy=False, k=1):
889
896
Traceback (most recent call last):
890
897
...
891
898
ValueError: vertex (foo) is not a vertex of the graph
899
+
900
+ The method is robust to vertices with incomparable labels::
901
+
902
+ sage: G = Graph([(1, 'A'), ('A', 2), (2, 3), (3, 1)])
903
+ sage: L = list(G.minimal_dominating_sets())
904
+ sage: len(L)
905
+ 6
906
+ sage: {3, 'A'} in L
907
+ True
892
908
"""
893
909
def tree_search (H , plng , dom , i ):
894
910
r"""
@@ -942,7 +958,8 @@ def tree_search(H, plng, dom, i):
942
958
# We complete dom with can_ext -> canD
943
959
canD = set ().union (can_ext , dom )
944
960
945
- if (not H .is_redundant (canD , V_next )) and set (dom ) == set (_parent (H , canD , plng [i ][1 ])):
961
+ if (not H .is_redundant (canD , V_next )
962
+ and set (dom ) == set (_parent (H , canD , plng [i ][1 ]))):
946
963
# By construction, can_ext is a dominating set of
947
964
# `V_next - N[dom]`, so canD dominates V_next.
948
965
# If canD is a legitimate child of dom and is not redundant, we
@@ -952,6 +969,12 @@ def tree_search(H, plng, dom, i):
952
969
##
953
970
# end of tree-search routine
954
971
972
+ if k < 0 :
973
+ raise ValueError ("the domination distance must be a non-negative integer" )
974
+ if not k :
975
+ yield set (G ) if to_dominate is None else set (to_dominate )
976
+ return
977
+
955
978
int_to_vertex = list (G )
956
979
vertex_to_int = {u : i for i , u in enumerate (int_to_vertex )}
957
980
@@ -963,28 +986,24 @@ def tree_search(H, plng, dom, i):
963
986
raise ValueError (f"vertex ({ u } ) is not a vertex of the graph" )
964
987
vertices_to_dominate = {vertex_to_int [u ] for u in to_dominate }
965
988
966
- if k < 0 :
967
- raise ValueError ( "the domination distance must be a non-negative integer" )
968
- elif not k :
969
- yield set (int_to_vertex ) if to_dominate is None else set ( to_dominate )
989
+ if not vertices_to_dominate :
990
+ # base case: vertices_to_dominate is empty
991
+ # the empty set/list is the only minimal DS of the empty set
992
+ yield set ()
970
993
return
971
994
elif k > 1 :
972
995
# We build a graph H with an edge between u and v if these vertices are
973
996
# at distance at most k in G
974
997
H = G .__class__ (G .order ())
975
998
for u , ui in vertex_to_int .items ():
976
- H .add_edges ((ui , vertex_to_int [v ]) for v in G .breadth_first_search (u , distance = k ) if u != v )
999
+ H .add_edges ((ui , vertex_to_int [v ])
1000
+ for v in G .breadth_first_search (u , distance = k ) if u != v )
977
1001
G = H
978
1002
elif work_on_copy :
979
- G .relabel (perm = vertex_to_int )
980
- else :
981
1003
G = G .relabel (perm = vertex_to_int , inplace = False )
982
-
983
- if not vertices_to_dominate :
984
- # base case: vertices_to_dominate is empty
985
- # the empty set/list is the only minimal DS of the empty set
986
- yield set ()
987
- return
1004
+ else :
1005
+ # The input graph is modified
1006
+ G .relabel (perm = vertex_to_int , inplace = True )
988
1007
989
1008
peeling = _peel (G , vertices_to_dominate )
990
1009
@@ -1117,6 +1136,12 @@ def greedy_dominating_set(G, k=1, vertices=None, ordering=None, return_sets=Fals
1117
1136
sage: G = graphs.PathGraph(5)
1118
1137
sage: dom = greedy_dominating_set(G, vertices=[0, 1, 3, 4])
1119
1138
1139
+ The method is robust to vertices with incomparable labels::
1140
+
1141
+ sage: G = Graph([(1, 'A')])
1142
+ sage: len(greedy_dominating_set(G))
1143
+ 1
1144
+
1120
1145
Check parameters::
1121
1146
1122
1147
sage: greedy_dominating_set(G, ordering="foo")
0 commit comments