Skip to content

Commit 40509f3

Browse files
committed
Initial implementation of multidim interval Newton method
1 parent 375deab commit 40509f3

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/newtonnd.jl

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using IntervalRootFinding, IntervalArithmetic, StaticArrays, ForwardDiff, BenchmarkTools, Compat
2+
"""
3+
Preconditions the matrix A and b with the inverse of mid(A)
4+
"""
5+
function preconditioner(A::AbstractMatrix, b::AbstractArray)
6+
7+
Aᶜ = mid.(A)
8+
B = pinv(Aᶜ) # TODO If Aᶜ is singular
9+
10+
return B*A, B*b
11+
12+
end
13+
14+
function newtonnd(f::Function, deriv::Function, x::IntervalBox{NUM, T}; reltol=eps(T), abstol=eps(T), debug=true, debugroot=false) where {T<:AbstractFloat} where {NUM} # TODO Incorporate Hull and Box consistencies
15+
16+
L = IntervalBox{NUM, T}[] # Array to hold the interval boxes still to be processed
17+
18+
R = Root{IntervalBox{NUM, T}}[] # Array to hold the `root` objects obtained
19+
20+
push!(L, x) # Initialize
21+
n = size(X, 1)
22+
while !isempty(L) # Until all interval boxes have been processed
23+
Xᴵ = pop!(L) # Process next interval box
24+
if !all(0 .∈ f(Xᴵ))
25+
continue
26+
end
27+
Xᴵ¹ = copy(Xᴵ)
28+
debug && (print("Current interval popped: "); println(Xᴵ))
29+
30+
if (isempty(Xᴵ))
31+
continue
32+
end
33+
if diam(Xᴵ) < reltol
34+
if max((abs.(IntervalBox(f(Xᴵ))))...) < abstol
35+
36+
debugroot && @show "Tolerance root found", Xᴵ
37+
38+
push!(R, Root(Xᴵ, :unknown))
39+
continue
40+
else
41+
continue
42+
end
43+
end
44+
45+
next_iter = false
46+
47+
while true
48+
49+
use_B = false
50+
next_iter = false
51+
52+
initial_width = diam(Xᴵ)
53+
debug && (print("Current interval popped: "); println(Xᴵ))
54+
if use_B
55+
# TODO Compute X using B in Step 19
56+
else
57+
X = mid(Xᴵ)
58+
end
59+
60+
J = SMatrix{n}{n}(deriv(Xᴵ)) # either jacobian or calculated using slopes
61+
62+
# Xᴵ = IntervalBox((X + linear_hull(J, -f(interval.(X)))) .∩ Xᴵ)
63+
Xᴵ = IntervalBox((X + (J \ -f(interval.(X)))) .∩ Xᴵ)
64+
65+
if (isempty(Xᴵ))
66+
next_iter = true
67+
break
68+
end
69+
70+
if diam(Xᴵ) < reltol
71+
if max((abs.(IntervalBox(f(Xᴵ))))...) < abstol
72+
73+
debugroot && @show "Tolerance root found", Xᴵ
74+
next_iter = true
75+
push!(R, Root(Xᴵ, :unknown))
76+
break
77+
else
78+
next_iter = true
79+
break
80+
end
81+
end
82+
83+
if all(0 .∈ f(interval.(X))) && initial_width > 0.9diam(Xᴵ)
84+
next_iter = true
85+
push!(R, Root(Xᴵ, :unique))
86+
break
87+
end
88+
89+
if diam(Xᴵ) > initial_width / 8
90+
break
91+
end
92+
93+
#Criterion C
94+
95+
96+
end
97+
98+
if next_iter
99+
continue
100+
end
101+
102+
if 0.25 * diam(Xᴵ¹) max((diam.(Xᴵ¹) .- diam.(Xᴵ))...)
103+
push!(L, Xᴵ)
104+
println("Sufficient")
105+
else
106+
push!(L, bisect(Xᴵ)...)
107+
end
108+
end
109+
110+
R
111+
112+
end
113+
114+
newtonnd(f::Function, x::IntervalBox{NUM, T}; args...) where {T<:AbstractFloat} where {NUM} = newtonnd(f, x->ForwardDiff.jacobian(f,x), x; args...)
115+
116+
f(x, y) = SVector(x^2 + y^2 - 1, y - 2x)
117+
f(X) = f(X...)
118+
X = (-6..6) × (-6..6)

0 commit comments

Comments
 (0)