Skip to content

backwards differentiation #142

@Gertian

Description

@Gertian

Firstly, thanks the developers for the great package !

I tried to use the package with Zygote.jl (for automatic differentiation) but sadly this failed due to the usage of =. in the definition of pfaffian(A).

The usual fix for this is to define the backwards derivative manually, in this case I got :

using Zygote
using ChainRulesCore
using ChainRules

function ChainRules.rrule(::typeof(pfaffian), x::Union{Number, AbstractMatrix})
    Ω = pfaffian(x)
    function det_pullback(ΔΩ)
        ∂x = x isa Number ? zero(ΔΩ) : #=0.5 *=# inv(x)' * dot(Ω, ΔΩ)  #we removed the 0.5 because changing element ij immediatelyu changes element ji. 
        return (NoTangent(), ∂x)
    end
    return Ω, det_pullback
end

which works well from the test :

for _ in 1:100
    n = rand(1:10)

    A = rand(2*n,2*n) 
    A = A - transpose(A)
    A = SkewHermitian(A)  

    epsi = 1e-6

    function make_zero_but_ij(i,j)
        out = zero(A)
        if i != j 
            out[i,j] =  1.   #note, the one half here is because the pfaffian is antisymmetric in the rows and columns. 
        end
        return out
    end

    numerical = gradient(x->pfaffian(x), A)[1]
    analytical = [(pfaffian(A + epsi*make_zero_but_ij(i,j)  )-pfaffian(A))/epsi for i  1:2*n, j  1:2*n]

    @show analytical  numerical
end

would it be desirable if I made a pull request with this code ?

All the best,
Gertian

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions