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

Pfaffian #14

Closed
stevengj opened this issue Aug 8, 2022 · 6 comments
Closed

Pfaffian #14

stevengj opened this issue Aug 8, 2022 · 6 comments

Comments

@stevengj
Copy link
Member

stevengj commented Aug 8, 2022

People are sometimes interested in computing this, and it's an interesting quantity defined for skew-Hermitian matrices. As for determinants, there are probably a large number of reasonable ways to compute it, but this algorithm is a possible starting point. (You could also use your Hessenberg factorization.)

As for the determinant, the Pfaffian will quickly overflow for large matrices, so you might want to compute its log instead.

@stevengj
Copy link
Member Author

stevengj commented Aug 8, 2022

In particular, this formula from that paper makes it trivial to implement both the Pfaffian and the log-Pfaffian from your Hessenberg reduction, so it's worth doing that even if there are slightly more efficient ways to compute it:
image
(noting that the determinant of your Q matrix in the Hessenberg factorization is just ±1 depending on whether the number reflectors is even/odd)

@stevengj
Copy link
Member Author

stevengj commented Aug 8, 2022

This algorithm looks nice for exact Pfaffians of BigInt matrices: https://core.ac.uk/download/pdf/82502568.pdf

@stevengj
Copy link
Member Author

stevengj commented Aug 9, 2022

In particular, here is an implementation of the exact Pfaffian of integer matrices using the algorithm from the paper above:

using SkewLinearAlgebra, LinearAlgebra
using LinearAlgebra: exactdiv

# in-place O(n³) algorithm to compute the exact Pfaffian of
# a skew-symmetric matrix over integers (or potentially any ring supporting exact division).
#
#     G. Galbiati & F. Maffioli, "On the computation of pfaffians,"
#     Discrete Appl. Math. 51, 269–275 (1994).
#     https://doi.org/10.1016/0166-218X(92)00034-J
function exactpfaffian!(A::AbstractMatrix{<:Integer})
    LinearAlgebra.require_one_based_indexing(A)
    isskewhermitian(A) || throw(ArgumentError("Pfaffian requires a skew-Hermitian matrix"))
    n = size(A,1)
    isodd(n) && return zero(eltype(A))
    c = one(eltype(A))
    signflip = false
    n = n ÷ 2
    while n > 1
        # find last k with A[2n-1,k] ≠ 0
        k = 2n
        while k > 0 && iszero(A[2n-1,k]); k -= 1; end
        iszero(k) && return zero(eltype(A))
        
        # swap rows/cols k and 2n
        if k != 2n
            for i = 1:2n
                A[i,k], A[i,2n] = A[i,2n], A[i,k]
                A[k,i], A[2n,i] = A[2n,i], A[k,i]
            end
            signflip = !signflip
        end
        
        # update, A, c, n
        for j = 1:2n-2, i = 1:j-1
            δ = A[2n-1,2n]*A[i,j] - A[i,2n-1]*A[j,2n] + A[j,2n-1]*A[i,2n]
            A[j,i] = -(A[i,j] = exactdiv(δ, c))
            # @assert A[i,j] * c == δ
        end
        c = A[2n-1,2n]
        n -= 1
    end
    return signflip ? -A[1,2] : A[1,2]
end
exactpfaffian(A::AbstractMatrix{<:Integer}) =
    exactpfaffian!(copyto!(similar(A, typeof(exactdiv(zero(eltype(A))^2, one(eltype(A))))), A))

You probably only want to use this for AbstractMatrix{<:BigInt} by default, since other types are likely to overflow etcetera, similar to how the LinearAlgebra package only uses the Bareiss algorithm by default for determinants of BigInt matrices (see JuliaLang/julia#40868).

@stevengj
Copy link
Member Author

stevengj commented Aug 9, 2022

And here's another paper on numerical algorithms: https://arxiv.org/abs/1012.5022

One of the algorithms they discuss is "tridiagonalization based on Householder transformations", i.e. by Hessenberg factorization as I suggested above. Probably I would just go with that approach since it is easiest.

Note also that they suggest that the Pfaffian of complex skew-Hermitian matrices is useful for some electronic-structure calculations, which adds some additional motivation to #15.

@smataigne
Copy link
Collaborator

Thank you very much for the documentation and the code above. I will add the functionality to the package.

@stevengj
Copy link
Member Author

Closed by #47

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

No branches or pull requests

2 participants