46
46
:meth:`acyclic_edge_coloring` | Compute an acyclic edge coloring of the current graph
47
47
48
48
49
-
50
49
AUTHORS:
51
50
52
51
- Tom Boothby (2008-02-21): Initial version
@@ -75,7 +74,69 @@ DLXCPP = LazyImport('sage.combinat.matrices.dlxcpp', 'DLXCPP')
75
74
MixedIntegerLinearProgram = LazyImport(' sage.numerical.mip' , ' MixedIntegerLinearProgram' )
76
75
77
76
78
- def all_graph_colorings (G , n , count_only = False , hex_colors = False , vertex_color_dict = False ):
77
+ def format_coloring (data , value_only = False , hex_colors = False , vertex_color_dict = False ):
78
+ r """
79
+ Helper method for vertex and edge coloring methods.
80
+
81
+ INPUT:
82
+
83
+ - ``data`` -- either a number when ``value_only`` is ``True`` or a list of
84
+ color classes
85
+
86
+ - ``value_only`` -- boolean ( default: ``False``) ; when set to ``True``, it
87
+ simply returns ``data``
88
+
89
+ - ``hex_colors`` -- boolean ( default: ``False``) ; when set to ``False``,
90
+ colors are labeled [0, 1, ..., `n - 1` ], otherwise the RGB Hex labeling
91
+ is used
92
+
93
+ - ``vertex_color_dict`` -- boolean ( default: ``False``) ; when set to
94
+ ``True``, it returns a dictionary ``{vertex: color}``, otherwise it
95
+ returns a dictionary ``{color: [list of vertices ]}``
96
+
97
+ EXAMPLES::
98
+
99
+ sage: from sage. graphs. graph_coloring import format_coloring
100
+ sage: color_classes = [['a', 'b' ], ['c' ], ['d' ]]
101
+ sage: format_coloring( color_classes, value_only=True)
102
+ [['a', 'b' ], ['c' ], ['d' ]]
103
+ sage: format_coloring( len( color_classes) , value_only=True)
104
+ 3
105
+ sage: format_coloring( color_classes, value_only=False)
106
+ {0: ['a', 'b' ], 1: ['c' ], 2: ['d' ]}
107
+ sage: format_coloring( color_classes, value_only=False, hex_colors=True)
108
+ {'#0000ff': ['d' ], '#00ff00': ['c' ], '#ff0000': ['a', 'b' ]}
109
+ sage: format_coloring( color_classes, value_only=False, hex_colors=False, vertex_color_dict=True)
110
+ {'a': 0, 'b': 0, 'c': 1, 'd': 2}
111
+ sage: format_coloring( color_classes, value_only=False, hex_colors=True, vertex_color_dict=True)
112
+ {'a': '#ff0000', 'b': '#ff0000', 'c': '#00ff00', 'd': '#0000ff'}
113
+
114
+ TESTS::
115
+
116
+ sage: from sage. graphs. graph_coloring import format_coloring
117
+ sage: format_coloring( [], value_only=True)
118
+ []
119
+ sage: format_coloring( [], value_only=False, hex_colors=True)
120
+ {}
121
+ sage: format_coloring( [], value_only=False, hex_colors=True, vertex_color_dict=True)
122
+ {}
123
+ sage: format_coloring( [], value_only=False, hex_colors=False, vertex_color_dict=True)
124
+ {}
125
+ """
126
+ if value_only:
127
+ return data
128
+ if hex_colors:
129
+ from sage.plot.colors import rainbow
130
+ colors = rainbow(len (data))
131
+ else :
132
+ colors = list (range (len (data)))
133
+ if vertex_color_dict:
134
+ return {u: col for col, C in zip (colors, data) for u in C}
135
+ return {col: C for col, C in zip (colors, data) if C}
136
+
137
+
138
+ def all_graph_colorings (G , n , count_only = False , hex_colors = False ,
139
+ vertex_color_dict = False , color_classes = False ):
79
140
r """
80
141
Compute all `n`-colorings of a graph.
81
142
@@ -90,7 +151,7 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d
90
151
* ``n`` -- a positive integer; the number of colors
91
152
92
153
* ``count_only`` -- boolean ( default: ``False``) ; when set to ``True``, it
93
- returns 1 for each coloring
154
+ returns 1 for each coloring and ignores other parameters
94
155
95
156
* ``hex_colors`` -- boolean ( default: ``False``) ; when set to ``False``,
96
157
colors are labeled [0, 1, ..., `n - 1` ], otherwise the RGB Hex labeling
@@ -100,6 +161,10 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d
100
161
``True``, it returns a dictionary ``{vertex: color}``, otherwise it
101
162
returns a dictionary ``{color: [list of vertices ]}``
102
163
164
+ * ``color_classes`` -- boolean ( default: ``False``) ; when set to ``True``,
165
+ the method returns only a list of the color classes and ignores parameters
166
+ ``hex_colors`` and ``vertex_color_dict``
167
+
103
168
.. WARNING::
104
169
105
170
This method considers only colorings using exactly `n` colors, even if a
@@ -170,27 +235,29 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d
170
235
sage: G = Graph( {0: [1 ], 1: [2 ]})
171
236
sage: for c in all_graph_colorings( G, 2, vertex_color_dict=True) :
172
237
.... : print( c)
173
- {0: 0, 1: 1, 2: 0 }
174
- {0: 1, 1: 0 , 2: 1}
238
+ {0: 0, 2: 0, 1: 1 }
239
+ {1: 0, 0: 1 , 2: 1}
175
240
sage: for c in all_graph_colorings( G, 2, hex_colors=True) :
176
241
.... : print( sorted( c. items( )))
177
242
[('#00ffff', [1 ]), ( '#ff0000', [0, 2 ]) ]
178
243
[('#00ffff', [0, 2 ]), ( '#ff0000', [1 ]) ]
179
244
sage: for c in all_graph_colorings( G, 2, hex_colors=True, vertex_color_dict=True) :
180
245
.... : print( c)
181
- {0: '#ff0000', 1 : '#00ffff ', 2 : '#ff0000 '}
182
- {0 : '#00ffff ', 1 : '#ff0000 ', 2: '#00ffff'}
246
+ {0: '#ff0000', 2 : '#ff0000 ', 1 : '#00ffff '}
247
+ {1 : '#ff0000 ', 0 : '#00ffff ', 2: '#00ffff'}
183
248
sage: for c in all_graph_colorings( G, 2, vertex_color_dict=True) :
184
249
.... : print( c)
185
- {0: 0, 1: 1, 2: 0 }
186
- {0: 1, 1: 0 , 2: 1}
250
+ {0: 0, 2: 0, 1: 1 }
251
+ {1: 0, 0: 1 , 2: 1}
187
252
sage: for c in all_graph_colorings( G, 2, count_only=True, vertex_color_dict=True) :
188
253
.... : print( c)
189
254
1
190
255
1
256
+ sage: for c in all_graph_colorings( G, 2, color_classes=True) :
257
+ .... : print( c)
258
+ [[0, 2 ], [1 ]]
259
+ [[1 ], [0, 2 ]]
191
260
"""
192
- from sage.plot.colors import rainbow
193
-
194
261
G._scream_if_not_simple(allow_multiple_edges = True )
195
262
196
263
if not n or n > G.order():
@@ -230,48 +297,29 @@ def all_graph_colorings(G, n, count_only=False, hex_colors=False, vertex_color_d
230
297
for i in range (n * nE):
231
298
ones.push_back((k + i, [nV + i]))
232
299
233
- cdef list colors = rainbow(n)
234
- cdef dict color_dict = {col: i for i, col in enumerate (colors)}
235
-
236
300
cdef list ones_second = [ones[i].second for i in range (len (ones))]
237
- cdef dict coloring
301
+ cdef list coloring
238
302
cdef set used_colors
239
303
240
304
try :
241
305
for a in DLXCPP(ones_second):
242
- coloring = {}
306
+ coloring = [[] for _ in range (n)]
243
307
used_colors = set ()
244
308
if count_only:
245
309
used_colors = set (colormap[x][1 ] for x in a if x in colormap)
246
- elif vertex_color_dict:
247
- for x in a:
248
- if x in colormap:
249
- v, c = colormap[x]
250
- used_colors.add(c)
251
- if hex_colors:
252
- coloring[v] = colors[c]
253
- else :
254
- coloring[v] = color_dict[colors[c]]
255
310
else :
256
311
for x in a:
257
312
if x in colormap:
258
313
v, c = colormap[x]
259
314
used_colors.add(c)
260
- if hex_colors:
261
- if colors[c] in coloring:
262
- coloring[colors[c]].append(v)
263
- else :
264
- coloring[colors[c]] = [v]
265
- else :
266
- if color_dict[colors[c]] in coloring:
267
- coloring[color_dict[colors[c]]].append(v)
268
- else :
269
- coloring[color_dict[colors[c]]] = [v]
315
+ coloring[c].append(v)
270
316
if len (used_colors) == n:
271
317
if count_only:
272
318
yield 1
273
319
else :
274
- yield coloring
320
+ yield format_coloring(coloring, value_only = color_classes,
321
+ hex_colors = hex_colors,
322
+ vertex_color_dict = vertex_color_dict)
275
323
except RuntimeError :
276
324
raise RuntimeError (" too much recursion, Graph coloring failed" )
277
325
@@ -310,11 +358,8 @@ cpdef first_coloring(G, n=0, hex_colors=False):
310
358
G._scream_if_not_simple(allow_multiple_edges = True )
311
359
cdef int o = G.order()
312
360
for m in range (n, o + 1 ):
313
- for C in all_graph_colorings(G, m, hex_colors = True ):
314
- if hex_colors:
315
- return C
316
- else :
317
- return list (C.values())
361
+ for C in all_graph_colorings(G, m, hex_colors = hex_colors, color_classes = not hex_colors):
362
+ return C
318
363
319
364
320
365
cpdef number_of_n_colorings(G, n):
@@ -402,7 +447,7 @@ cpdef chromatic_number(G):
402
447
# don't waste our time coloring.
403
448
return m
404
449
for n in range (m, o + 1 ):
405
- for C in all_graph_colorings(G, n):
450
+ for C in all_graph_colorings(G, n, count_only = True ):
406
451
return n
407
452
408
453
@@ -491,7 +536,6 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None,
491
536
4
492
537
"""
493
538
g._scream_if_not_simple(allow_multiple_edges = True )
494
- from sage.plot.colors import rainbow
495
539
cdef list colorings
496
540
cdef set vertices
497
541
cdef list deg
@@ -514,18 +558,15 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None,
514
558
if not g.size():
515
559
if value_only:
516
560
return 1
517
- elif hex_colors:
518
- return {rainbow(1 )[0 ]: list (g)}
519
- else :
520
- return [list (g)]
561
+ return format_coloring([list (g)], value_only = not hex_colors,
562
+ hex_colors = hex_colors)
521
563
# - Bipartite set
522
564
if g.is_bipartite():
523
565
if value_only:
524
566
return 2
525
- elif hex_colors:
526
- return dict (zip (rainbow(2 ), g.bipartite_sets()))
527
- else :
528
- return g.bipartite_sets()
567
+ return format_coloring(g.bipartite_sets(),
568
+ value_only = not hex_colors,
569
+ hex_colors = hex_colors)
529
570
530
571
# - No need to try any k smaller than the maximum clique in the graph
531
572
# - No need to try k less than |G|/alpha(G), as each color
@@ -553,10 +594,9 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None,
553
594
if not g.order():
554
595
if value_only:
555
596
return True
556
- elif hex_colors:
557
- return {color: [] for color in rainbow(k)}
558
- else :
559
- return [[] for i in range (k)]
597
+ return format_coloring([[] for i in range (k)],
598
+ value_only = not hex_colors,
599
+ hex_colors = hex_colors)
560
600
# Is the graph connected?
561
601
# This is not so stupid, as the graph could be disconnected
562
602
# by the test of degeneracy (as previously).
@@ -585,10 +625,9 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None,
585
625
for color in range (k):
586
626
for component in colorings:
587
627
value[color].extend(component[color])
588
- if hex_colors:
589
- return dict (zip (rainbow(k), value))
590
- else :
591
- return value
628
+
629
+ return format_coloring(value, value_only = not hex_colors,
630
+ hex_colors = hex_colors)
592
631
593
632
# Degeneracy
594
633
# Vertices whose degree is less than k are of no importance in
@@ -623,10 +662,9 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None,
623
662
classe.append(deg[- 1 ])
624
663
deg.pop(- 1 )
625
664
break
626
- if hex_colors:
627
- return dict (zip (rainbow(k), value))
628
- else :
629
- return value
665
+
666
+ return format_coloring(value, value_only = not hex_colors,
667
+ hex_colors = hex_colors)
630
668
631
669
p = MixedIntegerLinearProgram(maximization = True , solver = solver)
632
670
color = p.new_variable(binary = True )
@@ -664,10 +702,8 @@ def vertex_coloring(g, k=None, value_only=False, hex_colors=False, solver=None,
664
702
classes[i].append(v)
665
703
break
666
704
667
- if hex_colors:
668
- return dict (zip (rainbow(len (classes)), classes))
669
- else :
670
- return classes
705
+ return format_coloring(classes, value_only = not hex_colors,
706
+ hex_colors = hex_colors)
671
707
672
708
673
709
# Fractional relaxations
@@ -1088,9 +1124,9 @@ def b_coloring(g, k, value_only=True, solver=None, verbose=0,
1088
1124
proper coloring where each color class has a b-vertex.
1089
1125
1090
1126
In the worst case, after successive applications of the above procedure, one
1091
- get a proper coloring that uses a number of colors equal to the the
1092
- b-chromatic number of `G` ( denoted `\c hi_b( G) `) : the maximum `k` such that
1093
- `G` admits a b-coloring with `k` colors.
1127
+ get a proper coloring that uses a number of colors equal to the b-chromatic
1128
+ number of `G` ( denoted `\c hi_b( G) `) : the maximum `k` such that `G` admits a
1129
+ b-coloring with `k` colors.
1094
1130
1095
1131
A useful upper bound for calculating the b-chromatic number is the
1096
1132
following. If `G` admits a b-coloring with `k` colors, then there are `k`
@@ -1385,7 +1421,6 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No
1385
1421
{}
1386
1422
"""
1387
1423
g._scream_if_not_simple()
1388
- from sage.plot.colors import rainbow
1389
1424
1390
1425
if not g.order() or not g.size():
1391
1426
if value_only:
@@ -1492,10 +1527,7 @@ def edge_coloring(g, value_only=False, vizing=False, hex_colors=False, solver=No
1492
1527
return chi
1493
1528
1494
1529
# if needed, builds a dictionary from the color classes adding colors
1495
- if hex_colors:
1496
- return dict (zip (rainbow(len (classes)), classes))
1497
- else :
1498
- return classes
1530
+ return format_coloring(classes, value_only = not hex_colors, hex_colors = hex_colors)
1499
1531
1500
1532
1501
1533
def _vizing_edge_coloring (g ):
@@ -1861,8 +1893,6 @@ def linear_arboricity(g, plus_one=None, hex_colors=False, value_only=False,
1861
1893
else :
1862
1894
raise ValueError (" plus_one must be equal to 0,1, or to None!" )
1863
1895
1864
- from sage.plot.colors import rainbow
1865
-
1866
1896
p = MixedIntegerLinearProgram(solver = solver)
1867
1897
1868
1898
# c is a boolean value such that c[i,(u,v)] = 1 if and only if (u,v) is
@@ -1928,10 +1958,7 @@ def linear_arboricity(g, plus_one=None, hex_colors=False, value_only=False,
1928
1958
if c[i, frozenset ((u, v))]:
1929
1959
add((u, v), i)
1930
1960
1931
- if hex_colors:
1932
- return dict (zip (rainbow(len (answer)), answer))
1933
- else :
1934
- return answer
1961
+ return format_coloring(answer, value_only = not hex_colors, hex_colors = hex_colors)
1935
1962
1936
1963
1937
1964
def acyclic_edge_coloring (g , hex_colors = False , value_only = False , k = 0 ,
@@ -2079,7 +2106,6 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0,
2079
2106
2080
2107
from sage.rings.integer import Integer
2081
2108
from sage.combinat.subset import Subsets
2082
- from sage.plot.colors import rainbow
2083
2109
2084
2110
if not g.order() or not g.size():
2085
2111
if k == 0 :
@@ -2089,7 +2115,10 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0,
2089
2115
else :
2090
2116
if k is None :
2091
2117
return {} if hex_colors else []
2092
- return {c: [] for c in rainbow(k)} if hex_colors else [copy(g) for _ in range (k)]
2118
+ if hex_colors:
2119
+ return format_coloring([[] for _ in range (k)], hex_colors = True )
2120
+ else :
2121
+ return [copy(g) for _ in range (k)]
2093
2122
2094
2123
if k is None :
2095
2124
k = max (g.degree())
@@ -2181,10 +2210,7 @@ def acyclic_edge_coloring(g, hex_colors=False, value_only=False, k=0,
2181
2210
if c[i, E(u, v)]:
2182
2211
add((u, v), i)
2183
2212
2184
- if hex_colors:
2185
- return dict (zip (rainbow(len (answer)), answer))
2186
- else :
2187
- return answer
2213
+ return format_coloring(answer, value_only = not hex_colors, hex_colors = hex_colors)
2188
2214
2189
2215
2190
2216
cdef class Test:
0 commit comments