Skip to content

Commit 570d31b

Browse files
committed
Update has_diagonal
1 parent 95753e8 commit 570d31b

3 files changed

Lines changed: 54 additions & 43 deletions

File tree

src/coloring.jl

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ If `postprocessing=true`, some colors might be replaced with `0` (the "neutral"
7979
function star_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessing::Bool)
8080
# Initialize data structures
8181
S = pattern(g)
82+
has_diag = has_diagonal(g)
8283
nv = nb_vertices(g)
8384
ne = nb_edges(g)
8485
color = zeros(Int, nv)
@@ -91,8 +92,9 @@ function star_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessing::
9192
vertices_in_order = vertices(g, order)
9293

9394
for v in vertices_in_order
94-
for (iw, w) in enumerate(neighbors2(g, v))
95-
(v == w || iszero(color[w])) && continue
95+
for (iw, w) in enumerate(neighbors(g, v))
96+
!has_diag || (v == w && continue)
97+
iszero(color[w]) && continue
9698
index_vw = edge_to_index[S.colptr[v] + iw - 1]
9799
forbidden_colors[color[w]] = v
98100
(p, q, _) = first_neighbor[color[w]]
@@ -105,8 +107,9 @@ function star_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessing::
105107
_treat!(treated, forbidden_colors, g, v, w, color)
106108
else
107109
first_neighbor[color[w]] = (v, w, index_vw)
108-
for (ix, x) in enumerate(neighbors2(g, w))
109-
(w == x || x == v || iszero(color[x])) && continue
110+
for (ix, x) in enumerate(neighbors(g, w))
111+
!has_diag || (w == x && continue)
112+
(x == v || iszero(color[x])) && continue
110113
index_wx = edge_to_index[S.colptr[w] + ix - 1]
111114
if x == hub[star[index_wx]] # potential Case 2 (which is always false for trivial stars with two vertices, since the associated hub is negative)
112115
forbidden_colors[color[x]] = v
@@ -140,7 +143,9 @@ function _treat!(
140143
w::Integer,
141144
color::AbstractVector{<:Integer},
142145
)
146+
has_diag = has_diagonal(g)
143147
for x in neighbors(g, w)
148+
!has_diag || (w == x && continue)
144149
iszero(color[x]) && continue
145150
forbidden_colors[color[x]] = v
146151
end
@@ -160,12 +165,14 @@ function _update_stars!(
160165
edge_to_index::AbstractVector{<:Integer},
161166
)
162167
S = pattern(g)
163-
for (iw, w) in enumerate(neighbors2(g, v))
164-
(v == w || iszero(color[w])) && continue
168+
has_diag = has_diagonal(g)
169+
for (iw, w) in enumerate(neighbors(g, v))
170+
!has_diag || (v == w && continue)
171+
iszero(color[w]) && continue
165172
index_vw = edge_to_index[S.colptr[v] + iw - 1]
166173
x_exists = false
167-
for (ix, x) in enumerate(neighbors2(g, w))
168-
(w == x) && continue
174+
for (ix, x) in enumerate(neighbors(g, w))
175+
!has_diag || (w == x && continue)
169176
if x != v && color[x] == color[v] # vw, wx ∈ E
170177
index_wx = edge_to_index[S.colptr[w] + ix - 1]
171178
star_wx = star[index_wx]
@@ -232,6 +239,7 @@ If `postprocessing=true`, some colors might be replaced with `0` (the "neutral"
232239
function acyclic_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessing::Bool)
233240
# Initialize data structures
234241
S = pattern(g)
242+
has_diag = has_diagonal(g)
235243
nv = nb_vertices(g)
236244
ne = nb_edges(g)
237245
color = zeros(Int, nv)
@@ -244,13 +252,16 @@ function acyclic_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessin
244252

245253
for v in vertices_in_order
246254
for w in neighbors(g, v)
255+
!has_diag || (v == w && continue)
247256
iszero(color[w]) && continue
248257
forbidden_colors[color[w]] = v
249258
end
250259
for w in neighbors(g, v)
260+
!has_diag || (v == w && continue)
251261
iszero(color[w]) && continue
252-
for (ix, x) in enumerate(neighbors2(g, w))
253-
(w == x || iszero(color[x])) && continue
262+
for (ix, x) in enumerate(neighbors(g, w))
263+
!has_diag || (w == x && continue)
264+
iszero(color[x]) && continue
254265
if forbidden_colors[color[x]] != v
255266
index_wx = edge_to_index[S.colptr[w] + ix - 1]
256267
_prevent_cycle!(
@@ -272,15 +283,18 @@ function acyclic_coloring(g::AdjacencyGraph, order::AbstractOrder, postprocessin
272283
break
273284
end
274285
end
275-
for (iw, w) in enumerate(neighbors2(g, v)) # grow two-colored stars around the vertex v
276-
(v == w || iszero(color[w])) && continue
286+
for (iw, w) in enumerate(neighbors(g, v)) # grow two-colored stars around the vertex v
287+
!has_diag || (v == w && continue)
288+
iszero(color[w]) && continue
277289
index_vw = edge_to_index[S.colptr[v] + iw - 1]
278290
_grow_star!(v, w, index_vw, color, first_neighbor, forest)
279291
end
280-
for (iw, w) in enumerate(neighbors2(g, v))
281-
(v == w || iszero(color[w])) && continue
282-
for (ix, x) in enumerate(neighbors2(g, w))
283-
(w == x || x == v || iszero(color[x])) && continue
292+
for (iw, w) in enumerate(neighbors(g, v))
293+
!has_diag || (v == w && continue)
294+
iszero(color[w]) && continue
295+
for (ix, x) in enumerate(neighbors(g, w))
296+
!has_diag || (w == x && continue)
297+
(x == v || iszero(color[x])) && continue
284298
if color[x] == color[v]
285299
index_vw = edge_to_index[S.colptr[v] + iw - 1]
286300
index_wx = edge_to_index[S.colptr[w] + ix - 1]

src/graph.jl

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ end
9898
9999
Return a [`SparsityPatternCSC`](@ref) corresponding to the matrix `[0 Aᵀ; A 0]`, with a minimum of allocations.
100100
"""
101-
bidirectional_pattern(A::AbstractMatrix; symmetric_pattern) =
101+
bidirectional_pattern(A::AbstractMatrix; symmetric_pattern::Bool) =
102102
bidirectional_pattern(SparsityPatternCSC(SparseMatrixCSC(A)); symmetric_pattern)
103103

104-
function bidirectional_pattern(S::SparsityPatternCSC; symmetric_pattern)
104+
function bidirectional_pattern(S::SparsityPatternCSC; symmetric_pattern::Bool)
105105
m, n = size(S)
106106
p = m + n
107107
nnzS = nnz(S)
@@ -194,7 +194,7 @@ end
194194
## Adjacency graph
195195

196196
"""
197-
AdjacencyGraph{T,has_diagonal}
197+
AdjacencyGraph{T}
198198
199199
Undirected graph without self-loops representing the nonzeros of a symmetric matrix (typically a Hessian matrix).
200200
@@ -205,22 +205,24 @@ The adjacency graph of a symmetric matrix `A ∈ ℝ^{n × n}` is `G(A) = (V, E)
205205
206206
# Constructors
207207
208-
AdjacencyGraph(A::SparseMatrixCSC)
208+
AdjacencyGraph(A::SparseMatrixCSC; has_diagonal::Bool=true)
209209
210210
# Fields
211211
212-
- `S::SparsityPatternCSC{T}`: Underlying sparsity pattern, whose diagonal is empty whenever `has_diagonal` is `false`
212+
- `S::SparsityPatternCSC{T}`: Underlying sparsity pattern
213+
- `has_diagonal::Bool`: Diagonal is empty whenever `has_diagonal` is `false`
213214
214215
# References
215216
216217
> [_What Color Is Your Jacobian? SparsityPatternCSC Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005)
217218
"""
218-
struct AdjacencyGraph{T,has_diagonal}
219+
struct AdjacencyGraph{T}
219220
S::SparsityPatternCSC{T}
221+
has_diagonal::Bool
220222
end
221223

222224
function AdjacencyGraph(S::SparsityPatternCSC{T}; has_diagonal::Bool=true) where {T}
223-
return AdjacencyGraph{T,has_diagonal}(S)
225+
return AdjacencyGraph{T}(S, has_diagonal)
224226
end
225227

226228
function AdjacencyGraph(A::SparseMatrixCSC; has_diagonal::Bool=true)
@@ -234,22 +236,9 @@ end
234236
pattern(g::AdjacencyGraph) = g.S
235237
nb_vertices(g::AdjacencyGraph) = pattern(g).n
236238
vertices(g::AdjacencyGraph) = 1:nb_vertices(g)
239+
has_diagonal(g::AdjacencyGraph) = g.has_diagonal
237240

238-
has_diagonal(::AdjacencyGraph{T,hl}) where {T,hl} = hl
239-
240-
function neighbors(g::AdjacencyGraph{T,true}, v::Integer) where {T}
241-
S = pattern(g)
242-
neighbors_v = view(rowvals(S), nzrange(S, v))
243-
return Iterators.filter(!=(v), neighbors_v) # TODO: optimize
244-
end
245-
246-
function neighbors(g::AdjacencyGraph{T,false}, v::Integer) where {T}
247-
S = pattern(g)
248-
neighbors_v = view(rowvals(S), nzrange(S, v))
249-
return neighbors_v
250-
end
251-
252-
function neighbors2(g::AdjacencyGraph, v::Integer)
241+
function neighbors(g::AdjacencyGraph, v::Integer)
253242
S = pattern(g)
254243
neighbors_v = view(rowvals(S), nzrange(S, v))
255244
return neighbors_v
@@ -266,20 +255,27 @@ function degree(g::AdjacencyGraph, v::Integer)
266255
end
267256

268257
function nb_edges(g::AdjacencyGraph)
269-
ne = 0
270-
for v in vertices(g)
271-
for u in neighbors(g, v)
272-
ne += 1
258+
has_diag = has_diagonal(g)
259+
if !has_diag
260+
S = pattern(g)
261+
ne = nnz(S)
262+
return ne ÷ 2
263+
else
264+
ne = 0
265+
for v in vertices(g)
266+
ne += degree(g, v)
273267
end
268+
return ne ÷ 2
274269
end
275-
return ne ÷ 2
276270
end
277271

278272
maximum_degree(g::AdjacencyGraph) = maximum(Base.Fix1(degree, g), vertices(g))
279273
minimum_degree(g::AdjacencyGraph) = minimum(Base.Fix1(degree, g), vertices(g))
280274

281275
function has_neighbor(g::AdjacencyGraph, v::Integer, u::Integer)
282276
for w in neighbors(g, v)
277+
# We don't need the next line if we know that u != v
278+
v == w && continue
283279
if w == u
284280
return true
285281
end

src/order.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ function vertices(
209209
u = pop_next_candidate!(db; direction)
210210
direction == :low2high ? push!(π, u) : pushfirst!(π, u)
211211
for v in neighbors(g, u)
212+
u == v && continue
212213
already_ordered(db, v) && continue
213214
update_bucket!(db, v; degtype, direction)
214215
end

0 commit comments

Comments
 (0)