@@ -10,29 +10,27 @@ is a collection of trees—and hence is acyclic.
1010Reference: Gebremedhin AH, Manne F, Pothen A. **New Acyclic and Star Coloring Algorithms with Application to Computing Hessians**
1111"""
1212function color_graph (g:: LightGraphs.AbstractGraph , :: AcyclicColoring )
13-
1413 color = zeros (Int, nv (g))
15- forbidden_colors = zeros ( Int, nv (g ))
14+ two_colored_forest = DisjointSets { Int} (( ))
1615
17- set = DisjointSets {LightGraphs.Edge} ([])
16+ first_visit_to_tree = fill ((0 ,0 ), ne (g))
17+ first_neighbor = fill ((0 ,0 ), ne (g))
1818
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))
2120
2221 for v in vertices (g)
23- # enforces the first condition of acyclic coloring
2422 for w in outneighbors (g, v)
2523 if color[w] != 0
2624 forbidden_colors[color[w]] = v
2725 end
2826 end
29- # enforces the second condition of acyclic coloring
27+
3028 for w in outneighbors (g, v)
31- if color[w] != 0 # colored neighbor
29+ if color[w] != 0
3230 for x in outneighbors (g, w)
33- if color[x] != 0 # colored x
31+ if color[x] != 0
3432 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 )
3634 end
3735 end
3836 end
@@ -41,162 +39,177 @@ function color_graph(g::LightGraphs.AbstractGraph, ::AcyclicColoring)
4139
4240 color[v] = min_index (forbidden_colors, v)
4341
44- # grow star for every edge connecting colored vertices v and w
4542 for w in outneighbors (g, v)
4643 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)
4845 end
4946 end
5047
51- # merge the newly formed stars into existing trees if possible
5248 for w in outneighbors (g, v)
5349 if color[w] != 0
5450 for x in outneighbors (g, w)
5551 if color[x] != 0 && x != v
5652 if color[x] == color[v]
57- merge_trees! (set, v, w, x, g)
53+ merge_trees! (two_colored_forest,v,w,x, g)
5854 end
5955 end
6056 end
6157 end
6258 end
6359 end
64-
6560 return color
6661end
6762
63+
6864"""
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 })
7773
7874Subroutine to avoid generation of 2-colored cycle due to coloring of vertex v,
7975which 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'
8178"""
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 ,
8382 w:: Integer ,
8483 x:: Integer ,
8584 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]
9089
91- edge = find_edge (g, w, x)
92- e = find_root (set, edge)
93- p, q = first_visit_to_tree[edge_index (g, e)]
9490 if p != v
95- first_visit_to_tree[edge_index (g, e) ] = (v, w)
91+ first_visit_to_tree[e ] = (v,w)
9692 elseif q != w
9793 forbidden_colors[color[x]] = v
9894 end
9995end
10096
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
10997
11098"""
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})
117105
118106Grow a 2-colored star after assigning a new color to the
119107previously uncolored vertex v, by comparing it with the adjacent vertex w.
120108Disjoint set is used to store stars in sets, which are identified through key
121109edges present in g.
122110"""
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)
131118 p, q = first_neighbor[color[w]]
119+
132120 if p != v
133- first_neighbor[color[w]] = (v, w)
121+ first_neighbor[color[w]] = (v,w)
134122 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)
140126 end
141- return nothing
142127end
143128
144129
145130"""
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 )
151136
152137Subroutine to merge trees present in the disjoint set which have a
153138common edge.
154139"""
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)
166149 end
167150end
168151
169152
170153"""
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)
172158
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
175161"""
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)
185168end
186169
170+
187171"""
188- edge_index(g::LightGraphs.AbstractGraph, e::LightGraphs.Edge )
172+ min_index(forbidden_colors::AbstractVector{<:Integer}, v::Integer )
189173
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}
193175"""
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
199211 end
212+ pos = pos + 1
200213 end
201- throw (ArgumentError (" Edge $e is not present in graph g " ))
214+ throw (ArgumentError (" $v and $w are not connected in the graph " ))
202215end
0 commit comments