Skip to content

Commit 7ec2889

Browse files
jishnubdkarrasch
authored andcommitted
Fix issymmetric for matrices with empty columns (#606)
The `issymmetric` check tracks an `offset` that it uses to go from (row, col) to (col, row). However, currently this doesn't account for the fact that if a column is empty, entries in `colptr` will be identical. E.g., in #605, we have ```julia julia> S = sparse([2, 3, 1], [1, 1, 3], [1, 1, 1], 3, 3) 3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries: ⋅ ⋅ 1 1 ⋅ ⋅ 1 ⋅ ⋅ julia> SparseArrays.getcolptr(S) 4-element Vector{Int64}: 1 3 3 4 ``` The offset `3` corresponds to rows in the third column, as the second column is empty. This PR checks for empty columns, in which case we may exit the call immediately. Fixes #605
1 parent f3610c0 commit 7ec2889

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

src/sparsematrix.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4074,9 +4074,9 @@ function _blockdiag(::Type{Tv}, ::Type{Ti}, X::AbstractSparseMatrixCSC...) where
40744074
end
40754075

40764076
## Structure query functions
4077-
issymmetric(A::AbstractSparseMatrixCSC) = is_hermsym(A, identity)
4077+
issymmetric(A::AbstractSparseMatrixCSC) = is_hermsym(A, transpose)
40784078

4079-
ishermitian(A::AbstractSparseMatrixCSC) = is_hermsym(A, conj)
4079+
ishermitian(A::AbstractSparseMatrixCSC) = is_hermsym(A, adjoint)
40804080

40814081
function is_hermsym(A::AbstractSparseMatrixCSC, check::Function)
40824082
m, n = size(A)
@@ -4112,6 +4112,12 @@ function is_hermsym(A::AbstractSparseMatrixCSC, check::Function)
41124112
return false
41134113
end
41144114
else
4115+
# if nzrange(A, row) is empty, then A[:, row] is all zeros.
4116+
# Specifically, A[col, row] is zero.
4117+
# However, we know at this point that A[row, col] is not zero
4118+
# This means that the matrix is not symmetric
4119+
isempty(nzrange(A, row)) && return false
4120+
41154121
offset = tracker[row]
41164122

41174123
# If the matrix is unsymmetric, there might not exist

test/linalg.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,27 @@ end
425425
@test issymmetric(sparse([1 0; 1 0])) == false
426426
@test issymmetric(sparse([0 1; 1 0])) == true
427427
@test issymmetric(sparse([1 1; 1 0])) == true
428+
429+
# test some non-trivial cases
430+
local S
431+
@testset "random matrices" begin
432+
for sparsity in (0.1, 0.01, 0.0)
433+
S = sparse(Symmetric(sprand(20, 20, sparsity)))
434+
@test issymmetric(S)
435+
@test ishermitian(S)
436+
S = sparse(Symmetric(sprand(ComplexF64, 20, 20, sparsity)))
437+
@test issymmetric(S)
438+
@test !ishermitian(S) || isreal(S)
439+
S = sparse(Hermitian(sprand(ComplexF64, 20, 20, sparsity)))
440+
@test ishermitian(S)
441+
@test !issymmetric(S) || isreal(S)
442+
end
443+
end
444+
445+
@testset "issue #605" begin
446+
S = sparse([2, 3, 1], [1, 1, 3], [1, 1, 1], 3, 3)
447+
@test !issymmetric(S)
448+
end
428449
end
429450

430451
@testset "rotations" begin

0 commit comments

Comments
 (0)