Skip to content

Incorrect Hessian by exp function #677

Open
@rzyu45

Description

@rzyu45

I was trying to calculate the Hessian of a simple function such as

using ForwardDiff
function busPQ(Ybus, Vθ)
    n = length(Vθ)
    V=Vθ[1:Int(n/2)]
    θ=Vθ[Int(n/2)+1:n]
    Vbus=V.*exp.(im .*θ)
    # Vbus=V.*(cos.(θ)+im .*sin.(θ))
    # print(Vbus-Vbus)
    I = Ybus.*Vbus
    return vcat(reim(Vbus.*conj(I))...)
end

Ybus=[1 - 3im]
Vm=[1]
Va=[0]
Vθ = vcat(Vm,Va)
function Hessian(f, x)
    n = length(x)
    out = ForwardDiff.jacobian(x -> ForwardDiff.jacobian(f, x), x)
    return reshape(out, n, n, n)
end
H(y) = Hessian(x-> busPQ(Ybus, x), y)

At point [1,0], the above codes produce the wrong Hessian. However, if I set very small perturbation to , then the results are correct.

julia> H([1,0])
2×2×2 Array{Float64, 3}:
[:, :, 1] =
 2.0  0.0
 6.0  0.0

[:, :, 2] =
 0.0  2.0
 0.0  6.0

julia> H([1,1e-10])
2×2×2 Array{Float64, 3}:
[:, :, 1] =
 2.0  0.0
 6.0  0.0

[:, :, 2] =
 0.0  0.0
 0.0  0.0

julia> H([1,-1e-10])
2×2×2 Array{Float64, 3}:
[:, :, 1] =
 2.0  0.0
 6.0  0.0

[:, :, 2] =
 0.0  0.0
 0.0  0.0

It is found to be more robust to use cos.(θ)+im .*sin.(θ), which functioned correctly at point [1,0], instead of exp.(im .*θ).
I think the problem has something in common with #653.

The difference between cos.(θ)+im .*sin.(θ) and exp.(im .*θ) is printed as follows

Complex{ForwardDiff.Dual{ForwardDiff.Tag{var"#21#22", ForwardDiff.Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}, Int64, 2}}, ForwardDiff.Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}, Float64, 2}, 2}}[Dual{ForwardDiff.Tag{var"#21#22", ForwardDiff.Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}, Int64, 2}}}(Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}}(0.0,0.0,0.0),Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}}(0.0,0.0,0.0),Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}}(0.0,0.0,1.0)) + Dual{ForwardDiff.Tag{var"#21#22", ForwardDiff.Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}, Int64, 2}}}(Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}}(0.0,0.0,0.0),Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}}(0.0,0.0,0.0),Dual{ForwardDiff.Tag{var"#19#20"{var"#21#22"}, Int64}}(0.0,0.0,0.0))*im]2×2×2 Array{Float64, 3}:

It is clear that the above Dual is not all zero.

The dependencies are ForwardDiff v0.10.36 and Julia V1.9.3.

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