@@ -94,33 +94,44 @@ function Base.getindex(S::SparsityPatternCSC, i0::Integer, i1::Integer)
9494end
9595
9696"""
97- bidirectional_pattern(A::AbstractMatrix; symmetric_pattern::Bool)
97+ bidirectional_pattern(A::AbstractMatrix; symmetric_pattern::Bool=false )
9898
9999Return a [`SparsityPatternCSC`](@ref) corresponding to the matrix `[0 Aᵀ; A 0]`, with a minimum of allocations.
100100"""
101- bidirectional_pattern (A:: AbstractMatrix ; symmetric_pattern:: Bool ) =
101+ bidirectional_pattern (A:: AbstractMatrix ; symmetric_pattern:: Bool = false ) =
102102 bidirectional_pattern (SparsityPatternCSC (SparseMatrixCSC (A)); symmetric_pattern)
103103
104- function bidirectional_pattern (S:: SparsityPatternCSC ; symmetric_pattern:: Bool )
104+ function bidirectional_pattern (
105+ S:: SparsityPatternCSC{T} ; symmetric_pattern:: Bool = false
106+ ) where {T<: Integer }
105107 m, n = size (S)
106108 p = m + n
107109 nnzS = nnz (S)
108- rowval = Vector {Int} (undef, 2 * nnzS)
109- colptr = zeros (Int, p + 1 )
110+ rowval = Vector {T} (undef, 2 * nnzS)
111+ colptr = zeros (T, p + 1 )
112+ edge_to_index = Vector {T} (undef, 2 * nnzS)
110113
111114 # Update rowval and colptr for the block A
112115 for i in 1 : nnzS
113116 rowval[i] = S. rowval[i] + n
117+ edge_to_index[i] = i
114118 end
115119 for j in 1 : n
116120 colptr[j] = S. colptr[j]
117121 end
118122
119123 # Update rowval and colptr for the block Aᵀ
120124 if symmetric_pattern
125+ # Use colptr[n+1:n+m] to store the offsets during the update of edge_to_index
126+ offsets = colptr
127+
121128 # We use the sparsity pattern of A for Aᵀ
122- for i in 1 : nnzS
123- rowval[nnzS + i] = S. rowval[i]
129+ for k in 1 : nnzS
130+ r = S. rowval[k]
131+ rowval[nnzS + k] = r
132+ pos = S. colptr[r] + offsets[n + r]
133+ edge_to_index[nnzS + pos] = edge_to_index[k]
134+ offsets[n + r] += 1
124135 end
125136 # m and n are identical because symmetric_pattern is true
126137 for j in 1 : m
@@ -147,6 +158,7 @@ function bidirectional_pattern(S::SparsityPatternCSC; symmetric_pattern::Bool)
147158 i = S. rowval[index]
148159 pos = colptr[n + i]
149160 rowval[nnzS + pos] = j
161+ edge_to_index[nnzS + pos] = edge_to_index[index]
150162 colptr[n + i] += 1
151163 end
152164 end
@@ -159,12 +171,10 @@ function bidirectional_pattern(S::SparsityPatternCSC; symmetric_pattern::Bool)
159171 end
160172
161173 # Create the SparsityPatternCSC of the augmented adjacency matrix
162- S_and_Sᵀ = SparsityPatternCSC {Int } (p, p, colptr, rowval)
163- return S_and_Sᵀ
174+ S_and_Sᵀ = SparsityPatternCSC {T } (p, p, colptr, rowval)
175+ return S_and_Sᵀ, edge_to_index
164176end
165177
166- # Note that we don't need to do that for bicoloring,
167- # we can build that in the same time than the transposed sparsity pattern of A
168178function build_edge_to_index (S:: SparsityPatternCSC{T} ) where {T<: Integer }
169179 # edge_to_index gives an index for each edge
170180 edge_to_index = Vector {T} (undef, nnz (S))
@@ -221,11 +231,27 @@ struct AdjacencyGraph{T,has_diagonal}
221231 vertex_buffer:: Vector{T}
222232end
223233
224- function AdjacencyGraph (S:: SparsityPatternCSC{T} ; has_diagonal:: Bool = true ) where {T}
225- edge_to_index, vertex_buffer = build_edge_to_index (S)
234+ function AdjacencyGraph (
235+ S:: SparsityPatternCSC{T} ,
236+ edge_to_index:: Vector{T} ,
237+ vertex_buffer:: Vector{T} ;
238+ has_diagonal:: Bool = true ,
239+ ) where {T}
226240 return AdjacencyGraph {T,has_diagonal} (S, edge_to_index, vertex_buffer)
227241end
228242
243+ function AdjacencyGraph (
244+ S:: SparsityPatternCSC{T} , edge_to_index:: Vector{T} ; has_diagonal:: Bool = true
245+ ) where {T}
246+ vertex_buffer = Vector {Int} (undef, S. n)
247+ return AdjacencyGraph (S, edge_to_index, vertex_buffer; has_diagonal)
248+ end
249+
250+ function AdjacencyGraph (S:: SparsityPatternCSC ; has_diagonal:: Bool = true )
251+ edge_to_index, vertex_buffer = build_edge_to_index (S)
252+ return AdjacencyGraph (S, edge_to_index, vertex_buffer; has_diagonal)
253+ end
254+
229255function AdjacencyGraph (A:: SparseMatrixCSC ; has_diagonal:: Bool = true )
230256 return AdjacencyGraph (SparsityPatternCSC (A); has_diagonal)
231257end
248274
249275function neighbors_with_edge_indices (g:: AdjacencyGraph , v:: Integer )
250276 S = pattern (g)
251- neighbors_v = view (rowvals (S), nzrange (S, v))
252- edges_indices_v = view (edge_indices (g), nzrange (S, v))
277+ range_v = nzrange (S, v)
278+ neighbors_v = view (rowvals (S), range_v)
279+ edges_indices_v = view (edge_indices (g), range_v)
253280 return zip (neighbors_v, edges_indices_v)
254281end
255282
@@ -328,7 +355,7 @@ When `symmetric_pattern` is `true`, this construction is more efficient.
328355
329356> [_What Color Is Your Jacobian? SparsityPatternCSC Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005)
330357"""
331- struct BipartiteGraph{T<: Integer }
358+ struct BipartiteGraph{T}
332359 S1:: SparsityPatternCSC{T}
333360 S2:: SparsityPatternCSC{T}
334361end
0 commit comments