-
Notifications
You must be signed in to change notification settings - Fork 5
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
Comments
This algorithm looks nice for exact Pfaffians of BigInt matrices: https://core.ac.uk/download/pdf/82502568.pdf |
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 |
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. |
Thank you very much for the documentation and the code above. I will add the functionality to the package. |
Closed by #47 |
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.
The text was updated successfully, but these errors were encountered: