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

Problem with abs #377

Open
briochemc opened this issue Nov 16, 2018 · 0 comments
Open

Problem with abs #377

briochemc opened this issue Nov 16, 2018 · 0 comments

Comments

@briochemc
Copy link

briochemc commented Nov 16, 2018

Hi there,

I'm not sure this is intentional or if it is for numerical efficiency reasons, and I may be out of my league discussing this, but I figured I should point this out. When trying to copy the DualNumbers.jl structure into the HyperDualNumbers.jl structure, I noticed that there is a problem with how abs is dealt with. I believe the problem is that abs(x) returns x if x >= 0 (in DualNumbers.jl, HyperDualNumbers.jl, and I believe in ForwardDiff.jl's dual implementation).

Here is a small example where this causes problems. I use ForwardDiff.hessian to evaluate the second derivative of abs(-x^2), which should be the same as the second derivative of x^2, which is always 2:

julia> using ForwardDiff

julia> ForwardDiff.hessian(x -> abs(-x[1]^2), [0.0])
1×1 Array{Float64,2}:
 -2.0

(I used hessian and a single element Vector because I did not know how to get to second derivatives of scalars using ForwardDiff.)

I come with a suggestion: What about dealing with abs in the "physical" way, that is thinking of the absolute value of some x plus or minus some very small term ε. In other words, treating it recursively via something like:

function myabs(d::Dual)
    x, y = value(d), epsilon(d)
    if x > 0
        return d
    elseif x < 0
        return -d
    else
        if y  0
            return d
        else
            return -d
        end
    end
end

For hyper duals, something like

function myabs(h::Hyper)
    x, y, z, w = value(h), epsilon1(h), epsilon2(h), epsilon12(h)
    if x > 0
        return h
    elseif x < 0
        return -h
    else
        if y+z > 0
            return h
        elseif y+z < 0
            return -h
        else
            if z  0
                return h
            else z < 0
                return -h
            end
        end
    end
end

Now I know this is not DualNumbers.jl or HyperDualNumbers.jl, to which the above example suggestions apply, but I haven't really figured out how ForwardDiff.jl implements hyperduals so this was the best way I could convey my suggestions. I also believe that it is very likely that one can code the suggested abs in a much more efficient way than my if statements allow. But regardless of that, is that something worse paying some attention?

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

1 participant