Skip to content

Commit b0bc737

Browse files
committed
newton(): introduce oscillation dampening ("Newton-Roman")
1 parent 33c81f2 commit b0bc737

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
@@ -76,6 +76,14 @@ function newton(f, xs::T=mode(d), tol::Real=1e-12) where {T}
7676
while !converged(x[0], x[-1])
7777
df = f(x[0])
7878
r = x[0] + df
79+
# Vanilla Newton algorithm is known to be prone to oscillation,
80+
# where we, e.g., go from 24.0 to 42.0, back to 24.0 and so forth.
81+
# We can detect this situation by checking for convergence between
82+
# the newly-computed "root" and the "root" we had two steps before.
83+
if converged(r, x[-1])
84+
# To recover from oscillation, let's use just half of the delta.
85+
r = r - (df / 2)
86+
end
7987
push!(x, r)
8088
end
8189
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)