@@ -5,70 +5,151 @@ Optional keyword arguments give the tolerances `reltol` and `abstol`.
5
5
and a `debug` boolean argument that prints out diagnostic information."""
6
6
7
7
function newton1d {T} (f:: Function , f′:: Function , x:: Interval{T} ;
8
- reltol= eps (T), abstol= eps (T), debug= false )
8
+ reltol= eps (T), abstol= eps (T), debug= false , debugroot = false )
9
9
10
- L = Interval{T}[]
10
+ L = Interval{T}[] # Array to hold the intervals still to be processed
11
11
12
- R = Root{Interval{T}}[]
12
+ R = Root{Interval{T}}[] # Array to hold the `root` objects obtained
13
+ reps = reps1 = 0
13
14
14
- push! (L, x)
15
+ push! (L, x) # Initialize
16
+ initial_width = ∞
17
+ X = emptyinterval (T) # Initialize
18
+ while ! isempty (L) # Until all intervals have been processed
19
+ X = pop! (L) # Process next interval
20
+
21
+ debug && (print (" Current interval popped: " ); @show X)
15
22
16
- while ! isempty (L)
17
- X = pop! (L)
18
23
m = mid (X)
19
24
if (isempty (X))
20
25
continue
21
26
end
22
27
23
- if 0 ∉ f′ (X)
28
+ if 0 ∉ f′ (X) # if 0 ∉ f′(X), Newton steps can be made normally until either X becomes empty, or is known to contain a unique root
29
+
30
+ debug && println (" 0 ∉ f′(X)" )
31
+
24
32
while true
33
+
25
34
m = mid (X)
26
- N = m - (f (Interval (m)) / f′ (X))
35
+ N = m - (f (interval (m)) / f′ (X)) # Newton step
36
+
37
+ debug && (print (" Newton step1: " ); @show (X, X ∩ N))
38
+ if X == X ∩ N # Checking if Newton step was redundant
39
+ reps1 += 1
40
+ if reps1 > 20
41
+ reps1 = 0
42
+ break
43
+ end
44
+ end
27
45
X = X ∩ N
28
46
29
- if isempty (X)
47
+ if ( isempty (X)) # No root in X
30
48
break
31
49
32
- elseif 0 ∈ f (Interval (prevfloat (m), nextfloat (m)))
33
- push! (R, Root (X, :unique ))
50
+ elseif 0 ∈ f (wideinterval (mid (X))) # Root guaranteed to be in X
51
+ n = fa = fb = 0
52
+ root_exist = true
53
+ while (n < 4 && (fa == 0 || fb == 0 )) # Narrowing the interval further
54
+ if fa == 0
55
+ if 0 ∈ f (wideinterval (X. lo))
56
+ fa = 1
57
+ else
58
+ N = X. lo - (f (interval (X. lo)) / f′ (X))
59
+ X = X ∩ N
60
+ if (isempty (X))
61
+ root_exist = false
62
+ break
63
+ end
64
+ end
65
+ end
66
+ if fb == 0
67
+ if 0 ∈ f (wideinterval (X. hi))
68
+ fb = 1
69
+ else
70
+ if 0 ∈ f (wideinterval (mid (X)))
71
+ N = X. hi - (f (interval (X. hi)) / f′ (X))
72
+ else
73
+ N = mid (X) - (f (interval (mid (X))) / f′ (X))
74
+ end
75
+ X = X ∩ N
76
+ if (isempty (X))
77
+ root_exist = false
78
+ break
79
+ end
80
+ end
81
+ end
82
+ N = mid (X) - (f (interval (mid (X))) / f′ (X))
83
+ X = X ∩ N
84
+ if (isempty (X))
85
+ root_exist = false
86
+ break
87
+ end
88
+ n += 1
89
+ end
90
+ if root_exist
91
+ push! (R, Root (X, :unique ))
92
+ debugroot && @show " Root found" , X # Storing determined unique root
93
+ end
94
+
34
95
break
35
96
end
36
97
end
37
98
38
- else
39
- # 0 ∈ f'(X)
99
+ else # 0 ∈ f′(X)
100
+ if diam (X) == initial_width # if no improvement occuring for a number of iterations
101
+ reps += 1
102
+ if reps > 10
103
+ push! (R, Root (X, :unknown ))
104
+ debugroot && @show " Repeated root found" , X
105
+ reps = 0
106
+ continue
107
+ end
108
+ end
109
+ initial_width = diam (X)
110
+ debug && println (" 0 ∈ f'(X)" )
111
+
40
112
expansion_pt = Inf
41
113
# expansion point for the newton step might be m, X.lo or X.hi according to some conditions
42
114
43
- if 0 ∈ f (Interval (mid (X)))
115
+ if 0 ∈ f (wideinterval (mid (X))) # if root in X, narrow interval further
44
116
# 0 ∈ fⁱ(x)
45
- # Step 7
46
117
47
- if 0 ∉ f (Interval (X. lo))
118
+ debug && println (" 0 ∈ fⁱ(x)" )
119
+
120
+ if 0 ∉ f (wideinterval (X. lo))
48
121
expansion_pt = X. lo
49
122
50
- elseif 0 ∉ f (Interval (X. hi))
123
+ elseif 0 ∉ f (wideinterval (X. hi))
51
124
expansion_pt = X. hi
52
125
53
126
else
54
- x1 = mid (Interval (X. lo, mid (X)))
55
- x2 = mid (Interval (mid (X), X. hi))
56
- if 0 ∉ f (Interval (x1)) || 0 ∉ f (Interval (x2))
57
- push! (L, Interval (X. lo, m))
58
- push! (L, Interval (m, X. hi))
127
+ x1 = mid (interval (X. lo, mid (X)))
128
+ x2 = mid (interval (mid (X), X. hi))
129
+ if 0 ∉ f (wideinterval (x1)) || 0 ∉ f (wideinterval (x2))
130
+ push! (L, interval (X. lo, m))
131
+ push! (L, interval (m, X. hi))
59
132
continue
60
133
61
134
else
62
- push! (R, Root (X, :unique ))
135
+ push! (R, Root (X, :unknown ))
136
+
137
+ debugroot && @show " Multiple root found" , X
138
+
63
139
continue
64
140
end
65
141
end
66
142
67
143
else
68
144
# 0 ∉ fⁱ(x)
69
145
70
- if (diam (X)/ mag (X)) < reltol && diam (f (X)) < abstol
146
+ debug && println (" 0 ∉ fⁱ(x)" )
147
+
148
+ if (diam (X)/ mag (X)) < reltol && diam (f (X)) < abstol # checking if X is still within tolerances
71
149
push! (R, Root (X, :unknown ))
150
+
151
+ debugroot && @show " Tolerance root found" , X
152
+
72
153
continue
73
154
end
74
155
end
@@ -78,26 +159,28 @@ function newton1d{T}(f::Function, f′::Function, x::Interval{T};
78
159
expansion_pt = mid (X)
79
160
end
80
161
81
- initial_width = diam (X)
82
162
83
- a = f (Interval (expansion_pt))
163
+ a = f (interval (expansion_pt))
84
164
b = f′ (X)
85
-
165
+ # Newton steps with extended division creating two intervals
86
166
if 0 < b. hi && 0 > b. lo && 0 ∉ a
87
167
if a. hi < 0
88
- push! (L, X ∩ (expansion_pt - Interval (- Inf , a. hi / b. hi)))
89
- push! (L, X ∩ (expansion_pt - Interval (a. hi / b. lo, Inf )))
168
+ push! (L, X ∩ (expansion_pt - interval (- Inf , a. hi / b. hi)))
169
+ push! (L, X ∩ (expansion_pt - interval (a. hi / b. lo, Inf )))
90
170
91
171
elseif a. lo > 0
92
- push! (L, X ∩ (expansion_pt - Interval (- Inf , a. lo / b. lo)))
93
- push! (L, X ∩ (expansion_pt - Interval (a. lo / b. hi, Inf )))
172
+ push! (L, X ∩ (expansion_pt - interval (- Inf , a. lo / b. lo)))
173
+ push! (L, X ∩ (expansion_pt - interval (a. lo / b. hi, Inf )))
94
174
95
175
end
96
176
97
177
continue
98
178
99
179
else
100
- N = expansion_pt - (f (Interval (expansion_pt))/ f′ (X))
180
+ N = expansion_pt - (f (interval (expansion_pt))/ f′ (X))
181
+
182
+ debug && (print (" Newton step2: " ); @show (X, X ∩ N))
183
+
101
184
X = X ∩ N
102
185
m = mid (X)
103
186
@@ -106,12 +189,7 @@ function newton1d{T}(f::Function, f′::Function, x::Interval{T};
106
189
end
107
190
end
108
191
109
- if diam (X) > initial_width/ 2
110
- push! (L, Interval (m, X. hi))
111
- X = Interval (X. lo, m)
112
- end
113
-
114
- push! (L, X)
192
+ push! (L, X) # Pushing X into L to be processed again
115
193
end
116
194
end
117
195
0 commit comments