Skip to content

Commit

Permalink
Fix 1D Newton by checking correctly whether midpoint is exactly a root (
Browse files Browse the repository at this point in the history
#254)

* Fix 1D Newton by checking correctly whether midpoint is exactly a root

* Fix Krawczyk with new definition of guarded_mid

* Fix Krawczyk and logistic tests

* Fix Krawczyk
  • Loading branch information
dpsanders authored and lbenet committed Mar 16, 2017
1 parent 2d5f2a9 commit b050477
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 9 deletions.
9 changes: 5 additions & 4 deletions src/root_finding/krawczyk.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ does not contain zero, and the second is the inverse of its derivative"""
function guarded_derivative_midpoint{T}(f::Function, f_prime::Function, x::Interval{T})

α = convert(T, 0.46875) # close to 0.5, but exactly representable as a floating point
m = Interval( guarded_mid(x) )
# m = Interval( guarded_mid(f, x) )
m = Interval(mid(x))

C = inv(f_prime(m))

# Check that 0 is not in C; if so, consider another point rather than m
i = 0
while zero(T) C
while zero(T) C || isempty(C)
m = Interval( α*x.lo + (one(T)-α)*x.hi )
C = inv(f_prime(m))

Expand Down Expand Up @@ -70,12 +71,12 @@ function krawczyk{T}(f::Function, f_prime::Function, x::Interval{T}, level::Int=

isempty(Kx x) && return Root{T}[] # [(x, :none)]

if Kx x
if Kx x # isinterior
debug && (print("Refining "); @show(x))
return krawczyk_refine(f, f_prime, Kx, tolerance=tolerance, debug=debug)
end

m = guarded_mid(x)
m = guarded_mid(f, x)

debug && @show(x,m)

Expand Down
11 changes: 6 additions & 5 deletions src/root_finding/newton.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

# What is this guarded_mid for? Shouldn't it be checking if f(m)==0?
doc"""Returns the midpoint of the interval x, slightly shifted in case
it is zero"""
function guarded_mid{T}(x::Interval{T})
the midpoint is an exact root"""
function guarded_mid{T}(f, x::Interval{T})
m = mid(x)
if m == zero(T) # midpoint exactly 0

if f(m) == 0 # midpoint exactly a root
α = convert(T, 0.46875) # close to 0.5, but exactly representable as a floating point
m = α*x.lo + (one(T)-α)*x.hi # displace to another point in the interval
end
Expand All @@ -19,7 +20,7 @@ end


function N{T}(f::Function, x::Interval{T}, deriv::Interval{T})
m = guarded_mid(x)
m = guarded_mid(f, x)
m = Interval(m)

m - (f(m) / deriv)
Expand Down Expand Up @@ -85,7 +86,7 @@ function newton{T}(f::Function, f_prime::Function, x::Interval{T}, level::Int=0;
return newton_refine(f, f_prime, Nx, tolerance=tolerance, debug=debug)
end

m = guarded_mid(x)
m = guarded_mid(f, x)

debug && @show(x,m)

Expand Down
18 changes: 18 additions & 0 deletions test/root_finding_tests/findroots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,24 @@ end
end
end

@testset "Iterated logistic function fixed points" begin
(f, g) = x -> f(g(x))
iterate(f, n) = n == 1 ? f : f iterate(f, n-1)

f(x) = 4x*(1-x) # logistic map

for n in 1:10
g = x -> iterate(f, n)(x) - x # look for fixed points of f^n

roots = newton(g, 0..1)
@test length(roots) == 2^n

roots = krawczyk(g, 0..1)
@test length(roots) == 2^n

end
end



# Example of a function with a double root at 0 from Burden & Faires, 9th ed, p.84
Expand Down

0 comments on commit b050477

Please sign in to comment.