55
Algorytmy i ich poprawność Poprawność programów Jeśli uważasz, że jakiś program komputerowy jest bezbłędny, to się mylisz …. Po prostu nie zauważyłeś jeszcze skutków błędu, który jest w nim zawarty…

Weryfikacja poprawności programu

Embed Size (px)

Citation preview

Page 1: Weryfikacja poprawności programu

Algorytmy i ich poprawność

Poprawność programów

Jeśli uważasz, że jakiś program komputerowy jestbezbłędny, to się mylisz ….

Po prostu nie zauważyłeśjeszcze skutków błędu, który jest w nim zawarty…

Page 2: Weryfikacja poprawności programu

Błędy językowe

np. zamiast for i := 1 to N do X[i] := i ;napisano for i := 1 do N do X[i] := i ;

Powstają w wyniku naruszenia składni języka(programowania), którego używamy do zapisaniaalgorytmu.

Błędy językowe

Możliwe skutki i znaczenie:• zatrzymanie kompilacji lub interpretacji z

komunikatem lub bez,

• przerwanie realizacji programu nawet jeśli kompilatorbłędu nie wykrył,

• błędy nieprzyjemne, ale zwykle niezbyt poważne - sąwzględnie łatwe do poprawienia.

Page 3: Weryfikacja poprawności programu

np. sądziliśmy, że po zakończeniu iteracji for i := 1 to N do X[i] := i

zmienna i ma wartość N a nie N+1

Wynikają z niezrozumienia semantyki używanegojęzyka programowania.

Błędy semantyczne

Możliwe skutki i znaczenie:• program nie realizuje poprawnie algorytmu,

• błędy trudne do przewidzenia i potencjalnie groźne, ale są do uniknięcia przy większej wiedzy i starannymsprawdzaniu znaczenia używanych instrukcji.

Błędy semantyczne

Page 4: Weryfikacja poprawności programu

np. w algorytmie zliczania zdań, w którychwystępuje słowo “algorytm” nie zauważyliśmy, żeznak “. ” może występować także wewnątrz zdania

(“Na rys. 2 pokazano schemat...”),

a używaliśmy jej do wyszukiwania końca zdania.

Błędy logiczne

Możliwe skutki i znaczenie:• algorytm przestaje być poprawnym rozwiązaniem zadania

algorytmicznego,

• dla pewnych zestawów danych wejściowych algorytmpodaje wyniki niezgodne z oczekiwanymi,

• procesor może nie być w stanie wykonać pewnych instrukcji(np. Żądamy dzielenia przez 0),

• błędy bardzo groźne - mogą być trudne do znalezienia i pozostawać długo w ukryciu nawet w trakcie używaniaprogramu w postaci kodu.

Błędy logiczne

Page 5: Weryfikacja poprawności programu

wynikają z wadliwie skonstruowanych struktur sterującychnp.

• niewłaściwych zakresów iteracji,

• niewłaściwych warunków użytych do zatrzymywaniaiteracji warunkowych

• przeniesienia sterowania w niewłaściwe miejsceprocesu w wyniku zastosowania wyboruwarunkowego (lub instrukcji skoku).

Błędy algorytmiczne

Możliwe skutki i znaczenie:• algorytm dla pewnych dopuszczalnych danych

wejściowych daje niepoprawny wynik,

• wykonanie programu realizującego algorytm jest przerywane w trybie awaryjnym,

• program realizujący algorytm nie kończy w normalnymtrybie swego działania.

Błędy algorytmiczne

Page 6: Weryfikacja poprawności programu

Przykład błędu algorytmicznego

Pętla nieskończona:

Co to oznacza?Rozmaitość źródeł błędów różnych typów

Złożone programy wymagają:

• testowania na licznych danych (zestawy testowe)

• uruchamiania (badanie wyników końcowych i pośrednich; DEBUGGING – odpluskwianie)

• Za pomocą debaggingu nie można udowodnić, że nie ma błędów – można jedynie je wykrywać

Obydwie metody nie dają gwarancji wykrycia i usunięcia wszystkich błędów.

Page 7: Weryfikacja poprawności programu

Intuicyjnie poprawność = zgodność z zamierzeniami

• Specyfikacja wyraża, co program ma robić, i określa związek miedzy jego danymi wejściowymi i wyjściowymi.

• Weryfikacja opiera się o sprawdzenie specyfikacji

Weryfikacja poprawności programu

Weryfikacja poprawności programu

Warunek wstępny Warunek końcowy

<wp, wk>

Page 8: Weryfikacja poprawności programu

Warunek wstępny i końcowy

• Warunek wstępny - warunek dotyczący danych wejściowych, który musi być spełniony na początku programu.

• jeżeli dane nie spełniają tego warunku, to nie ma gwarancji że program będzie działał poprawnie ani nawet że się zatrzyma.

• Warunek końcowy - co oblicza program przy założeniu że się zatrzyma.

• warunek końcowy jest zawsze prawdziwy jeżeli zachodzi warunek wstępny.

Weryfikacja poprawności programu

Aby wykazać, że program jest zgodny ze specyfikacją, trzeba podzielić ją na wiele kroków, podobnie jak dzieli się na kroki sam program.

Każdy krok programu ma swój warunek wstępny i warunek końcowy.

Page 9: Weryfikacja poprawności programu

Dowodzimy poprawności specyfikacji przez podstawienie wyrażenia x+1 pod każde wystąpienie x w warunku końcowym.

Otrzymujemy formułę x+1 ≥ 1, która wynika z warunku wstępnego x ≥ 0

Zatem specyfikacja tej instrukcji podstawienia jest poprawna

Weryfikacja poprawności programu

Problem: instrukcja przypisania

warunek wstępny: x ≥ 0wyrażenie: x = x+1warunek końcowy: x ≥ 1

, x-zmienna, v-wyrażeniex = v

1. bloki instrukcji wykonywane sekwencyjnie2. instrukcje wyboru3. instrukcje powtarzania (pętli)4. wywołania funkcji

Każdej z tych metod budowania kodu odpowiada metoda przekształcania warunku wstępnego i końcowego w celu wykazania poprawności specyfikacji kroku złożonego

Weryfikacja poprawności programu

Istnieją cztery sposoby łączenia prostych kroków w celu otrzymania kroków bardziej złożonych.

Page 10: Weryfikacja poprawności programu

• Aby wykazać prawdziwość specyfikacji instrukcji wyboru, należy dowieść, że warunek końcowy wynika z warunku wstępnego i warunku testu w każdym z przypadków instrukcji wyboru.

• Funkcje też mają swoje warunki wstępne i warunki końcowe; musimy sprawdzić że warunek wstępny funkcji wynika z warunku wstępnego kroku wywołania, a warunek końcowy pociąga za sobąwarunek końcowy kroku wywołania.

• Wykazanie poprawności programowania dla pętli wymaga użycia niezmiennika pętli.

Weryfikacja poprawności programu

Niezmienniki pętli

Niezmiennik pętli określa warunki jakie muszą być zawsze spełnione przez zmienne w pętli, a także przez wartości wczytane lub wypisane (jeżeli takie operacje zawiera).

Warunki te muszą być prawdziwe przed pierwszym wykonaniem pętli oraz po każdym jej obrocie. (mogą stać się chwilowo fałszywe w trakcie wykonywania wnętrza pętli, ale musza ponownie stać się prawdziwe przy końcu każdej iteracji)

Page 11: Weryfikacja poprawności programu

Niezmienniki pętli – przykład

int a=5, b=0;

for (int i=0; i<9; i++)

b++;

Zdanie a jest równe 5 jest trywialnym niezmiennikiem pętli.

W praktyce niezmiennik pętli traktowany jest jako założenie indukcyjne, na podstawie którego wykazuje się prawdziwość kroku indukcyjnego.

Niezmienniki pętli – przykładint NWD(int a, int b) int c; while (b!=0) c = a%b; a = b; b = c; return a;

Niezmiennikiem pętli, pozwalającym dowieśćpoprawność algorytmu NWD jest zdanie: NWD(a,b)=NWD(b,a mod b).

Page 12: Weryfikacja poprawności programu

• Stwierdzenie jest prawdziwe przed pierwszym wykonaniem pętli, ale po dokonaniu całej inicjacji; wynika ono z warunku wstępnego pętli.

• Jeśli założymy, że stwierdzenie jest prawdziwe przed jakimś przebiegiem pętli i że pętla zostanie wykonana ponownie, a więc warunek pętli jest spełniony, to stwierdzenie będzie nadal prawdziwe po kolejnym wykonaniu wnętrza pętli.

Dowodzenie niezmienników pętli

Proste pętle maja zazwyczaj proste niezmienniki.

Pętle dzielimy na trzy kategorie

• pętla z wartownikiem: czyta i przetwarza dane aż do momentu napotkania niedozwolonego elementu

• pętla z licznikiem: zawczasu wiadomo ile razy pętla będzie wykonana

• pętle ogólne: wszystkie inne

Dowodzenie niezmienników pętli

Page 13: Weryfikacja poprawności programu

Problem „STOP-u”

Aby udowodnić że program się zatrzyma, musimy wykazać, że zakończą działanie wszystkie pętle programu i wszystkie wywołania funkcji rekurencyjnych.

• Dla pętli z wartownikiem wymaga to umieszczenia w warunku wstępnym informacji, że dane wejściowe zawierają wartownika.

• Dla pętli z licznikiem wymaga to dodefiniowania granicy dolnej (górnej) tego licznika.

Poprawność programów – uwagi końcowe

Istnieje wiele innych elementów, które muszą być brane pod uwagę przy dowodzeniu poprawności programu:

• możliwość przepełnienia wartości całkowitoliczbowych

• możliwość przepełnienia lub niedomiar dla liczb zmiennopozycyjnych

• możliwość przekroczenia zakresów tablic

• prawidłowość otwierania i zamykania plików

Page 14: Weryfikacja poprawności programu

Niepoprawność algorytmu

Wykonanie algorytmu rozwiązania zadania dla pewnego zestawu danych zakończy się prawidłowo, ale wyniki sąniepoprawne

np. źle sformułowany warunek, powinna być silna nierówność, a jest słaba

Działanie algorytmu dla pewnego zestawu danych zostanie przerwane;

np. dzielenie przez zero, obliczenie pierwiastka kwadratowego z liczby ujemnej

Algorytm dla pewnego zestawu danych działa w nieskończoność (pętle nieskończone);

np. przy przeglądaniu listy wskaźnikowej, wskaźnik nie jest przesuwany do następnego elementu listy

Dowód poprawności algorytmu zawsze składa się z dwóch części:

dowód, że jeśli algorytm się zakończy, to da poprawny wynik,

dowód, że przy poprawnych danych wejściowych algorytm zawsze się zakończy.

Weryfikacja poprawności algorytmu

Page 15: Weryfikacja poprawności programu

Algorytmy poprawne częściowo i całkowicie

Poprawność częściowa algorytmu

Algorytm Alg działający w strukturze danych S jest częściowo poprawny ze względu na specyfikację<wp, wk>, wtedy i tylko wtedy, gdy dla wszystkich danych spełniających warunek początkowy wp, jeżeli algorytm zatrzyma się, to uzyskane wyniki spełniająwarunek końcowy wk.

Page 16: Weryfikacja poprawności programu

Powiemy, że algorytm Alg działający w strukturze danych S jest całkowicie poprawny ze względu na specyfikację <wp,wk>, wtedy i tylko wtedy, gdy dla wszystkich danych w strukturze S spełniających warunek początkowy wp, algorytm zatrzymuje się i daje wyniki spełniające warunek końcowy wk.

Poprawność całkowita algorytmu

Niezmienniki pętli

Niezmiennikiem pętli nazywać będziemy własność (formułę), która jeśli jest prawdziwa na początku wykonania pętli, to jest również prawdziwa po wykonaniu treści pętli.

Page 17: Weryfikacja poprawności programu

Częściowej poprawności algorytmu można dowodzićpoprzez:

• wybranie punktów kontrolnych

• związanie z każdym punktem asercji (funkcji logicznejreprezentującej przypuszczenie)

• ustalenie niezmienników w obrębie iteracji

• dowiedzenie, że z prawdziwości jednej asercji wynikaprawdziwość następnej, że niezmiennik pozostajeprawdziwy w kolejnych iteracjach i pociąga za sobąprawdziwość ostatniej asercji.

Metoda niezmienników i zbieżników

Całkowitej poprawności algorytmu można dowodzićpoprzez:

• dodatkowe ustalenie zbieżnika (wielkości zależnejod zmiennych i danych, która jest zbieżna)

• dowiedzenie, że po skończonej liczbie iteracjialgorytm się zatrzyma w ostatnim punkciekontrolnym.

Metoda niezmienników i zbieżników

Page 18: Weryfikacja poprawności programu

Przykład zastosowania metody niezmienników i zbieżników

Algorytm odwracający dowolny napis (procedura odwrócone):

odwrócone(“alama2koty”) = “ytok2amala”

• pomocnicze funkcje:głowa(“alama2koty”) = “a”ogon(“alama2koty”) = “lama2koty”

• operator konkatenacji (złożenia napisów):“alama” & “2koty” = “alama2koty”

• dla dowolnego napisu T zachodzi: głowa(T) & ogon(T) = T

Przykład zastosowania metody

Page 19: Weryfikacja poprawności programu

Przykład zastosowania metody

• Jeśli asercja 1 jest prawdziwa, to 2 też jest prawdziwa (przedrozpoczęciem iteracji)

• Jeśli w pewnym kroku iteracji asercja 2 jest prawdziwa, to w następnym kroku też jest ona prawdziwa (warunek z asercji 2 jest niezmiennikiem iteracji)

• Jeśli w ostatnim kroku iteracjiasercja 2 jest prawdziwa, to 3 jest też prawdziwa

Aby wykazać częściową poprawność algorytmu należy udowodnić:

Przykład zastosowania metody• Ad 1.: oczywiście zachodzi równość odwrócone(“”) & T = T• Ad 2.: trzeba sprawdzić czy

odwrócone(Y) & X = odwrócone(głowa(X) & Y) & ogon(X)dla każdego Y i X ≠ “”

Ad 3.: zachodzi równość odwrócone(odwrócone(Y) & “”) = Y

Page 20: Weryfikacja poprawności programu

Przykład zastosowania metody

• Aby wykazać całkowitą poprawność algorytmu należy jeszcze dodatkowo udowodnić, że dla każdego napisu T punkt kontrolny 2 jest przechodzony tylko skończoną liczbę razy tzn. 3 punkt kontrolny jest zawsze osiągany.

• Długość napisu X jest zbieżnikiem, który może byćw tym celu wykorzystany - w każdej iteracji długośćX maleje o jeden znak i nie może stać się mniejsza od 0!

Co z rekurencją?

• Metoda niezmienników i zbieżników może byćzastosowana także dla dowodzenia poprawności algorytmów rekurencyjnych

• Łatwiej jest skorzystać z tej metody po usunięciu rekurencji i zastąpieniu jej iteracją.

Page 21: Weryfikacja poprawności programu

Przykład – wieże Hanoi

Danych jest n krążków, umieszczonych w porządku rosnących średnic, na drążku A. Zadanie polega na przeniesieniu wszystkich krążków na drążek B z wykorzystaniem pomocniczego drążka C (oba drążki B i C sąpoczątkowo puste), ale mniejszy krążek musi zawsze leżeć na większym.

A B C

Przykład – wieże Hanoi

Page 22: Weryfikacja poprawności programu

procedura przenieś N z X na Y używając Z;(1) jeśli N = 1, to wypisz “X → Y”;(2) w przeciwnym razie (tj. jeśli N > 1) wykonaj co

następuje:(2.1) wywołaj przenieś N - 1 z X na Z używając Y;(2.2) wypisz “X → Y”;(2.3) wywołaj przenieś N -1 z Z na Y używając X;

(3) wróć do poziomu wywołania

Wieże Hanoi – rekurencyjnie

Algorytm iteracyjny równoważny algorytmowirekurencyjnemu!Ustaw trzy kołki w kółko.1. powtarzaj co następuje, aż do uzyskania po

kroku 1.1 rozwiązania problemu:1.1. przenieś najmniejszy z dostępnych krążków z

kołka, na którym się znajduje, na kołek następny w kierunku ruchu wskazówek zegara,

1.2. wykonaj jedyne możliwe przeniesienie nie zmieniające położenia najmniejszego krążka, który został przeniesiony w kroku 1.1.

Wieże Hanoi – iteracyjnie

Page 23: Weryfikacja poprawności programu

Złożonośćobliczeniowa

Algorytm jest dokładnie określonym układem skończonej liczby elementarnych instrukcji wraz z porządkiem ich wykonywania.

Każda instrukcja ma precyzyjnie określonąinterpretację za pomocą podstawowych operacji arytmetycznych i logicznych, a jej wykonanie jest skończone i ma jednoznacznie określony efekt końcowy.

Jako elementy komunikacji ze światem w algorytmie można wyróżnić: dane, na których są wykonywane obliczenia i wyniki, które są oczekiwanym rezultatem działań

Algorytm - definicja raz jeszcze

Page 24: Weryfikacja poprawności programu

Cechy dobrego algorytmu

Każdy dobry algorytm powinien posiadać następujące cechy:

mieć określone operacje podstawowe,

każdy krok jednoznacznie i precyzyjnie zdefiniowany,

każdy możliwy przypadek przewidziany,

może korzystać z danych wejściowych,

prowadzi do jednej lub więcej danych wyjściowych,

wykorzystuje możliwie jak najmniej pamięci,

wykonuje się w możliwie jak najkrótszym czasie.

Złożoność obliczeniowa

Ten sam problem można rozwiązać różnymi metodami. Problemy mogą więc posiadać kilka alternatywnych algorytmów rozwiązujących je.

Przy porównywaniu algorytmów zwykle bierze się pod uwagę ich efektywność (szybkość działania) i zapotrzebowanie na zasoby pamięciowe systemu

W celu porównywania algorytmów pod względem ich prędkości działania, wprowadzono pojęcie złożoności obliczeniowej.

Page 25: Weryfikacja poprawności programu

Złożoność obliczeniowa (ang. computationalcomplexity) – miara służąca do określania ilości zasobów komputerowych potrzebnych do rozwiązania problemów obliczeniowych.

Złożoność obliczeniowa algorytmu charakteryzuje jak szybko rośnie liczba operacji (elementarnych kroków algorytmu) niezbędnych do znalezienia rozwiązania, gdy wzrasta ilość przetwarzanych danych.

Złożoność obliczeniowa

Złożoność obliczeniowa - cele

Cele, dla których wyznaczamy złożonośćobliczeniową algorytmów są następujące:

można wybrać z grupy algorytmów rozwiązujących ten sam problem, algorytm o najlepszej (najmniejszej) złożoności.

można zbadać jak zmieni się złożoność, gdy zwiększymy rozmiar danych wejściowych (wpływ wzrost rozmiaru danych wejściowych na czas wykonywania się algorytmu).

Page 26: Weryfikacja poprawności programu

Koszt algorytmu

• liczba instrukcji

• liczba operacji arytmetycznych

• liczba wywołańprocedury

• liczba zmiennych

• ilość miejsca potrzebna dla danych

Mamy dwa kryteria (miary kosztu) efektywności:

Złożoność obliczeniowa - rodzaje

Złożoność pamięciowaWynika z liczby i rozmiaru struktur danych wykorzystywanych w algorytmie

Złożoność czasowaWynika z liczby operacji elementarnych wykonywanych w trakcie przebiegu algorytmu

Page 27: Weryfikacja poprawności programu

Pamięciowa złożoność obliczeniowa informuje nas o ilości pamięci komputera wyrażanej w liczbie bajtów lub liczbie zmiennych typów elementarnych wymaganej przez dany algorytm dla n przetwarzanych danych.

• Liczba bajtów zależy od liczby zmiennych typów elementarnych użytego języka programowania i reprezentacji zmiennych w pamięci maszyny.

Pamięciowa złożonośćobliczeniowa

Czasowa złożoność obliczeniowa - zależność pomiędzy liczbą operacji elementarnych wykonywanych w trakcie przebiegu algorytmu a rozmiarem danych wejściowych (podawana jako funkcja rozmiaru tych danych)

Czasowa złożoność obliczeniowa

Page 28: Weryfikacja poprawności programu

wielkość złożoności czasowej musi być niezależna od typu maszyny, na której uruchamiamy program

za jednostkę czasowej złożoności obliczeniowej przyjęto wykonanie tzw. operacji dominującej(podstawowej), czyli takiej, wokół której koncentruje się przetwarzanie danych w algorytmie.

Ilość wykonań operacji dominujących jest proporcjonalna do czasu wykonania algorytmu.

Czasowa złożoność obliczeniowa

Złożoność czasowa podawana jest jako funkcja rozmiaru danych, której wartości podają liczbę operacji, np.

• W algorytmie sortowania bąbelkowego dla listy o długości N:

F(N) = liczba porównań par sąsiednich elementów

• W algorytmie rozwiązania wież Hanoi dla N krążków:F(N) = liczba przeniesień pojedynczego krążka z kołka na kołek

Czasowa złożoność obliczeniowa

Page 29: Weryfikacja poprawności programu

Szukamy elementu x na liście o długości N.Dane wejściowe to lista i element do wyszukania.

Algorytm 11. weź pierwszy element listy ;2. wykonuj:

2.1. sprawdź czy bieżący element jest tym szukanym ;2.2. sprawdź czy osiągnąłeś koniec listy ;2.3. weź następny element z listy

aż znajdziesz lub przejrzysz całą listę

Złożoność obliczeniowa – przykład

Jeśli operacją elementarną jest sprawdź, to F(N)=2N

Szukamy elementu x na liście o długości N.Dane wejściowe to lista i element do wyszukania.

Algorytm 21. dopisz szukany element na końcu listy ;2. weź pierwszy element listy ;3. wykonuj:

3.1. sprawdź czy bieżący element jest tym szukanym ;3.2. weź następny element z listy

aż znajdziesz ;4. sprawdź czy jesteś na końcu listy

Złożoność obliczeniowa – przykład

Jeśli operacją elementarną jest sprawdź, to F(N)=N+1

Page 30: Weryfikacja poprawności programu

jest mitem stwierdzenie, że komputery są tak szybkie, że czas nie stanowi problemu (rozkład na czynniki pierwsze dużych liczb - 300 cyfr wymaga milionów lat)

potrzebne jest rozwiązywanie coraz większych problemów: komputerowe systemy wspomagania decyzji komputerowe symulacje i prognozy

muszą funkcjonować systemy komputerowe czasu rzeczywistego

automatyczne sterowanie w złożonych układach

Złożoność czasowa decyduje o tym czy dany algorytm jest przydatny.

Co to znaczy w praktyce?

Rozróżniamy dwa rodzaje czasowej i pamięciowej złożoności obliczeniowej:

• Pesymistyczna złożoność obliczeniowa W(n)

• Oczekiwana złożoność obliczeniowa A(n)

Złożoność pesymistyczna i oczekiwana

Page 31: Weryfikacja poprawności programu

Pesymistyczna złożoność obliczeniowa W(n)dotyczy najgorszego przypadku zestawu danych, zatem określa ona największą ilość operacji dominujących (lub komórek pamięci), która może być wymagana dla najgorszego przypadku n danych wejściowych.

Oczekiwana złożoność obliczeniowa A(n)dotyczy typowego zestawu danych i określa statystycznie średnią ilość operacji dominujących (komórek pamięci), które należy wykonać dla typowego zestawu danych, aby rozwiązać problem.

Złożoność pesymistyczna i oczekiwana

Koszt algorytmu Alg dla danych d: t(Alg,d)

Niech Dn będzie zbiorem danych rozmiaru n dla pewnego problemu P oraz Alg algorytmem rozwiązującym problem P.

Pesymistyczna złożoność obliczeniowa:

W(Alg,n) = sup t(Alg,d) : d ∈Dn

Oczekiwana złożoność obliczeniowa:

A(Alg,n) = Σ p(d) * t(Alg,d) : d ∈Dn,

gdzie p(d) – prawdopodobieństwo wystąpienia danych d.

Złożoność pesymistyczna i oczekiwana

Page 32: Weryfikacja poprawności programu

Rozważmy wyszukiwanie elementu w n elementowym, nieuporządkowanym zbiorze danych.

Operacja dominująca – sprawdzanie, czy i-ty element zbioru jest elementem poszukiwanym, i = 1,2,3,...,n.

Przykład obliczenia złożoności pesymistycznej i oczekiwanej

Za końcową złożoność obliczeniową danego algorytmu przyjmuje się najczęściej jego złożonośćpesymistyczną.

Przykład - złożoność pesymistyczna

W przypadku najgorszym poszukiwany element jest ostatnim, zatem znaleziony będzie po sprawdzeniu wszystkich elementów tego zbioru.

Również stwierdzenie, iż elementu w zbiorze nie ma, wymaga przeglądnięcia wszystkich elementów.

Stąd: W(n) = n

Page 33: Weryfikacja poprawności programu

Przykład - złożoność oczekiwana

Jeśli prawdopodobieństwo wystąpienia poszukiwanego elementu na każdej pozycji w zbiorze jest takie samo, to dla każdego elementu wynosi ono:

Oczekiwana złożoność obliczeniowa jest równa wartości oczekiwanej zmiennej losowej rozkładu prawdopodobieństwa pi, zatem:

1 1

1 1 ( 1) 1( )2 2

n n

ii i

n n nA n ip in n= =

+ += = = ⋅ =∑ ∑

1 , 1, 2,...,ip dla i nn

= =

Porównywanie czasów działania algorytmów

Chcemy porównać dwa algorytmy wykonujące to samo zadanie za pomocą jednej pętli ograniczonej, w której liczba iteracji N jest proporcjonalna do rozmiaru danych wejściowych.

Złożoności czasowe tych algorytmów wynoszą: F1(N) = K1 + L1 * NF2(N) = K2 + L2 * N

Page 34: Weryfikacja poprawności programu

Do porównania algorytmów można wykorzystać iloraz:

1

2

( )( )( )

F Ns NF N

=

s(N) = 1 oznacza jednakową szybkość działania

s(N) < 1 oznacza, że algorytm pierwszy jest szybszy

Porównywanie czasów działania algorytmów

Kiedy zachodzi s(N)=1?

s(N) = 1 wtedy i tylko wtedy, gdy K1 = K2 i L1 = L2

Wniosek: w takim przypadku oba algorytmy sąidentyczne.

0

0

1( )

1dla N N

s Ndla N N

≥ ≤⎧= ⎨ < >⎩

Który algorytm jest lepszy gdy zachodzą następujące nierówności? :

Porównywanie czasów działania algorytmów

Page 35: Weryfikacja poprawności programu

Przyjmuje się, że w celu porównania algorytmów bada się wartość ilorazu s(N) dla bardzo dużych wartości N, czyli dla N →∞

Porównywanie czasów działania algorytmów

Porównywanie czasów działania algorytmów

O wyniku porównania czasów działania dwóch algorytmów decyduje wartość:

Jest to tzw. analiza asymptotyczna

1

2

lim ( )N

Ls NL→∞

=

Page 36: Weryfikacja poprawności programu

Porównywanie czasów działania algorytmów

Asymptotyczna złożoność algorytmu – określenie rzędu wielkości czasu działania algorytmu, tzn. określenie szybkości wzrostu czasu działania algorytmu, gdy rozmiar danych dąży do nieskończoności.

Rząd wielkości funkcji :• opisuje czas działania algorytmu• charakteryzuje efektywność algorytmu• za jego pomocą można porównać różne algorytmy

Porównywanie czasów działania algorytmów

Dwa algorytmy o czasach wykonania F1(N) i F2(N) majązłożoność tego samego rzędu, jeśli:

Algorytm o czasie wykonania F1(N) ma nie wyższy rząd złożoności od algorytmu o czasie wykonania F2(N), jeśli:

1

2

( )lim , 0( )N

F N C gdzie CF N→∞

= < < ∞

1

2

( )lim( )N

F N CF N→∞

= < ∞

Page 37: Weryfikacja poprawności programu

Porównanie rzędów złożoności

Dopiero zmniejszenie rzędu złożoności obliczeniowej algorytmu jest istotnym ulepszeniem rozwiązania problemu algorytmicznego !

Złożoność asymptotyczna = przybliżona miara efektywności

Z reguły dane nie są uporządkowane i ocena złożoności algorytmu jest rzeczą niełatwą ale bardzo istotna.

Często wystarczają przybliżone, asymptotyczne oszacowania ciągów lub ogólniej funkcji.

Opisują one zachowanie funkcji wraz ze wzrostem argumentu.

Podczas przekształceń rachunkowych celowo ograniczana jest wiedza o funkcji, dzięki czemu łatwiej jest rachować i otrzymać zadowalającą postać przybliżającą.

Dlaczego analiza asymptotyczna?

Page 38: Weryfikacja poprawności programu

Notacja O Notacja Ω (Omega) Notacja Θ (Teta)

Złożoność asymptotyczna

W oszacowaniach asymptotycznych posługujemy sięogólnie przyjętymi symbolami opisującymi asymptotyczne zachowanie jednej funkcji wobec drugiej.

Staramy się wyznaczy złożoność w „przypadku optymistycznym”, „przypadku pesymistycznym” oraz „przypadku średnim”.

Często posługujemy się przybliżeniami opartymi o notacje:

Notacja ONiech , oraz niech będą dane funkcje f oraz g: * 0R R+= ∪

* *( ), ( ):f x g x R R→

Definicja:Mówimy, że funkcja f(x) jest rzędu O(g(x), jeśli istnieje taka stała c>0 oraz , że dla każdego zachodzi:

(f nie rośnie szybciej niż g).

*0x R∈

0x x≥

( ) ( )f x cg x≤

Page 39: Weryfikacja poprawności programu

Notacja O używana jest w analizie górnej granicy asymptotycznej. Służy do szacowania czasu działania algorytmu w przypadku pesymistycznym

Po raz pierwszy tego symbolu użył niemiecki teorio-liczbowiec Paul Bachmann w 1894.

Prace Edmunda Landau'a spopularyzowały tęnotację, stąd czasami jest nazywany symbolem Landau'a.

Notacja O

Określenia "złożoność co najwyżej O(g(n))" i "złożoność O(g(n))" są matematycznie równoważne.

Stwierdzenie, ze algorytm sortowania ma złożonośćO(n2) oznacza, ze jeśli zastosujemy go do 2-krotnie dłuższego ciągu danych, czas jego działania wzrośnie mniej więcej 4-krotnie, gdy zaś sortowany ciąg danych wydłuży się 10-krotnie, na uzyskanie wyniku trzeba poczekać około 100 razy dłużej.

Notacja O

Page 40: Weryfikacja poprawności programu

Załóżmy, iż oczekiwana złożoność obliczeniowa pewnego algorytmu jest następująca: A(n) = n2 + 3n.

Gdy n → ∞ , czynnik 3n stanie się coraz mniej znaczący w stosunku do czynnika n2. Stąd wnioskujemy, iż jest to algorytm o złożoności O(n2).

Aby to udowodnić, musimy znaleźć stałą c oraz no, dla których zachodzi:

n2 + 3n ≤ cn2 dla n ≥ no

Wystarczy przyjąć c = 4 i no = 1:n2 + 3n ≤ 4n2 dla n ≥ 1, co dowodzi, iż podany algorytm ma rzeczywiście rząd złożoności obliczeniowej równy O(n2).

Notacja O - przykład

Własności notacji OWłasność 1 (przechodniość)Jeśli f(n) jest O(g(n)) i g(n) jest O(h(n)), to f(n) jest O(h(n))

Własność 2Jeśli f(n) jest O(h(n)) i g(n) jest O(h(n)), to f(n)+g(n) jest O(h(n))

Własność 3Funkcja ank jest O(nk)

Własność 4Funkcja nk jest O(nk+j) dla dowolnego dodatniego j

Wniosek: dowolny wielomian jest O( ) dla n podniesionego do najwyższej w nim potęgi, czyli

f(n) = aknk + ak-1 nk-1 + ..... + a1n +a0 jest O(nk)

Page 41: Weryfikacja poprawności programu

Własność 5 Jeśli f(n)=c g(n), to f(n) jest O(g(n))

Własność 6 Funkcja logan jest O(logbn) dla dowolnych a i b większych niż 1

Własność 7 logan jest O(log2n) dla dowolnego dodatniego a

Własności notacji O( )

Niech , oraz niech będą dane funkcje f oraz g: * 0R R+= ∪* *( ), ( ):f x g x R R→

Definicja:Mówimy, że funkcja f(x) jest rzędu Ω(g(x)), ,jeśli istnieje taka stała c>0 oraz , że dla każdego zachodzi:

(f nie rośnie wolniej niżg).

*0x R∈

0x x≥

( ) ( )g x cf x≤

Notacja Ω

Page 42: Weryfikacja poprawności programu

Niech , oraz niech będą dane funkcje f oraz g: * 0R R+= ∪* *( ), ( ):f x g x R R→

Definicja:Mówimy, że funkcja f(x) jest rzędu Θ (g(x)), , jeśli istnieją takie stałe c1,c2>0 oraz , że dla każdego zachodzi:

(f rośnie tak samo jak g).

*0x R∈

0x x≥

1 2( ) ( ) ( )c g x f x c g x≤ ≤

Notacja Θ

Uwagi

2. Można powiedzieć, żef(n) = Θ(g(n)),

gdy f(n) jest jednocześnie rzędu Ο(g(n)) i Ω(g(n)).

Notacja Ω jest asymptotyczną granicę dolną – oszacowuje czas działania algorytmu dla najlepszego przypadku

Notacja Θ jest asymptotycznie dokładnym oszacowaniem –ogranicza funkcję od góry i od dołu.

1. Równoważnośćf(n) jest Ω(g(n)) wtedy i tylko wtedy, gdy g(n) jest O(f(n))

Page 43: Weryfikacja poprawności programu

Najczęściej algorytmy mają złożoność czasowąproporcjonalną do pewnych funkcji:

1 stałe

log n logarytmiczne

n liniowe

n log n liniowo-logarytmiczne

n2 wielomianowe (małe wykładniki)

n3 wielomianowe (małe wykładniki)

2n wykładnicza

n! ponadwykładnicza

nn wielomianowa (duże wykładniki)

Złożoność czasowa algorytmów

Złożoność czasowa stała - O(1)• Algorytm wykonuje stałą ilość operacji dominujących bez

względu na rozmiar danych wejściowych. • W takim algorytmie czas wykonania jest stały i nie zmienia

się przy zmianie liczby przetwarzanych elementów.

Złożoność czasowa liniowa - O(n)• Dla każdej danej algorytm wykonuje stałą ilość operacji

dominujących.• Czas wykonania jest proporcjonalny do liczby n danych

wejściowych.• Czas wykonania rośnie liniowo ze wzrostem liczby

elementów.

Rodzaje złożoności

Page 44: Weryfikacja poprawności programu

Złożoność czasowa kwadratowa - O(n2)• Algorytm dla każdej danej wykonuje ilość operacji dominujących

proporcjonalną do liczby wszystkich przetwarzanych danych. • Czas wykonania jest proporcjonalny do kwadratu liczby danych n.• Inne złożoności tego typu O(n3), O(n4)... noszą nazwę

wielomianowych złożoności obliczeniowych.

Złożoność czasowa logarytmiczna - O(log n)• W algorytmie zadanie rozmiaru n da się sprowadzić do zadania

rozmiaru n/2. • Typowym przykładem jest wyszukiwanie binarne w zbiorze

uporządkowanym. • Sprawdzenie środkowego elementu pozwala określić, w której z

dwóch połówek zbioru może znajdować się poszukiwany element.

Rodzaje złożoności

logax = y wtedy i tylko wtedy, gdy ay = x

W określeniu rodzajów złożoności obliczeniowej nie podajemy podstawy logarytmu, ponieważ logarytmy o różnych podstawach z tej samej wartości różnią się od siebie jedynie iloczynem przez stałą:Niech

logax = y oraz logbx = cyWtedy

ay = x, oraz bcy = xStąd

ay = bcy

(a)y = (bc)y

Zatema = bc oraz logbx = c logax

Ponieważ podstawy a i b są stałe, to i c musi być stałe. Z kolei z definicji notacji O wynika, iż klasa złożoności dwóch funkcji różniących sięjedynie iloczynem przez stałą jest taka sama.

Pojecie logarytmu - przypomnienie

Page 45: Weryfikacja poprawności programu

Złożoność czasowa liniowo logarytmiczna - O(n log n)• Zadanie rozmiaru n daje się sprowadzić do dwóch podzadań

rozmiaru n/2 plus pewna ilość operacji, których liczba jest proporcjonalna do ilości danych n.

• Tego typu złożoność obliczeniową posiadają dobre algorytmy sortujące.

Złożoność czasowa wykładnicza - O(2n), O(n!)• Złożoność obliczeniową O(2n) posiada algorytm, w którym

wykonywana jest stała liczba operacji dla każdego podzbioru n danych wejściowych.

• Złożoność obliczeniową O(n!) posiada algorytm, w którym wykonywana jest stała liczba operacji dla każdej permutacji n danych wejściowych.

Rodzaje złożoności

• Złożoność obliczeniowa wykładnicza jest bardzo niekorzystna, ponieważ czas wykonania rośnie szybko wraz ze wzrostem liczby danych wejściowych.

• Algorytm o takiej złożoności obliczeniowej uważa się za wewnętrznie nierealizowalny i należy go unikać.

Algorytm o złożoności O(2n)

Page 46: Weryfikacja poprawności programu

Porównanie1 - komputer wykonujący milion operacji dominujących w ciągu sekundy2 - superkomputer wykonujący 1000 miliardów operacji dominujących w ciągu sekundy.

5x1031

mld lat40,17mld lat

1126sekund

10-6

sekundCzas wykonania dlasuperkomputera 2

5x1037

mld lat40169423

mld lat35,7lat

1,05sekund

Czas wykonaniadla komputera 1

2001005020Rozmiar danych n

Algorytm o złożoności O(2n)

Porównanie szybkości wzrostu funkcji

f(n)= log n

f(n)=n

f(n) = 2n

f(n) =0.25 n2

Page 47: Weryfikacja poprawności programu

Porównanie złożoności

nierealizowalny dlawiększych n

wykładniczaO(2n), O(n!)

wolny dla większych nsześciennaO(n3)

wolny dla dużych nkwadratowaO(n2)

dosyć szybkiliniowo-logarytmicznaO(n log n)

szybkiliniowaO(n)

niesamowicie szybkilogarytmicznaO(log n)

działa prawie natychmiaststałaO(1)

Cechy algorytmuNazwa rodzaju złożoności

obliczeniowej

Rodzajzłożonościczasowej

Przykłady

Page 48: Weryfikacja poprawności programu

Znajdowanie złożoności asymptotycznej

Przykład 1: Prosta pętla

for (i=sum=0; i<n; i++) sum+=a[i];

Powyższa pętla powtarza się n razy, podczas każdego jej przebiegu realizuje dwa przypisania:

• aktualizujące zmienną „sum”• zmianę wartości zmiennej „i”

Mamy zatem 2n przypisań podczas całego wykonania pętli.

Asymptotyczna złożoność wynosi O(n)

Przykład 2: Pętla zagnieżdżonafor (i=0; i<n; i++)

for (j=1, sum=a[0]; j<=i; j++)sum+=a[j];

• zmiennej „i” nadawana jest wartość początkowa.• Pętla zewnętrzna powtarza się n razy, a w każdej jej iteracji

wykonuje się wewnętrzna pętla oraz instrukcja przypisania wartości zmiennym „i”, „ j”, „ sum”.

• Pętla wewnętrzna wykonuje się „i” razy dla każdego i∈1,...,n-1, a na każdą iteracje przypadają dwa przypisania: jedno dla „sum”, jedno dla„j”.

Przypisania wykonywane w całym programie:1+3n+2(1+2+...+n-1) = 1+3n+n(n-1) = O(n)+O(n2) = O(n2)

Asymptotyczna złożoność wynosi O(n2).

Znajdowanie złożoności asymptotycznej

Page 49: Weryfikacja poprawności programu

• Wyznaczenie złożoności asymptotycznej jest trudniejsze jeżeli liczba iteracji nie jest zawsze jednakowa.

Przykład 3Znajdź najdłuższą podtablice zawierającą liczby uporządkowane rosnąco.

for (i=0; len=1; i<n-1; i++) for (i1=i2=k=i; k<n-1 && a[k]<a[k+1]; k++,i2++);

if(len < i2-i1+1) len=i2-i1+1;

Jeśli liczby w tablicy są uporządkowane malejąco, to pętla zewnętrzna wykonuje się n-1 razy, a w każdym jej przebiegu pętla wewnętrzna wykona się tylko raz.

Złożoność algorytmu jest więc O(n).

Znajdowanie złożoności asymptotycznej

Jeśli liczby w tablicy są uporządkowane rosnąco, to pętla zewnętrzna wykonuje się n-1 razy, a w każdym jej przebiegu pętla wewnętrzna wykona się i razy dla i∈1,...,n-1.

Złożoność algorytmu jest więc O(n2).

Przykład 3Znajdź najdłuższą podtablice zawierającą liczby uporządkowane rosnąco.

for (i=0; len=1; i<n-1; i++) for (i1=i2=k=i; k<n-1 && a[k]<a[k+1]; k++,i2++);

if(len < i2-i1+1) len=i2-i1+1;

Znajdowanie złożoności asymptotycznej

Page 50: Weryfikacja poprawności programu

Wyszukiwanie elementu maksymalnego

Lista kroków:krok 1: wmax ← d[1]; pmax ← 1krok 2: Dla i = 2,3,...,n:

jeśli wmax < d[i], to wmax ← d[i];pmax ← i

krok 3: Zakończ algorytm

Jeśli za operacjedominujące przyjmiemyilość wykonanychporównań elementówzbioru, to złożonośćobliczeniowa algorytmuwyszukiwania elementumaksymalnego jest równa T(n) = n – 1.

Algorytm posiada liniową klasę czasowej złożonościobliczeniowej O(n).

Lista kroków:krok 1: wn ← d[1]; pn ← 1; ln ← 1krok 2: Dla i = 1,2,...,n: wykonuj kroki 3...5krok 3: licznik ← 0krok 4: Dla j = 1,2,...,n:

jeśli d[i] = d[j], tolicznik ← licznik + 1

krok 5: Jeśli licznik > ln , town ← d[i];pn ← i;ln ← licznik

krok 6: Zakończ algorytm

Wyszukiwanie najczęstszego elementu

• Wybór n elementów wymaga n operacji.

• Po każdym wyborze musimywykonać n porównań wybranegoelementu z elementami zbioru w celu zliczenia ilości jegowystąpień.

• Daje to wynik: T(n) = n2

Algorytm posiada klasę złożoności obliczeniowej O(n2).

Page 51: Weryfikacja poprawności programu

Modyfikacja programu przez przeniesienie instrukcji ze środka na zewnątrz pętli.

max = maksimum(t); //zwraca największą wartość w tablicy t

for(i=0; i<100; i++)t[i] = t[i]* 100/max;

Ulepszenia rzędu wielkości

po ulepszeniu:

max = maksimum(t); //zwraca największą wartość w tablicy t

wspol = 100/max;for(i=0; i<100; i++)t[i] = t[i] * wspol;

Wyszukanie w liście liniowej L elementu o wartości x.

Prosty algorytm zawiera warunek postaci:

1. „czy znaleziono w L wartość x”i

2. „czy został osiągnięty koniec listy L?”

Ulepszenia rzędu wielkości

po ulepszeniu:

Na koniec listy dodawany jest element o wartości x.Wyszukiwanie sprowadza się tylko do sprawdzania warunku 1.

Page 52: Weryfikacja poprawności programu

Wyszukiwanie binarne dla problemu wyszukiwania elementu w posortowanej liście L o długości N.

Ulepszenia rzędu wielkości

Ulepszenia rzędu wielkości

• Policzenie porównań• Każde porównanie skraca długość listy wejściowej o

połowę• Proces ten kończy się, gdy lista jest pusta lub

znaleziony zostanie poszukiwany element • Pesymistyczna liczba porównań ilość możliwych

operacji dzielenia wielkości N przez 2, zanim osiągnie 0, czyli log2N.

Page 53: Weryfikacja poprawności programu

Czy można skonstruować jeszcze lepszy algorytm?

• Każdy poprawnyalgorytm znajdującyrozwiązanie danegoproblemu ustanawia dlaniego górne ograniczeniezłożoności.

• Możliwości dalszejpoprawy rzęduzłożoności algorytmubędącego rozwiązaniemproblemu wyznaczadolne ograniczenie!

Taki pogląd funkcjonuje w środowisku programistów - nie określono przecież granicy rozwoju mocy obliczeniowych komputerów.

Mitem jest stwierdzenie, że komputery są tak szybkie, że czas nie stanowi problemu (rozkład na czynniki pierwsze dużych liczb - 300 cyfr wymaga milionów lat)

Należy zdecydowanie przeciwstawiać się przekonaniu o tym, że ulepszenia sprzętowe uczynią pracę nad efektywnymi algorytmami zbyteczną.

Nie przejmuj się efektywnością algorytmu…wystarczy poczekać kilka lat

Page 54: Weryfikacja poprawności programu

• Istnieją problemy których rozwiązanie za pomocązasobów komputerowych jest teoretycznie możliwe, ale praktycznie przekracza możliwości istniejących technologii.

• Przykładem takiego problemu jest rozumienie języka naturalnego, przetwarzanie obrazów (do pewnego stopnia oczywiście) czy “inteligentna”komunikacja pomiędzy komputerami a ludźmi na rozmaitych poziomach.

Nie przejmuj się efektywnością algorytmu…wystarczy poczekać kilka lat

• Kiedy pewne problemy stają się “proste”… Nowa grupa wyzwań, które na razie można sobie tylko próbować wyobrażać, wytyczy nowe granice możliwości wykorzystania komputerów.

Nie przejmuj się efektywnością algorytmu…wystarczy poczekać kilka lat

Page 55: Weryfikacja poprawności programu

Cormen T.H., Leiserson Ch.E., Rivest R.L., Stein C.: „Wprowadzenie do algorytmow”. WNT, Warszawa, 2005Wroblewski P.: „Algorytmy, struktury danych i techniki programowania, Wydanie III”, Helion, Gliwice, 2003

N. Wirth: „Algorytmy + struktury danych = programy”. WNT, Warszawa, 2004.http://we.pb.edu.pl/~jforenc/dydaktyka.htmlhttp://pl.wikipedia.org

Literatura