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