Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hermitian, ishermitian now check diagonals #10672

Merged
merged 4 commits into from
Mar 31, 2015
Merged

Hermitian, ishermitian now check diagonals #10672

merged 4 commits into from
Mar 31, 2015

Conversation

jiahao
Copy link
Member

@jiahao jiahao commented Mar 29, 2015

Fix #10671

I also had to fix some tests which had incorrectly neglected to check the diagonals.

Hermitian(A::AbstractMatrix, uplo::Symbol=:U) = (chksquare(A);Hermitian{eltype(A),typeof(A)}(A, char_uplo(uplo)))
function Hermitian(A::AbstractMatrix, uplo::Symbol=:U)
chksquare(A)
all(isreal(diag(A))) || throw(ArgumentError(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do this without allocation.

@jiahao
Copy link
Member Author

jiahao commented Mar 30, 2015

Can anyone shed light on the 32-bit build failure?

julia-debug: ast.c:686: jl_lam_vinfo: Assertion (((jl_value_t*)(((jl_taggedvalue_t *) ((char )((l)) - __builtin_offsetof (jl_taggedvalue_t, value)))->type_bits&~(size_t)3))==(jl_value_t)(jl_expr_type))' failed.`

Also refactor symmetric/Hermitian tests

Tests for issues #8057 and #8058 were changed to deterministic matrices
@jiahao
Copy link
Member Author

jiahao commented Mar 31, 2015

Build failure seems unrelated.

jiahao added a commit that referenced this pull request Mar 31, 2015
Hermitian, ishermitian now check diagonals
@jiahao jiahao merged commit f0a33c4 into master Mar 31, 2015
@jiahao jiahao deleted the cjh/fix-10671 branch March 31, 2015 07:45
@tkelman
Copy link
Contributor

tkelman commented Apr 6, 2015

This is causing intermittent failures, the tolerances look a little too tight

@jiahao
Copy link
Member Author

jiahao commented Apr 6, 2015

Could you point me to a failure?

@tkelman
Copy link
Contributor

tkelman commented Apr 10, 2015

Bump. Any suggestions for mitigating these?

@jiahao
Copy link
Member Author

jiahao commented Apr 10, 2015

I wrote a simple PR but I got an inscrutable error.

@andreasnoack
Copy link
Member

I think we should revert because it gives some annoying exceptions this are often unwanted. We don't check that a matrix is symmetric in cholfact so I don't think we should check the input of Hermitian. We should simply ignore the imaginary part of the diagonal and document the behavior.

cc: @bnels

@tkelman
Copy link
Contributor

tkelman commented Oct 24, 2015

Ignoring the diagonal sounds like a pretty bad idea - the constructors here should verify the invariants that their types represent.

@andreasnoack
Copy link
Member

No. The point is that the user already knows that the matrix has the property or that the matrix should be interpreted in that way. Similarly to allowing

julia> LowerTriangular(randn(3,3))
3x3 LowerTriangular{Float64,Array{Float64,2}}:
 -0.193406   0.0       0.0    
 -0.225881  -1.29177   0.0    
  1.83933    1.77965  -1.24135

@tkelman
Copy link
Contributor

tkelman commented Oct 25, 2015

Unlike LowerTriangular, you aren't proposing ignoring uninitialized data - you're proposing ignoring actual imaginary parts of values of elements that matter. You'd have to zero them and make the Hermitian constructor mutating, which is surprising and inconsistent with the rest of the wrapper types.

@andreasnoack
Copy link
Member

It's not necessary to mutate anything. The methods for Hermitian should just ignore any imaginary components in the diagonal. That is also what LAPACK is doing and what we are doing for Cholesky

julia> cholfact(fill(complex(1.0,1.0), 1, 1))
Base.LinAlg.Cholesky{Complex{Float64},Array{Complex{Float64},2}} with factor:
1x1 UpperTriangular{Complex{Float64},Array{Complex{Float64},2}}:
 1.0+0.0im

@tkelman
Copy link
Contributor

tkelman commented Oct 25, 2015

Every single method then. getindex and everything else you might ever call on a Hermitian will need extra special casing to ignore the imaginary component any time it touches a diagonal. Sounds very very easy to get wrong for not much benefit, easier to explicitly verify up front.

@andreasnoack
Copy link
Member

No. It's not easy to verify without a lot of unnecesary exceptions. One of the main reasons to use Hermitian is when floating point errors results in a computation like A = QΛQ' begin slightly non-hermitian. Then you want to use Hermaitan(A), but it defeats the purpose to throw an exception in that case.

I dont' think ingoring imaginary parts in the diagonal will be that demanding. Making the very small change to getindex will probably take care of most of it.

@tkelman
Copy link
Contributor

tkelman commented Oct 25, 2015

tril and friends as well, copytri!, probably others. And when you send the data to a C library?

@andreasnoack
Copy link
Member

There might be a few other places in symmetric.jl, but the file is only 239 lines so it's very doable. As far as I can tell, we are calling out to three libraries with Hermitian: BLAS, LAPACK and CHOLMOD. The first two use the assumption I advocate for here and CHOLMOD checks the imaginary part like we are doing now.

@tkelman
Copy link
Contributor

tkelman commented Oct 25, 2015

Methods that use in any way other than getindex, or leave alone without checking, diagonal elements for any abstract supertype of Hermitian would need to be made aware of this special case, or have a more specific method written for Hermitian. I'm anticipating there will be quite a few places in base that would get this wrong. This is the kind of thing where we start needing type-based coverage stats.

I'm more referring to users sending their data to C libraries outside of base. The proposal is to store undefined data that we intentionally want to be meaningless inline within the same diagonal scalar values. This could be documented and tested thoroughly for corner cases, and left up to the user to manually zero the imaginary components for this ccall case, but this isn't something we've done any other places to my knowledge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug with Hermitian() and ishermitian()
3 participants