Jacek Złydach (JW) Wstęp Interpolacja krzywymi sklejanymi stopnia drugiego (SPLINE-) Implementacja praktyczna Poniższa praktyczna implementacja stanowi uzupełnienie teoretycznych rozważań na temat interpolacji za pomocą krzywych sklejanych drugiego stopnia. Wykorzystuje ona kod omówiony dokładnie w III sprawozdaniu z Metod Numerycznych (metody numerycznego rozwiązywania układów równań liniowych). Funkcje Poniżej umieściłem garść funkcji pomocniczych dokładnie omówionych w trzecim sprawozdaniu (między innymi faktoryzacja LU). sklej_macierze_poziomo( lhs, rhs) := ( ) wydziel_macierz_lewa( lhs, leftcols) := for i.. cols( rhs) cols lhs lhs ( ) + i lhs leftmatrix i if rows( lhs) rows( rhs) rhs i for i.. leftcols leftmatrix lhs i wydziel_macierz_prawa( lhs, leftcols) := for i leftcols.. cols( lhs) rightmatrix i leftcols rightmatrix lhs i b last( b) podstawienia_u( A, b) := x last( b) A last( b), last( b) for i last( b).. x i last( b) b i j = i+ x A i, i ( A x i, j j ) str. /9
Jacek Złydach (JW) b podstawienia_l( A, b) := x A, for i.. last( b) x i i b i j = x ( if ( i j, A x, i, j j )) A i, i gaussian_lu( A) := for i.. rows( A) for r i +.. rows( A) A r, i A i, i for j i.. cols( A) A A A r, j r, j i, j A r, i A wydziel_l( A) := for i.. rows( A) for j.. i L A if i j i, j i, j L i, j L otherwise wydziel_u( A) := for i.. rows( A) for j i.. cols( A) U A i, j i, j U Wstęp do interpolacji krzywą SPLINE- Zagadnienie interpolacji rozpatrzyłem na przykładzie poniższych dwóch funkcji: f( x) := + 5x Przedział badania funkcji to: x f( x) := e + x str. /9
Jacek Złydach (JW) x := 5 step :=. x := 5 x := x, x + step.. x Do interpolacji użyłem węzłów równoodległych: 4 3 w := y := f( = y := f( = 3 4.493765586349 3 4.44778766947 3 9.9999999 3.384653846538.384653846538 9.9999999 3 4.44778766947 3.493765586349 3.386843666.5936336.6466476763387.6787944744.46787944744.335335833663.34978768367864.4835638888734 Obie funkcje wraz z zaznaczonymi węzłami można zobaczyć na poniższym wykresie: Interpolowane funkcje.5.5 6 4 4 6 Funkcja Funkcja Węzły funkcji Węzły funkcji str. 3/9
Jacek Złydach (JW) W celu umożliwienia elastycz nego badania krzywych oraz optymalizacji czasu obliczeń postanowiłem, że wszystkie punkty wielomianu interpolacyjnego w zadanym wyżej zakresie zostaną wyliczone raz i nie będą przeliczane przy odświeżaniu wykresu. Dlatego zdefiniowałem poniższą funkcję pomocniczą: W( x, C, w, y) := ktory last( i = wynik C x w ktory ktory wynik ( ) if x > w x w, i, i i+ ( ) C x w ktory+ ( ktory ) ( ) + if x > w, last(, last( + + y ktory Funkcja ta oblicza wartość krzywej SPLINE- w punkcie x na podstawie wektora współczynników C oraz węzłów w i wartościach w węzłach y. Poniższa funkcja tworzy wektor wartości wielomianu SPLINE- na podanym przedziale: S( C, w, y, x, step, x) := licznik for p x, x + step.. x wynik W( p, C, w, y) licznik licznik licznik + wynik Dodatkowa pomocnicza funkcja tworząca wektor wartości x w podanym przedziale: X( x, step, x) := licznik for p x, x + step.. x wynik p licznik licznik licznik + wynik Poniższa funkcja oblicza odległość między węzłami: dist( k, := w w k+ k Równanie macierzowe SPLINE- We wstępie teoretycznym opisałem dokładne wyprowadzenie macierzowych równań dla krzywej SPLINE-; poniżej znajduje się implementacja tego układu: Funkcja poniżej tworzy fragment macierzy współczynników odpowiedzialny za n-tą parę równań ciągłości. rmax oznacza całkowita liczbę równań. str. 4/9
Jacek Złydach (JW) R( n, rmax, := A dist( n, n, n A dist( n, n, ( n) + A dist( n, ( n) +, n A ( n) +, ( n) + A ( n) +, ( n) + 3 A rmax, rmax A Poniższa funkcja tworzy fragment macierzy współczynników odpowiedzialny za ostatni wielomian składowy SPLINE- i ostatni węzeł interpolacyjny. Przyjęty jest wariant z parametryzowaną pochodną w ostatnim węźle. Rost( n, := A dist( n, n, n A dist( n, n, ( n) + A dist( n, ( n+ ), n A ( n+ ), ( n) + A Poniższa funkcja tworzy fragment macierz wyrazów wolnych B odpowiedzialny za n-tą parę równań ciągłości. B( n, rmax, w, y) := B y y n, n+ n B rmax, B ( n) +, B Zapewnienie właściwego rozmiaru macierz y potrzebnego do sumowania. Poniższa funkcja oblicza współczynniki krzywej SPLINE- dla podanych węzłów w i wartości y w tych węzłach oraz wartości ostatniej pochodnej d przez bezpośrednie rozwiązanie równania macierzowego. S_mat( w, y, d) := A B last( i = last( i = B last( r A B r R( i, last(, + Rost( last(, B( i, last(, w, y) d Parametryzacja pochodnej str. 5/9
Jacek Złydach (JW) Współczynniki wielomianu interpolacyjnego dla funkcji i przy ostatniej pochodnej równej : smat_ := S_mat( w, y, ) = 3 4 5 6 7 3.748-3.746-3.744 3.75 3.768-3.739 -.835 3.796 smat_ := S_mat( w, y, ) = 8.9 9 -.873. -.5.64-3 3-7.9-3 4.93-3 5-3.86-3 3 4 5 6 7 8 9 3 4 5.946 -.85 -.89.78.39 -.76 -.639.37.375 -.97.4 -.57.3 -.8 -.69.37 Wektor X potrzebny do wykresu: X_mat := X( x, step, x) Wartości SPLINE- dla dwóch funkcji: Y_mat_ := S( smat_, w, y, x, step, x) Y_mat_ := S( smat_, w, y, x, step, x) Wykresy przedstawiające rezultat interpolacji SPLINE-: str. 6/9
Jacek Złydach (JW) f( x) y Y_mat_ 6 4 4 6 x, w, X_mat str. 7/9
Jacek Złydach (JW) f( x) y Y_mat_ 6 4 4 6 x, w, X_mat (brak dodatkowego formatowania wykresów wynika po raz kolejny z błędów Mathcada) Powyższe wykresy dość dobrze ilustrują problem z krzywymi SPLINE-: występują w nich czasem bardzo potężne oscylacje, które czynią interpolację tymi krzywymi praktycznie bezużyteczną praktycznie. W powyższym wykresie ostatnia pochodna została ręcznie ustawiona na wartość, która jest bliska wartości pochodnej w tym punkcie dla obu interpolowanych funkcji. Można jednak sprawdzić, że dla wartości ostatniej pochodnej znacznie różniących się od wartości pochodnej interpolowanej funkcji także z prawej strony wykresu pojawią się pokaźne oscylacje. Faktoryzacja LU W części teoretycznej wysunąłem twierdzenie, jakoby przekształcone równanie krzywej SPLINE- nadawało się do faktoryzacji LU, pozwalając dla danego zestawu węzłów wyliczyć dane pośrednie. Obliczenia te pozwalają na szybsze wyliczenie współczynników krzywej SPLINE- dla dowolnej funkcji, którą roz patrujemy w tych węzłach. Poniższy fragment sprawozdania przeznaczyłem na praktyczne sprawdzenie tego zagadnienia: Zmodyfikowana macierz współczynników: str. 8/9
Jacek Złydach (JW) R_LU( n, rmax, := A dist( n, n, n A dist( n, n, ( n) + A ( n) +, n A ( n) +, ( n) + A ( n) +, ( n) + 3 A rmax, rmax A Rost_LU( n, := A dist( n, n, n A dist( n, n, ( n) + A ( n+ ), n A ( n+ ), ( n) + Zmodyfikowana macierz wyrazów wolnych B: B_LU( n, rmax, w, y) := B y y n, n+ n A B rmax, B ( n) +, B y y n+ n dist( n, Faktoryzacja LU macierzy współczynników dla węzłów równo odległych: A_LU_przed := last( i = R_LU( i, last(, + Rost_LU( last(, A_LU := gaussian_lu( A_LU_przed) Obliczenie macierzy współczynników B dla obu interpolowanych funkcji: B_LU_ := B_LU_ := last( i = last( i = B_LU( i, last(, w, y) B_LU( i, last(, w, y) B_LU_ := (ostatnia pochodna) last( B_LU_ := (ostatnia pochodna) last( Poniższa funkcja oblicza współczynniki krzywej SPLINE- dla podanych macierzy A i B wyliczonych z procesu str. 9/9
Jacek Złydach (JW) faktoryzacji LU. S_LU( A, B) := y podstawienia_l( wydziel_l( A), B) r podstawienia_u( wydziel_u( A), y) Obliczone współczynniki: r 3 4 5 6 -.838 slu_ := S_LU( A_LU, B_LU_) = 7 3.8 slu_ := S_LU( A_LU, B_LU_) = 8 9 3 4 5 3.75-3.75-3.748 3.754 3.77-3.743.95 -.877.8 -.46 5.476-3 -. -.93-3 3 4 5 6 7 8 9 3 4 5.89 -.678 -.755.94.9 -.569 -.5.34.38 -.77.6 -.94 -.4.9.69 Wartości SPLINE- dla dwóch funkcji: Y_lu_ := S( slu_, w, y, x, step, x) Y_lu_ := S( slu_, w, y, x, step, x) Wykresy interpolacji faktoryzacją LU: str. /9
Jacek Złydach (JW) f( x) y Y_lu_ 6 4 4 6 x, w, X_mat str. /9
Jacek Złydach (JW) f( x) y Y_lu_ 6 4 4 6 x, w, X_mat Przewidywanie okazało się słuszne, wzory dla faktoryzacji LU sprawdzone. W powyższym przykładzie macierz współczynników policzyliśmy tylko raz, wobec czego złożoność obliczeniowa spadła z n 3 do n. Wynika z tego, że gdybyśmy mieli k funkcji do interpolowania przy użyciu SPLINE- na tych samych węzłach, każdorazowe rozwiązanie równania miałoby łączną złożoność kn 3, a w przypadku metody LU uzyskalibyśmy złożoność kn. Przy k porównywalnym z n taka oszczędność ma duże znaczenie. Wzory jawne dla krzywej SPLINE- Jeszcze szybszą od faktoryzacji LU metodą obliczenia współczynników krzywej SPLINE- jest wykorzystanie wzorów rekurencyjnych wyprowadzonych w części teoretycznej. Poniższa funkcja oblicza współczynniki b wielomianów składowych SPLINE-: str. /9
Jacek Złydach (JW) wzory_b( w, y, lastb) := b lastb dodatkowy współczynnik b last( + for i last(, last( 3.. i ktory floor ( ) b b + i i+ b y y ktory+ ktory w w ktory+ ktory Po rekurencyjnym wyliczeniu współczynników b można użyć ich do obliczenia współczynników a. Poniższa funkcja realizuje to zadanie, uzupełniając przekazaną macierz o konieczne współczynniki: wzory_a( w, y, b) := for i last(, last( 4.. i ktory floor b b i+ 3 i+ b i w w ktory+ ktory b ( ) Współczynniki SPLINE- obliczone dla obu funkcji: swzory_ := swzory_ := wzory_a( w, y, wzory_b( w, y, ) ) wzory_a( w, y, wzory_b( w, y, ) ) swzory_ = 3 4 5 6 7 3.748-3.746-3.744 3.75 3.768-3.739 -.835 3.796 swzory_ = 8.9 9 -.873. -.5.64-3 3-7.9-3 4.93-3 5... 3 4 5 6 7 8 9 3 4 5.946 -.85 -.89.78.39 -.76 -.639.37.375 -.97.4 -.57.3 -.8 -.69... str. 3/9
Jacek Złydach (JW) Y_wz_ := S( swzory_, w, y, x, step, x) Y_wz_ := S( swzory_, w, y, x, step, x) Wykresy interpolacji wzorami jawnymi: f( x) y Y_wz_ 6 4 4 6 x, w, X_mat str. 4/9
Jacek Złydach (JW) f( x) y Y_wz_ 6 4 4 6 x, w, X_mat Ciekawe problemy Poniżej zaprezentowałem doświadczalnie kilka zagadnień wspomnianych w części teoretycznej a związanych z krzywymi SPLINE-: Dobór ostatniej pochodnej Żeby zilustrować, jak dobór pochodnej w ostatnim punkcie wpływa na całą interpolację, rozważyłem kilka krzywych SPLINE- dla funkcji : S_dv := S_dv := S_dv3 := S_dv4 := Y_dv := Y_dv := Y_dv3 := S_mat( w, y, 4) S_mat( w, y, ) S_mat( w, y, 5) S_mat( w, y, linear_derv) S( S_dv, w, y, x, step, x) S( S_dv, w, y, x, step, x) S( S_dv3, w, y, x, step, x) Przybliżenie pochodnej na końcu przy użyciu dwóch ostatnich węzłów: y y last( y) last( y) linear_derv := w w last( last( =.69 str. 5/9
Jacek Złydach (JW) Y_dv4 := S( S_dv4, w, y, x, step, x) f( x) y Y_dv Y_dv Y_dv3 Y_dv4 6 4 4 6 x, w, X_mat Powyższa mozajka kolorystyczna pokazuje, że w zależności od doboru ostatniej pochodnej znacząco zmienia się zarówno kształt krzywej SPLINE- jak i dokładność, z jaką interpoluje ona zadaną funkcję. Zapętlenie pochodnej Ostatnią pochodną możemy też zdefiniować w taki sposób, by jej wartość była równa wartości pochodnej w pierwszym węźle. Wymaga to modyfikacji równania macierzowego, opisanej dokładniej w części teoretycznej. Modyfikacja została zaimplementowana poniżej: Rost_loop( n, := A dist( n, n, n A dist( n, n, ( n) + A ( n+ ), n A ( n+ ), ( n) + A n+, A str. 6/9
Jacek Złydach (JW) S_loop( w, y) := A B last( i = last( i = B last( r A B Wyliczenie współczynników: r R( i, last(, + Rost_loop( last(, B( i, last(, w, y) W tym miejscu współczynnik musi przyjąć wartość sloop_ := S_loop( w, y) = 3 4 5 6 7 8 9 3 4 5.877 -.875 -.873.879.896 -.868 -.963.95 -.96 -.93-3.893 -.9 -.87.864.873 -.875 sloop_ := S_loop( w, y) = 3 4 5 6 7 8 9 3 4 5.97 -.839 -.96..63 -.73 -.664.396 -.6.69 -.33 -.853.868.97 -.839 Y_loop := Y_loop := S( sloop_, w, y, x, step, x) S( sloop_, w, y, x, step, x) str. 7/9
Jacek Złydach (JW) f( x) y Y_mat_ Y_loop 6 4 4 6 x, w, X_mat str. 8/9
Jacek Złydach (JW) f( x) y Y_mat_ Y_loop 6 4 4 6 x, w, X_mat Warto przy tym zauważyć, że w przypadku funkcji uzyskaliśmy SPLINE- okresową, gdyż wartości w pierwszym i ostatnim węźle były takie same. str. 9/9