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

Newton fails with abs #98

Open
dpsanders opened this issue Oct 1, 2018 · 6 comments · May be fixed by #203
Open

Newton fails with abs #98

dpsanders opened this issue Oct 1, 2018 · 6 comments · May be fixed by #203

Comments

@dpsanders
Copy link
Member

julia> f(p) = abs(1 / ( (1+p)^30 ) * 10_000 - 100)
f (generic function with 1 method)

julia> roots(f, -1000..1000, Newton)
2-element Array{Root{Interval{Float64}},1}:
 Root(∅, :unique)
 Root(∅, :unique)
@Kolaru
Copy link
Collaborator

Kolaru commented Oct 5, 2018

It looks like the fact an interval should not be bisected on its center was lost on recent update

julia> roots(f, -1000..1000.001, Newton)
2-element Array{Root{Interval{Float64}},1}:
 Root([0.165881, 0.165943], :unique)
 Root([-2.16602, -2.16504], :unique)

@Kolaru
Copy link
Collaborator

Kolaru commented Feb 3, 2019

Still not fixed despite the corrections in #93. Seems that the problem is indeed the absolute value:

julia> f(p) = abs(1 / ( (1+p)^30 ) * 10_000 - 100)
f (generic function with 1 method)

julia> roots(f, -1000..1000, Newton)
2-element Array{Root{Interval{Float64}},1}:
 Root(∅, :unique)
 Root(∅, :unique)

julia> f3(p) = (1 / ( (1+p)^30 ) * 10_000 - 100)^2
f3 (generic function with 1 method)

julia> roots(f3, -1000..1000, Newton)
2-element Array{Root{Interval{Float64}},1}:
 Root([0.16551, 0.166413], :unknown)
 Root([-2.16653, -2.16564], :unknown)

(squaring instead of taking the absolute value should yield a very similar problem)

The abs function together with Interval confuses ForwardDiff:

julia> fp(x) = derivative(f, x)
fp (generic function with 1 method)

julia> fp((-2.167..(-2.165)))
[2378.6, 2770.9]

julia> fp(-2.167)
-2499.911977412291

julia> fp(-2.165)
2636.4380353856686

@dpsanders
Copy link
Member Author

I think this will require directly specifying how the derivative of abs on an Interval behaves; but I don't know how to do so.

@lbenet
Copy link
Member

lbenet commented Feb 5, 2019

I think this will require directly specifying how the derivative of abs on an Interval behaves; but I don't know how to do so.

In TaylorSeries.jl, we define |f(x)| as the Taylor expansion of f(x) if f(x_0)>0, otherwise as as the Taylor expansion of -f(x) if f(x_0)<0, where x_0 is the expansion point. If f(x_0)=0 there is no first derivative of |f(x)| at x_0, so we throw an error.

Note that the above answer is valid for small enough δx = x-x_0, such that f(x) does not change sign. The problem here is that the Intervals may include x_0 somewhere in the middle.

I hope this may help.

@dpsanders
Copy link
Member Author

dpsanders commented Feb 5, 2019

What I mean is that we should define the derivative of abs on an interval as something like

function abs_derivative(x::Interval{T}) where {T}
    0  x && return Interval{T}(-1, 1)
    x.hi < 0 && return Interval{T}(-1)
    return Interval{T}(1)
end

But I don't know how to plug this into ForwardDiff's structure.

@dpsanders
Copy link
Member Author

This should now be fixable after JuliaDiff/DiffRules.jl#33.

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

Successfully merging a pull request may close this issue.

3 participants