forked from JuliaDiff/SparseMatrixColorings.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmatrices.jl
More file actions
129 lines (109 loc) · 4.09 KB
/
matrices.jl
File metadata and controls
129 lines (109 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
const TransposeOrAdjoint{T,M} = Union{Transpose{T,M},Adjoint{T,M}}
"""
matrix_versions(A::AbstractMatrix)
Return various versions of the same matrix:
- dense and sparse
- transpose and adjoint
Used for internal testing.
"""
function matrix_versions(A::AbstractMatrix)
A_dense = Matrix(A)
A_sparse = sparse(A)
versions = [
A_dense,
transpose(Matrix(transpose(A_dense))),
adjoint(Matrix(adjoint(A_dense))),
A_sparse,
transpose(sparse(transpose(A_sparse))),
adjoint(sparse(adjoint(A_sparse))),
]
if issymmetric(A)
lower_triangles = [
Matrix(LowerTriangular(A_dense)), sparse(LowerTriangular(A_sparse))
]
upper_triangles = [
Matrix(UpperTriangular(A_dense)), sparse(UpperTriangular(A_sparse))
]
symmetric_versions = vcat(
Symmetric.(versions),
Hermitian.(versions),
Symmetric.(lower_triangles, :L),
Symmetric.(upper_triangles, :U),
)
append!(versions, symmetric_versions)
end
return versions
end
"""
respectful_similar(A::AbstractMatrix)
respectful_similar(A::AbstractMatrix, ::Type{T})
Like `Base.similar` but returns a transpose or adjoint when `A` is a transpose or adjoint.
"""
respectful_similar(A::AbstractMatrix) = respectful_similar(A, eltype(A))
respectful_similar(A::AbstractMatrix, ::Type{T}) where {T} = similar(A, T)
# Needed if using `coloring(::SparsityPatternCSC, ...)`
function respectful_similar(A::SparsityPatternCSC, ::Type{T}) where {T}
return SparseArrays.SparseMatrixCSC(
A.m,
A.n,
A.colptr,
A.rowval,
similar(A.rowval, T),
)
end
function respectful_similar(A::Transpose, ::Type{T}) where {T}
return transpose(respectful_similar(parent(A), T))
end
function respectful_similar(A::Adjoint, ::Type{T}) where {T}
return adjoint(respectful_similar(parent(A), T))
end
function respectful_similar(A::Union{Symmetric,Hermitian}, ::Type{T}) where {T}
return respectful_similar(sparse(A), T)
end
"""
compatible_pattern(A::AbstractMatrix, bg::BipartiteGraph)
compatible_pattern(A::AbstractMatrix, ag::AdjacencyGraph, uplo::Symbol)
Perform a coarse compatibility check between the sparsity pattern of `A`
and the reference sparsity pattern encoded in a graph structure.
This function only checks necessary conditions for the two sparsity patterns to match.
In particular, it may return `true` even if the patterns are not identical.
When A is a `SparseMatrixCSC`, additional checks on the sparsity structure are performed.
# Return value
- `true` : the sparsity patterns are potentially compatible
- `false` : the sparsity patterns are definitely incompatible
"""
compatible_pattern(A::AbstractMatrix, bg::BipartiteGraph) = size(A) == size(bg.S2)
function compatible_pattern(A::SparseMatrixCSC, bg::BipartiteGraph)
return size(A) == size(bg.S2) && nnz(A) == nnz(bg.S2)
end
function compatible_pattern(A::AbstractMatrix, ag::AdjacencyGraph, uplo::Symbol)
return size(A) == size(ag.S)
end
function compatible_pattern(A::SparseMatrixCSC, ag::AdjacencyGraph, uplo::Symbol)
nnzS = (uplo == :L || uplo == :U) ? (nb_edges(ag) + ag.nb_self_loops) : nnz(ag.S)
return size(A) == size(ag.S) && nnz(A) == nnzS
end
function check_compatible_pattern(A::AbstractMatrix, bg::BipartiteGraph)
if !compatible_pattern(A, bg)
throw(DimensionMismatch("`A` and `bg.S2` must have the same sparsity pattern."))
end
end
function check_compatible_pattern(A::AbstractMatrix, ag::AdjacencyGraph, uplo::Symbol)
if !compatible_pattern(A, ag, uplo)
if uplo == :L
throw(
DimensionMismatch(
"`A` and `tril(ag.S)` must have the same sparsity pattern."
),
)
elseif uplo == :U
throw(
DimensionMismatch(
"`A` and `triu(ag.S)` must have the same sparsity pattern."
),
)
else # uplo == :F
throw(DimensionMismatch("`A` and `ag.S` must have the same sparsity pattern."))
end
end
end