forked from JuliaIntervals/IntervalRootFinding.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroot_object.jl
More file actions
109 lines (88 loc) · 3.72 KB
/
Copy pathroot_object.jl
File metadata and controls
109 lines (88 loc) · 3.72 KB
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""
Root
Object representing a possible root inside a given region. The field `status`
is either `:unknown` or `:unique`. If `status` is `:unique` then we know that
there is a unique root of the function in question inside the given region.
Internally the status may also be `:empty` for region guaranteed to contain no
root, however such `Root`s are discarded by default and thus never returned by
the `roots` function.
# Fields
- `region`: a region (either `Interval` or `SVector` of interval
representing an interval box) searched for roots.
- `status`: the status of the region, valid values are `:empty`, `unknown`
and `:unique`.
- `convergence`: the convergence status of the region. It is always `:converged`
for roots with status `:unique`,
and can be either `:max_iterartion` or `:tolerance` for roots with status `:unknown`,
depending on whether they stopped being processing due to reaching
the maximum number of iteration or the tolerance, respectively.
- `error`: an error that was encounter but ignored during the processing of this region.
Set to `nothing` if no error was encountered.
The ignored errors are controlled by the `ignored_errors` field of the `RootProblem`.
"""
struct Root{T}
region::T
status::Symbol
convergence::Symbol
error
end
function Root(region, status::Symbol, convergence = :none, error = nothing)
return Root(region, status, convergence, error)
end
"""
root_status(rt)
Return the status of a `Root`.
"""
root_status(rt::Root) = rt.status # Use root_status since just `status` is too generic
"""
root_region(rt)
Return the region associated to a `Root`.
"""
root_region(rt::Root) = rt.region
"""
isunique(rt)
Return whether a `Root` is unique.
"""
isunique(rt::Root{T}) where {T} = (rt.status == :unique)
function show(io::IO, rt::Root)
print(io, "Root($(rt.region), :$(rt.status))")
if !get(io, :compact, false) && rt.status == :unknown
connector = isnothing(rt.error) ? "└" : "├"
if rt.convergence == :tolerance
print(io, "\n $connector Not converged: region size smaller than the tolerance")
elseif rt.convergence == :max_iterartion
print(io, "\n $connector Not converged: reached maximal number of iterations")
elseif rt.convergence == :none
print(io, "\n $connector Not converged: the root is still being processed")
else
print(io, "\n $connector Not converged: unknown reason $(rt.convergence)")
end
if !isnothing(rt.error)
print(io, "\n ├ Warning: error encountered during computation (use showerror(root.error) to see the whole stacktrace)\n └ ")
showerror(io, rt.error[1])
end
end
end
Base.showerror(io::IO, rt::Root) = showerror(io, rt.error...)
Base.showerror(rt::Root) = showerror(stdout, rt.error...)
⊆(a::Interval, b::Root) = a ⊆ b.region
⊆(a::Root, b::Root) = a.region ⊆ b.region
IntervalArithmetic.diam(r::Root) = diam_region(root_region(r))
IntervalArithmetic.mag(r::Root) = mag_region(root_region(r))
IntervalArithmetic.mig(r::Root) = mig_region(root_region(r))
IntervalArithmetic.isnai(r::Root) = isnai_region(root_region(r))
function Base.:(==)(r1::Root, r2::Root)
root_status(r1) != root_status(r2) && return false
return isequal_region(root_region(r1), root_region(r2))
end
big(a::Root) = Root(big(a.interval), a.status)
"""
Base.iterate(r::Root [, state])
Return successively the root region and status,
allowing to unpack the root object as `region, status = root`.
"""
function Base.iterate(r::Root{T}, state::Integer=1) where {T}
state == 1 && return (r.region, 2)
state == 2 && return (r.status, 3)
return nothing
end