Skip to content

Commit c8a2ae1

Browse files
committed
newton(): introduce oscillation dampening ("Newton-Roman")
1 parent 786338b commit c8a2ae1

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/quantilealgs.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ function newton(f, xs::T=mode(d), tol::Real=1e-12) where {T}
8282
while !converged(x[0], x[-1])
8383
df = f(x[0])
8484
r = x[0] + df
85+
# Vanilla Newton algorithm is known to be prone to oscillation,
86+
# where we, e.g., go from 24.0 to 42.0, back to 24.0 and so forth.
87+
# We can detect this situation by checking for convergence between
88+
# the newly-computed "root" and the "root" we had two steps before.
89+
if converged(r, x[-1])
90+
# To recover from oscillation, let's use just half of the delta.
91+
r = r - (df / 2)
92+
end
8593
push!(x, r)
8694
end
8795
return x[0]

test/univariate/continuous/inversegaussian.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,27 @@
1515
@test (p + q) 1
1616
end
1717
end
18-
end
18+
end
19+
20+
@testset "InverseGaussian quantile" begin
21+
p(num_σ) = erf(num_σ/sqrt(2))
22+
23+
begin
24+
dist = InverseGaussian{Float64}(1.187997687788096, 60.467382225458564)
25+
@test quantile(dist, p(4)) 1.9990956368573651
26+
@test quantile(dist, p(5)) 2.295607340999747
27+
@test quantile(dist, p(6)) 2.6249349452113484
28+
end
29+
30+
@test quantile(InverseGaussian{Float64}(17.84806245738152, 163.707062977564), 0.9999981908772995) 69.37000274656731
31+
32+
begin
33+
dist = InverseGaussian(1.0, 0.25)
34+
@test quantile(dist, 0.99) 9.90306205018232
35+
@test quantile(dist, 0.999) 21.253279722084798
36+
@test quantile(dist, 0.9999) 34.73673452136752
37+
@test quantile(dist, 0.99999) 49.446586395457985
38+
@test quantile(dist, 0.999996) 55.53114044452607
39+
@test quantile(dist, 0.999999) 64.92521558088777
40+
end
41+
end

0 commit comments

Comments
 (0)