Variant of the Secant Method - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html) +--- Forum: General Forum (/forum-4.html) +--- Thread: Variant of the Secant Method (/thread-16025.html) |
Variant of the Secant Method - ttw - 12-09-2020 04:33 AM The order of the secant method for finding zeros of a real function can be improved by using spline-like interpolants. This gives a method which has order just under 2 and uses only 1 function evaluation per step. https://arxiv.org/pdf/2012.04248.pdf RE: Variant of the Second Method - Valentin Albillo - 12-09-2020 05:40 AM (12-09-2020 04:33 AM)ttw Wrote: The order of the secant method for finding zeros of a real function can be improved by using spline-like interpolants. This gives a method which has order just under 2 and uses only 1 function evaluation per step. Interesting. Perhaps you might consider implementing it yourself for some HP calc and telling us how it compares in terms of speed and memory versus plain old Newton's method {two evaluations of f(x) per iteration), which can be implemented in as few as 34 steps even in the simple HP-10C model (fewer in RPN models with subroutine capability like the HP-11C). Anyway, thanks for sharing and take care. V. RE: Variant of the Second Method - Albert Chan - 12-09-2020 04:38 PM Let's try solving x, for sinc(x) = 1/6.5 lua> function f(x) return sin(x)/x - 1/6.5 end lua> function secant(x1,y1,x2,y2) return x1-y1/(y2-y1)*(x2-x1) end lua> x1, x2 = 2.711, 2.712 lua> y1, y2 = f(x1) , f(x2) lua> x3 = secant(x1,y1, x2,y2) lua> y3 = f(x3) lua> x3 2.7113129474671775 -- Inverse Interpolation, assumed f(x) is strictly increasing or descreasing around root -- Fit x = g(y), then evaluate g(0) lua> x12 = (x2-x1)/(y2-y1) lua> x23 = (x3-x2)/(y3-y2) lua> x123 = (x23-x12)/(y3-y1) lua> x3 + (0-y3)*(x23 + (0-y2)*x123) 2.711312910356982 -- Aikten interpolation, as 1 liner: inner secant = x4, outer secant = x5 -- y1 x1 -- y2 x2 x3 -- y3 x3 x4 x5 lua> secant(secant(x3,y3, x1,y1),y3, x3,y2) 2.711312910356982 -- improved secant, interpolate for slope lua> y23 = (y3-y2)/(x3-x2) lua> y12 = (y2-y1)/(x2-x1) lua> y123 = (y23-y12)/(x3-x1) lua> slope = y23 + (x3-x2)*y123 lua> x3 - y3/slope 2.7113129103569826 -- Newton's method, actual slope lua> x, y = x3, y3 lua> slope = (x*cos(x) - sin(x))/x^2 lua> x - y/slope 2.711312910356983 For reference, I used ASINC, for Free-42 Decimal. Comparing apples to apples, input is float(1/6.5) = 0x1.3b13b13b13b14p-3 5542891849071380 2 55 X^Y ÷ XEQ "ASINC" 2.71131291035698331469084928874754 All 3 methods gives excellent results, doubling accuracy of x3 RE: Variant of the Secant Method - Albert Chan - 12-09-2020 11:51 PM I extend previous post, with another round of iteration, using all points. (First iteration matched previous post, done in double precision) inverse-interpolation: 2.71131291035698220988289207111279 2.71131291035698331469084928874683 improved secant: 2.71131291035698244759230088334763 2.71131291035698331469084928874750 newton's method: 2.71131291035698307703744887554087 2.71131291035698331469084928874753 RE: Variant of the Secant Method - Namir - 12-10-2020 01:54 PM I implemented the Generalized Secant algorithm in Excel VBA. I used the same order as in the article's example (divided differences for first and second derivatives). The algorithm did better than Newton's method in most cases. The Generalized Secant algorithm needs two initial guesses, while Newton's method needs one. It made a difference in some test if I gave Newton's method the second guess OR averaged the two guesses. The closer of these two values to the neighboring root gave better results. The algorithm is very interesting!!! Thanks! Namir RE: Variant of the Secant Method - Namir - 12-10-2020 02:56 PM I was able to implement in Excel VBA a version of the Generalized Secant algorithm using divided differences for the first, second and third derivatives. Here is the VBA listing for the version that uses two initial guesses and divided differences for the first and second derivatives. Code:
Here is the version of the VBA code that uses three initial guesses and the divided differences for the first three derivatives: Code:
Use different worksheets for each of the above methods as the input values in column A are not the same. I wrote the above code to make it easy to ready. A programmer can optimize the above code by using arrays, matrices, and loops. RE: Variant of the Secant Method - Albert Chan - 12-11-2020 04:34 PM Quadratic interpolation is simply 2 linear interpolations, followed by linear interpolation. x3 y3 x2 y2 y23 x1 y1 y13 y123 Similarly, cubic interpolation is 2 quadratic interpolations, followed by linear interpolation. x4 y4 x3 y3 x2 y2 y234 x1 y1 y134 y1234 Using this recursive nature of polynomial interpolation, I get this neat Lua code Code: function interp(x1,y1,x2,y2,x3,y3,x4,y4) -- estimate y = p(0) Extending interp(...) is trivial, by adding (x5,y5), ... The down-side is each bump up in polynomial degree, doubled the work. For high degree fit, divided-difference style is better, because it can cache previous results. OTTH, assuming we have convergence, old points are very, very far away. Fitting those probably may not help much ... --- For slope of improved secant, we can also consider this an interpolation problem. Example, for a cubic fit, we generate divided-difference table: x4 y4 x3 y3 y34 x2 y2 y24 y234 x1 y1 y14 y123 y1234 p(x) = y4 + (x-x4)*(y34 + (x-x3)*(y234 + (x-x2)*y1234)) = y4 + (x-x4)*M p'(x) = M + (x-x4)*M' → p'(x4) = M Basing all values relative to (x4, y4). Example X3 = x3-x4, Y3 = y3-y4 ... M is just interpolation of individual slopes. X3 Y3/X3 X2 Y2/X2 X1 Y1/X1 M Again, extending this is simply adding more slopes to fit Code: function secant(x1,y1,x2,y2,x3,y3,x4,y4) -- estimate root of p(x) Example: lua> function f(x) return sin(x)/x - 1/6.5 end lua> x1, x2 = 2.711, 2.712 lua> y1, y2 = f(x1), f(x2) lua> x3 = secant(x1,y1, x2,y2) lua> y3 = f(x3) lua> interp(y1,x1, y2,x2, y3,x3) -- inverse interpolate, x = g(0) 2.711312910356982 lua> secant(x1,y1, x2,y2, x3,y3) -- improved secant, x = x3 - y3/slope 2.7113129103569826 RE: Variant of the Secant Method - Albert Chan - 12-11-2020 04:46 PM Let's compare inverse-interpolation vs improved-secant (code from previous post) Code: function test(f, x0, x1, n) -- n = 1 (linear) to 3 (cubic) lua> function f(x) return x^3 - 8 end lua> test(f, 5, 4, 2) -- https://arxiv.org/pdf/2012.04248.pdf, Table 2 2 3.081967213114754 3.081967213114754 3 2.3945608933295457 2.2862188297178117 4 2.0980163342039635 2.010344209437878 5 2.0088865345029276 1.99979593345267 6 2.0001129292461193 2.0000000722313933 7 2.0000000388749792 2.000000000000015 8 2.0000000000000164 2 9 2 2 Last column is improved secant, fitting data up to quadratic (slope by linear interpolation) Middle column is inverse-interpolation for x, at y = 0, also fitting up to quadratic. Improved secant uses the last point as the "base", then does correction. Inverse-interpolation is not as good, probably due to putting equal weight to its points. Let's try again, but with up to cubic fit. lua> test(f, 5, 4, 3) 2 3.081967213114754 3.081967213114754 3 2.3945608933295457 2.2862188297178117 4 2.082744738020821 2.034337291023909 5 2.0058425366743506 2.000576313421517 6 2.0000383915262443 2.000000166004798 7 2.0000000023200664 2.0000000000000138 8 1.9999999999999998 2 9 2 2 Based on above, anything more than a cubic fit probably not worth the trouble. For example, lets see how Newton's method does (actual slope) lua> function df(x) return 3*x*x end lua> x = 4 lua> for i=2, 9 do x = x - f(x)/df(x); print(i, x) end 2 2.833333333333333 3 2.221068819684737 4 2.0212735368091126 5 2.0002231146078984 6 2.0000000248863623 7 2.0000000000000004 8 2 9 2 RE: Variant of the Secant Method - Namir - 12-12-2020 04:22 AM I went back to my Excel VBA code and added statements to implement Halley's method. The Generalized Secant method did better than Newton's method but ws behind Halley's method in the number of steps. Of course results depend on the function tested and the initial guess. Namir RE: Variant of the Secant Method - ttw - 12-12-2020 02:41 PM Methods with high convergence can have problems numerically; they also tend to have a smaller domain of convergence. Multi-point methods seem to be a bit more stable than high order methods. RE: Variant of the Secant Method - Albert Chan - 12-12-2020 04:27 PM (12-12-2020 02:41 PM)ttw Wrote: Methods with high convergence can have problems numerically; they also tend to have a smaller domain of convergence. This might not always true. In fact, recently we come across opposite case, LambertW function implementation. Solving f(x) = x*e^x - a, with Newton's method is very unstable. Higher convergence method, say Halley, it becomes "safe" P.S. the next post, I had suggested another way, to suppress the exponential. This version, Newton's method is fast, and safe. >>> from mpmath import * >>> a = -1e99 >>> findroot(lambda x: x + ln(x/a), 200+3j) # bad guess mpc(real='222.55067066150301', imag='3.1275404175517207') >>> lambertw(a) mpc(real='222.55067066150301', imag='3.127540417551721') RE: Variant of the Secant Method - Albert Chan - 12-11-2023 03:25 PM (12-11-2020 04:34 PM)Albert Chan Wrote: Quadratic interpolation is simply 2 linear interpolations, followed by linear interpolation. It may seems we need 3 secant root steps for 3-points fit, in a loop, we only need 2 x2 y2 x3 y3 y23 x1 y1 y12 y123 Next iteration y23 → y12, can be reused. Secant setup code Code: function newx(a,fa, b,fb) return b - fb/(fb-fa)*(b-a) end Code: function S.secant2(f,a,b,eps,verbal,c) -- 3 pt fit lua> f = fn'x: x^3 - 8' lua> x = S.secant2(f, 5, 4, 1e-9, true) 5 4 3.081967213114754 2.3945608933295457 2.0980163342039635 2.0088865345029276 2.0001129292461193 2.0000000388749792 2.0000000000000164 2 Result matched post #8 For completeness, here is S.secant3 (OP "improved" secant) Code: function S.secant3(f,a,b,eps,verbal,c) -- slope extrapolated lua> x = S.secant3(f, 5, 4, 1e-9, true) 5 4 3.081967213114754 2.2862188297178117 2.010344209437878 1.99979593345267 2.0000000722313933 2.000000000000015 2 RE: Variant of the Secant Method - Thomas Klemm - 12-16-2023 08:11 PM These functions implement the described secant method in Python for orders \(k \in \{1, 2, 3\}\): Code: def f(x): We can run them using the Decimal library: Code: from decimal import Decimal, getcontext Code: secant_1(Decimal(5), Decimal(4), 1e-32) 5 4 3.081967213114754098360655737704918 2.519552120040923041946117994770945 2.180972989759050190092856538085551 2.037953100909517790045306042203723 2.003198489980016115117431120840932 2.000059872823468592338193344700047 2.000000095647401657566635004047756 2.000000000002863282761488899959229 2.000000000000000000136932773807772 2.000000000000000000000000000000196 2.000000000000000000000000000000000 Code: secant_2(Decimal(5), Decimal(4), 1e-32) 5 4 3.081967213114754098360655737704918 2.286218829717811307322668037730626 2.010344209437878312641529731720143 1.999795933452669925783583536567984 2.000000072231393330599606713662298 2.000000000000015319238844912588532 2.000000000000000000000000018934481 2.000000000000000000000000000000000 Code: secant_3(Decimal(5), Decimal(4), 1e-32) 5 4 3.081967213114754098360655737704918 2.286218829717811307322668037730626 2.034337291023909027923796138229571 2.000576313421516741692818211990178 2.000000166004797850203846960058336 2.000000000000013778794929746133383 2.000000000000000000000000000094928 2.000000000000000000000000000000000 These are the corresponding programs for the HP-42S: Code: 00 { 76-Byte Prgm } Code: 00 { 127-Byte Prgm } Code: 00 { 195-Byte Prgm } From the paper: \(s_1 \doteq 1.618, \; s_2 \doteq 1.839, \; s_3 \doteq 1.928\) It appears that the benefit of order 3 compared to order 2 is not that big. Registers Interestingly the 3 variants share registers and also some of the code. SEC-1: 00: x_4 01: x_5 02: ε 03: f_4 04: f_5 05: f_45 = (f_4 - f_5) ÷ (x_4 - x_5) 06: x_6 = x_5 - f_5 ÷ f_45 SEC-2: 00: x_4 01: x_5 02: ε 03: f_4 04: f_5 05: f_45 = (f_4 - f_5) ÷ (x_4 - x_5) 06: x_6 = x_5 - f_5 ÷ f_45 07: f_6 08: f_56 = (f_5 - f_6) ÷ (x_5 - x_6) 09: f_456 = (f_45 - f_56) ÷ (x_4 - x_6) 10: x_7 = x_6 - f_6 ÷ ((x_6 - x_5) × f_456 + f_56) SEC-3: 00: x_4 01: x_5 02: ε 03: f_4 04: f_5 05: f_45 = (f_4 - f_5) ÷ (x_4 - x_5) 06: x_6 = x_5 - f_5 ÷ f_45 07: f_6 08: f_56 = (f_5 - f_6) ÷ (x_5 - x_6) 09: f_456 = (f_45 - f_56) ÷ (x_4 - x_6) 10: x_7 = x_6 - f_6 ÷ ((x_6 - x_5) × f_456 + f_56) 11: f_7 12: f_67 = (f_6 - f_7) ÷ (x_6 - x_7) 13: f_567 = (f_56 - f_67) ÷ (x_5 - x_7) 14: f_4567 = (f_456 - f_567) ÷ (x_4 - x_7) 15: x_8 = x_7 - f_7 ÷ (((x_7 - x_5) × f_4567 + f_567) × (x_7 - x_6) + f_67) 16: f_8 Example This is the example from the paper in table 2. Keep hitting the R/S key to get the next result. 5 ENTER 4 ENTER 1E-32 XEQ "SEC-2" 5 4 3.081967213114754098360655737704918 2.286218829717811307322668037730626 2.010344209437878312641529731720143 1.999795933452669925783583536567984 2.000000072231393330599606713662298 2.000000000000015319238844912588532 2.000000000000000000000000018934481 2.000000000000000000000000000000000 |