@@ -14,7 +14,7 @@ Copied from `SparseMatrixCSC`:
1414- `colptr::Vector{Ti}`: column `j` is in `colptr[j]:(colptr[j+1]-1)`
1515- `rowval::Vector{Ti}`: row indices of stored values
1616"""
17- struct SparsityPatternCSC{Ti<: Integer }
17+ struct SparsityPatternCSC{Ti<: Integer } <: AbstractMatrix{Bool}
1818 m:: Int
1919 n:: Int
2020 colptr:: Vector{Ti}
@@ -93,6 +93,76 @@ function Base.getindex(S::SparsityPatternCSC, i0::Integer, i1::Integer)
9393 return ((r1 > r2) || (rowvals (S)[r1] != i0)) ? false : true
9494end
9595
96+ """
97+ bidirectional_pattern(A::AbstractMatrix; symmetric_pattern::Bool)
98+
99+ Return a [`SparsityPatternCSC`](@ref) corresponding to the matrix `[0 Aᵀ; A 0]`, with a minimum of allocations.
100+ """
101+ bidirectional_pattern (A:: AbstractMatrix ; symmetric_pattern) =
102+ bidirectional_pattern (SparsityPatternCSC (SparseMatrixCSC (A)); symmetric_pattern)
103+
104+ function bidirectional_pattern (S:: SparsityPatternCSC ; symmetric_pattern)
105+ m, n = size (S)
106+ p = m + n
107+ nnzS = nnz (S)
108+ rowval = Vector {Int} (undef, 2 * nnzS)
109+ colptr = zeros (Int, p + 1 )
110+
111+ # Update rowval and colptr for the block A
112+ for i in 1 : nnzS
113+ rowval[i] = S. rowval[i] + n
114+ end
115+ for j in 1 : n
116+ colptr[j] = S. colptr[j]
117+ end
118+
119+ # Update rowval and colptr for the block Aᵀ
120+ if symmetric_pattern
121+ # We use the sparsity pattern of A for Aᵀ
122+ for i in 1 : nnzS
123+ rowval[nnzS + i] = S. rowval[i]
124+ end
125+ # m and n are identical because symmetric_pattern is true
126+ for j in 1 : m
127+ colptr[n + j] = nnzS + S. colptr[j]
128+ end
129+ colptr[p + 1 ] = 2 * nnzS + 1
130+ else
131+ # We need to determine the sparsity pattern of Aᵀ
132+ # We adapt the code of transpose(SparsityPatternCSC) in graph.jl
133+ for k in 1 : nnzS
134+ i = S. rowval[k]
135+ colptr[n + i] += 1
136+ end
137+
138+ counter = 1
139+ for col in (n + 1 ): p
140+ nnz_col = colptr[col]
141+ colptr[col] = counter
142+ counter += nnz_col
143+ end
144+
145+ for j in 1 : n
146+ for index in S. colptr[j]: (S. colptr[j + 1 ] - 1 )
147+ i = S. rowval[index]
148+ pos = colptr[n + i]
149+ rowval[nnzS + pos] = j
150+ colptr[n + i] += 1
151+ end
152+ end
153+
154+ colptr[p + 1 ] = nnzS + counter
155+ for col in p: - 1 : (n + 2 )
156+ colptr[col] = nnzS + colptr[col - 1 ]
157+ end
158+ colptr[n + 1 ] = nnzS + 1
159+ end
160+
161+ # Create the SparsityPatternCSC of the augmented adjacency matrix
162+ S_and_Sᵀ = SparsityPatternCSC {Int} (p, p, colptr, rowval)
163+ return S_and_Sᵀ
164+ end
165+
96166# # Adjacency graph
97167
98168"""
0 commit comments