Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions src/coloring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ function star_coloring(

for v in vertices_in_order
for (w, index_vw) in neighbors_with_edge_indices(g, v)
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
color_w = color[w]
iszero(color_w) && continue
forbidden_colors[color_w] = v
Expand All @@ -139,7 +139,7 @@ function star_coloring(
else
first_neighbor[color[w]] = (v, w, index_vw)
for (x, index_wx) in neighbors_with_edge_indices(g, w)
!has_diagonal(g) || (w == x && continue)
augmented_graph(g) || (w == x && continue)
color_x = color[x]
(x == v || iszero(color_x)) && continue
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)
Expand Down Expand Up @@ -184,7 +184,7 @@ function _treat!(
color::AbstractVector{<:Integer},
)
for x in neighbors(g, w)
!has_diagonal(g) || (w == x && continue)
augmented_graph(g) || (w == x && continue)
color_x = color[x]
iszero(color_x) && continue
forbidden_colors[color_x] = v
Expand All @@ -204,12 +204,12 @@ function _update_stars!(
first_neighbor::AbstractVector{<:Tuple},
)
for (w, index_vw) in neighbors_with_edge_indices(g, v)
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
color_w = color[w]
iszero(color_w) && continue
x_exists = false
for (x, index_wx) in neighbors_with_edge_indices(g, w)
!has_diagonal(g) || (w == x && continue)
augmented_graph(g) || (w == x && continue)
if x != v && color[x] == color[v] # vw, wx ∈ E
star_wx = star[index_wx]
hub[star_wx] = w # this may already be true
Expand Down Expand Up @@ -286,16 +286,16 @@ function acyclic_coloring(

for v in vertices_in_order
for w in neighbors(g, v)
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
color_w = color[w]
iszero(color_w) && continue
forbidden_colors[color_w] = v
end
for w in neighbors(g, v)
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
iszero(color[w]) && continue
for (x, index_wx) in neighbors_with_edge_indices(g, w)
!has_diagonal(g) || (w == x && continue)
augmented_graph(g) || (w == x && continue)
color_x = color[x]
iszero(color_x) && continue
if forbidden_colors[color_x] != v
Expand All @@ -320,16 +320,16 @@ function acyclic_coloring(
end
end
for (w, index_vw) in neighbors_with_edge_indices(g, v) # grow two-colored stars around the vertex v
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
color_w = color[w]
iszero(color_w) && continue
_grow_star!(v, w, index_vw, color_w, first_neighbor, forest)
end
for (w, index_vw) in neighbors_with_edge_indices(g, v)
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
iszero(color[w]) && continue
for (x, index_wx) in neighbors_with_edge_indices(g, w)
!has_diagonal(g) || (w == x && continue)
augmented_graph(g) || (w == x && continue)
color_x = color[x]
(x == v || iszero(color_x)) && continue
if color_x == color[v]
Expand Down
4 changes: 2 additions & 2 deletions src/decompression.jl
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ function decompress!(
end

# Recover the diagonal coefficients of A
if has_diagonal(ag)
if !augmented_graph(ag)
for i in axes(S, 1)
if !iszero(S[i, i])
A[i, i] = B[i, color[i]]
Expand Down Expand Up @@ -616,7 +616,7 @@ function decompress!(
end

# Recover the diagonal coefficients of A
if has_diagonal(ag)
if !augmented_graph(ag)
if uplo == :L
for i in diagonal_indices
# A[i, i] is the first element in column i
Expand Down
32 changes: 16 additions & 16 deletions src/graph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ end
## Adjacency graph

"""
AdjacencyGraph{T,has_diagonal}
AdjacencyGraph{T,augmented_graph}

Undirected graph without self-loops representing the nonzeros of a symmetric matrix (typically a Hessian matrix).

Expand All @@ -213,18 +213,18 @@ The adjacency graph of a symmetric matrix `A ∈ ℝ^{n × n}` is `G(A) = (V, E)

# Constructors

AdjacencyGraph(A::SparseMatrixCSC; has_diagonal::Bool=true)
AdjacencyGraph(A::SparseMatrixCSC; augmented_graph::Bool=false)

# Fields

- `S::SparsityPatternCSC{T}`: Underlying sparsity pattern, whose diagonal is empty whenever `has_diagonal` is `false`
- `S::SparsityPatternCSC{T}`: Underlying sparsity pattern, which represents an augmented graph whenever `augmented_graph` is `true`.
- `edge_to_index::Vector{T}`: A vector mapping each nonzero of `S` to a unique edge index (ignoring diagonal and accounting for symmetry, so that `(i, j)` and `(j, i)` get the same index)

# References

> [_What Color Is Your Jacobian? SparsityPatternCSC Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005)
"""
struct AdjacencyGraph{T<:Integer,has_diagonal}
struct AdjacencyGraph{T<:Integer,augmented_graph}
S::SparsityPatternCSC{T}
edge_to_index::Vector{T}
end
Expand All @@ -234,24 +234,24 @@ Base.eltype(::AdjacencyGraph{T}) where {T} = T
function AdjacencyGraph(
S::SparsityPatternCSC{T},
edge_to_index::Vector{T}=build_edge_to_index(S);
has_diagonal::Bool=true,
augmented_graph::Bool=false,
) where {T}
return AdjacencyGraph{T,has_diagonal}(S, edge_to_index)
return AdjacencyGraph{T,augmented_graph}(S, edge_to_index)
end

function AdjacencyGraph(A::SparseMatrixCSC; has_diagonal::Bool=true)
return AdjacencyGraph(SparsityPatternCSC(A); has_diagonal)
function AdjacencyGraph(A::SparseMatrixCSC; augmented_graph::Bool=false)
return AdjacencyGraph(SparsityPatternCSC(A); augmented_graph)
end

function AdjacencyGraph(A::AbstractMatrix; has_diagonal::Bool=true)
return AdjacencyGraph(SparseMatrixCSC(A); has_diagonal)
function AdjacencyGraph(A::AbstractMatrix; augmented_graph::Bool=false)
return AdjacencyGraph(SparseMatrixCSC(A); augmented_graph)
end

pattern(g::AdjacencyGraph) = g.S
edge_indices(g::AdjacencyGraph) = g.edge_to_index
nb_vertices(g::AdjacencyGraph) = pattern(g).n
vertices(g::AdjacencyGraph) = 1:nb_vertices(g)
has_diagonal(::AdjacencyGraph{T,hd}) where {T,hd} = hd
augmented_graph(::AdjacencyGraph{T,ag}) where {T,ag} = ag

function neighbors(g::AdjacencyGraph, v::Integer)
S = pattern(g)
Expand All @@ -267,17 +267,17 @@ function neighbors_with_edge_indices(g::AdjacencyGraph, v::Integer)
return zip(neighbors_v, edges_indices_v)
end

degree(g::AdjacencyGraph{T,false}, v::Integer) where {T} = g.S.colptr[v + 1] - g.S.colptr[v]
degree(g::AdjacencyGraph{T,true}, v::Integer) where {T} = g.S.colptr[v + 1] - g.S.colptr[v]

function degree(g::AdjacencyGraph{T,true}, v::Integer) where {T}
function degree(g::AdjacencyGraph{T,false}, v::Integer) where {T}
neigh = neighbors(g, v)
has_selfloop = insorted(v, neigh)
return g.S.colptr[v + 1] - g.S.colptr[v] - has_selfloop
end

nb_edges(g::AdjacencyGraph{T,false}) where {T} = nnz(g.S) ÷ 2
nb_edges(g::AdjacencyGraph{T,true}) where {T} = nnz(g.S) ÷ 2

function nb_edges(g::AdjacencyGraph{T,true}) where {T}
function nb_edges(g::AdjacencyGraph{T,false}) where {T}
ne = 0
for v in vertices(g)
ne += degree(g, v)
Expand All @@ -290,7 +290,7 @@ minimum_degree(g::AdjacencyGraph) = minimum(Base.Fix1(degree, g), vertices(g))

function has_neighbor(g::AdjacencyGraph, v::Integer, u::Integer)
for w in neighbors(g, v)
!has_diagonal(g) || (v == w && continue)
augmented_graph(g) || (v == w && continue)
if w == u
return true
end
Expand Down
8 changes: 4 additions & 4 deletions src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ function _coloring(
symmetric_pattern::Bool;
forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing,
)
ag = AdjacencyGraph(A; has_diagonal=true)
ag = AdjacencyGraph(A; augmented_graph=false)
color_and_star_set_by_order = map(algo.orders) do order
vertices_in_order = vertices(ag, order)
return star_coloring(ag, vertices_in_order, algo.postprocessing; forced_colors)
Expand All @@ -300,7 +300,7 @@ function _coloring(
decompression_eltype::Type{R},
symmetric_pattern::Bool,
) where {R}
ag = AdjacencyGraph(A; has_diagonal=true)
ag = AdjacencyGraph(A; augmented_graph=false)
color_and_tree_set_by_order = map(algo.orders) do order
vertices_in_order = vertices(ag, order)
return acyclic_coloring(ag, vertices_in_order, algo.postprocessing)
Expand All @@ -323,7 +323,7 @@ function _coloring(
forced_colors::Union{AbstractVector{<:Integer},Nothing}=nothing,
) where {R}
A_and_Aᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern)
ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index; has_diagonal=false)
ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index; augmented_graph=true)
outputs_by_order = map(algo.orders) do order
vertices_in_order = vertices(ag, order)
_color, _star_set = star_coloring(
Expand Down Expand Up @@ -370,7 +370,7 @@ function _coloring(
symmetric_pattern::Bool,
) where {R}
A_and_Aᵀ, edge_to_index = bidirectional_pattern(A; symmetric_pattern)
ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index; has_diagonal=false)
ag = AdjacencyGraph(A_and_Aᵀ, edge_to_index; augmented_graph=true)
outputs_by_order = map(algo.orders) do order
vertices_in_order = vertices(ag, order)
_color, _tree_set = acyclic_coloring(ag, vertices_in_order, algo.postprocessing)
Expand Down
2 changes: 1 addition & 1 deletion src/order.jl
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ function vertices(

π[index] = u
for v in neighbors(g, u)
!has_diagonal(g) || (u == v && continue)
augmented_graph(g) || (u == v && continue)
dv = degrees[v]
dv == -1 && continue
update_bucket!(db, v, dv; degtype, direction)
Expand Down
2 changes: 1 addition & 1 deletion src/postprocessing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function postprocess!(
color_used = zeros(Bool, nb_colors)

# nonzero diagonal coefficients force the use of their respective color (there can be no neutral colors if the diagonal is fully nonzero)
if has_diagonal(g)
if !augmented_graph(g)
for i in axes(S, 1)
if !iszero(S[i, i])
color_used[color[i]] = true
Expand Down
2 changes: 1 addition & 1 deletion src/result.jl
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ function TreeSetColoringResult(
diagonal_nzind = T[]
ndiag = 0

if has_diagonal(ag)
if !augmented_graph(ag)
for j in axes(S, 2)
for k in nzrange(S, j)
i = rv[k]
Expand Down
2 changes: 1 addition & 1 deletion test/graph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ end;
@test degree(g, 7) == 6
@test degree(g, 8) == 6

g = AdjacencyGraph(transpose(A) * A; has_diagonal=false)
g = AdjacencyGraph(transpose(A) * A; augmented_graph=true)
# wrong degree
@test degree(g, 1) == 4
@test degree(g, 2) == 4
Expand Down
18 changes: 8 additions & 10 deletions test/order.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,14 @@ end;
end;

@testset "LargestFirst" begin
for has_diagonal in (false, true)
A = sparse([
0 1 0 0
1 0 1 1
0 1 0 1
0 1 1 0
])
ag = AdjacencyGraph(A; has_diagonal)
@test vertices(ag, LargestFirst()) == [2, 3, 4, 1]
end
A = sparse([
0 1 0 0
1 0 1 1
0 1 0 1
0 1 1 0
])
ag = AdjacencyGraph(A)
@test vertices(ag, LargestFirst()) == [2, 3, 4, 1]

A = sparse([
1 1 0 0
Expand Down
Loading