Show code cell source
import numpy as np;
import scipy as sc;
import matplotlib.pyplot as plt;
%matplotlib inline
3.1. Interpolacija polinomima#
Opis problema. Zadana je funkcija \(f : [a, b] \to \R\). Želimo odrediti polinom \(p\) takav da vrijedi \(p(x_0) = f(x_0)\), …, \(p(x_n) = f(x_n)\), gdje su \(x_0, \dots, x_n \in [a, b]\) odabrane međusobno različite točke. Kažemo da takav polinom interpolira funkciju \(f\) u čvorovima interpolacije \(x_0, \ldots, x_n\). Uočimo da nam u cijelom ovom poglavlju nije potrebna pretpostavka da su točke \(x_k\) uzlazno sortirane; to će biti vrlo bitno za neke od dokaza koji slijede.
Odgovor na pitanje postoji li takav polinom \(p\), te je li jedinstven daje sljedeći teorem.
Neka je \(n \in \N \cup \{0\}\). Za zadane parove \((x_k, f_k)\), \(k=0, \ldots, n\), gdje su svi \(x_0, \dots, x_n\) međusobno različiti, postoji jedinstveni interpolacijski polinom \(\varphi \in \mathcal{P}_n\),
takav da za svaki \(k=0, \ldots, n\) vrijedi \(p_n(x_k) = f_k\).
Ovdje smo sa \(\mathcal{P}_n\) označili skup svih polinoma stupnja manjeg ili jednakog \(n\).
Neka je \(p_n \in \mathcal{P}_n\) polinom stupnja \(\leq n\) čiji koeficijenti su \(a_0, \ldots, a_n\) kao u (3.1). Uvjete interpolacije napišemo u obliku sustava linearnih jednadžbi s nepoznanicama \(a_0, \ldots, a_n\):
Pokažimo da je matrica ovog sustava regularna ako i samo ako su čvorovi \(x_0, \ldots, x_n\) različiti. Tada sustav ima jedistveno rješenje, tj. postoji polinom \(p_n\) i jedinstven je.
Determinanta sustava je tzv. Vandermondeova determinanta
Definirajmo još sličnu determinantu koja u zadnjem retku umjesto fiksne vrijednosti \(x_n\) ima varijablu \(x\):
Vrijedi \(D_n = V_n(x_n)\).
Razvijmo \(V_n(x)\) po zadnjem retku i uočimo:
\(V_n(x)\) je polinom stupnja najviše \(n\) u varijabli \(x\);
koeficijent tog polinoma uz \(x^n\) je upravo \(D_{n-1}\) jer ga dobijemo kada prekrižimo zadnji redak i stupac od \(V_n(x)\).
Uočimo još sljedeće:
jer svaka od ovih determinanti ima dva jednaka retka, pa je njezina vrijednost \(0\). Stoga su \(x_0, \ldots, x_{n-1}\) nultočke polinoma \(V_n(x)\). Taj polinom je stupnja \(n\) i ima vodeći koeficijent \(D_{n-1}\), pa stoga mora biti jednak
Uvrstimo \(x=x_n\) i dobivamo
Sada isti postupak primijenimo na \(D_{n-1}\), pa na \(D_{n-2}\), sve do \(D_0 = 1\), te dobivamo:
Dakle, \(D_n \neq 0\) ako i samo ako su svi čvorovi \(x_k\) različiti, i tada postoji interpolacijski polinom stupnja najviše \(n\) i on je jedinstven.
Upozorenje
U nastavku ćemo se baviti raznim oblicima interpolacijskog polinoma. No to će uvijek biti jedan te isti polinom, čiju smo jedinstvenost pokazali u gornjem teoremu. Jedino što će se mijenjati je izbor baze u kojoj prikazujemo taj uvijek isti polinom.
Sljedeći primjer pokazuje kako izbor kanonske baze za prikaz interpolacijskog polinoma može biti problematičan.
Primjer. Pronađimo interpolacijski polinom \(p_{40}\) stupnja \(40\) zapisan u standardnoj bazi potencija koji interpolira funkciju
na ekvidistantnoj mreži čvorova \(x_k = k \frac{\pi}{2}\) na intervalu \([0, 20\pi]\).
Matrica sustava koji trebamo riješiti da bismo odredili nepoznate koeficijente je Vandermondeova, kao u dokazu Teorema 3.4. Odredimo njezinu uvjetovanost.
Show code cell content
# Čvorovi interpolacije: 41 ekvidistantna točka između 0 i 20pi, uključujući rubove.
x = np.linspace(0.0, 20.0*np.pi, num=41);
# Vandermondeova matrica za čvorove interpolacije.
A = np.vander(x, increasing=True);
# Uvjetovanost od A.
print(np.linalg.cond(A));
3.2572831130142366e+72
Uvjetovanost matrice sustava je jednaka \(\approx 3.26 \cdot 10^{72}\), što je iznimno veliko i stoga očekujemo velike greške prilikom rješavanja sustava. Zaista, ako odredimo koeficijente interpolacijskog polinoma \(p_{40}\) kao rješenja linearnog sustava, vrijednosti \(p_{40}(x_k)\) bi se morale podudarati sa \(f(x_k)=\sin(x_k)\) u čvorovima interpolacije \(x_k\). No zbog velikih grešaka u rješavanju sustava vidimo da to nije slučaj, te se na donjoj slici crvene oznake – vrijednosti \(p(x_k)\) – ni približno ne podudaraju s plavim oznakama – vrijednostima \(f(x_k) = \sin(x_k)\).
Show code cell source
# Vrijednosti funkcije f u čvorovima interpolacije.
f = np.sin(x);
# Rješenje sustava A*koef = f daje koeficijente interpolacijskog polinoma.
koef = np.linalg.solve(A, f);
# Napravimo polinom s koeficijentima koef[0], koef[1], ...
p = np.polynomial.polynomial.Polynomial(koef);
# Nacrtamo vrijednosti od p(x) u čvorovima interpolacije, te sin(x) u čvorovima interpolacije.
# Uzmimo samo prvih 10 čvorova.
x_first = x[0:9];
plt.figure(figsize=[10.4, 4.8]);
plt.plot(x_first, p(x_first), 'rx', label='p(x)');
plt.plot(x_first, np.sin(x_first), 'bo', label='sin(x)', fillstyle='none');
# Nacrtamo još i graf funkcije sin(x).
x_all = np.linspace(0, 4*np.pi, 1000);
plt.plot(x_all, np.sin(x_all), '--', color='#aaaaaa');
plt.legend();
plt.grid();
plt.xticks(ticks=[0, np.pi, 2*np.pi, 3*np.pi, 4*np.pi], labels=['0', '$\pi$', '2$\pi$', '3$\pi$', '4$\pi$']);
plt.show();

Stoga je problematično računati interpolacijske polinome zapisane u kanonskoj bazi, pogotovo one imalo većeg stupnja.
Tipično, Vandermondeove matrice imaju veliku uvjetovanost za većinu izbora čvorova interpolacije. Pokušajte sami modificirati gornje programe u Pythonu i odrediti uvjetovanosti za razne druge mreže čvorova interpolacije na intervalu \([0, 20\pi]\): na primjer, za mrežu \(x_k = \frac{20 \pi}{k}\), \(k=1, \ldots, 41\).
S druge strane, postoje i dobre mreže čvorova za interpolaciju, ali takvi čvorovi su u \(\C\), a ne u \(\R\)! Najvažniji takav primjer su kompleksni korijeni iz jedinice:
Tada je Vandermondova matrica jednaka \(V_n = \sqrt{n+1} \cdot U\), gdje je \(U\) unitarna matrica, pa je uvjetovanost od \(V_n\) jednaka \(1\), što je idealna uvjetovanost! Ovo je podloga za tzv. brzu Fourierovu transformaciju (FFT), proglašenu najvažnijim algoritmom u povijesti!
Napomena
Zaključimo: ako je zadano \(n\) čvorova interpolacije, da bismo prikazali polinom u kanonskoj bazi, potrebno je riješiti sustav linearnih jednadžbi s potencijalno vrlo visokom uvjetovanosti. Osim toga, rješavanje tog sustava kojim određujemo koeficijente polinoma ima veliku vremensku složenost \(\bigO(n^3)\).
Lagrangeov oblik interpolacijskog polinoma#
Ako u prostoru polinoma \(\mathcal{P}_n\) odaberemo neku bazu \(\{ \varphi_0, \ldots, \varphi_n \}\), onda interpolacijski polinom možemo prikazati u obliku
Linearni sustav za nepoznate koeficijente \(a_0, \ldots, a_n\) ima oblik
pa je njegova matrica sustava
Možemo li pronaći bazu u kojoj je matrica ovog sustava jedinična?
Lagrangeova baza \(\{\ell_0, \ell_1, \ldots, \ell_n\}\) u prostoru polinoma \(\mathcal{P}_n\) je ona baza za koju je matrica sustava za interpolaciju upravo jedinična matrica.
(U gornji sustav, tj. matricu, uvrstimo \(\varphi_k = \ell_k\).)
Tada uopće neće biti potrebno rješavati sustav, nego ćemo moći odmah očitati rješenje: \(k\)-ta jednadžba prelazi jednostavno u \(a_k = f_k\), pa polinom glasi
Jednadžba (3.2) daje Lagrangeov oblik interpolacijskog polinoma. Kako bi matrica sustava za koeficijente bila jedinična, za svaki \(k=0, \ldots, n\) mora vrijediti
Uočimo da je polinom \(\ell_k\) zapravo interpolacijski polinom koji u čvoru \(x_k\) poprima vrijednost \(1\), a u svim ostalim čvorovima vrijednost \(0\). Stoga taj polinom postoji po Teoremu 3.4.
S druge strane, možemo lako pronaći i eksplicitnu formulu za taj polinom:
Neka su \(x_0, x_1, \ldots, x_n\) čvorovi interpolacije. Polinom
zovemo polinom čvorova.
Koristeći polinom čvorova, elemente Lagrangeove baze možemo zapisati i ovako:
a lako se, derivacijom produkta, vidi da je \(\omega_k(x_k) = \omega'(x_k)\), pa stoga
Napomena
Koristeći formulu (3.4), vrijednost \(p_n(x)\) za zadanu točku \(x\) možemo izračunati u \(\bigO(n)\): toliko operacija nam treba za računanje produkta \(\omega(x)\) i za računanje sume u (3.4).
To vrijedi u slučaju da unaprijed izračunamo i u nekom polju zapamtimo sve vrijednosti \(\omega'(x_k) = \omega_k(x_k)\). Za tu pripremnu fazu nam treba ukupno \(\bigO(n^2)\) operacija, a nakon toga, izračun svakog novog \(p_n(x)\) zahtijeva samo \(\bigO(n)\) operacija. To je bitno efikasnije od zapisa u kanonskoj bazi, koja je trebala \(\bigO(n^3)\) operacija u pripremnoj fazi za rješavanje sustava.
Iako gornja napomena sugerira da je Lagrangeova baza pogodna za računanje interpolacijskog polinoma, ona se ipak uglavnom koristi za teoretske svrhe, kao što ćemo vidjeti u narednim cjelinama. Iznimno, varijanta koja koristi baricentričku formu Lagrangeovog interpolacijskog polinoma je pogodna i za implementaciju na računalu.
Newtonov oblik interpolacijskog polinoma#
Primijetimo da Lagrangeov oblik nije pogodan za naknadno dodavanje čvorova, tj. postupno povećanje stupnja interpolacije. Naime, ako dodamo novi čvor \(x_{n+1}\), promijenit će se svi elementi baze \(\ell_0, \ldots, \ell_n\) i morat ćemo ih ponovno izračunati.
Za tu svrhu puno je pogodniji tzv. Newtonov oblik interpolacijskog polinoma. Njega ćemo izvesti upravo tako da, počevši od trivijalnog interpolacijskog polinoma stupnja \(0\), u svakom koraku dodajemo po jedan novi čvor.
Polinom \(p_0\) koji interpolira funkciju \(f\) u čvoru \(x_0\) glasi
Dodajmo još jedan čvor \(x_1\). Polinom \(p_1\) dobijemo iz \(p_0\) dodavanjem korekcije \(r_1\):
Polinom \(r_1\) ima stupanj \(\leq 1\). Kako \(p_1\) interpolira \(f\) i u \(x_0\), vrijedi
pa \(r_1\) ima nultočku u \(x_0\):
za neki \(a_1 \in \R\). Kako \(p_1\) interpolira \(f\) u \(x_1\), imamo
pa iz \(r_1(x_1) = a_1(x_1 - x_0)\) imamo
Dodajmo još jedan čvor interpolacije \(x_2\). Polinom \(p_2\) dobivamo korekcijom iz \(p_1\):
gdje je \(r_2\) stupnja \(\leq 2\). Kako \(p_2\) interpolira \(f\) u \(x_0\) i \(x_1\), kao i ranije dobivamo da su \(x_0\) i \(x_1\) nultočke od \(r_2\), koji stoga ima oblik
za neki \(a_2 \in \R\) koji onda možemo odrediti iz uvjeta \(p_2(x_2) = f_2\).
Sada je jasno da će u nastavku konstrukcije korekcije uvijek imati nultočke u svim ranijim čvorovima, a da ćemo vodeći koeficijent u korekciji moći odrediti iz uvjeta interpolacije u novom čvoru. Tako dobivamo interpolacijski polinom u obliku
zapisan u Newtonovoj bazi za \(\mathcal{P}_n\) koju čine polinomi
Potrebno je još samo odrediti koeficijente \(a_0, a_1, \ldots, a_n\). Iz naše konstrukcije je jasno da \(a_k\) ovisi samo o čvorovima \(x_0, \ldots, x_{k}\) i pripadnim funkcijskim vrijednostima \(f_0, \ldots, f_k\). Uvodimo specijalnu oznaku kojom naznačavamo tu ovisnost.
Sada ćemo izvesti rekurzivnu formulu kojom podijeljenu razliku reda \(k\) možemo prikazati pomoću dvije podijeljene razlike reda \((k-1)\). Ta formula će omogućiti vrlo jednostavno računanje koeficijenata u (3.5).
Za međusobno različite čvorove \(x_0, \ldots, x_n\), podijeljena razlika \(f[x_0, \ldots, x_n]\) ne ovisi o permutaciji čvorova, tj. za svaku permutaciju \(\sigma\) vrijedi
Označimo sa:
\(a_0, \ldots, a_n\) koeficijente interpolacijskog polinoma u Newtonovoj bazi u kojoj čvorove dodajemo redom \(x_0, \ldots, x_n\);
\(b_0, \ldots, b_n\) koeficijente tog istog interpolacijskog polinoma u Newtonovoj bazi u kojoj čvorove dodajemo redom \(x_{\sigma(0)}, \ldots, x_{\sigma(n)}\).
Dakle,
Koeficijenti u oba prikaza uz odgovarajuće potencije od \(x\) moraju biti jednake. Izjednačavanjem koeficijenata uz \(x^n\) slijedi \(a_n = b_n\), a oni su po definiciji upravo podijeljene razlike iz iskaza Leme.
Za podijeljene razlike vrijedi sljedeća rekurzivna formula:
pri čemu je \(f[x_k] = f_k\).
Slično kao u prethodnoj Lemi, označimo sa:
\(a_0, \ldots, a_n\) koeficijente interpolacijskog polinoma u Newtonovoj bazi u kojoj čvorove dodajemo redom \(x_0, \ldots, x_n\);
\(b_0, \ldots, b_n\) koeficijente tog istog interpolacijskog polinoma u Newtonovoj bazi u kojoj čvorove dodajemo redom \(x_n, \ldots, x_0\).
Dakle,
U prethodnoj Lemi smo dokazali da je \(a_n = b_n\). Izjednačimo sada koeficijente uz \(x^{n-1}\); on se javlja u zadnja dva pribrojnika u oba gornja prikaza:
U predzadnjem pribrojniku taj koeficijent je \(a_{n-1}\), odnosno, \(b_{n-1}\).
U zadnjem pribrojniku se pojavljuje kada u točno jednoj od zagrada uzmemo \(-x_k\), a u svim preostalim zagradama \(x\).
Izjednačavanjem koeficijenata dobivamo:
Iskoristimo \(a_n = b_n\) i pokratimo sve \(x_k\) koji se pojavljuju na obje strane u gornjoj jednakosti. Preostaje
iz čega možemo izraziti \(a_n\):
Tvrdnja slijedi kada uočimo da je
gdje smo za zadnju jednakost iskoristili prethodnu Lemu.
Kako bismo izračunali sve koeficijente potrebne za prikaz interpolacijskog polinoma u Newtonovoj bazi, popunjavamo sljedeću tablicu.
Tablicu popunjavamo stupac po stupac, slijeva na desno. Brojeve u svakom stupcu dobivamo pomoću brojeva iz prethodnog stupca, korištenjem rekurzivne formule iz Leme 3.9. Na kraju su nam potrebni samo brojevi označeni crvenom bojom u tablici – no moramo popuniti cijelu tablicu da bismo odredili te brojeve:
Algoritam koji na početku u f[k]
ima spremljene vrijednosti \(f[x_k]\), a na kraju u f[k]
čuva vrijednosti \(f[x_0, \ldots, x_k]\) je vrlo jednostavan:
n = 40; # n = stupanj polinoma -> broj čvorova = n+1.
x = np.linspace(0, 20*np.pi, n+1);
f = np.sin(x);
for i in range(1, n+1): # za i = 1, 2, ..., n
for j in range(n, i-1, -1): # za j = n, n-1, ..., i
f[j] = (f[j] - f[j-1]) / (x[j] - x[j-i]);
U algoritmu u \(i\)-tom koraku vanjske petlje u polje f
zapisujemo vrijednosti \((i+1)\)-vog stupca tablice, no vrijednosti na indexima \(0, \ldots, i-1\) u polju f
ostavljamo na miru, u njima su već izračunati \(f[x_0], \ldots, f[x_0, \ldots, x_{i-1}]\). Nije potrebno pamtiti cijelu tablicu. Ova pripremna faza ima vremensku složenost \(\bigO(n^2)\). Nakon toga, vrijednost \(p_n(x)\) možemo izračunati u složenosti \(\bigO(n)\) koristeći algoritam sličan Hornerovoj shemi:
def pn(xx, x, f):
# Vraća vrijednost interpolacijskog polinoma p_n u točki xx.
# Čvorovi su u polju x, a koeficijenti polinoma u Newtonovoj bazi u polju f.
n = x.shape[0] - 1; # Stupanj polinoma je za 1 manji od broja čvorova.
sum = f[n];
for i in range(n-1, -1, -1): # za i = n-1, n-2, ..., 0
sum = sum * (xx-x[i]) + f[i];
return sum;
Za razliku od prikaza u kanonskoj bazi, sada nemamo problema s numeričkom nestabilnosti prilikom izvrednjavanja interpolacijskog polinoma i vrijednosti u čvorovima se podudaraju s funkcijskim vrijednostima.
Show code cell source
x_first = x[0:9];
plt.figure(figsize=[10.4, 4.8]);
plt.plot(x_first, pn(x_first, x, f), 'rx', label='$p_n(x)$');
plt.plot(x_first, np.sin(x_first), 'bo', label='sin(x)', fillstyle='none');
# Nacrtamo još i graf funkcije sin(x).
x_all = np.linspace(0, 4*np.pi, 1000);
plt.plot(x_all, np.sin(x_all), '--', color='#aaaaaa');
plt.legend();
plt.grid();
plt.xticks(ticks=[0, np.pi, 2*np.pi, 3*np.pi, 4*np.pi], labels=['0', '$\pi$', '2$\pi$', '3$\pi$', '4$\pi$']);
plt.show();

Greška interpolacijskog polinoma#
Nakon što odredimo interpolacijski polinom \(p_n\) za zadanu funkciju \(f\), znamo da se vrijednosti od \(p_n\) i od \(f\) podudaraju u čvorovima interpolacije. No možemo li nešto reći o tome koliko dobro \(p_n\) aproksimira \(f\) u točkama koje nisu čvorovi?
Pretpostavimo:
funkcija \(f\) ima \((n+1)\)-u derivaciju na segmentu \([a, b]\);
čvorovi interpolacije \(x_0, \ldots, x_n \in [a, b]\) su međusobno različiti.
Neka je \(p_n\) interpolacijski polinom za \(f\). Tada za svaku točku \(x \in [a, b]\), postoji \(\xi\) takav da je
te da za grešku interpolacijskog polinoma u točki \(x\) vrijedi
Uočimo da je greška u čvorovima interpolacije jednaka \(e(x_k) = 0\), a da je i desna strana u (3.7) također jednaka \(0\) zbog \(\omega(x_k)=0\). Stoga tvrdnja vrijedi ako je \(x\) čvor interpolacije.
Pretpostavimo dakle da \(x\) nije čvor interpolacije. Tada \(\omega(x) \neq 0\), te iz greške \(e(x)\) „izvucimo” \(\omega(x)\) kao što je napravljeno u (3.7): definirajmo broj \(s(x)\) tako da je
Za fiksnu vrijednost \(x\), uvedimo funkciju \(g\) koja ovisi o varijabli \(t \in [a, b]\):
Uočimo da, kako su \(p_n\) i \(\omega\) polinomi, funkcija \(g\) ima (n+1)-u derivaciju kao i \(f\). Također, čvorovi interpolacije su nultočke od \(g\):
kao i točka \(x\):
Dakle, \(g\) ima barem \(n+2\) različite nultočke u \([x_{min}, x_{max}]\). Označimo te nultočke u uzlaznom poretku sa \(y_1 < y_2 < \ldots < y_{n+2}\). Sada primijenimo Rolleov teorem na interval \([y_1, y_2]\): kako je \(g(y_1) = g(y_2)\), postoji \(z_1 \in \langle y_1, y_2 \rangle\) takav da je \(g'(z_1) = 0\). Analogno, primjenom Rolleovog teorema redom na \([y_2, y_3]\), …, \([y_{n+1}, y_{n+2}]\), slijedi da postoje \(z_j \in \langle y_j, y_{j+1} \rangle\) takvi da \(g'(z_j) = 0\), \(j=2, \ldots, n+1\), te je \(z_1 < z_2 < \ldots < z_{n+1}\).
Drugim riječima, \(g'\) ima barem \(n+1\) različitu nultočku u \(\langle x_{min}, x_{max} \rangle\). Induktivnom primjenom Rolleovog teorema, slijedi da \(g''\) ima barem \(n\) nultočki, \(g'''\) ima barem \(n-1\) nultočku, … Na kraju, \(g^{(n+1)}\) ima barem jednu nultočku u \(\langle x_{min}, x_{max} \rangle\). Označimo ju s \(\xi\).
Kako je \(p_n\) polinom stupnja \(\leq n\), vrijedi \(p_n^{(n+1)}(t) = 0\), a kako je \(\omega\) normirani polinom stupnja \(n+1\), vrijedi \(\omega^{(n+1)}(t) = (n+1)!\) za svaki \(t\). Stoga je
pa uvrštavanjem \(t = \xi\) dobivamo traženi izraz
Direktno iz prethodnog teorema možemo dobiti i sljedeću ocjenu za grešku interpolacije.
Pretpostavimo da je \(f \in C^{n+1}([a, b])\), te označimo \(M_{n+1} := \max_{x \in [a, b]} |f^{(n+1)}(x)|\). Tada za svaki \(x \in [a, b]\) vrijedi:
Korištenjem podijeljenih razlika i zapisa interpolacijskog polinoma u Newtonovoj bazi možemo dobiti još jedan koristan izraz za grešku interpolacije. Uočimo, za razliku od Teorema 3.10, ovdje nemamo pretpostavke na glatkoću funkcije \(f\).
Pretpostavimo:
funkcija \(f\) je proizvoljna funkcija na segmentu \([a, b]\);
čvorovi interpolacije \(x_0, \ldots, x_n \in [a, b]\) su međusobno različiti.
Neka je \(p_n\) interpolacijski polinom za \(f\). Tada za svaku točku \(x \in [a, b]\) koja nije čvor interpolacije vrijedi
U Newtonov oblik polinoma dodajmo još jedan novi čvor \(x_{n+1}\), različit od svih \(x_0, \ldots, x_n\). Dobivamo polinom \(p_{n+1}\) za koji vrijedi:
gdje je \(\omega\) polinom čvorova za polazne čvorove \(x_0, \ldots, x_n\) (bez \(x_{n+1}\)). Uvjet interpolacije za polinom \(p_{n+1}\) u novom čvoru \(x_{n+1}\) je
pa uvrštavanjem \(x=x_{n+1}\) gore dobivamo
Ovo vrijedi za svaki \(x_{n+1} \in [a, b]\) različit od čvorova \(x_0, \ldots, x_n\), pa obično umjesto \(x_{n+1}\) pišemo samo \(x\) u izrazu (3.9), čime dobivamo tvrdnju iz iskaza teorema.
Usporedimo sada oba izraza za grešku interpolacije:
Dobili smo sljedeću bitnu tvrdnju o podijeljenim razlikama:
Neka su zadani čvorovi \(x_0, \ldots, x_n \in [a, b]\). Pretpostavimo da \(f^{(n+1)}\) postoji na cijelom \([a, b]\). Tada za svaku točku \(x \in [a, b]\) postoji \(\xi \in \langle x_{min}, x_{max} \rangle\) takva da vrijedi
Ova tvrdnja je poopćenje teorema srednje vrijednosti: kada je \(n=0\), tvrdnja kaže da postoji \(\xi\) takav da vrijedi
Podijeljene razlike i višestruki čvorovi#
Ako bismo Teorem 3.12 htjeli iskoristiti i u slučaju kada je \(x\) jednak nekom od čvorova, morali bismo definirati značenje izraza \(f[x_0, \ldots, x_n, x]\) kada je \(x = x_k\), odnosno, dopuniti definiciju podijeljene razlike tako da dopušta čvorove koji se pojavljuju više puta. To možemo napraviti proširenjem po neprekidnosti:
Uz ovakvu definiciju, \(f[x_0, x_0]\) je korektno definirana ako i samo ako prva derivacija \(f'\) postoji u točki \(x_0\). Slijedi da tvrdnja Teorema 3.12 vrijedi i kada je \(x = x_k\), za neki čvor \(x_k\), pod pretpostavkom da je \(f'\) definirana u \(x_k\) (naravno, tada je greška jednaka nuli).
Iz gornje diskusije, jasno je da za funkciju dvije varijable
vrijedi:
\(f\) definirana na \([a, b]\) \(\Rightarrow\) \(f[x, y]\) je definirana na \(S \setminus D\);
\(f\) neprekidna na \([a, b]\) \(\Rightarrow\) \(f[x, y]\) je neprekidna na \(S \setminus D\);
\(f\) derivabilna na \([a, b]\) \(\Rightarrow\) \(f[x, y]\) je definirana na cijelom \(S\);
\(f\) klase \(C^1\) na \([a, b]\) \(\Rightarrow\) \(f[x, y]\) je neprekidna na cijelom \(S\).
Ovdje je \(S = [a, b] \times [a, b]\), a \(D = \{ (x, x) : x \in [a, b] \}\) je njegova dijagonala.
Analogno, po neprekidnosti možemo proširiti definiciju podijeljenih razlika i na slučaj kada se pojavljuje više identičnih čvorova. Uz dovoljnu glatkoću funkcije \(f\), tada vrijedi:
i u slučaju kada se neki čvorovi podudaraju. Dovoljna glatkoća znači da, ako se čvor \(x_k\) pojavljuje („ima kratnost”) \(n_k\) puta, onda \(f\) mora biti \(n_k-1\) puta neprekidno derivabilna u \(x_k\). Uz takvu pretpostavku, pokažite za vježbu da vrijede tvrdnje iz sljedeće propozicije.
Uz pretpostavku o dovoljnoj glatkoći funkcije \(f\) na \([a, b]\), za sve \(x_0, x_1, \ldots, x_n \in [a, b]\) vrijedi:
\(f[x_0, \ldots, x_n]\) je neprekidna na \([a, b] \times [a, b] \times \ldots \times [a, b]\).
\(f[\underbrace{x_0, \ldots, x_0}_{k+1}] = \frac{f^{(k)}(x_0)}{k!}\), za \(k = 0, 1, \ldots\)
Za svaku permutaciju \(\sigma\) vrijedi \(f[x_0, x_1, \ldots, x_n] = f[x_{\sigma(0)}, x_{\sigma(1)}, \ldots, x_{\sigma(n)}]\).
\(f[x_0, x_1, \ldots, x_{n-1}, x_n] = \frac{f[x_1, \ldots, x_n] - f[x_0, \ldots, x_{n-1}]}{x_n - x_0}\), ako je \(x_0 \neq x_n\).
Kasnije će nam trebati i sljedeće činjenice o derivacijama funkcije vezane uz podijeljenu razliku. Lako ih je dokazati korištenjem prethodne propozicije.
Neka su \(x_0, \ldots, x_n \in [a, b]\) „fiksni” čvorovi, a neka je \(x \in [a, b]\) „varijablni” čvor u podijeljenoj razlici po kojem ju deriviramo. Tada vrijedi:
te
Dokažimo prvu tvrdnju; druga ide slično.
Prva jednakost je definicija derivacije, druga i četvrta koriste da se podijeljena razlika ne mijenja permutiranjem čvorova, treća koristi rekurziju za podijeljene razlike, a peta neprekidnost podijeljenih razlika.
Interpolacijski polinom u Pythonu#
U biblioteci scipy.interpolate
postoji nekoliko funkcija koje mogu računati vrijednosti interpolacijskog polinoma. Konkretno, poziv funkcije yy = barycentric_interpolate(x, f, xx)
će napraviti sljedeće:
Odredit će interpolacijski polinom \(p\) koji u čvorovima
x[0]
,x[1]
, …,x[n]
poprima redom vrijednostif[0]
,f[1]
, …,f[n]
. Ovdje jen
duljina poljax
if
;Za svaki element polja
xx
će izračunati vrijednost polinoma \(p\) u toj točki;Vratit će izračunate vrijednosti interpolacijskog polinoma za elemente od
xx
redom u poljuyy
.
Funkcija barycentric_interpolate
koristi tzv. baricentrički zapis Lagrangeove forme prilikom izračunavanja \(p\).
from scipy.interpolate import barycentric_interpolate;
# Čvorovi interpolacije: 41 ekvidistantna točka između 0 i 20pi, uključujući rubove.
x = np.linspace(0.0, 20.0*np.pi, num=41);
# Vrijednosti funkcije f u čvorovima interpolacije.
f = np.sin(x);
# Točke u kojima želimo izračunati vrijednost interpolacijskog polinoma.
# Ovdje uzimamo prvih 9 čvorova interpolacije, no to mogu biti i bilo koje druge točke.
xx = x[0:9];
# Vrijednosti interpolacijskog polinoma pomoću funkcije iz biblioteke scipy.
yy = barycentric_interpolate(x, f, xx);
# Nacrtamo slike kao gore.
plt.figure(figsize=[10.4, 4.8]);
plt.plot(xx, yy, 'rx', label='p(x)');
plt.plot(xx, np.sin(xx), 'bo', label='sin(x)', fillstyle='none');
# Nacrtamo još i graf funkcije sin(x).
x_all = np.linspace(0, 4*np.pi, 1000);
plt.plot(x_all, np.sin(x_all), '--', color='#aaaaaa');
plt.legend();
plt.grid();
plt.xticks(ticks=[0, np.pi, 2*np.pi, 3*np.pi, 4*np.pi], labels=['0', '$\pi$', '2$\pi$', '3$\pi$', '4$\pi$']);
plt.show();
