Skip to content

Commit 6491d43

Browse files
eeshan9815dpsanders
authored andcommitted
Add solvers for quadratic interval equations (#68)
* Add solvers for quadratic interval equations * Add tests * interval arithmetic to bound rounding errors and refine tests * Documentation * optimization
1 parent 4153a9d commit 6491d43

File tree

4 files changed

+96
-2
lines changed

4 files changed

+96
-2
lines changed

src/IntervalRootFinding.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export
1818
derivative, jacobian, # reexport derivative from ForwardDiff
1919
Root, is_unique,
2020
roots, find_roots,
21-
bisect, newton1d
21+
bisect, newton1d, quadratic_roots
2222

2323
export isunique, root_status
2424

@@ -58,7 +58,7 @@ include("complex.jl")
5858
include("contractors.jl")
5959
include("roots.jl")
6060
include("newton1d.jl")
61-
61+
include("quadratic.jl")
6262

6363

6464
gradient(f) = X -> ForwardDiff.gradient(f, SVector(X))

src/quadratic.jl

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
Helper function for quadratic_interval that computes roots of a
3+
real quadratic using interval arithmetic to bound rounding errors.
4+
"""
5+
function quadratic_helper!{T}(a::Interval{T}, b::Interval{T}, c::Interval{T}, L::Array{Interval{T}})
6+
7+
Δ = b^2 - 4*a*c
8+
9+
Δ.hi < 0 && return
10+
11+
Δ = sqrt(Δ)
12+
13+
if (b.lo >= 0)
14+
x0 = -0.5 * (b + Δ)
15+
16+
else
17+
x0 = -0.5 * (b - Δ)
18+
end
19+
20+
if (0 x0)
21+
push!(L, x0)
22+
23+
else
24+
x1 = c / x0
25+
x0 = x0 / a
26+
push!(L, x0, x1)
27+
end
28+
29+
end
30+
31+
32+
"""
33+
Function to solve a quadratic equation where the coefficients are intervals.
34+
Returns an array of intervals of the roots.
35+
Arguments `a`, `b` and `c` are interval coefficients of `x²`, `x` and `1` respectively.
36+
The interval case differs from the non-interval case in that
37+
there might be three disjoint interval roots. In the third
38+
case, one interval root extends to −∞ and another extends to +∞.
39+
This algorithm finds the set of points where `F.lo(x) ≥ 0` and the set
40+
of points where `F.hi(x) ≤ 0` and takes the intersection of these two sets.
41+
Eldon Hansen and G. William Walster : Global Optimization Using Interval Analysis - Chapter 8
42+
"""
43+
function quadratic_roots{T}(a::Interval{T}, b::Interval{T}, c::Interval{T})
44+
45+
L = Interval{T}[]
46+
R = Interval{T}[]
47+
48+
quadratic_helper!(Interval(a.lo), Interval(b.lo), Interval(c.lo), L)
49+
quadratic_helper!(Interval(a.hi), Interval(b.hi), Interval(c.hi), L)
50+
quadratic_helper!(Interval(a.lo), Interval(b.hi), Interval(c.lo), L)
51+
quadratic_helper!(Interval(a.hi), Interval(b.lo), Interval(c.hi), L)
52+
53+
if (length(L) == 8)
54+
resize!(L, 4)
55+
end
56+
57+
if (a.lo < 0 || (a.lo == 0 && b.hi == 0) || (a.lo == 0 && b.hi == 0 && c.lo 0))
58+
push!(L, Interval(-∞))
59+
end
60+
61+
if (a.lo < 0 || (a.lo == 0 && b.lo == 0) || (a.lo == 0 && b.lo == 0 && c.lo 0))
62+
push!(L, Interval(∞))
63+
end
64+
65+
sort!(L, by = x -> x.lo)
66+
67+
for i in 1:2:length(L)
68+
push!(R, Interval(L[i].lo, L[i+1].hi))
69+
end
70+
71+
R
72+
end

test/quadratic.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using IntervalArithmetic, IntervalRootFinding
2+
3+
struct Quad{T}
4+
a::Interval{T}
5+
b::Interval{T}
6+
c::Interval{T}
7+
x::Vector{Interval{T}}
8+
end
9+
10+
11+
@testset "Quadratic Interval Equations" begin
12+
rts = Quad{Float64}[]
13+
push!(rts, Quad(interval(1, 5), interval(2, 4), interval(0, 2), [interval(-4, -2), interval(-0, -0)]))
14+
push!(rts, Quad(interval(-1, 1), interval(-2, 2), interval(-1, 1), [interval(-∞, -1), interval(-1, -1), interval(-1, ∞)]))
15+
push!(rts, Quad(interval(1, 2), interval(1, 3), interval(2, 6), [interval(-2, -1)]))
16+
push!(rts, Quad(interval(1, 1), interval(2, 2), interval(1, 1), [interval(-1, -1), interval(-1, -1)]))
17+
18+
for i in 1:length(rts)
19+
@test quadratic_roots(rts[i].a, rts[i].b, rts[i].c) == rts[i].x
20+
end
21+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ using Base.Test
55
#include("findroots.jl")
66
include("roots.jl")
77
include("newton1d.jl")
8+
include("quadratic.jl")

0 commit comments

Comments
 (0)