1
+ """
2
+ color_graph(g::LightGraphs.AbstractGraphs, ::AcyclicColoring)
3
+
4
+ Returns a coloring vector following the acyclic coloring rules (1) the coloring
5
+ corresponds to a distance-1 coloring, and (2) vertices in every cycle of the
6
+ graph are assigned at least three distinct colors. This variant of coloring is
7
+ called acyclic since every subgraph induced by vertices assigned any two colors
8
+ is a collection of trees—and hence is acyclic.
9
+
10
+ Reference: Gebremedhin AH, Manne F, Pothen A. **New Acyclic and Star Coloring Algorithms with Application to Computing Hessians**
11
+ """
1
12
function color_graph (g:: LightGraphs.AbstractGraph , :: AcyclicColoring )
2
13
color = zeros (Int, nv (g))
3
14
set = DisjointSets {Int} ([])
@@ -8,71 +19,39 @@ function color_graph(g::LightGraphs.AbstractGraph, ::AcyclicColoring)
8
19
init_array! (first_visit_to_tree, ne (g))
9
20
init_array! (first_neighbor, ne (g))
10
21
11
-
12
-
13
22
forbidden_colors = zeros (Int, nv (g))
14
23
15
24
for v in vertices (g)
16
- # println(">>>\nOUTER LOOP")
17
- # println(">>> v = $v")
18
- # println(">>> first block")
19
25
for w in outneighbors (g, v)
20
- # println(">>> w = $w")
21
26
if color[w]!= 0
22
- # wc = color[w]
23
- # println(">>> $w has nonzero color = $wc")
24
- # println(">>> setting forbidden color[$wc] = $v")
25
27
forbidden_colors[color[w]] = v
26
28
end
27
29
end
28
30
29
- # println(">>> second block")
30
31
for w in outneighbors (g, v)
31
- # println(">>> w = $w")
32
32
if color[w]!= 0
33
- # wc = color[w]
34
- # println(">>> $w has nonzero color = $wc")
35
33
for x in outneighbors (g, w)
36
- # println(">>> x = $x")
37
- # wx = color[x]
38
- # println(">>> $x has color = $wx")
39
34
if color[x]!= 0
40
- # println(">>> $wx != 0")
41
- # fbc = forbidden_colors[color[x]]
42
- # println(">>> forbidden color[$wx] = $fbc")
43
35
if forbidden_colors[color[x]] != v
44
- # println(">>> $fbc != $v")
45
- # println(">>> calling prevent cycle with $v, $w, $x")
46
36
prevent_cycle! (v, w, x, g, set, first_visit_to_tree, forbidden_colors,color)
47
37
end
48
38
end
49
39
end
50
40
end
51
41
end
52
42
53
- # println(">>> third block")
54
43
color[v] = min_index (forbidden_colors, v)
55
- # vc = color[v]
56
- # println(">>> color of v = $vc")
44
+
57
45
for w in outneighbors (g, v)
58
- # println(">>> w = $w")
59
46
if color[w]!= 0
60
- # println(">>> calling grow star for v = $v, w = $w")
61
47
grow_star! (v, w, g, set,first_neighbor,color)
62
48
end
63
49
end
64
50
65
- # println(">>> fourth block")
66
51
for w in outneighbors (g, v)
67
- # println(">>> w = $w")
68
52
if color[w]!= 0
69
- # wc = color[w]
70
- # println(">>> $w has non zero color = $wc")
71
53
for x in outneighbors (g, w)
72
- # wx = color[x]
73
- # println(">>> x = $x")
74
54
if color[x]!= 0 && x!= v
75
- # println(">>> $x has nonzero color = $wx")
76
55
if color[x]== color[v]
77
56
merge_trees! (v,w,x,g,set)
78
57
end
@@ -84,29 +63,62 @@ function color_graph(g::LightGraphs.AbstractGraph, ::AcyclicColoring)
84
63
return color
85
64
end
86
65
87
- function init_array! (array, n)
88
- for i in 1 : n
89
- push! (array,(0 ,0 ))
90
- end
91
- end
92
66
93
- function prevent_cycle! (v:: Int , w:: Int , x:: Int , g, set, first_visit_to_tree, forbidden_colors,color)
67
+ """
68
+ prevent_cycle(v::Integer,
69
+ w::Integer,
70
+ x::Integer,
71
+ g::LightGraphs.AbstractGraph,
72
+ color::AbstractVector{<:Integer},
73
+ forbidden_colors::AbstractVector{<:Integer},
74
+ first_visit_to_tree::Array{Tuple{Integer, Integer}, 1},
75
+ set::DisjointSets{LightGraphs.Edge})
76
+
77
+ Subroutine to avoid generation of 2-colored cycle due to coloring of vertex v,
78
+ which is adjacent to vertices w and x in graph g. Disjoint set is used to store
79
+ the induced 2-colored subgraphs/trees where the id of set is a key edge of g
80
+ """
81
+ function prevent_cycle! (v:: Integer ,
82
+ w:: Integer ,
83
+ x:: Integer ,
84
+ g:: LightGraphs.AbstractGraph ,
85
+ set:: DisjointSets{<:Integer} ,
86
+ first_visit_to_tree:: AbstractVector{<:Tuple{Integer,Integer}} ,
87
+ forbidden_colors:: AbstractVector{<:Tuple{Integer, Integer}} ,
88
+ color:: AbstractVector{<:Integer} )
94
89
e = find (w, x, g, set)
95
90
p, q = first_visit_to_tree[e]
96
- # println(">>> first visit to tree : p = $p, q = $q")
91
+
97
92
if p != v
98
93
first_visit_to_tree[e] = (v,w)
99
94
elseif q != w
100
95
forbidden_colors[color[x]] = v
101
96
end
102
97
end
103
98
104
- function grow_star! (v, w,g,set,first_neighbor,color)
99
+
100
+ """
101
+ grow_star!(set::DisjointSets{LightGraphs.Edge},
102
+ v::Integer,
103
+ w::Integer,
104
+ g::LightGraphs.AbstractGraph,
105
+ first_neighbor::AbstractVector{<:Tuple{Integer, Integer}},
106
+ color::AbstractVector{<: Integer})
107
+
108
+ Grow a 2-colored star after assigning a new color to the
109
+ previously uncolored vertex v, by comparing it with the adjacent vertex w.
110
+ Disjoint set is used to store stars in sets, which are identified through key
111
+ edges present in g.
112
+ """
113
+ function grow_star! (v:: Integer ,
114
+ w:: Integer ,
115
+ g:: LightGraphs.AbstractGraph ,
116
+ set:: DisjointSets{Integer} ,
117
+ first_neighbor:: AbstractVector{<:Tuple{Integer,Integer}} ,
118
+ color:: AbstractVector{<:Integer} )
105
119
make_set! (v,w,g,set)
106
120
p, q = first_neighbor[color[w]]
107
- # wc = color[w]
108
- # println(">>> color of w = $wc")
109
- # println(">>> first neighbor : p = $p, q = $q")
121
+
110
122
if p != v
111
123
first_neighbor[color[w]] = (v,w)
112
124
else
@@ -116,37 +128,104 @@ function grow_star!(v, w,g,set,first_neighbor,color)
116
128
end
117
129
end
118
130
119
- function merge_trees! (v,w,x,g,set)
131
+
132
+ """
133
+ merge_trees!(v::Integer,
134
+ w::Integer,
135
+ x::Integer,
136
+ g::LightGraphs.AbstractGraph,
137
+ set::DisjointSets{LightGraphs.Edge})
138
+
139
+ Subroutine to merge trees present in the disjoint set which have a
140
+ common edge.
141
+ """
142
+ function merge_trees! (v:: Integer ,
143
+ w:: Integer ,
144
+ x:: Integer ,
145
+ g:: LightGraphs.AbstractGraph ,
146
+ set:: DisjointSets{<:Integer} )
120
147
e1 = find (v,w,g,set)
121
148
e2 = find (w,x,g,set)
122
149
if e1 != e2
123
150
union! (set, e1, e2)
124
151
end
125
152
end
126
153
127
- function make_set! (v,w,g,set)
154
+
155
+ """
156
+ make_set!(v::Integer,
157
+ w::Integer,
158
+ g::LightGraphs.AbstractGraph,
159
+ set::DisjointSets{<:Integer})
160
+
161
+ creates a new singleton set in the disjoint set 'set' consisting
162
+ of the edge connecting v and w in the graph g
163
+ """
164
+ function make_set! (v:: Integer ,
165
+ w:: Integer ,
166
+ g:: LightGraphs.AbstractGraph ,
167
+ set:: DisjointSets{<:Integer} )
128
168
edge_index = find_edge_index (v,w,g)
129
169
push! (set,edge_index)
130
170
end
131
171
132
- function min_index (forbidden_colors, v)
172
+
173
+ """
174
+ min_index(forbidden_colors::AbstractVector{<:Integer}, v::Integer)
175
+
176
+ Returns min{i > 0 such that forbidden_colors[i] != v}
177
+ """
178
+ function min_index (forbidden_colors:: AbstractVector{<:Integer} , v:: Integer )
133
179
return findfirst (! isequal (v), forbidden_colors)
134
180
end
135
181
136
- function find (w, x, g, set)
182
+
183
+ """
184
+ find(w::Integer,
185
+ x::Integer,
186
+ g::LightGraphs.AbstractGraph,
187
+ set::DisjointSets{<:Integer})
188
+
189
+ Returns the root of the disjoint set to which the edge connecting vertices w and x
190
+ in the graph g belongs to
191
+ """
192
+ function find (w:: Integer ,
193
+ x:: Integer ,
194
+ g:: LightGraphs.AbstractGraph ,
195
+ set:: DisjointSets{<:Integer} )
137
196
edge_index = find_edge_index (w, x, g)
138
197
return find_root (set, edge_index)
139
198
end
140
199
141
- function find_edge_index (v, w, g)
142
- # print("function called")
200
+
201
+ """
202
+ find_edge(g::LightGraphs.AbstractGraph, v::Integer, w::Integer)
203
+
204
+ Returns an integer equivalent to the index of the edge connecting the vertices
205
+ v and w in the graph g
206
+ """
207
+ function find_edge_index (v:: Integer , w:: Integer , g:: LightGraphs.AbstractGraph )
143
208
pos = 1
144
209
for i in edges (g)
145
- # print("inside loop")
210
+
146
211
if (src (i)== v && dst (i)== w) || (src (i)== w && dst (i)== v)
147
212
return pos
148
213
end
149
214
pos = pos + 1
150
215
end
151
216
throw (ArgumentError (" $v and $w are not connected in the graph" ))
152
217
end
218
+
219
+
220
+ """
221
+ init_array(array::AbstractVector{<:Tuple{Integer, Integer}},
222
+ n::Integer)
223
+
224
+ Helper function to initialize the data structures with tuple (0,0)
225
+ """
226
+ function init_array! (array:: AbstractVector{<:Tuple{Integer, Integer}} ,
227
+ n:: Integer )
228
+ for i in 1 : n
229
+ push! (array,(0 ,0 ))
230
+ end
231
+ end
0 commit comments