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