@@ -9,30 +9,31 @@ is a collection of trees—and hence is acyclic.
9
9
10
10
Reference: Gebremedhin AH, Manne F, Pothen A. **New Acyclic and Star Coloring Algorithms with Application to Computing Hessians**
11
11
"""
12
- function color_graph (g:: LightGraphs.AbstractGraph )
13
-
12
+ function color_graph (g:: LightGraphs.AbstractGraph , :: AcyclicColoring )
14
13
color = zeros (Int, nv (g))
15
- forbidden_colors = zeros (Int, nv (g))
14
+ set = DisjointSets {Int} ([])
15
+
16
+ first_visit_to_tree = Array {Tuple{Int, Int}, 1} ()
17
+ first_neighbor = Array {Tuple{Int, Int}, 1} ()
16
18
17
- set = DisjointSets {LightGraphs.Edge} ([])
19
+ init_array! (first_visit_to_tree, ne (g))
20
+ init_array! (first_neighbor, ne (g))
18
21
19
- first_visit_to_tree = Array {Tuple{Int, Int}, 1} (undef, ne (g))
20
- first_neighbor = Array {Tuple{Int, Int}, 1} (undef, nv (g))
22
+ forbidden_colors = zeros (Int, nv (g))
21
23
22
24
for v in vertices (g)
23
- # enforces the first condition of acyclic coloring
24
25
for w in outneighbors (g, v)
25
- if color[w] != 0
26
+ if color[w]!= 0
26
27
forbidden_colors[color[w]] = v
27
28
end
28
29
end
29
- # enforces the second condition of acyclic coloring
30
+
30
31
for w in outneighbors (g, v)
31
- if color[w] != 0 # colored neighbor
32
+ if color[w]!= 0
32
33
for x in outneighbors (g, w)
33
- if color[x] != 0 # colored x
34
+ if color[x]!= 0
34
35
if forbidden_colors[color[x]] != v
35
- prevent_cycle (v, w, x, g, color, forbidden_colors, first_visit_to_tree, set )
36
+ prevent_cycle! (v, w, x, g, set, first_visit_to_tree, forbidden_colors,color )
36
37
end
37
38
end
38
39
end
@@ -41,30 +42,28 @@ function color_graph(g::LightGraphs.AbstractGraph)
41
42
42
43
color[v] = min_index (forbidden_colors, v)
43
44
44
- # grow star for every edge connecting colored vertices v and w
45
45
for w in outneighbors (g, v)
46
- if color[w] != 0
47
- grow_star! (set, v, w, g, first_neighbor, color)
46
+ if color[w]!= 0
47
+ grow_star! (v, w, g, set, first_neighbor,color)
48
48
end
49
49
end
50
50
51
- # merge the newly formed stars into existing trees if possible
52
51
for w in outneighbors (g, v)
53
- if color[w] != 0
52
+ if color[w]!= 0
54
53
for x in outneighbors (g, w)
55
- if color[x] != 0 && x != v
56
- if color[x] == color[v]
57
- merge_trees! (set, v, w, x, g )
54
+ if color[x]!= 0 && x!= v
55
+ if color[x]== color[v]
56
+ merge_trees! (v,w,x,g,set )
58
57
end
59
58
end
60
59
end
61
60
end
62
61
end
63
62
end
64
-
65
63
return color
66
64
end
67
65
66
+
68
67
"""
69
68
prevent_cycle(v::Integer,
70
69
w::Integer,
@@ -79,33 +78,24 @@ Subroutine to avoid generation of 2-colored cycle due to coloring of vertex v,
79
78
which is adjacent to vertices w and x in graph g. Disjoint set is used to store
80
79
the induced 2-colored subgraphs/trees where the id of set is a key edge of g
81
80
"""
82
- function prevent_cycle (v:: Integer ,
81
+ function prevent_cycle! (v:: Integer ,
83
82
w:: Integer ,
84
83
x:: Integer ,
85
84
g:: LightGraphs.AbstractGraph ,
86
- color:: AbstractVector{<:Integer} ,
87
- forbidden_colors:: AbstractVector{<:Integer} ,
88
- first_visit_to_tree:: AbstractVector{<:Tuple{Integer, Integer}} ,
89
- set:: DisjointSets{LightGraphs.Edge} )
90
-
91
- edge = find_edge (g, w, x)
92
- e = find_root (set, edge)
93
- p, q = first_visit_to_tree[edge_index (g, e)]
85
+ set:: DisjointSets{<:Integer} ,
86
+ first_visit_to_tree:: AbstractVector{<:Tuple{Integer,Integer}} ,
87
+ forbidden_colors:: AbstractVector{<:Tuple{Integer, Integer}} ,
88
+ color:: AbstractVector{<:Integer} )
89
+ e = find (w, x, g, set)
90
+ p, q = first_visit_to_tree[e]
91
+
94
92
if p != v
95
- first_visit_to_tree[edge_index (g, e) ] = (v, w)
93
+ first_visit_to_tree[e ] = (v,w)
96
94
elseif q != w
97
95
forbidden_colors[color[x]] = v
98
96
end
99
97
end
100
98
101
- """
102
- min_index(forbidden_colors::AbstractVector{<:Integer}, v::Integer)
103
-
104
- Returns min{i > 0 such that forbidden_colors[i] != v}
105
- """
106
- function min_index (forbidden_colors:: AbstractVector{<:Integer} , v:: Integer )
107
- return findfirst (! isequal (v), forbidden_colors)
108
- end
109
99
110
100
"""
111
101
grow_star!(set::DisjointSets{LightGraphs.Edge},
@@ -120,25 +110,22 @@ previously uncolored vertex v, by comparing it with the adjacent vertex w.
120
110
Disjoint set is used to store stars in sets, which are identified through key
121
111
edges present in g.
122
112
"""
123
- function grow_star! (set:: DisjointSets{LightGraphs.Edge} ,
124
- v:: Integer ,
125
- w:: Integer ,
126
- g:: LightGraphs.AbstractGraph ,
127
- first_neighbor:: AbstractVector{<:Tuple{Integer, Integer}} ,
128
- color:: AbstractVector{<: Integer} )
129
- edge = find_edge (g, v, w)
130
- push! (set, edge)
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} )
119
+ make_set! (v,w,g,set)
131
120
p, q = first_neighbor[color[w]]
121
+
132
122
if p != v
133
- first_neighbor[color[w]] = (v, w)
123
+ first_neighbor[color[w]] = (v,w)
134
124
else
135
- edge1 = find_edge (g, v, w)
136
- edge2 = find_edge (g, p, q)
137
- e1 = find_root (set, edge1)
138
- e2 = find_root (set, edge2)
125
+ e1 = find (v,w,g,set)
126
+ e2 = find (p,q,g,set)
139
127
union! (set, e1, e2)
140
128
end
141
- return nothing
142
129
end
143
130
144
131
@@ -152,51 +139,93 @@ end
152
139
Subroutine to merge trees present in the disjoint set which have a
153
140
common edge.
154
141
"""
155
- function merge_trees! (set:: DisjointSets{LightGraphs.Edge} ,
156
- v:: Integer ,
157
- w:: Integer ,
158
- x:: Integer ,
159
- g:: LightGraphs.AbstractGraph )
160
- edge1 = find_edge (g, v, w)
161
- edge2 = find_edge (g, w, x)
162
- e1 = find_root (set, edge1)
163
- e2 = find_root (set, edge2)
164
- if (e1 != e2)
142
+ function merge_trees! (v:: Integer ,
143
+ w:: Integer ,
144
+ x:: Integer ,
145
+ g:: LightGraphs.AbstractGraph ,
146
+ set:: DisjointSets{<:Integer} )
147
+ e1 = find (v,w,g,set)
148
+ e2 = find (w,x,g,set)
149
+ if e1 != e2
165
150
union! (set, e1, e2)
166
151
end
167
152
end
168
153
169
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} )
168
+ edge_index = find_edge_index (v,w,g)
169
+ push! (set,edge_index)
170
+ end
171
+
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 )
179
+ return findfirst (! isequal (v), forbidden_colors)
180
+ end
181
+
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} )
196
+ edge_index = find_edge_index (w, x, g)
197
+ return find_root (set, edge_index)
198
+ end
199
+
200
+
170
201
"""
171
202
find_edge(g::LightGraphs.AbstractGraph, v::Integer, w::Integer)
172
203
173
- Returns an edge object of the type LightGraphs.Edge which represents the
174
- edge connecting vertices v and w of the undirected graph g
204
+ Returns an integer equivalent to the index of the edge connecting the vertices
205
+ v and w in the graph g
175
206
"""
176
- function find_edge ( g:: LightGraphs.AbstractGraph ,
177
- v :: Integer ,
178
- w :: Integer )
179
- for e in edges (g)
180
- if (src (e) == v && dst (e) == w) || (src (e) == w && dst (e) == v)
181
- return e
207
+ function find_edge_index (v :: Integer , w :: Integer , g:: LightGraphs.AbstractGraph )
208
+ pos = 1
209
+ for i in edges (g )
210
+
211
+ if (src (i) == v && dst (i) == w) || (src (i) == w && dst (i) == v)
212
+ return pos
182
213
end
214
+ pos = pos + 1
183
215
end
184
- throw (ArgumentError (" $v and $w are not connected in graph g " ))
216
+ throw (ArgumentError (" $v and $w are not connected in the graph " ))
185
217
end
186
218
219
+
187
220
"""
188
- edge_index(g::LightGraphs.AbstractGraph, e::LightGraphs.Edge)
221
+ init_array(array::AbstractVector{<:Tuple{Integer, Integer}},
222
+ n::Integer)
189
223
190
- Returns an Integer value which uniquely identifies the edge e in graph
191
- g. Used as an index in main function to avoid custom arrays with non-
192
- numerical indices.
224
+ Helper function to initialize the data structures with tuple (0,0)
193
225
"""
194
- function edge_index (g:: LightGraphs.AbstractGraph ,
195
- e:: LightGraphs.Edge )
196
- for (i, edge) in enumerate (edges (g))
197
- if edge == e
198
- return i
199
- end
226
+ function init_array! (array:: AbstractVector{<:Tuple{Integer, Integer}} ,
227
+ n:: Integer )
228
+ for i in 1 : n
229
+ push! (array,(0 ,0 ))
200
230
end
201
- throw (ArgumentError (" Edge $e is not present in graph g" ))
202
231
end
0 commit comments