1+ """
2+ `Alefeld()`
3+
4+ An implementation of algorithm 4.2 from [Alefeld](https://dl.acm.org/doi/10.1145/210089.210111).
5+
6+ The paper brought up two new algorithms. Here choose to implement algorithm 4.2 rather than
7+ algorithm 4.1 because, in certain sense, the second algorithm(4.2) is an optimal procedure.
8+ """
9+ struct Alefeld <: AbstractBracketingAlgorithm end
10+
11+ function SciMLBase. solve (prob:: IntervalNonlinearProblem ,
12+ alg:: Alefeld , args... ; abstol = nothing ,
13+ reltol = nothing ,
14+ maxiters = 1000 , kwargs... )
15+
16+ f = Base. Fix2 (prob. f, prob. p)
17+ a, b = prob. tspan
18+ c = a - (b - a) / (f (b) - f (a)) * f (a)
19+
20+ fc = f (c)
21+ if iszero (fc)
22+ return SciMLBase. build_solution (prob, alg, c, fc;
23+ retcode = ReturnCode. Success,
24+ left = a,
25+ right = b)
26+ end
27+ a, b, d = _bracket (f, a, b, c)
28+ e = zero (a) # Set e as 0 before iteration to avoid a non-value f(e)
29+
30+ # Begin of algorithm iteration
31+ for i in 2 : maxiters
32+ # The first bracketing block
33+ f₁, f₂, f₃, f₄ = f (a), f (b), f (d), f (e)
34+ if i == 2 || (f₁ == f₂ || f₁ == f₃ || f₁ == f₄ || f₂ == f₃ || f₂ == f₄ || f₃ == f₄)
35+ c = _newton_quadratic (f, a, b, d, 2 )
36+ else
37+ c = _ipzero (f, a, b, d, e)
38+ if (c - a) * (c - b) ≥ 0
39+ c = _newton_quadratic (f, a, b, d, 2 )
40+ end
41+ end
42+ ē, fc = d, f (c)
43+ (a == c || b == c) &&
44+ return SciMLBase. build_solution (prob, alg, c, fc;
45+ retcode = ReturnCode. FloatingPointLimit,
46+ left = a,
47+ right = b)
48+ iszero (fc) &&
49+ return SciMLBase. build_solution (prob, alg, c, fc;
50+ retcode = ReturnCode. Success,
51+ left = a,
52+ right = b)
53+ ā, b̄, d̄ = _bracket (f, a, b, c)
54+
55+ # The second bracketing block
56+ f₁, f₂, f₃, f₄ = f (ā), f (b̄), f (d̄), f (ē)
57+ if f₁ == f₂ || f₁ == f₃ || f₁ == f₄ || f₂ == f₃ || f₂ == f₄ || f₃ == f₄
58+ c = _newton_quadratic (f, ā, b̄, d̄, 3 )
59+ else
60+ c = _ipzero (f, ā, b̄, d̄, ē)
61+ if (c - ā) * (c - b̄) ≥ 0
62+ c = _newton_quadratic (f, ā, b̄, d̄, 3 )
63+ end
64+ end
65+ fc = f (c)
66+ (ā == c || b̄ == c) &&
67+ return SciMLBase. build_solution (prob, alg, c, fc;
68+ retcode = ReturnCode. FloatingPointLimit,
69+ left = ā,
70+ right = b̄)
71+ iszero (fc) &&
72+ return SciMLBase. build_solution (prob, alg, c, fc;
73+ retcode = ReturnCode. Success,
74+ left = ā,
75+ right = b̄)
76+ ā, b̄, d̄ = _bracket (f, ā, b̄, c)
77+
78+ # The third bracketing block
79+ if abs (f (ā)) < abs (f (b̄))
80+ u = ā
81+ else
82+ u = b̄
83+ end
84+ c = u - 2 * (b̄ - ā) / (f (b̄) - f (ā)) * f (u)
85+ if (abs (c - u)) > 0.5 * (b̄ - ā)
86+ c = 0.5 * (ā + b̄)
87+ end
88+ fc = f (c)
89+ (ā == c || b̄ == c) &&
90+ return SciMLBase. build_solution (prob, alg, c, fc;
91+ retcode = ReturnCode. FloatingPointLimit,
92+ left = ā,
93+ right = b̄)
94+ iszero (fc) &&
95+ return SciMLBase. build_solution (prob, alg, c, fc;
96+ retcode = ReturnCode. Success,
97+ left = ā,
98+ right = b̄)
99+ ā, b̄, d = _bracket (f, ā, b̄, c)
100+
101+ # The last bracketing block
102+ if b̄ - ā < 0.5 * (b - a)
103+ a, b, e = ā, b̄, d̄
104+ else
105+ e = d
106+ c = 0.5 * (ā + b̄)
107+ fc = f (c)
108+ (ā == c || b̄ == c) &&
109+ return SciMLBase. build_solution (prob, alg, c, fc;
110+ retcode = ReturnCode. FloatingPointLimit,
111+ left = ā,
112+ right = b̄)
113+ iszero (fc) &&
114+ return SciMLBase. build_solution (prob, alg, c, fc;
115+ retcode = ReturnCode. Success,
116+ left = ā,
117+ right = b̄)
118+ a, b, d = _bracket (f, ā, b̄, c)
119+ end
120+ end
121+
122+ # Reassign the value a, b, and c
123+ if b == c
124+ b = d
125+ elseif a == c
126+ a = d
127+ end
128+ fc = f (c)
129+
130+ # Reuturn solution when run out of max interation
131+ return SciMLBase. build_solution (prob, alg, c, fc; retcode = ReturnCode. MaxIters,
132+ left = a, right = b)
133+ end
134+
135+ # Define subrotine function bracket, check fc before bracket to return solution
136+ function _bracket (f:: F , a, b, c) where F
137+ if iszero (f (c))
138+ ā, b̄, d = a, b, c
139+ else
140+ if f (a) * f (c) < 0
141+ ā, b̄, d = a, c, b
142+ elseif f (b) * f (c) < 0
143+ ā, b̄, d = c, b, a
144+ end
145+ end
146+
147+ return ā, b̄, d
148+ end
149+
150+ # Define subrotine function newton quadratic, return the approximation of zero
151+ function _newton_quadratic (f:: F , a, b, d, k) where F
152+ A = ((f (d) - f (b)) / (d - b) - (f (b) - f (a)) / (b - a)) / (d - a)
153+ B = (f (b) - f (a)) / (b - a)
154+
155+ if iszero (A)
156+ return a - (1 / B) * f (a)
157+ elseif A * f (a) > 0
158+ rᵢ₋₁ = a
159+ else
160+ rᵢ₋₁ = b
161+ end
162+
163+ for i in 1 : k
164+ rᵢ = rᵢ₋₁ - (f (a) + B * (rᵢ₋₁ - a) + A * (rᵢ₋₁ - a) * (rᵢ₋₁ - b)) / (B + A * (2 * rᵢ₋₁ - a - b))
165+ rᵢ₋₁ = rᵢ
166+ end
167+
168+ return rᵢ₋₁
169+ end
170+
171+ # Define subrotine function ipzero, also return the approximation of zero
172+ function _ipzero (f:: F , a, b, c, d) where F
173+ Q₁₁ = (c - d) * f (c) / (f (d) - f (c))
174+ Q₂₁ = (b - c) * f (b) / (f (c) - f (b))
175+ Q₃₁ = (a - b) * f (a) / (f (b) - f (a))
176+ D₂₁ = (b - c) * f (c) / (f (c) - f (b))
177+ D₃₁ = (a - b) * f (b) / (f (b) - f (a))
178+ Q₂₂ = (D₂₁ - Q₁₁) * f (b) / (f (d) - f (b))
179+ Q₃₂ = (D₃₁ - Q₂₁) * f (a) / (f (c) - f (a))
180+ D₃₂ = (D₃₁ - Q₂₁) * f (c) / (f (c) - f (a))
181+ Q₃₃ = (D₃₂ - Q₂₂) * f (a) / (f (d) - f (a))
182+
183+ return a + Q₃₁ + Q₃₂ + Q₃₃
184+ end
0 commit comments