Skip to content

Commit 85a6c84

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 08b8168 commit 85a6c84

2 files changed

Lines changed: 29 additions & 2 deletions

File tree

src/sparsematrix.jl

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

39733973
## Structure query functions
3974-
issymmetric(A::AbstractSparseMatrixCSC) = is_hermsym(A, identity)
3974+
issymmetric(A::AbstractSparseMatrixCSC) = is_hermsym(A, transpose)
39753975

3976-
ishermitian(A::AbstractSparseMatrixCSC) = is_hermsym(A, conj)
3976+
ishermitian(A::AbstractSparseMatrixCSC) = is_hermsym(A, adjoint)
39773977

39783978
function is_hermsym(A::AbstractSparseMatrixCSC, check::Function)
39793979
m, n = size(A)
@@ -4009,6 +4009,12 @@ function is_hermsym(A::AbstractSparseMatrixCSC, check::Function)
40094009
return false
40104010
end
40114011
else
4012+
# if nzrange(A, row) is empty, then A[:, row] is all zeros.
4013+
# Specifically, A[col, row] is zero.
4014+
# However, we know at this point that A[row, col] is not zero
4015+
# This means that the matrix is not symmetric
4016+
isempty(nzrange(A, row)) && return false
4017+
40124018
offset = tracker[row]
40134019

40144020
# 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
@@ -395,6 +395,27 @@ end
395395
@test issymmetric(sparse([1 0; 1 0])) == false
396396
@test issymmetric(sparse([0 1; 1 0])) == true
397397
@test issymmetric(sparse([1 1; 1 0])) == true
398+
399+
# test some non-trivial cases
400+
local S
401+
@testset "random matrices" begin
402+
for sparsity in (0.1, 0.01, 0.0)
403+
S = sparse(Symmetric(sprand(20, 20, sparsity)))
404+
@test issymmetric(S)
405+
@test ishermitian(S)
406+
S = sparse(Symmetric(sprand(ComplexF64, 20, 20, sparsity)))
407+
@test issymmetric(S)
408+
@test !ishermitian(S) || isreal(S)
409+
S = sparse(Hermitian(sprand(ComplexF64, 20, 20, sparsity)))
410+
@test ishermitian(S)
411+
@test !issymmetric(S) || isreal(S)
412+
end
413+
end
414+
415+
@testset "issue #605" begin
416+
S = sparse([2, 3, 1], [1, 1, 3], [1, 1, 1], 3, 3)
417+
@test !issymmetric(S)
418+
end
398419
end
399420

400421
@testset "rotations" begin

0 commit comments

Comments
 (0)