MN14: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Przykry (dyskusja | edycje)
Przykry (dyskusja | edycje)
mNie podano opisu zmian
Linia 1: Linia 1:
W poniższych dwóch pierwszych rozdziałach testowych (pliki źródłowe:
\lstux!WIKIwyklad01.tex! i \lstux!WIKIcwiczenia01.tex!)  zobaczymy, jak
konwerter (wymiennie nazywany parserem) \LaTeX{} do Wiki radzi sobie z prostym
dokumentem. Informacje o tym, jakich poleceń \LaTeX'a możemy używać dla wygodnej
[[#sec:podstawy|Podstawy pisania dokumentów w \LaTeX'u dla OSIŁKA]] \lstux!WIKIwyklad02.tex!).


=Całkowanie=


=Przykładowy wykład=
Zajmiemy się teraz zadaniem całkowania numerycznego.
Polega ono na obliczeniu (a raczej przybliżeniu)
całki oznaczonej 


{{definicja|Trójkąt prostokątny|dfn:kat_prosty|'''Trójkątem prostokątnym''' nazywamy taki trójkąt, który ma przynajmniej jeden kątprosty.
<center><math>\displaystyle S(f)\,=\,\int_a^b f(x)\,dx,
</math></center>
 
gdzie <math>\displaystyle -\infty<a<b<+\infty</math>, a <math>\displaystyle f</math> należy do pewnej klasy
<math>\displaystyle F</math> funkcji rzeczywistych określonych i całkowalnych w
sensie Riemanna na całym przedziale <math>\displaystyle [a,b]</math>.
 
Będziemy zakładać, że mamy możliwość obliczania
wartości funkcji <math>\displaystyle f</math>, a w niektórych przypadkach
również jej pochodnych, o ile istnieją. Dokładna
całka <math>\displaystyle S(f)</math> będzie więc w ogólności przybliżana
wartością <math>\displaystyle A(f)</math>, która zależy tylko od wartości <math>\displaystyle f</math>
i ew. jej pochodnych w skończonej liczbie punktów.
 
==Kwadratury==
 
<strong>Kwadraturami</strong> nazywamy funkcjonały liniowe <math>\displaystyle Q:F\toR</math>
postaci
 
<center><math>\displaystyle Q(f)\,=\,\sum_{i=0}^n a_i f(x_i),
</math></center>
 
albo ogólniej
 
<center><math>\displaystyle
  Q(f)\,=\,\sum_{i=0}^k\sum_{j=0}^{n_i-1}
                  a_{i,j}f^{(j)}(x_i),
</math></center>
 
gdzie <math>\displaystyle x_i</math> są punktami z <math>\displaystyle [a,b]</math>, a <math>\displaystyle a_i</math> (albo <math>\displaystyle a_{i,j}</math>)
są pewnymi współczynnikami rzeczywistymi. Zauważmy,
że obliczenia kwadratur są dopuszczalne w naszym modelu
obliczeniowym, mogą więc służyć jako sposób
przybliżania całki.
 
Jeden z możliwych sposobów konstrukcji kwadratur jest
następujący. Najpierw wybieramy węzły <math>\displaystyle x_j</math> (pojedyncze
lub wielokrotne), budujemy wielomian interpolacyjny
odpowiadający tym węzłom, a następnie całkujemy go.
Ponieważ postać wielomianu interpolacyjnego zależy tylko
od danej informacji o <math>\displaystyle f</math>, otrzymana w ten sposób wartość
też będzie zależeć tylko od tej informacji, a w
konsekwencji funkcjonał wynikowy będzie postaci
ja wyżej. Są to tzw. kwadratury interpolacyjne.
 
{{definicja|||
Kwadraturę <math>\displaystyle Q^I</math> opartą na węzłach
o łącznej krotności <math>\displaystyle n+1</math> nazywamy interpolacyjną,
jeśli
 
<center><math>\displaystyle Q^{I}(f)\,=\,\int_a^b w_f(x)\,dx,
</math></center>
 
gdzie <math>\displaystyle w_f</math> jest wielomianem interpolacyjnym funkcji <math>\displaystyle f</math>
stopnia co najwyżej <math>\displaystyle n</math>, opartym na tych węzłach.  
}}
}}
{{twierdzenie|Pitagoras|thm:pitagoras|
W trójkącie prostokątnym o przyprostokątnych <math>a</math>, <math>b</math> i przeciwprostokątnej <math>c</math>
{\em zawsze} zachodzi
{<math>a2+b2 = c2,
</math>}
[[#eq:wujek]]}}
<span id="eq:wujek"/> <math>a2 + b2 = 10
</math>
\rysunek{WIKItrojkat.png}{Ilustracja twierdzenia Pitagorasa.}


\begin{proof}
Współczynniki kwadratur interpolacyjnych można łatwo
Prosty dowód twierdzenia Pitagorasa może być {\em czysto geometryczny}, dlatego
wyliczyć. Rozpatrzmy dla uproszczenia przypadek, gdy
pomijamy go, w zamian przedstawiając działający aplet:
węzły są jednokrotne. Zapisując wielomian interpolacyjny
w postaci jego rozwinięcia w bazie kanonicznej Lagrange'a
<math>\displaystyle l_i</math> (zob. ([[##Lagrbaza|Uzupelnic: Lagrbaza ]])), otrzymujemy
 
<center><math>\displaystyle Q^{I}(f) \,=\, \int_a^b \sum_{i=0}^n f(x_i)l_i(x)\,dx
          \,=\, \sum_{i=0}^n f(x_i)\int_a^b l_i(x)\,dx,
</math></center>
 
a stąd i z postaci <math>\displaystyle l_i</math>,
 
<center><math>\displaystyle a_i\,=\,\int_a^b \frac
  {(x-x_0)\cdots(x-x_{i-1})(x-x_{i+1})\cdots(x-x_n)}
  {(x_i-x_0)\cdots(x_i-x_{i-1})(x_i-x_{i+1})\cdots(x_i-x_n)}
    \,dx,
</math></center>
 
<math>\displaystyle 0\le i\le n</math>.


\applet{WIKIpitagoras.jar}{Dowód twierdzenia Pitagorasa.}
Podamy teraz kilka przykładów.  


Dodatkowo, skądinąd wiadomo, że twierdzenie jest prawdziwe, co kończy dowód.
\noindent
\end{proof}
<strong>Kwadratura prostokątów</strong> jest oparta na jednym węźle
<math>\displaystyle x_0=(a+b)//2</math>,


  [[#thm:pitagoras|twierdzeniu Pitagorasa]] [[#dfn:kat_prosty]] [http://www.microsoft.com[PowerPoincie]]  
<center><math>\displaystyle Q^{I}_0(f)\,=\,(b-a)f\Big(\frac{a+b}2\Big).
</math></center>
 
\noindent
<strong>Kwadratura trapezów</strong> jest oparta na jednokrotnych
węzłach <math>\displaystyle x_0=a</math>, <math>\displaystyle x_1=b</math> i jest równa polu odpowiedniego
trapezu,
 
<center><math>\displaystyle Q^{I}_1(f)\,=\,T(f)\,=\,\frac{b-a}2 \Big(f(a)+f(b)\Big).
</math></center>
 
\noindent
<strong>Kwadratura parabol (Simpsona)</strong> jest oparta na
jednokrotnych węzłach <math>\displaystyle x_0=a</math>, <math>\displaystyle x_1=b</math>, <math>\displaystyle x_2=(a+b)//2</math>,
i jest równa polu pod parabolą interpolującą <math>\displaystyle f</math>
w tych węzłach,
 
<center><math>\displaystyle Q^I_2(f)\,=\,P(f)\,=\,\frac{b-a}6
    \Big( f(a)+4f\Big(\frac{a+b}2\Big)+f(b) \Big).
</math></center>
 
Zauważmy, że kwadratury trapezów i parabol są oparte
na węzłach jednokrotnych i równoodległych, przy czym
<math>\displaystyle x_0=a</math> i <math>\displaystyle x_n=b</math>. Ogólnie, kwadratury interpolacyjne
oparte na węzłach równoodległych <math>\displaystyle x_i=a+(b-a)i/ń</math>,
<math>\displaystyle 0\le i\le n</math>, nazywamy <strong>kwadraturami Newtona--Cotesa</strong>.
 
==Błąd kwadratur interpolacyjnych==
 
Zajmiemy się teraz błędem kwadratur interpolacyjnych.
Przypomnijmy, że <math>\displaystyle F^n_M([a,b])</math> oznacza klasę funkcji
<math>\displaystyle (n+1)</math> razy różniczkowalnych w sposób ciągły
i takich, że <math>\displaystyle |f^{(n+1)}(x)|\le M</math>, <math>\displaystyle \forall x</math>.
 
{{twierdzenie|||
  Niech <math>\displaystyle Q^I</math> będzie kwadraturą
interpolacyjną opartą na (jednokrotnych lub wielokrotnych)
węzłach <math>\displaystyle x_i</math>, <math>\displaystyle 0\le i\le n</math>. Jeśli <math>\displaystyle f\in F^n_M([a,b])</math> to
 
<center><math>\displaystyle
  |S(f)\,-\,Q^I(f)|\,\le\,\frac M{(n+1)!}(b-a)^{n+2}.
</math></center>
 
W klasie <math>\displaystyle F^n_M([a,b])</math>, maksymalny błąd kwadratury <math>\displaystyle Q^I</math> 
wynosi
 
<center><math>\displaystyle \sup_{f\in F_M^n([a,b])} |S(f)-Q^I(f)|\,=\,\frac M{(n+1)!}
    \int_a^b |(x-x_0)(x-x_1)\cdots(x-x_n)|\,dx.
</math></center>


{{stwierdzenie|||Nie każdy trójkąt jest prosty.
}}
}}
\flash{WIKIvideo.swf}{Przegląd możliwych trójkątów}


{{wniosek|||Są trójkąty o bokach długości <math>a</math>, <math>b</math>, <math>c</math>, dla których <math>a2 + b2 \neq c2</math>.
\noindent
''Dowód''\quad Korzystając ze znanego nam już wzoru na
błąd interpolacji wielomianowej z Lematu [[##leblint|Uzupelnic: leblint ]], mamy
 
<center><math>\displaystyle S(f)\,-\,Q^{I}(f)\,=\,\int_a^b
(x-x_0)(x-x_1)\cdots(x-x_n)f(x_0,x_1,\ldots,x_n,x)\,dx.
</math></center>
 
Stąd, jeśli <math>\displaystyle f\in F^n_M([a,b])</math> to
 
<center><math>\displaystyle |S(f)\,-\,Q^I(f)|\,\le\,\int_a^b (b-a)^{n+1}\frac M{(n+1)!}\,dx
    \,=\,(b-a)^{n+2}\frac M{(n+1)!}.
</math></center>
 
Ograniczenie górne w dokładnej formule na błąd w klasie
<math>\displaystyle F^n_M([a,b])</math> wynika bezpośrednio z oszacowania ([[##blkwad|Uzupelnic: blkwad ]]).
Aby pokazać ograniczenie dolne zauważmy, że dla funkcji <math>\displaystyle g</math>
takiej, że <math>\displaystyle g^{(n+1)}</math> przyjmuje na przedziałach <math>\displaystyle (a,x_0)</math>,
<math>\displaystyle (x_0,x_1)</math>, <math>\displaystyle \ldots</math>, <math>\displaystyle (x_n,b)</math> naprzemiennie wartości
<math>\displaystyle M</math> i <math>\displaystyle -M</math> mamy
 
<center><math>\displaystyle |S(g)-Q^I(g)|\,=\,\frac M{(n+1)!}
    \int_a^b |(x-x_0)(x-x_1)\cdots(x-x_n)|\,dx.
</math></center>
 
Co prawda, <math>\displaystyle g</math> nie jest w <math>\displaystyle F^n_M{[a,b]}</math>, ale może być
dla dowolnego <math>\displaystyle \epsilon>0</math> przybliżana funkcjami
<math>\displaystyle f_\epsilon\in F^n_M([a,b])</math> w ten sposób, że całka
 
<center><math>\displaystyle \int_a^b |(x-x_0)\cdots(x-x_n)(f-g)^{(n+1)}(x)|\,dx
    \,\le\,\epsilon\,(n+1)!.
</math></center>
 
Zapisując <math>\displaystyle f_\epsilon=g+(f_\epsilon-g)</math> mamy
 
<center><math>\displaystyle \aligned |S(f_\epsilon)\,-\,Q^I(f_\epsilon)| &\le & |S(g)\,-\,Q^I(g)|\,+\,
      |S(f_\epsilon-g)-Q^I(f_\epsilon-g)| \\
  &\le & \frac M{(n+1)!}\int_a^b |(x-x_0)\cdots(x-x_n)|
    \,dx\,+\,\epsilon,
\endaligned</math></center>
 
co wobec dowolności <math>\displaystyle \epsilon</math> daje dowód twierdzenia.
<math>\displaystyle \quad\Box</math>
 
W szczególnych przypadkach kwadratur trapezów <math>\displaystyle T</math>
i parabol <math>\displaystyle P</math> możemy otrzymać innego rodzaju formuły
na błąd.
 
{{twierdzenie|||
(i) Jeśli <math>\displaystyle f\in C^{(2)}([a,b])</math>
to dla kwadratury trapezów mamy
 
<center><math>\displaystyle S(f)\,-\,T(f)\,=\,-\frac{(b-a)^3}{12}f^{(2)}(\xi_1).
</math></center>
 
(ii) Jeśli <math>\displaystyle f\in C^{(4)}([a,b])</math> to dla kwadratury
parabol mamy
 
<center><math>\displaystyle S(f)\,-\,P(f)\,=\,-\frac{(b-a)^5}{2280}f^{(4)}(\xi_2).
</math></center>
 
(<math>\displaystyle \xi_1,\xi_2\in [a,b]</math>).  
}}
}}
{{uwaga|||To nie jest cała prawda o trójkątach! Dodatkowo, wiemy, że:
 
*w każdym trójkącie o bokach <math>a</math>, <math>b</math>, <math>c</math> zachodzi:
\noindent
*;{<math>a+b \geq c
''Dowód''\quad (i) Ze wzoru ([[##blkwad|Uzupelnic: blkwad ]])
</math>}
 
*;
<center><math>\displaystyle S(f)\,-\,T(f)\,=\,\int_a^b (x-a)(x-b)f(a,b,x)\,dx.
*suma kątów w trójkącie jest większa od 90 stopni
</math></center>
*;
 
*itd.
Ponieważ funkcja <math>\displaystyle x\mapsto f(a,b,x)</math> jest ciągła, a
*;
wielomian <math>\displaystyle (x-a)(x-b)</math> przyjmuje jedynie wartości
nieujemne, można zastosować twierdzenie o wartości
średniej dla całki, aby otrzymać
 
<center><math>\displaystyle \aligned S(f)\,-\,T(f) &= f(a,b,c)\int_a^b (x-a)(x-b)\,dx \\
    &= -\frac{f^{(2)}(\xi_1)}{2!}\frac{(b-a)^3}6,
\endaligned</math></center>
 
dla pewnych <math>\displaystyle c,\xi_1\in [a,b]</math>.
 
\noindent
(ii) Niech <math>\displaystyle w_{f,2}\in\Pi_2</math> i <math>\displaystyle w_{f,3}\in\Pi_3</math> będą
wielomianami interpolacyjnymi funkcji <math>\displaystyle f</math> odpowiednio dla
węzłów <math>\displaystyle a,b,(a+b)//2</math> oraz <math>\displaystyle a,b,(a+b)//2,(a+b)//2</math>. Wtedy
 
<center><math>\displaystyle w_{f,3}(x)\,=\,w_{f,2}(x)\,+\,
    f\Big(a,b,\frac{a+b}2,\frac{a+b}2\Big)
      (x-a)\Big(x-\frac{a+b}2\Big)(x-b).
</math></center>
 
Wobec
 
<center><math>\displaystyle \int_a^b (x-a)\Big(\frac{a+b}2\Big)(x-b)\,dx\,=\,0
</math></center>
 
mamy
 
<center><math>\displaystyle P(f) \,=\, \int_a^b w_{f,2}(x)\,dx\,=\,
          \int_a^b w_{f,3}(x)\,dx.
</math></center>
 
Stąd i ze wzoru na błąd interpolacji Hermite'a otrzymujemy
 
<center><math>\displaystyle \aligned \lefteqn{ S(f)\,-\,P(f)\;=\;\int_a^b (f-w_{f,3})(x)\,dx } \\
    && =\; \int_a^b (x-a)\Big(x-\frac{a+b}2\Big)^2(x-b)
        f\Big(a,b,\frac{a+b}2,\frac{a+b}2,x\Big)\,dx.
\endaligned</math></center>
 
Ponieważ wielomian <math>\displaystyle (x-a)(x-(a+b)//2)^2(x-b)</math> jest  
niedodatni na <math>\displaystyle [a,b]</math>, możemy znów zastosować twierdzenie
o wartości średniej. Mamy
 
<center><math>\displaystyle \aligned S(f)\,-\,P(f) &= f\Big(a,b,\frac{a+b}2,\frac{a+b}2,c\Big) \\
  && \qquad\qquad\qquad
  \int_a^b (x-a)\Big(x-\frac{a+b}2\Big)^2(x-b)\,dx \\
  &= -\frac{f^{(4)}(\xi_2)}{4!}\frac{(b-a)^5}{120},
\endaligned</math></center>
 
co kończy dowód. <math>\displaystyle \quad\Box</math>
 
==Kwadratury złożone==
 
Podobnie jak w przypadku zadania interpolacji chcielibyśmy,
aby błąd kwadratur malał do zera, gdy liczba węzłów
rośnie do nieskończoności. Można to osiągnąć stosując
np. <strong>kwadratury złożone</strong>. Są to kwadratury, które
powstają przez scałkowanie funkcji kawałkami
wielomianowej interpolującej <math>\displaystyle f</math>.
 
Prostym przykładem kwadratury złożonej jest suma Riemanna,  
 
<center><math>\displaystyle \bar Q(f)\,=\,\sum_{i=0}^n (t_{i+1}-t_i)f(x_i),
</math></center>
 
gdzie <math>\displaystyle a=t_0<t_1<\cdots<t_{n+1}=b</math> oraz
<math>\displaystyle x_i\in [t_i,t_{i+1}]</math>. Jeśli średnica podziału,
<math>\displaystyle \max_{0\le i\le n}(t_i-t_{i-1})</math>, maleje do zera to
<math>\displaystyle \lim_{n\to\infty}\bar Q(f)=S(f)</math>.
 
Będziemy rozpatrywać kwadratury złożone postaci
 
<center><math>\displaystyle \bar Q(f)\,=\,\int_a^b \bar w_f(x)\,dx,
</math></center>
 
gdzie <math>\displaystyle \bar w_f</math> jest kawałkami wielomianem z
Rozdziału [[##kawwiel|Uzupelnic: kawwiel ]]. To znaczy, dla danego <math>\displaystyle n</math>
kładziemy <math>\displaystyle t_i=a+(b-a)i//k</math>, <math>\displaystyle 0\le i\le k</math>, a następnie
dla każdego <math>\displaystyle i</math> wybieramy dowolne węzły
<math>\displaystyle x_{i,j}\in [t_{i-1},t_i]</math>, <math>\displaystyle 0\le j\le r</math>. Wtedy <math>\displaystyle \bar w_f</math>
jest na każdym przedziale wielomianem interpolacyjnym
funkcji <math>\displaystyle f</math> stopnia co najwyżej <math>\displaystyle r</math> opartym na węzłach
<math>\displaystyle x_{i,j}</math>. Kwadratura <math>\displaystyle \bar Q</math> korzysta z węzłów
o łącznej krotności <math>\displaystyle n\le k(r+1)</math>.
 
{{twierdzenie|||
Błąd kwadratury złożonej
<math>\displaystyle \bar Q(f)</math> w klasie <math>\displaystyle F^r_M([a,b])</math> jest ograniczony przez
 
<center><math>\displaystyle \sup_{f\in F^r_M([a,b])} |S(f)-\bar Q(f)|\,\le\,
    \frac{(b-a)^{r+2}}{k^{r+1}}
    \frac{M}{(r+1)!}\,\le\,C\,\Big(\frac 1n\Big)^{r+1},
</math></center>
 
gdzie
 
<center><math>\displaystyle C\,=\,\frac{M(r+1)^{r+1}(b-a)^{r+2}}{(r+1)!}.
</math></center>
 
}}
 
\noindent
''Dowód''\quad Twierdzenie to jest bezpośrednim
wnioskiem z Twierdzenia [[##twblkw|Uzupelnic: twblkw ]]. Mamy bowiem
 
<center><math>\displaystyle \aligned |S(f)-\bar Q(f)| &\le & \sum_{i=1}^k
    \int_{t_{i-1}}^{t_i} |f(x)-\bar w_f(x)|\,dx \\
    &\le & \sum_{i=1}^k \Big(\frac{b-a}{k}\Big)^{r+2}
              \frac M{(r+1)!} \,=\,
    \frac{(b-a)^{r+2}}{k^{r+1}}\frac M{(r+1)!},
\endaligned</math></center>
 
co kończy dowód. <math>\displaystyle \quad\Box</math>
 
W klasie <math>\displaystyle F^r_M([a,b])</math>, błąd kwadratur złożonych
jest rzędu <math>\displaystyle n^{-(r+1)}</math>, czyli jest taki sam jak
błąd interpolacji kawałkami wielomianowej. I tak
jak przy interpolacji można pokazać, że błąd każdej
innej metody całkowania korzystającej jedynie
z wartości funkcji w <math>\displaystyle n</math> punktach nie może w klasie
<math>\displaystyle F^r_M([a,b])</math> maleć szybciej niż <math>\displaystyle n^{-(r+1)}</math>,
zob. U. [[##optzlo|Uzupelnic: optzlo ]]. Podane kwadratury złożone mają
więc optymalny rząd zbieżności.
 
Zajmiemy się teraz błędem szczególnych kwadratur
złożonych, mianowicie złożonych kwadratur trapezów
<math>\displaystyle \bar T_k</math> i parabol <math>\displaystyle \bar P_k</math>. Powstają one przez
zastosowanie na każdym przedziale <math>\displaystyle [t_{i-1},t_i]</math>
odpowiednio kwadratur trapezów <math>\displaystyle T</math> i parabol <math>\displaystyle P</math>.
Jak łatwo się przekonać,
 
<center><math>\displaystyle \bar T_k(f)\,=\,\frac{b-a}{k}\left(\frac{f(a)+f(b)}2
    \,+\,\sum_{j=1}^{k-1} f\Big(\frac jk\Big)\right),
</math></center>
 
oraz
 
<center><math>\displaystyle \bar P_k(f)\,=\,\frac{b-a}{3k}\left(\frac{f(a)+f(b)}2
    \,+\,\sum_{j=1}^{k-1} f\Big(\frac jk\Big)\,+\,
        2\,\sum_{j=1}^k f\Big(\frac{2j-1}{2k}\Big)\right).
</math></center>
 
{{twierdzenie|||
* Jeśli <math>\displaystyle f\in C^{(2)}([a,b])</math> to 
 
<center><math>\displaystyle S(f)\,-\,\bar T_k(f)\,=\,-\frac{(b-a)^2}{12\,k^2}
      f^{(2)}(\xi_1).
</math></center>
* Jeśli <math>\displaystyle f\in C^{(4)}([a,b])</math> to
 
<center><math>\displaystyle S(f)\,-\,\bar P_k(f)\,=\,-\frac{(b-a)^4}{2280\,k^4}
      f^{(4)}(\xi_2).
</math></center>
 
}}
 
{{dowod|||
Dla kwadratury trapezów mamy
 
<center><math>\displaystyle \aligned \lefteqn{ S(f)\,-\,\bar T_k(f) \;=\; -\sum_{i=1}^k
      \frac{(b-a)^3}{12 k^3}f^{(2)}(\alpha_i) } \\
    && =\;-\frac{(b-a)^2}{12 k^2}\sum_{i=1}^k
      \frac{b-a}k f^{(2)}(\alpha_i) \,=\,
    -\frac{(b-a)^2}{12 k^2} f^{(2)}(\xi_1),
\endaligned</math></center>
 
a dla kwadratury parabol podobnie
 
<center><math>\displaystyle \aligned \lefteqn{ S(f)\,-\,\bar P_k(f) \;=\; -\sum_{i=1}^k
      \frac{(b-a)^5}{2280 k^5}f^{(4)}(\beta_i) } \\
    && =\; -\frac{(b-a)^4}{2280 k^4}\sum_{i=1}^k
      \frac{b-a}k f^{(4)}(\beta_i) \,=\,
    -\frac{(b-a)^4}{2280 k^4} f^{(4)}(\xi_2).
\endaligned</math></center>


}}
}}
Ciekawa może być w tym kontekście następująca nierówność:


{{fakt|||Dla <math>a,b>0</math>,
Kwadratura parabol ma więc optymalny rząd zbieżności
nie tylko w klasie <math>\displaystyle F^2_M([a,b])</math>, ale też w <math>\displaystyle F^3_M([a,b])</math>.
 
==Przyspieszanie zbieżności kwadratur==
 
W praktyce często stosuje się obliczanie kwadratur
poprzez zagęszczanie podziału przedziału <math>\displaystyle [a,b]</math>.
Na przykład, dla złożonej kwadratury trapezów zachodzi
następujący wygodny wzór rekurencyjny:
 
<center><math>\displaystyle
  \bar T_{2k}\,=\,\frac 12\left(\bar T_k(f)\,+\,
      \frac{b-a}k\,\sum_{i=1}^k
      f\Big(\frac{2i-1}{2k}\Big)\right).
</math></center>
 
Pozwala on obliczyć <math>\displaystyle \bar T_{2k}(f)</math> na podstawie
<math>\displaystyle \bar T_k(f)</math> poprzez "doliczenie" wartości funkcji
w punktach "gęstszej" siatki. W ten sposób możemy
obserwować zachowanie się kolejnych przybliżeń
<math>\displaystyle \bar T_{2^s}(f)</math> (<math>\displaystyle s\ge 0</math>) całki <math>\displaystyle S(f)</math>. Jest to
szczególnie istotne wtedy, gdy nie mamy żadnej informacji
a priori o <math>\displaystyle \|f''\|_{ C([a,b])}</math>, a przez to nie potrafimy
oszacować liczby <math>\displaystyle n</math> węzłów, dla której osiągniemy
pożądaną dokładność, zob. U. [[##kwas|Uzupelnic: kwas ]].
 
Jeśli funkcja jest więcej niż dwa razy różniczkowalna
to użycie złożonych kwadratur trapezów zdaje się tracić
sens. Wtedy istnieją przecież kwadratury, których błąd
maleje do zera szybciej niż <math>\displaystyle n^{-2}</math>. Okazuje się jednak,
że kwadratury <math>\displaystyle \bar T_k</math> mogą być podstawą dla prostej
rekurencyjnej konstrukcji innych kwadratur posiadających już
optymalną zbieżność. Konstrukcja ta bazuje na
następującym ważnym lemacie.
 
[[grafika:Euler.jpg|thumb|right||Leonhard Euler<br>  [[Biografia Euler|Zobacz biografię]]]]
 
[[grafika:MacLaurin.jpg|thumb|right|| MacLaurin<br>  [[Biografia MacLaurin|Zobacz biografię]]]]
 
{{lemat|Formuła Eulera-Maclaurina||
 
Dla funkcji <math>\displaystyle f\in C^{(2m+2)}([a,b])</math>, błąd złożonej
kwadratury trapezów <math>\displaystyle \bar T_k</math> wyraża się wzorem
 
<center><math>\displaystyle \aligned S(f)\,-\,\bar T_k(f) &= \sum_{i=1}^{m} c_ih^{2i}
  \Big(f^{(2i-1)}(b)-f^{(2i-1)}(a)\Big) \\
  &&\qquad\qquad\qquad \,+\,c_{m+1}h^{2m+2}(b-a)f^{(2m+2)}(\xi_{m,k}),
\endaligned</math></center>
 
gdzie <math>\displaystyle h=(b-a)//k</math>, <math>\displaystyle \xi_{m,k}\in[a,b]</math>, a <math>\displaystyle c_i</math> są pewnymi stałymi
liczbowymi. Mamy <math>\displaystyle c_1=-1//12</math>, <math>\displaystyle c_2=-1//720</math> i, ogólnie, 
<math>\displaystyle c_i=B_i//(2i)!</math>, gdzie <math>\displaystyle B_i</math> są tzw. liczbami Bernoulliego.
<math>\displaystyle \quad\Box</math>
}}
}}


Wynika to wprost z poniższego lematu:
Dowód tego lematu pominiemy.
 
Formułę Eulera-Maclaurina można przepisać w postaci
 
<center><math>\displaystyle S(f)\,-\,\bar T_k(f)\,=\,\sum_{i=1}^{m} c^{(0)}_i(f)\,k^{-2i}
    \,+\,c^{(0)}_{m+1,k}(f)\,k^{-(2m+2)},
</math></center>
 
gdzie <math>\displaystyle c^{(0)}_i(f)=c_i(b-a)^{2i}(f^{(2i-1)}(b)-f^{(2i-1)}(a))</math>,
<math>\displaystyle 1\le i\le m</math>, oraz
<math>\displaystyle c^{(0)}_{m+1,k}(f)=c_{m+1}(b-a)^{2m+2}f^{(2m+2)}(\xi_{m+1,k})</math>.
Zauważmy przy tym, że jeśli <math>\displaystyle f\in F^{2m+1}_M([a,b])</math> to współczynniki
<math>\displaystyle c^{(0)}_{m+1,k}(f)</math> są wspólnie ograniczone przez <math>\displaystyle c_{m+1}(b-a)^{2m+2}M</math>.
 
Definiując teraz kwadraturę
 
<center><math>\displaystyle \bar T^1_k(f)\,=\,\frac{4\,\bar T_{2k}(f)\,-\,\bar T_k(f)}{3},
</math></center>
 
dla <math>\displaystyle f\in C^{(4)}([a,b])</math> mamy
 
<center><math>\displaystyle \aligned S(f)\,-\,\bar T^1_k(f) &= \frac{4\,(S(f)-\bar T_{2k}(f)-
  (S(f)-\bar T_k(f))}{3} \\
  &= \frac 43\left(\frac{c^{(0)}_1(f)}{4k^2}+
      \frac{c^{(0)}_{2,2k}(f)}{4^2k^4}\right)\,-\,
      \frac 13\left(\frac{c^{(0)}_1(f)}{k^2}+
      \frac{c^{(0)}_{2,k}(f)}{k^4}\right) \\
  &= \frac{c^{(1)}_{2,k}(f)}{k^4},
\endaligned</math></center>
 
gdzie <math>\displaystyle c^{(1)}_{2,k}(f)=(1//12)c^{(0)}_{2,2k}(f)-(1//3)c^{(0)}_{2,k}(f)</math>
i jest wspólnie ograniczone dla <math>\displaystyle f\in F^3_M([a,b])</math>. Kwadratura <math>\displaystyle T^1_k</math>
ma więc optymalny w <math>\displaystyle F^3_M([a,b])</math> rząd zbieżności <math>\displaystyle k^{-4}</math>.
Proces ten można kontynuować dalej tworząc kolejne kwadratury
o coraz to wyższym rzędzie zbieżności. Dokładniej, połóżmy
<math>\displaystyle \bar T^0_k(f)=\bar T_k(f)</math> oraz, dla <math>\displaystyle s\ge 1</math>,
 
<center><math>\displaystyle
  \bar T^s_k(f)\,=\,\frac
  {4^s\,\bar T^{s-1}_{2k}(f)\,-\,\bar T^{s-1}_k(f)}{4^s-1}.
</math></center>
 
Wtedy, dla <math>\displaystyle f\in F^{2m+1}_M([a,b])</math>, rząd zbieżności
kwadratury <math>\displaystyle \bar T^m_k</math> wynosi <math>\displaystyle k^{-(2m+2)}</math>. Rzeczywiście,
sprawdziliśmy, że jest to prawdą dla <math>\displaystyle m=0,1</math>. Niech <math>\displaystyle m\ge 2</math>.
Postępując indukcyjnie ze względu na <math>\displaystyle s=1,2,\ldots,m</math> mamy
 
<center><math>\displaystyle \aligned \lefteqn{  S(f)\,-\,\bar T^s_k(f) \;=\;
  \frac{ 4^s(S(f)-\bar T^{s-1}_{2k}(f))-
  (S(f)-\bar T^{s-1}_k(f)) }{ 4^s\,-\,1 } } \\
  &&=\; \left( 4^s\,\left(\sum_{i=s}^{m}c_i^{(s-1)}(f)(2k)^{-2i}+
      c_{m+1,2k}^{(s-1)}(f)(2k)^{-(2m+2)}\right)\right. \\
  && \left.\quad \,-\,\left( \sum_{i=s}^mc_i^{(s-1)}(f)k^{-2i}+
      c_{m+1,k}^{(s-1)}(f)k^{-(2m+2)}
      \right) \right)\,\frac{1}{4^s\,-\,1}\\
  &&=\; \sum_{i=s+1}^m c_i^{(s)}(f)k^{-2i}\,+\,
        c_{m+1,k}^{(s)}(f)k^{-(2m+2)},
\endaligned</math></center>
 
ponieważ współczynniki przy <math>\displaystyle k^{-2s}</math> redukują się.
<math>\displaystyle c_i^{(s)}(f)</math> są tutaj pewnymi nowymi stałymi, a
<math>\displaystyle c_{m+1,k}^{(s)}(f)</math> może być w klasie <math>\displaystyle F^{2m+1}_M([a,b])</math>
ograniczona przez stałą niezależną od <math>\displaystyle f</math>. Ostatecznie, dla
<math>\displaystyle s=m</math> mamy więc
 
<center><math>\displaystyle S(f)\,-\,\bar T^m_k(f)\,=\,c_{m+1,k}^{(m)}(f)k^{-(2m+2)}
</math></center>
 
i w klasie <math>\displaystyle F^{2m+1}_M([a,b])</math>
 
<center><math>\displaystyle |S(f)\,-\,\bar T^m_k(f)|\,\le\,c_m\, k^{-(2m+2)}
</math></center>
 
dla pewnej stałej <math>\displaystyle c_m</math> niezależnej od <math>\displaystyle f</math>.
 
Zauważmy jeszcze, że <math>\displaystyle \bar T^m_k</math> wykorzystuje
<math>\displaystyle n=k2^m+1</math> wartości <math>\displaystyle f</math> w punktach równoodległych
na <math>\displaystyle [a,b]</math> co oznacza, że w terminach <math>\displaystyle n</math> rząd
zbieżności wynosi też <math>\displaystyle n^{-(2m+2)}</math>, a więc jest
optymalny w klasie <math>\displaystyle F^{2m+1}_M([a,b])</math>.
 
Kwadratury <math>\displaystyle \bar T^s_k</math> nazywane są <strong>kwadraturami
Romberga</strong>. Dla danej funkcji <math>\displaystyle f</math>, można je łatwo
konstruować budując następującą tablicę trójkątną:
 
<center><math>\displaystyle
  \begin{array} {cccccc}
  \bar T^0_1(f) \\
  \bar T^0_2(f) &\bar T^1_1(f) \\
  \bar T^0_4(f) &\bar T^1_2(f) &\bar T^2_1(f) \\
  \bar T^0_8(f) &\bar T^1_4(f) &\bar T^2_2(f)
                                &\bar T^3_1(f) \\
  \vdots &\vdots &\vdots &\vdots &\ddots \\
  \bar T^0_{2^s}(f) &\bar T^1_{2^{s-1}}(f)
        &\bar T^2_{2^{s-2}}(f) &\bar T^3_{2^{s-3}}(f)
        &\cdots &\bar T^s_1(f),
  \end{array}
</math></center>
 
w której pierwsza kolumna jest tworzona indukcyjnie
zgodnie ze wzorem ([[##indtrap|Uzupelnic: indtrap ]]), a kolejne zgodnie
z ([[##indRom|Uzupelnic: indRom ]]).
 
==Biblioteki==
 
W Octave dostępne są jedynie procedury całkujące funkcje skalarne jednej
zmiennej na odcinku:
<center><math>\displaystyle
I = \int_a^b f(x)\, dx.
</math></center>
Robi
to funkcja DQAGP ze znakomitego pakietu QUADPACK. Najlepiej od razu posłużmy się przykładem.
 
<div style="margin-top:1em; padding-top,padding-bottom:1em;">
<span  style="font-variant:small-caps;">Przykład: Prosta całka funkcji jednej zmiennej</span>
<div class="solution">
 
Przypuśćmy, że chcemy obliczyć całkę <math>\displaystyle I = \int_0^1 F(x)\, dx</math>,
gdzie np. <math>\displaystyle F(x) = \sin(23x) + (1-x^2)^{-1/2}</math>. W tym celu najpierw
implementujemy <math>\displaystyle F</math> w Octave:
 
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
function y = F(x)
y = sin(23*x)+1/sqrt(1-x^2);
endfunction
</pre></div>
Aby teraz obliczyć całkę <math>\displaystyle I = \int_0^1 F(x)\, dx</math>, wystarczy wywołać
 
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
I = quad("F", 0, 1);
</pre></div>
</div></div>
 
W rzeczywistości, podobnie jak w przypadku funkcji <code>fsolve</code>, funkcja
<code>quad</code> zwraca więcej informacji, można jej także przekazać dodatkowe
parametry. I tak, jeśli chcemy ustawić poziom tolerancji błędu obliczenia
całki:
 
<center><math>\displaystyle
|I - \text{\lstoct{quad(...)}}| \leq \max\{\text{ATOL}, \text{RTOL}\cdot |I|\}
</math></center>


\begin{lem}
z wartościami <math>\displaystyle \text{ATOL = 1e-3}</math> <math>\displaystyle \text{RTOL = 1e-6}</math>, to wywołamy funkcję
Dla <math>a,b>0</math>,
przekazując jej te parametry następująco:
{<math></math>}
\end{lem}


A teraz pora na przykład.
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
quad("F", 0, 1, [1e-3, 1e-6]);
</pre></div>
Musimy jednak pamiętać, by pojęcia tolerancji "błędu" nie traktować zbyt
dosłownie: tym, co naprawdę kontroluje <code>quad</code> podczas wyznaczania
wartości całki, jest jedynie pewien <strong>estymator</strong> błędu,  dlatego wartość
tolerancji należy zawsze wybierać w sposób konserwatywny, czyli z pewnym zapasem
bezpieczeństwa, np.


\begin{example}[Jak to działa]
<blockquote  style="background-color:#fefeee">  Jeśli chcemy wyznaczyć wartość całki z błędem bezwzględnym na
Można pliczyć na kalkulatorze, że rzeczywiście
poziomie <math>\displaystyle 10^{-6}</math>, ustawimy -- na wszelki wypadek --
\[
<code>ATOL = 1e-7</code>, a nie, prostodusznie,
32 + 42 = 52.
<code>ATOL = 1e-6</code>... Musimy także pamiętać, że  choć są bardzo mało
\]
prawdopodobne do spotkania w praktyce, to jednak istnieją <strong>wyuzdane</strong>
\end{example}
funkcje, dla których estymator błędu może dać całkowicie fałszywe wartości,
przez co i obliczona całka może być obarczona dowolnie wielkim błędem.</blockquote>


Dodajmy, że <code>quad</code> doskonale radzi sobie także z funkcjami z osobliwościami (o
ile tylko ją o nich uprzedzimy). Przykładowo, scałkujmy funkcję ze złośliwą nieciągłością w
zerze:
<center><math>\displaystyle
f(x) = \begincases  \frac{1}{x}, \qquad x\neq 0,\\
10^6, \qquad x=0.
\endcases
</math></center>


==Równania==
Oczywiście, <math>\displaystyle \int_{-1}^1 f(x)\, dx = 0</math>, tymczasem definiując
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
function y = osobliwa(x)
if (x != 0.0)
y = 1/x;
else
y = 1e6;
endif
endfunction


<span id="eq:wujek"/> <math>a + b = c
quad("osobliwa", -1, 1)
</math>
</pre></div>
<span id=""/> <math>a + b &= c\\
c + d + e &= f
daje w rezultacie
</math>
<span id=""/> <math>a + b = c
</math>
<span id=""/> <math>a + b &= c\\
c + d + e &= f
</math>


==Hiperłącza==
<div class="output" style="background-color:#e0e8e8; padding:1em"><pre>
<span id="sec:hiper" \>
Na zewnątrz:
ABNORMAL RETURN FROM DQAGP
ans = -81.098
</pre></div>
-- błędny wynik i (na szczęście!) także komunikat o jakichś problemach procedury
całkującej. Jeśli jednak wspomożemy <code>quad</code> informacją o tym, że w <math>\displaystyle x=0</math> czai
się osobliwość, wszystko przebiegnie już gładko:


http://www.mimuw.edu.pl
<div class="output" style="background-color:#e0e8e8; padding:1em"><pre>
  [http://www.mimuw.edu.pl[Wydział Matematyki]]  
   
Wewnątrz dokumentu:
quad("osobliwa", -1, 1, [1e-8 1e-8], 0)
*do definicji, twierdzeń, itp.:
ans = 0
*;
</pre></div>
*; [[#thm:pitagoras|twierdzeniu Pitagorasa]] *; [[#dfn:kat_prosty|definicję kąta prostego]] *;stosowania slajdów.
*;
(<code>1e-8</code> jest żądaną tolerancją błędu, równą wartości domyślnej).
*; [[#code:hello|Hello World w C]] *;


Do innych wykładów na Osiłku:
====QUADPACK====


Właściwie jedynym klasycznym pakietem, jaki mamy do dyspozycji jest
ponaddwudziestoletni QUADPACK .
Jest to zestaw kilkunastu procedur fortranowskich, służących obliczaniu typowych całek
jednowymiarowych, w tym kilka ogólnego stosowania:


==Podstawowy \LaTeX==
\begintable [ht]


Wyliczenia:
{| border=1
#pierwszy
|+ <span style="font-variant:small-caps"> </span>
#drugi
|-
#trzeci
|


Wypunktowania:
Typ całki  ||  Procedura QUADPACKa
|-
|
  <math>\displaystyle \int_a^b f(x)</math>  ||  DQNG, DQAG, DQAGS, DQAGP
|-
|
<math>\displaystyle \int_{-\infty}^{\infty} f(x)</math>  ||  DQAGI
|-
|
<math>\displaystyle \int_a^b f(x)\cos(\omega x)</math>  ||  DQAWO
|-
|
<math>\displaystyle \int_a^b \dfrac{f(x)}{x-c}</math>  ||  DQAWC
|-
|


*pierwszy
|}
*drugi
*trzeci


Listy:
\caption{Tabela najważniejszych procedur QUADPACKa i ich zastosowań.}
\endtable


\begin{description}
oraz spora liczba podstawowych kwadratur, na których oparto te ogólne. Nazwy
\item[raz] pierwszy pierwszy pierwszy  pierwszy  pierwszy  pierwszy  pierwszy  pierwszy  pierwszy  pierwszy  pierwszy
procedur rozszyfrowuje się podobnie jak nazwy procedur LAPACKa, zatem
\item[dwa] drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi drugi
* przedrostek <code>D</code> w nazwie każdej  procedury wymienionej w
\item[dwa i pół] trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzeci trzecitrzeci
Tabeli&nbsp;[[##table:quadpack|Uzupelnic: table:quadpack ]] (np. <code>DQAGI</code>) oznacza, że będzie działać na liczbach typu
\end{description}
<code>double</code> (całkując funkcję <math>\displaystyle f</math> zwracającą wartości tego samego typu).
Gdybyśmy chcieli użyć pojedynczej precyzji, użylibyśmy nazwy procedury <strong>bez
przedrostka</strong>.
* Kolejna litera, <code>Q</code>, oczywiście oznacza kwadraturę
(''Quadrature '').
* Trzecia litera --- <code>A</code> lub <code>N</code> oznacza, odpowiednio,
kwadraturę adaptacyjną lub nieadaptacyjną. Jak wiadomo, w praktyce lepiej
sprawdzają się kwadratury adaptacyjne, potrafiące w jakiejś mierze dostosować
się do przebiegu funkcji podcałkowej. Kwadratury nieadaptacyjne nie mają tej
własności, natomiast są tańsze, warto więc je stosować w szczególnych
przypadkach, gdy wiemy ''a priori '', że adaptacja niewiele pomoże: np. do
wolno zmiennych funkcji.
* Pozostałe litery precyzują typ liczonej całki i zakres ingerencji
użytkownika; <code>G</code> --- "zwykła" całka, bez wagi, <code>W</code> --- całka z
wagą, <code>O</code> --- oscylacyjną, <code>C</code> --- wartość główna całki (tzw. całka
Cauchy'ego), <code>I</code> --- przedział nieskończony, <code>S</code> --- możliwe
osobliwości, <code>P</code> --- użytkownik poda listę punktów, gdzie są osobliwości.


Proste tabele:
====GSL====


\begin{tabular}{c|cc}
Biblioteka GSL reimplementuje podstawowe procedury QUADPACKa w języku C, zob.
\hline\\
{GSL-reference}, gdzie zostały one bardzo przystępnie i
Procesor & MFLOPs & Cena\\
szczegółowo opisane. Procedury GSL mają nazwy analogiczne, jak procedury
\hline\\
QUADPACKa, ale z przedrostkiem <code>gsl_integration</code>, jak w poniższym
Pentium 4 & 2000 & 200\\
przykładzie, gdzie  wywołamy odpowiednik procedury <code>DQAG</code>: funkcję
Z80 & 0.0002  & 200\\
<code>gsl_integration_qag</code>.
\hline
\end{tabular}


==Obsługa cudzysłowów==
<div class="code" style="background-color:#e8e8e8; padding:1em"><pre>
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>


,,Hello!'', ``cytat'', ''dziwny cytat''.
double F(double X, void * param) /* wrapper dla funkcji sin(x)/x */
{
return(sin(X)/X);
}


==Wstawki w gołym Wikitekście==
int main(void)
{
gsl_function f; /* argument z funkcją podcałkową */


W tekście źródłowym poniżej znajduje się wstawka w wikitekście:
double A,ABSERR,B, EPSABS,EPSREL,RESULT;
int IER,NEVAL;


\begin{rawiki}
gsl_integration_workspace *workspace;
== Możemy pisać wstawki w gołymi Wikitekście ==


[[image.png]]
int KEY, LIMIT;


<nowiki>
/* przygotowujemy argument z funkcją podcałkową */
...stosując dowolne znaczniki Wikitekstu.
f.function = &F;
</nowiki>
\end{rawiki}
A = 0.0E0; B = 10*M_PI; /* przedział całkowania */
EPSABS = 0.0E0; EPSREL = 1.0E-3; /* tolerancja błędu */


Nie widzimy jej na wydruku, ale powinniśmy widzieć w Wikitekście wyprodukowanym
/* parametry specyficzne dla QAG */
przez konwerter!
KEY = 1; /* tzn. użyj minimalnej liczby punktów kwadratury bazowej */
LIMIT = 100; /* maksymalny podział przedziału całkowania */
workspace  = gsl_integration_workspace_alloc(LIMIT);
/* całkujemy: QAG! */


Podobnie możemy zamieszczać krótkie fragmenty gołego wikitekstu: \wiki{<cite>Pan Tadeusz</cite>}.
IER = gsl_integration_qag(&f, A, B, EPSABS, EPSREL,
Znów widoczne to jest tylko na Wiki.
LIMIT, KEY, workspace, &RESULT, &ABSERR);


==Teksty do pominięcia w Wikitekście==
if (IER != 0)
fprintf(stderr,"GSL_QAG: Kłopoty z całkowaniem\n");
fprintf(stderr,"Całka:
gsl_integration_workspace_free(workspace);
return(0);
}


\begin{artonly}
</pre></div>
Ten tekst nie ukaże się na Wiki. Ani poniższe równanie:
{<math>x + y = 5.
W powyższym przykładzie specjalnie pozostawiliśmy oznaczenia wykorzystywane w
</math>}
poprzednim programie. Jak widać, funkcje całkujące GSL mają bardzo podobną
\end{artonly}
składnię do odpowiadających im funkcji QUADPACKa.


To zdanie będzie na Wiki. \textonly{To zdanie nie ukaże się na Wiki}. To będzie na Wiki.
Miłym rozszerzeniem funkcjonalności jest możliwość
przekazywania parametrów do wnętrza funkcji podcałkowej.

Wersja z 18:50, 1 wrz 2006

Całkowanie

Zajmiemy się teraz zadaniem całkowania numerycznego. Polega ono na obliczeniu (a raczej przybliżeniu) całki oznaczonej

S(f)=abf(x)dx,

gdzie <a<b<+, a f należy do pewnej klasy F funkcji rzeczywistych określonych i całkowalnych w sensie Riemanna na całym przedziale [a,b].

Będziemy zakładać, że mamy możliwość obliczania wartości funkcji f, a w niektórych przypadkach również jej pochodnych, o ile istnieją. Dokładna całka S(f) będzie więc w ogólności przybliżana wartością A(f), która zależy tylko od wartości f i ew. jej pochodnych w skończonej liczbie punktów.

Kwadratury

Kwadraturami nazywamy funkcjonały liniowe Parser nie mógł rozpoznać (nieznana funkcja „\toR”): {\displaystyle \displaystyle Q:F\toR} postaci

Q(f)=i=0naif(xi),

albo ogólniej

Q(f)=i=0kj=0ni1ai,jf(j)(xi),

gdzie xi są punktami z [a,b], a ai (albo ai,j) są pewnymi współczynnikami rzeczywistymi. Zauważmy, że obliczenia kwadratur są dopuszczalne w naszym modelu obliczeniowym, mogą więc służyć jako sposób przybliżania całki.

Jeden z możliwych sposobów konstrukcji kwadratur jest następujący. Najpierw wybieramy węzły xj (pojedyncze lub wielokrotne), budujemy wielomian interpolacyjny odpowiadający tym węzłom, a następnie całkujemy go. Ponieważ postać wielomianu interpolacyjnego zależy tylko od danej informacji o f, otrzymana w ten sposób wartość też będzie zależeć tylko od tej informacji, a w konsekwencji funkcjonał wynikowy będzie postaci ja wyżej. Są to tzw. kwadratury interpolacyjne.

Definicja

Kwadraturę QI opartą na węzłach o łącznej krotności n+1 nazywamy interpolacyjną, jeśli

QI(f)=abwf(x)dx,

gdzie wf jest wielomianem interpolacyjnym funkcji f stopnia co najwyżej n, opartym na tych węzłach.

Współczynniki kwadratur interpolacyjnych można łatwo wyliczyć. Rozpatrzmy dla uproszczenia przypadek, gdy węzły są jednokrotne. Zapisując wielomian interpolacyjny w postaci jego rozwinięcia w bazie kanonicznej Lagrange'a li (zob. (Uzupelnic: Lagrbaza )), otrzymujemy

QI(f)=abi=0nf(xi)li(x)dx=i=0nf(xi)abli(x)dx,

a stąd i z postaci li,

ai=ab(xx0)(xxi1)(xxi+1)(xxn)(xix0)(xixi1)(xixi+1)(xixn)dx,

0in.

Podamy teraz kilka przykładów.

\noindent Kwadratura prostokątów jest oparta na jednym węźle x0=(a+b)//2,

Q0I(f)=(ba)f(a+b2).

\noindent Kwadratura trapezów jest oparta na jednokrotnych węzłach x0=a, x1=b i jest równa polu odpowiedniego trapezu,

Q1I(f)=T(f)=ba2(f(a)+f(b)).

\noindent Kwadratura parabol (Simpsona) jest oparta na jednokrotnych węzłach x0=a, x1=b, x2=(a+b)//2, i jest równa polu pod parabolą interpolującą f w tych węzłach,

Q2I(f)=P(f)=ba6(f(a)+4f(a+b2)+f(b)).

Zauważmy, że kwadratury trapezów i parabol są oparte na węzłach jednokrotnych i równoodległych, przy czym x0=a i xn=b. Ogólnie, kwadratury interpolacyjne oparte na węzłach równoodległych Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle x_i=a+(b-a)i/ń} , 0in, nazywamy kwadraturami Newtona--Cotesa.

Błąd kwadratur interpolacyjnych

Zajmiemy się teraz błędem kwadratur interpolacyjnych. Przypomnijmy, że FMn([a,b]) oznacza klasę funkcji (n+1) razy różniczkowalnych w sposób ciągły i takich, że |f(n+1)(x)|M, x.

Twierdzenie

Niech QI będzie kwadraturą 

interpolacyjną opartą na (jednokrotnych lub wielokrotnych) węzłach xi, 0in. Jeśli fFMn([a,b]) to

|S(f)QI(f)|M(n+1)!(ba)n+2.

W klasie FMn([a,b]), maksymalny błąd kwadratury QI wynosi

supfFMn([a,b])|S(f)QI(f)|=M(n+1)!ab|(xx0)(xx1)(xxn)|dx.

\noindent Dowód\quad Korzystając ze znanego nam już wzoru na błąd interpolacji wielomianowej z Lematu Uzupelnic: leblint , mamy

S(f)QI(f)=ab(xx0)(xx1)(xxn)f(x0,x1,,xn,x)dx.

Stąd, jeśli fFMn([a,b]) to

|S(f)QI(f)|ab(ba)n+1M(n+1)!dx=(ba)n+2M(n+1)!.

Ograniczenie górne w dokładnej formule na błąd w klasie FMn([a,b]) wynika bezpośrednio z oszacowania (Uzupelnic: blkwad ). Aby pokazać ograniczenie dolne zauważmy, że dla funkcji g takiej, że g(n+1) przyjmuje na przedziałach (a,x0), (x0,x1), , (xn,b) naprzemiennie wartości M i M mamy

|S(g)QI(g)|=M(n+1)!ab|(xx0)(xx1)(xxn)|dx.

Co prawda, g nie jest w FMn[a,b], ale może być dla dowolnego ϵ>0 przybliżana funkcjami fϵFMn([a,b]) w ten sposób, że całka

ab|(xx0)(xxn)(fg)(n+1)(x)|dxϵ(n+1)!.

Zapisując fϵ=g+(fϵg) mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned |S(f_\epsilon)\,-\,Q^I(f_\epsilon)| &\le & |S(g)\,-\,Q^I(g)|\,+\, |S(f_\epsilon-g)-Q^I(f_\epsilon-g)| \\ &\le & \frac M{(n+1)!}\int_a^b |(x-x_0)\cdots(x-x_n)| \,dx\,+\,\epsilon, \endaligned}

co wobec dowolności ϵ daje dowód twierdzenia.

W szczególnych przypadkach kwadratur trapezów T i parabol P możemy otrzymać innego rodzaju formuły na błąd.

Twierdzenie

(i) Jeśli fC(2)([a,b]) 

to dla kwadratury trapezów mamy

S(f)T(f)=(ba)312f(2)(ξ1).

(ii) Jeśli fC(4)([a,b]) to dla kwadratury parabol mamy

S(f)P(f)=(ba)52280f(4)(ξ2).

(ξ1,ξ2[a,b]).

\noindent Dowód\quad (i) Ze wzoru (Uzupelnic: blkwad )

S(f)T(f)=ab(xa)(xb)f(a,b,x)dx.

Ponieważ funkcja xf(a,b,x) jest ciągła, a wielomian (xa)(xb) przyjmuje jedynie wartości nieujemne, można zastosować twierdzenie o wartości średniej dla całki, aby otrzymać

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned S(f)\,-\,T(f) &= f(a,b,c)\int_a^b (x-a)(x-b)\,dx \\ &= -\frac{f^{(2)}(\xi_1)}{2!}\frac{(b-a)^3}6, \endaligned}

dla pewnych c,ξ1[a,b].

\noindent (ii) Niech wf,2Π2 i wf,3Π3 będą wielomianami interpolacyjnymi funkcji f odpowiednio dla węzłów a,b,(a+b)//2 oraz a,b,(a+b)//2,(a+b)//2. Wtedy

wf,3(x)=wf,2(x)+f(a,b,a+b2,a+b2)(xa)(xa+b2)(xb).

Wobec

ab(xa)(a+b2)(xb)dx=0

mamy

P(f)=abwf,2(x)dx=abwf,3(x)dx.

Stąd i ze wzoru na błąd interpolacji Hermite'a otrzymujemy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \lefteqn{ S(f)\,-\,P(f)\;=\;\int_a^b (f-w_{f,3})(x)\,dx } \\ && =\; \int_a^b (x-a)\Big(x-\frac{a+b}2\Big)^2(x-b) f\Big(a,b,\frac{a+b}2,\frac{a+b}2,x\Big)\,dx. \endaligned}

Ponieważ wielomian (xa)(x(a+b)//2)2(xb) jest niedodatni na [a,b], możemy znów zastosować twierdzenie o wartości średniej. Mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned S(f)\,-\,P(f) &= f\Big(a,b,\frac{a+b}2,\frac{a+b}2,c\Big) \\ && \qquad\qquad\qquad \int_a^b (x-a)\Big(x-\frac{a+b}2\Big)^2(x-b)\,dx \\ &= -\frac{f^{(4)}(\xi_2)}{4!}\frac{(b-a)^5}{120}, \endaligned}

co kończy dowód.

Kwadratury złożone

Podobnie jak w przypadku zadania interpolacji chcielibyśmy, aby błąd kwadratur malał do zera, gdy liczba węzłów rośnie do nieskończoności. Można to osiągnąć stosując np. kwadratury złożone. Są to kwadratury, które powstają przez scałkowanie funkcji kawałkami wielomianowej interpolującej f.

Prostym przykładem kwadratury złożonej jest suma Riemanna,

Q¯(f)=i=0n(ti+1ti)f(xi),

gdzie a=t0<t1<<tn+1=b oraz xi[ti,ti+1]. Jeśli średnica podziału, max0in(titi1), maleje do zera to limnQ¯(f)=S(f).

Będziemy rozpatrywać kwadratury złożone postaci

Q¯(f)=abw¯f(x)dx,

gdzie w¯f jest kawałkami wielomianem z Rozdziału Uzupelnic: kawwiel . To znaczy, dla danego n kładziemy ti=a+(ba)i//k, 0ik, a następnie dla każdego i wybieramy dowolne węzły xi,j[ti1,ti], 0jr. Wtedy w¯f jest na każdym przedziale wielomianem interpolacyjnym funkcji f stopnia co najwyżej r opartym na węzłach xi,j. Kwadratura Q¯ korzysta z węzłów o łącznej krotności nk(r+1).

Twierdzenie

Błąd kwadratury złożonej 

Q¯(f) w klasie FMr([a,b]) jest ograniczony przez

supfFMr([a,b])|S(f)Q¯(f)|(ba)r+2kr+1M(r+1)!C(1n)r+1,

gdzie

C=M(r+1)r+1(ba)r+2(r+1)!.

\noindent Dowód\quad Twierdzenie to jest bezpośrednim wnioskiem z Twierdzenia Uzupelnic: twblkw . Mamy bowiem

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned |S(f)-\bar Q(f)| &\le & \sum_{i=1}^k \int_{t_{i-1}}^{t_i} |f(x)-\bar w_f(x)|\,dx \\ &\le & \sum_{i=1}^k \Big(\frac{b-a}{k}\Big)^{r+2} \frac M{(r+1)!} \,=\, \frac{(b-a)^{r+2}}{k^{r+1}}\frac M{(r+1)!}, \endaligned}

co kończy dowód.

W klasie FMr([a,b]), błąd kwadratur złożonych jest rzędu n(r+1), czyli jest taki sam jak błąd interpolacji kawałkami wielomianowej. I tak jak przy interpolacji można pokazać, że błąd każdej innej metody całkowania korzystającej jedynie z wartości funkcji w n punktach nie może w klasie FMr([a,b]) maleć szybciej niż n(r+1), zob. U. Uzupelnic: optzlo . Podane kwadratury złożone mają więc optymalny rząd zbieżności.

Zajmiemy się teraz błędem szczególnych kwadratur złożonych, mianowicie złożonych kwadratur trapezów T¯k i parabol P¯k. Powstają one przez zastosowanie na każdym przedziale [ti1,ti] odpowiednio kwadratur trapezów T i parabol P. Jak łatwo się przekonać,

T¯k(f)=bak(f(a)+f(b)2+j=1k1f(jk)),

oraz

P¯k(f)=ba3k(f(a)+f(b)2+j=1k1f(jk)+2j=1kf(2j12k)).

Twierdzenie

  • Jeśli fC(2)([a,b]) to
S(f)T¯k(f)=(ba)212k2f(2)(ξ1).
  • Jeśli fC(4)([a,b]) to
S(f)P¯k(f)=(ba)42280k4f(4)(ξ2).

Dowód

Dla kwadratury trapezów mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \lefteqn{ S(f)\,-\,\bar T_k(f) \;=\; -\sum_{i=1}^k \frac{(b-a)^3}{12 k^3}f^{(2)}(\alpha_i) } \\ && =\;-\frac{(b-a)^2}{12 k^2}\sum_{i=1}^k \frac{b-a}k f^{(2)}(\alpha_i) \,=\, -\frac{(b-a)^2}{12 k^2} f^{(2)}(\xi_1), \endaligned}

a dla kwadratury parabol podobnie

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \lefteqn{ S(f)\,-\,\bar P_k(f) \;=\; -\sum_{i=1}^k \frac{(b-a)^5}{2280 k^5}f^{(4)}(\beta_i) } \\ && =\; -\frac{(b-a)^4}{2280 k^4}\sum_{i=1}^k \frac{b-a}k f^{(4)}(\beta_i) \,=\, -\frac{(b-a)^4}{2280 k^4} f^{(4)}(\xi_2). \endaligned}

Kwadratura parabol ma więc optymalny rząd zbieżności nie tylko w klasie FM2([a,b]), ale też w FM3([a,b]).

Przyspieszanie zbieżności kwadratur

W praktyce często stosuje się obliczanie kwadratur poprzez zagęszczanie podziału przedziału [a,b]. Na przykład, dla złożonej kwadratury trapezów zachodzi następujący wygodny wzór rekurencyjny:

T¯2k=12(T¯k(f)+baki=1kf(2i12k)).

Pozwala on obliczyć T¯2k(f) na podstawie T¯k(f) poprzez "doliczenie" wartości funkcji w punktach "gęstszej" siatki. W ten sposób możemy obserwować zachowanie się kolejnych przybliżeń T¯2s(f) (s0) całki S(f). Jest to szczególnie istotne wtedy, gdy nie mamy żadnej informacji a priori o fC([a,b]), a przez to nie potrafimy oszacować liczby n węzłów, dla której osiągniemy pożądaną dokładność, zob. U. Uzupelnic: kwas .

Jeśli funkcja jest więcej niż dwa razy różniczkowalna to użycie złożonych kwadratur trapezów zdaje się tracić sens. Wtedy istnieją przecież kwadratury, których błąd maleje do zera szybciej niż n2. Okazuje się jednak, że kwadratury T¯k mogą być podstawą dla prostej rekurencyjnej konstrukcji innych kwadratur posiadających już optymalną zbieżność. Konstrukcja ta bazuje na następującym ważnym lemacie.

Leonhard Euler
Zobacz biografię
Plik:MacLaurin.jpg
MacLaurin
Zobacz biografię

Lemat Formuła Eulera-Maclaurina

Dla funkcji fC(2m+2)([a,b]), błąd złożonej kwadratury trapezów T¯k wyraża się wzorem

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned S(f)\,-\,\bar T_k(f) &= \sum_{i=1}^{m} c_ih^{2i} \Big(f^{(2i-1)}(b)-f^{(2i-1)}(a)\Big) \\ &&\qquad\qquad\qquad \,+\,c_{m+1}h^{2m+2}(b-a)f^{(2m+2)}(\xi_{m,k}), \endaligned}

gdzie h=(ba)//k, ξm,k[a,b], a ci są pewnymi stałymi liczbowymi. Mamy c1=1//12, c2=1//720 i, ogólnie, ci=Bi//(2i)!, gdzie Bi są tzw. liczbami Bernoulliego.

Dowód tego lematu pominiemy.

Formułę Eulera-Maclaurina można przepisać w postaci

S(f)T¯k(f)=i=1mci(0)(f)k2i+cm+1,k(0)(f)k(2m+2),

gdzie ci(0)(f)=ci(ba)2i(f(2i1)(b)f(2i1)(a)), 1im, oraz cm+1,k(0)(f)=cm+1(ba)2m+2f(2m+2)(ξm+1,k). Zauważmy przy tym, że jeśli fFM2m+1([a,b]) to współczynniki cm+1,k(0)(f) są wspólnie ograniczone przez cm+1(ba)2m+2M.

Definiując teraz kwadraturę

T¯k1(f)=4T¯2k(f)T¯k(f)3,

dla fC(4)([a,b]) mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned S(f)\,-\,\bar T^1_k(f) &= \frac{4\,(S(f)-\bar T_{2k}(f)- (S(f)-\bar T_k(f))}{3} \\ &= \frac 43\left(\frac{c^{(0)}_1(f)}{4k^2}+ \frac{c^{(0)}_{2,2k}(f)}{4^2k^4}\right)\,-\, \frac 13\left(\frac{c^{(0)}_1(f)}{k^2}+ \frac{c^{(0)}_{2,k}(f)}{k^4}\right) \\ &= \frac{c^{(1)}_{2,k}(f)}{k^4}, \endaligned}

gdzie c2,k(1)(f)=(1//12)c2,2k(0)(f)(1//3)c2,k(0)(f) i jest wspólnie ograniczone dla fFM3([a,b]). Kwadratura Tk1 ma więc optymalny w FM3([a,b]) rząd zbieżności k4. Proces ten można kontynuować dalej tworząc kolejne kwadratury o coraz to wyższym rzędzie zbieżności. Dokładniej, połóżmy T¯k0(f)=T¯k(f) oraz, dla s1,

T¯ks(f)=4sT¯2ks1(f)T¯ks1(f)4s1.

Wtedy, dla fFM2m+1([a,b]), rząd zbieżności kwadratury T¯km wynosi k(2m+2). Rzeczywiście, sprawdziliśmy, że jest to prawdą dla m=0,1. Niech m2. Postępując indukcyjnie ze względu na s=1,2,,m mamy

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \lefteqn{ S(f)\,-\,\bar T^s_k(f) \;=\; \frac{ 4^s(S(f)-\bar T^{s-1}_{2k}(f))- (S(f)-\bar T^{s-1}_k(f)) }{ 4^s\,-\,1 } } \\ &&=\; \left( 4^s\,\left(\sum_{i=s}^{m}c_i^{(s-1)}(f)(2k)^{-2i}+ c_{m+1,2k}^{(s-1)}(f)(2k)^{-(2m+2)}\right)\right. \\ && \left.\quad \,-\,\left( \sum_{i=s}^mc_i^{(s-1)}(f)k^{-2i}+ c_{m+1,k}^{(s-1)}(f)k^{-(2m+2)} \right) \right)\,\frac{1}{4^s\,-\,1}\\ &&=\; \sum_{i=s+1}^m c_i^{(s)}(f)k^{-2i}\,+\, c_{m+1,k}^{(s)}(f)k^{-(2m+2)}, \endaligned}

ponieważ współczynniki przy k2s redukują się. ci(s)(f) są tutaj pewnymi nowymi stałymi, a cm+1,k(s)(f) może być w klasie FM2m+1([a,b]) ograniczona przez stałą niezależną od f. Ostatecznie, dla s=m mamy więc

S(f)T¯km(f)=cm+1,k(m)(f)k(2m+2)

i w klasie FM2m+1([a,b])

|S(f)T¯km(f)|cmk(2m+2)

dla pewnej stałej cm niezależnej od f.

Zauważmy jeszcze, że T¯km wykorzystuje n=k2m+1 wartości f w punktach równoodległych na [a,b] co oznacza, że w terminach n rząd zbieżności wynosi też n(2m+2), a więc jest optymalny w klasie FM2m+1([a,b]).

Kwadratury T¯ks nazywane są kwadraturami Romberga. Dla danej funkcji f, można je łatwo konstruować budując następującą tablicę trójkątną:

T¯10(f)T¯20(f)T¯11(f)T¯40(f)T¯21(f)T¯12(f)T¯80(f)T¯41(f)T¯22(f)T¯13(f)T¯2s0(f)T¯2s11(f)T¯2s22(f)T¯2s33(f)T¯1s(f),

w której pierwsza kolumna jest tworzona indukcyjnie zgodnie ze wzorem (Uzupelnic: indtrap ), a kolejne zgodnie z (Uzupelnic: indRom ).

Biblioteki

W Octave dostępne są jedynie procedury całkujące funkcje skalarne jednej zmiennej na odcinku:

I=abf(x)dx.

Robi to funkcja DQAGP ze znakomitego pakietu QUADPACK. Najlepiej od razu posłużmy się przykładem.

Przykład: Prosta całka funkcji jednej zmiennej

Przypuśćmy, że chcemy obliczyć całkę I=01F(x)dx, gdzie np. F(x)=sin(23x)+(1x2)1/2. W tym celu najpierw implementujemy F w Octave:

 
function y = F(x)
	y = sin(23*x)+1/sqrt(1-x^2);
endfunction

Aby teraz obliczyć całkę I=01F(x)dx, wystarczy wywołać

 
I = quad("F", 0, 1);

W rzeczywistości, podobnie jak w przypadku funkcji fsolve, funkcja quad zwraca więcej informacji, można jej także przekazać dodatkowe parametry. I tak, jeśli chcemy ustawić poziom tolerancji błędu obliczenia całki:

Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle |I - \text{\lstoct{quad(...)}}| \leq \max\{\text{ATOL}, \text{RTOL}\cdot |I|\} }

z wartościami ATOL = 1e-3 i RTOL = 1e-6, to wywołamy funkcję przekazując jej te parametry następująco:

 
quad("F", 0, 1, [1e-3, 1e-6]);

Musimy jednak pamiętać, by pojęcia tolerancji "błędu" nie traktować zbyt dosłownie: tym, co naprawdę kontroluje quad podczas wyznaczania wartości całki, jest jedynie pewien estymator błędu, dlatego wartość tolerancji należy zawsze wybierać w sposób konserwatywny, czyli z pewnym zapasem bezpieczeństwa, np.

Jeśli chcemy wyznaczyć wartość całki z błędem bezwzględnym na

poziomie 106, ustawimy -- na wszelki wypadek -- ATOL = 1e-7, a nie, prostodusznie, ATOL = 1e-6... Musimy także pamiętać, że choć są bardzo mało prawdopodobne do spotkania w praktyce, to jednak istnieją wyuzdane funkcje, dla których estymator błędu może dać całkowicie fałszywe wartości,

przez co i obliczona całka może być obarczona dowolnie wielkim błędem.

Dodajmy, że quad doskonale radzi sobie także z funkcjami z osobliwościami (o ile tylko ją o nich uprzedzimy). Przykładowo, scałkujmy funkcję ze złośliwą nieciągłością w zerze:

Parser nie mógł rozpoznać (nieznana funkcja „\begincases”): {\displaystyle \displaystyle f(x) = \begincases \frac{1}{x}, \qquad x\neq 0,\\ 10^6, \qquad x=0. \endcases }

Oczywiście, 11f(x)dx=0, tymczasem definiując

 
function y = osobliwa(x)
if (x != 0.0)
	y = 1/x;
else
	y = 1e6;
endif
endfunction

quad("osobliwa", -1, 1)

daje w rezultacie

 
 ABNORMAL RETURN FROM DQAGP
ans = -81.098

-- błędny wynik i (na szczęście!) także komunikat o jakichś problemach procedury całkującej. Jeśli jednak wspomożemy quad informacją o tym, że w x=0 czai się osobliwość, wszystko przebiegnie już gładko:

 
quad("osobliwa", -1, 1, [1e-8 1e-8], 0)
ans = 0

(1e-8 jest żądaną tolerancją błędu, równą wartości domyślnej).

QUADPACK

Właściwie jedynym klasycznym pakietem, jaki mamy do dyspozycji jest ponaddwudziestoletni QUADPACK . Jest to zestaw kilkunastu procedur fortranowskich, służących obliczaniu typowych całek jednowymiarowych, w tym kilka ogólnego stosowania:

\begintable [ht]

Typ całki || Procedura QUADPACKa

 abf(x)  ||  DQNG, DQAG, DQAGS, DQAGP 

f(x) || DQAGI

abf(x)cos(ωx) || DQAWO

abf(x)xc || DQAWC

\caption{Tabela najważniejszych procedur QUADPACKa i ich zastosowań.} \endtable

oraz spora liczba podstawowych kwadratur, na których oparto te ogólne. Nazwy procedur rozszyfrowuje się podobnie jak nazwy procedur LAPACKa, zatem

  • przedrostek D w nazwie każdej procedury wymienionej w

Tabeli Uzupelnic: table:quadpack (np. DQAGI) oznacza, że będzie działać na liczbach typu double (całkując funkcję f zwracającą wartości tego samego typu). Gdybyśmy chcieli użyć pojedynczej precyzji, użylibyśmy nazwy procedury bez przedrostka.

  • Kolejna litera, Q, oczywiście oznacza kwadraturę

(Quadrature ).

  • Trzecia litera --- A lub N oznacza, odpowiednio,

kwadraturę adaptacyjną lub nieadaptacyjną. Jak wiadomo, w praktyce lepiej sprawdzają się kwadratury adaptacyjne, potrafiące w jakiejś mierze dostosować się do przebiegu funkcji podcałkowej. Kwadratury nieadaptacyjne nie mają tej własności, natomiast są tańsze, warto więc je stosować w szczególnych przypadkach, gdy wiemy a priori , że adaptacja niewiele pomoże: np. do wolno zmiennych funkcji.

  • Pozostałe litery precyzują typ liczonej całki i zakres ingerencji

użytkownika; G --- "zwykła" całka, bez wagi, W --- całka z wagą, O --- oscylacyjną, C --- wartość główna całki (tzw. całka Cauchy'ego), I --- przedział nieskończony, S --- możliwe osobliwości, P --- użytkownik poda listę punktów, gdzie są osobliwości.

GSL

Biblioteka GSL reimplementuje podstawowe procedury QUADPACKa w języku C, zob. {GSL-reference}, gdzie zostały one bardzo przystępnie i szczegółowo opisane. Procedury GSL mają nazwy analogiczne, jak procedury QUADPACKa, ale z przedrostkiem gsl_integration, jak w poniższym przykładzie, gdzie wywołamy odpowiednik procedury DQAG: funkcję gsl_integration_qag.

#include <stdio.h>
#include <math.h>
#include <gsl/gsl_integration.h>

double F(double X, void * param) /* wrapper dla funkcji sin(x)/x */
{
	return(sin(X)/X);
}

int main(void)
{
	gsl_function f; /* argument z funkcją podcałkową */

	double A,ABSERR,B, EPSABS,EPSREL,RESULT;
	int IER,NEVAL;

	gsl_integration_workspace *workspace;

	int KEY, LIMIT; 

	/* przygotowujemy argument z funkcją podcałkową */
	f.function = &F;
	
	A = 0.0E0; B = 10*M_PI; /* przedział całkowania */
	EPSABS = 0.0E0; EPSREL = 1.0E-3; /* tolerancja błędu */

	/* parametry specyficzne dla QAG */
	KEY = 1; /* tzn. użyj minimalnej liczby punktów kwadratury bazowej */
	LIMIT = 100; /* maksymalny podział przedziału całkowania */
	workspace  = gsl_integration_workspace_alloc(LIMIT);
	
	/* całkujemy: QAG! */

	IER = gsl_integration_qag(&f, A, B, EPSABS, EPSREL, 
					LIMIT, KEY, workspace, &RESULT, &ABSERR);

	if (IER != 0)
		fprintf(stderr,"GSL_QAG: Kłopoty z całkowaniem\n");
	fprintf(stderr,"Całka: 
	gsl_integration_workspace_free(workspace);
	
	return(0);
}

W powyższym przykładzie specjalnie pozostawiliśmy oznaczenia wykorzystywane w poprzednim programie. Jak widać, funkcje całkujące GSL mają bardzo podobną składnię do odpowiadających im funkcji QUADPACKa.

Miłym rozszerzeniem funkcjonalności jest możliwość przekazywania parametrów do wnętrza funkcji podcałkowej.