Treści kształcenia. Ciągi zadane rekurencyjnie w informatyce. Granice ciągów, algorytmy obliczania granic
(problem zbieżności). Interpretacja geometryczna (programy), obliczanie granic ciągów rekurencyjnych,
postać rekurencyjna a ogólna.
Efekty kształcenia: Student potrafi operować ciągami rekurencyjnymi, badać ich zbieżność i granice.
Potrafi określić podstawowe wady i zalety takich ciągów w zastosowaniach informatycznych.
Ciągi rekurencyjne a obliczanie funkcji pierwiastek a.¶
Metoda naiwna (jak to było w szkole...) jest zła: mamy zgadnąć (a komputer w tym nie pomoże...) kwadrat
jak największej liczby nie przekraczającej a. To działa ‘‘w pamięci’’ np. dla 10,
znajdziemy 32=9<10, czyli 3<10 itp. Ale już np. dla
125624726
nie jest to dobry algorytm, nie mówiąc np. o obliczeniu tego pierwiastka:
1213,86428997.
A na komputerze:
def sqrt5(m:float):
i=float(0)
while(i**2 <= m):
i+=float(1/10)
x1=i
for j in range(10):
x2=m
x2/=x1
x2+=x1
x2/=2
x1=x2
return x2
Lepszym algorytmem było omawiane ujęcie poprzez twierdzenie Cauchy’ego o średnich.
Ale to nadal dalekie od optymalności.
Kolejna metoda (rekurencyjna) będzie bazowała na poprzedniej, ale z wykorzystaniem
tylko jednego ciągu. Metoda babilońska (Herona) (bazująca na geometrii - pierwiastek
jako bok kwadratu o polu a, rozpoczynamy od prostokąta i zmniejszamy różnicę pomiędzy
długościami boków korzystając ze średniej arytmetycznej) a>0:
xn+1=21(xn+xna),x1=2a.
Jak widać: wyraz xn+1 jest tu średnią arytmetyczną liczb xn oraz xna.
W pętli while:
def sqrt9(fg:float):
n=fg/float(2)
lstX=float(0)
while n!=lstX:
lstX = n
n = (n + fg/n)/float(2)
return n
def newton_method(number, number_iters = 500):
a = float(number)
for i in range(number_iters):
number = 0.5 * (number + a / number)
return number
a=int(input("Podaj pierwsza liczba:"))
b=int(input("Podaj druga liczba:"))
print("Pierwiastek z pierwszej liczby to:",newton_method(a))
print("Pierwiastek z drugiej liczby to:",newton_method(b))
Podaj pierwsza liczba: 154
Podaj druga liczba: 4579
Pierwiastek z pierwszej liczby to: 12.4096736459909
Pierwiastek z drugiej liczby to: 67.6683086828687
Dla porównania predefiniowana funkcja z modułu math Pythona (dla zainteresowanych - poszukać, jakim algorytmem jest obliczana).
Wartości do porównania...
Sprawdzić, że ten ciąg jest zbieżny do a.
A jak być może pamiętamy: to (na ogół) liczba niewymierna, a więc wymaga obliczeń na komputerze.
A to, czego jeszcze nie mówiliśmy: funkcja pierwiastkowa sprawi pewne problemy obliczeniowe
i warto opracować specjalne algorytmy - zwłaszcza za pomocą ciągów rekurencyjnych!
Rozwiązanie. Zbadamy oczywiście ograniczoność i monotoniczność tego ciągu.
Zastanowimy się, skąd ten algorytm. To proste: bierzemy prostokąt o polu a i bokach xn
oraz xna. Algorytm zakłada dążenie do uzyskania kwadratu, a wówczas jego bok ma długość a.
.... rysunek - może być na tablicy ....
Mamy więc dwie liczby: xn i xna, a (jak już przypominaliśmy) ich
średnia arytmetyczna, czyli xn+1 jest ‘‘pomiędzy nimi’’. Rozpatrzmy
przypadek x1<x1a (odwrotny przypadek jest analogiczny - samodzielnie!).
Aby uniknąć rozważań co do porównania wielkości xn i xna w kolejnych krokach będziemy
zawsze przyjmować za xn mniejszą z tych liczb (tj. obliczając powyższym wzorem xn+1
wyznaczymy też xn+1a i do dalszych obliczeń zakładać będziemy, że xn+1 oznacza
mniejszą z nich (czyli zawsze krótszy bok prostokąta)). Formalnie:
xn+1=min{21(xn+xna),21(xn+xna)a}.
Wtedy
x1≤x2≤x3≤…≤x3a≤x2a≤x1a,
czyli ciąg (xn) jest rosnący i ograniczony z góry. Jest więc zbieżny (oznaczmy tę granicę przez x).
Tak jak we wcześniejszych przykładach przechodzimy do granicy z n→∞ we wzorze rekurencyjnym
i uzyskujemy
x=21(x+xa)
Rozwiązujemy równanie uzyskując
x2=a⇒x=a.
Wyjaśnienie źródeł pomysłu i komentarz do drugiego przypadku - pozostawionego do samodzielnego uzupełnienia:
xn≈a⇒xna≈aa=a,
xn>a⇒xna<aa=a,
xn<a⇒xna>aa=a,
czyli w każdym przypadku
∣∣21(xn+xna)−a∣∣
jest mniejsze albo od ∣xn−a∣, albo od ∣∣xna−a∣∣.
Jeśli xn leży blisko a, to xna też leży blisko a;
przy tym jeśli xn leży po
jednej stronie a, to xna leży po drugiej
stronie a. Jedna z liczb xn, xna znajduje się bliżej
a niż druga, ale niezależnie od tego, która, ich średnia
21(xn+xna) znajdzie się
bliżej a od obu z nich.
Czy jest ‘‘najlepszy algorytm’’? Dla zainteresowanych przegląd algorytmów dla
funkcji f(x)=x można znaleźć tu:
przegląd kilkunastu algorytmów
Może ograniczymy się do jednego algorytmu rekurencyjnego pozwalającego obliczać pierwiastki
(tak naprawdę: ich przybliżone wartości) - ale co ważne - tylko za pomocą mnożenia i dodawania ({N. Wirth}):
an=an−1⋅(1+21cn−1),cn=cn−12⋅41⋅(3+cn−1),
gdzie a0=x,c0=1−x,x∈(0,2).
Pozostawimy zbadanie granicy w tym zadaniu do samodzielnego rozwiązania...
Wskazówka.
Można pokazać, że an=x⋅(1−cn), ∣c0∣<1 i cn→0,
gdy n→∞, i dalej podobnie jak w przypadku x1.
A może rekurencja dla innych typowych operacji w informatyce? {N. Wirth}
Obliczanie odwrotności liczby x1 dla rzeczywistych liczb x∈(0,2) (jedynie
poprzez mnożenie i dodawanie) i za pomocą rekurencji...
Dane: a0=1, c0=1−x (x=0). Definiujemy dwa ciągi rekurencyjne:
an=an−1⋅(1+cn−1)
cn=cn−1⋅cn−1
Wtedy (dlaczego?)
n→∞liman=x1
Ale najpierw (!!) wypadałoby sprawdzić, że te ciągi są zbieżne.
Proszę sprawdzić te fakty.
Rozwiązanie. Po pierwsze zauważmy, że ∣c0∣<1 oraz, że c1=c02, c2=c12=c04 i ogólnie
cn=c02n.
Ponieważ ∣c0∣<1, to ∣cn∣=∣c0∣2n≤∣c0∣n, w szczególności limn→∞cn=0. Teraz
zajmiemy się ciągem (an):
Teraz zauważmy, że dla k=1,2,…,n mamy (bo 1−ck=1−ck−12=(1−ck−1)⋅(1+ck−1))
1−ck1+ck−1=1−ck−11.
Podstawiając do wzoru i pamiętając, że c0=1−x uzyskujemy:
an=x1−cn.
A teraz można skorzystać z własności ciągów zbieżnych i przejść obustronnie do granicy
(pamiętając, że zbieżność (an) można też sprawdzić bezpośrednio):
A teraz wrócimy do wspominanej wcześniej (zajęcia z liczb rzeczywistych)
metody bisekcji rozwiązywania równań nieliniowych
f(x)=0.
Tam była taka metoda ‘‘wspomagana graficznie’’, ale chodzi nam o algorytm, którym posłuży się sam program,
bez oceny przez jego twórcę. Definiujemy dwa ciągi rekurencyjne: x1=a, y1=b oraz
xn+1=xngdyf(xn)⋅f(2xn+yn)<0
xn+1=2xn+yngdyf(xn)⋅f(2xn+yn)≥0
yn+1=2xn+yngdyf(xn)⋅f(2xn+yn)<0
yn+1=yngdyf(xn)⋅f(2xn+yn)≥0.
A teraz najciekawsze (dla matematyka, a najważniejsze dla informatyka): to, czy te ciągi są zbieżne
i to do wspólnej granicy będącej miejscem zerowym funkcji f w przedziale [a,b],
zależy od własności funkcji f.
Czyli: konkretny algorytm metody ma swoje założenia - jak każde z twierdzeń...
Dokładniej da się to wprowadzić albo na metodach numerycznych, albo zajęciach z analizy matematycznej.
Kiedy istnieje (dla jakich wartości początkowych: rozpocznij od a0=x>0, b0=1 i s0=0)?
Jak zakończyć obliczenia typu ‘‘while do’’ (warunek stopu)?
Kolejny ciąg określamy rekurencyjnie:
c1=2a,cn+1=21⋅(a+cn2),
przy czym 0<a<1. Wykazać, że (cn) jest ograniczony i cn<1−1−a oraz,
że jest zbieżny. Obliczyć jego granicę.
Czym różni się metoda jego rozwiązywania od tej z poprzedniego zadania?
Rekurencja liniowa: od wzoru rekurencyjnego do ogólnego¶
Podamy, jak sobie radzić w 2 najprostszych (ale typowych) przypadkach. Dotyczyć to będzie rekurencji
liniowej I i II rzędu i wyjaśnimy też, na czym polega trudność dla wyższych rzędów
(dla przypadku ogólnego rekurencji liniowej). A dlaczego takie rekurencje?
Z pewnością wszyscy poznają (lub poznali) algorytmy sortowania, złożoność czasowa takich algorytmów
wyraża się w naturalny sposób rekurencjami liniowymi.
Zbadamy rekurencje o stałych współczynnikach.
Rekurencja liniowa I rzędu. Dotyczy to przypadku
an+1=k⋅an+s,a1=a
dla pewnych stałych k i s. Zobaczmy pierwsze wyrazy
Warto powtórzyć zasadę indukcji zupełnej - dowód prawdziwości powyższego wzoru proszę przeprowadzić
samodzielnie poprzez indukcję matematyczną... Udało się więc zamienić wzór rekurencyjny na ogólny.
Kolejny ważny przypadek (dwa ciągi rekurencyjne - już takie napotkaliśmy):
Oczywiście jako szczególny przypadek yn=s mamy nasz pierwszy wzór.
Uwaga: działanie nieskończone. Procedury z ciągami rekurencyjnymi - niekoniecznie
liniowymi - będą napotykane w trudniejszych problemach, tu jeszcze za wcześnie na wszystkie przypadki.
Warto zwrócić uwagę na:
(a) Ułamki łańcuchowe
Rn=[a0;a1,a2,…,an−2,an−1,an]
n-ty redukt ułamka łańcuchowego
[a0;a1,a2,a3,…]=a0+a1+a2+a3+⋱111,
zakładamy przy tym an>0. Wartością ułamka łańcuchowego nazywamy granicę
n→∞limRn.
Ciekawy jest przypadek [a0;a1,a2,…], gdy liczby an są całkowite.
Liczby wymierne posiadają skończone rozwinięcie w taki ułamek
łańcuchowy. Liczby niewymierne mogą mieć rozwinięcia okresowe.
Ułamek 48253 zapisujemy w postaci ułamka łańcuchowego następująco:
dla pewnych stałych k,m. Podamy tylko jedną z metod - zainteresowani znajdą inne.
Teraz czeka nas zdecydowanie więcej pracy, ale za to mamy dobry algorytm. Będziemy szukali rozwiązań postaci an=xn
(nie będziemy tego uzasadniali - pozostawimy to zainteresowanym).
Rozpoczniemy (bez uzasadniania...) od poszukiwań an w postaci potęgi:
an=qn.
Przy przyjęciu ustalonych 2 wyrazów początkowych (a wiemy, że to istotne)
a0=A,a1=B
i po podstawieniu do równania uzyskujemy
q2⋅qn=k⋅q⋅qn+m⋅qn⇒q2=k⋅q+m
i te ostatnie równanie nazwiemy równaniem charakterystycznym.
To trójmian kwadratowy, więc ma 2 pierwiastki (niestety - być może zespolone, do
czego wrócimy po wprowadzeniu liczb zespolonych) i rozpatrzymy te 3 przypadki:
a) 2 pierwiastki rzeczywiste,
b) 1 pierwiastek rzeczywisty podwójny,
c) dwa pierwiastki zespolone (sprzężone).
ad a) Skoro mamy 2 pierwiastki równania charakterystycznego α i β,
to z liniowości wynika, że ich kombinacje liniowe
an=v⋅(α)n+w⋅(β)n,v,w∈R
spełniają równanie. Pozostaje dobrać v i w tak, aby pierwsze wyrazy były uzyskane
A=a0=v+w,B=a1=v⋅α+w⋅β
i rozwiązujemy ten układ równań liniowych wyznaczając v i w.
ad b) Teraz mamy tylko jeden pierwiastek (podwójny) α, a więc ciągi rozwiązań
to (α)n oraz (n⋅(α)n), czyli
an=v⋅(α)n+w⋅n⋅(α)n,v,w∈R.
Także tu dobieramy v i w w celu uzgodnienia pierwszych wyrazów:
A=a0=v,B=a1=v⋅α+w⋅α.
Łatwo to rozwiązujemy...
ad c)Uwaga - jeśli nie znamy jeszcze liczb zespolonych -
pominąć ten przypadek i dokończyć te zadanie po ich wprowadzeniu!
Teraz skorzystamy, że trójmian ma 2 pierwiastki zespolone sprzężone:
z=z1+iz2 oraz zˉ=z1−iz2. Bierzemy ich kombinację
liniową o współczynnikach zespolonych (!):
an=v⋅zn+w⋅zˉn,v,w∈C.
To nie zmienia dalszego rozumowania, ponownie szukamy v i w tak, aby dwa pierwsze wyrazy były
zgodne z danymi wejściowymi:
A=a0=v+w,B=a1=v⋅z+w⋅zˉ.
Jak widać - rozwiązujemy układ równań zespolonych, mogą się przydać np. wzór Moivre’a...
O tym - w jednym z kolejnych ćwiczeń.
Wersja a): Rozpatrzmy ciąg rekurencyjny
a0=5,a1=13,an+2=2⋅an+1+3⋅an.
Odpowiednie równanie charakterystyczne jest więc w postaci
x2=2x+3⇒x2−2x−3=0.
Rozwiązujemy równanie: Δ=4+12=16, czyli Δ=4, a więc
Ale teraz mamy kolejne zadanie: nasz ciąg składa się z wartości rzeczywistych, a więc powinniśmy z powyższego ciągu wyeliminować liczby zespolone. Co będzie potrzebne? Ponieważ potęgujemy liczby zespolone, to skorzystamy ze wzoru de Moivre’a.
Mamy ∣∣21−i7∣∣=∣∣21+i7∣∣=2.
Postać trygonometryczna to 21−i7=2⋅(cosϕ+isinϕ)
oraz
21+i7=2⋅(cosϕ−isinϕ) dla pewnego kąta ϕ, gdzie
możemy go wyliczyć w danych funkcji trygonometrycznych, nie obliczamy, to ćwiczenie z algebry...) Czyli
a więc an=c⋅7n+d⋅2n. Wstawiając a0 i a1 uzyskamy układ równań:
c+d=a0=2,7c+2d=a1=24.
Ostatecznie c=4 i d=−2, czyli
an=4⋅7n−2n+1
i dalej
bn=7n+2n+1.
Uwaga: można było inaczej, ale taka jest ogólna metoda...
Zauważmy, że metoda tu podawana ograniczyła się do przypadku
rekurencji liniowych (o stałych współczynnikach).
To ograniczenie pozwala na pominięcie całego aparatu matematycznego szeregów potęgowych
(o tym: na analizie matematycznej)! Zamiast tego uzyskujemy wyłącznie wielomiany,
a więc wystarczy badać ich pierwiastki. To i tak sprawia, że przydatne są liczby zespolone,
albo musimy potrafić to zrobić wyłącznie dla wielomianów, dla których znajdziemy
pierwiastki - a w ogólnym przypadku to nie jest możliwe!
Ćwiczenie samodzielne. Na wzór tej metody można łatwo rozwiązać wiele zadań. Np. takie:
Wyrazy pewnego ciągu geometrycznego (an) spełniają warunki:
{a1+a2+a3=2a4+a5+a6=−2
Aby wyznaczyć iloraz q tego ciągu, postąpimy następująco:
(1) Zapisujemy drugie równanie jak przy rekurencjach liniowych: q3(a1+a2+a3)=−2.
2. Korzystając z równania pierwszego uzyskamy a1+a2+a3=2
3. Teraz mamy: q3=−1.
4. Obliczmy, że q=−1.
A teraz - wyznaczyć iloraz q ciągu geometrycznego (bn), o wyrazach b3,b4,…,b8 spełniających:
{b3+b4+b5+b6=2b5+b6+b7+b8=8
Rekurencja - trudniejsze pytanie. Dane są ciągi:
an+1=(an)2 o ile (an)2<2 oraz an+1=21an2 o ile (an)2≥2,
bn+1=2bn,
sn+1=sn o ile (an)2<2 oraz sn+1=sn+bn+1 o ile (an)2≥2.
Pytania: czy istnieje i jaka jest granica ciągu (sn)?
Kiedy istnieje (dla jakich wartości początkowych: rozpocznij od a0=x>0, b0=1 i s0=0)?
Jak zakończyć obliczenia (warunek stopu)?
Rekurencja jest silnie związana z zastosowaniem pętli bez wskazania liczby przebiegów,
a raczej ze sprawdzeniem osiągnięcia założonego celu, czyli pętli ‘‘while... do’’.
I tu problem: obliczając symulacje istnienia i wartości granicy mamy dwa problemy:
pierwszy, to nie możemy zweryfikować, czy granica istnieje (o czym mówiliśmy),
a drugi, to kiedy zakończyć obliczenia (problem ‘‘stopu’’). W tym drugim przypadku możemy uzyskać
fałszywą sugestię odnośnie wartości granicy, a na ogół chcemy znać tę wartość z zadaną precyzją
ε>0. Nie znając granicy g nie możemy sprawdzać w pętli warunku z definicji
∣an−g∣<ε.
Powinniśmy badać warunek Cauchy’ego, bo on nie wymaga znajomości granicy, a jedynie wyrazów ciągu.
Niestety - wszystkich od pewnego miejsca. Tego się nie da, więc często sprawdzamy różnice
∣an−an−1∣<ε.
To za mało: proszę zrobić symulację np. dla an=∑k=3nklnkln(lnk)1
lub po prostu dla an=lnn. Problem jest otwarty, a pewne istniejące rozwiązania podamy
na analizie matematycznej...
Proszę być świadomym ograniczeń obliczeń komputerowych:
Diagonal arguments are used
to prove many fundamental results about the limitations of computation, such as
the undecidability of the Halting Problem for programs and the inherent, unavoidable inefficiency
(exponential time or worse) of procedures for other computational
problems. So computer scientists do need to study diagonal arguments in order to
understand the logical limits of computation. A well-educated computer scientist will be comfortable dealing
with countable sets, finite as well as infinite.{Mathematics for Computer Science,
Eric Lehman, F Thomson Leighton, Albert R Meyer}