Przejdź do zawartości

Złożoność obliczeniowa

Z Wikipedii, wolnej encyklopedii

Teoria złożoności obliczeniowej – dział teorii obliczeń, którego głównym celem jest określanie ilości zasobów potrzebnych do rozwiązania problemów obliczeniowych. Rozważanymi zasobami są takie wielkości jak czas, pamięć lub liczba procesorów.

Za twórców tej teorii uważani są Juris Hartmanis i Richard Stearns. Jako przykłady problemów t.z.o. można podać problem spełnialności, problem najkrótszej ścieżki, problem faktoryzacji oraz wiele innych, o których wiadomo, że są obliczalne. Kwestią obliczalności zajmuje się teoria obliczalności, będąca drugą ważną gałęzią teorii obliczeń.

Wyniki, jakie podaje t.z.o., można podzielić na dwie kategorie: pozytywne i negatywne, czyli na takie, które podają, co i jak można obliczyć, oraz takie, w których dowodzi się, czego nie da się obliczyć, wykorzystując określoną ilość zasobów. Wyniki pozytywne są łatwiejsze do uzyskania i zwykle mają postać algorytmu rozwiązującego dany problem wraz z dowodem poprawności oraz opisem potrzebnych zasobów.

Złożoność algorytmów

[edytuj | edytuj kod]

Liczbę zasobów niezbędnych do wykonania algorytmu można rozumieć jako jego złożoność. W zależności od rozważanego zasobu mówi się o złożoności czasowej czy też złożoności pamięciowej. Oczywiście w większości wypadków liczba potrzebnych zasobów będzie się różnić w zależności od danych wejściowych z zakresu danego zagadnienia.

Przykładowo można by rozpatrzyć rozkład liczb na czynniki pierwsze. Przewidzieć można, że (niezależnie od zastosowanego algorytmu) im większa liczba, tym więcej zasobów będzie potrzebnych do jej rozłożenia. Tę cechę podziela większość zagadnień obliczeniowych – im większe rozmiary danych wejściowych, tym więcej zasobów (czasu, procesorów, pamięci) jest koniecznych do wykonania danych obliczeń. Złożoność algorytmu jest więc funkcją rozmiaru danych wejściowych.

Kolejnym problemem jest fakt, iż złożoność zwykle nie zależy wyłącznie od rozmiaru danych, ale może się znacznie różnić dla danych wejściowych o identycznym rozmiarze. Dwoma często stosowanymi sposobami podejścia są:

Czasowa złożoność obliczeniowa

[edytuj | edytuj kod]

Przyjętą miarą złożoności czasowej jest liczba operacji podstawowych w zależności od rozmiaru wejścia. Pomiar rzeczywistego czasu zegarowego jest mało użyteczny ze względu na silną zależność od sposobu realizacji algorytmu, użytego kompilatora oraz maszyny, na której algorytm wykonujemy. Dlatego w charakterze czasu wykonania rozpatruje się zwykle liczbę operacji podstawowych (dominujących). Operacjami podstawowymi mogą być na przykład: podstawienie, porównanie lub prosta operacja arytmetyczna.

Kolejny problem polega na tym, w jakim języku programowania formułować będzie się algorytmy oraz co można założyć, mówiąc o maszynie, na której algorytm ten będzie wykonywany. Istniejące komputery różnią się między sobą istotnymi (z punktu widzenia konstruowania algorytmów) parametrami, jak na przykład liczbą i rozmiarem rejestrów, udostępnianymi operacjami matematycznymi, a ponadto podlegają ciągłym ulepszeniom. Wobec tego algorytmy analizuje się, wykorzystując abstrakcyjne modele obliczeń. Do popularnych modeli należą maszyna RAM, maszyna Turinga i maszyna wskaźnikowa (ang. pointer machine).

Pamięciowa złożoność obliczeniowa

[edytuj | edytuj kod]

Podobnie jak złożoność czasowa jest miarą czasu działania algorytmu, tak złożoność pamięciowa jest miarą ilości wykorzystanej pamięci. Jako tę ilość najczęściej przyjmuje się użytą pamięć maszyny abstrakcyjnej (na przykład liczbę komórek pamięci maszyny RAM) w funkcji rozmiaru wejścia. Możliwe jest również obliczanie rozmiaru potrzebnej pamięci fizycznej wyrażonej w bitach lub bajtach.

Porównywanie złożoności algorytmów

[edytuj | edytuj kod]

Porównując złożoność algorytmów, bierze się pod uwagę asymptotyczne tempo wzrostu, czyli to jak zachowuje się funkcja określająca złożoność dla odpowiednio dużych, granicznych argumentów (rozmiarów danych wejściowych), ignorując zachowanie dla małych danych. Ponadto złożoności algorytmów różniące się o stałą uważa się za takie same, co eliminuje wpływ szybkości działania komputera, na którym dany algorytm ma być wykonany, oraz wybór operacji podstawowej, która na jednym komputerze może wykonywać się błyskawicznie, na innym zaś musi być zastąpiona szeregiem instrukcji.

Klasy złożoności

[edytuj | edytuj kod]

Klasa złożoności to klasa zagadnień obliczeniowych o podobnej złożoności obliczeniowej – innymi słowy problemy, do których rozwiązania potrzebna jest podobna ilość zasobów, łączy się w klasy. Przykładowo mówi się o problemach o liniowej złożoności pamięciowej, jeśli ilość potrzebnej pamięci rośnie liniowo względem rozmiaru danych; czy też o problemach o kwadratowej złożoności czasowej, jeśli liczba operacji podstawowych rośnie z kwadratem rozmiaru danych. Podobne określenia stosuje się również do algorytmów.

Stosuje się też szersze pojęcia takie jak klasa P, czy NP, mając odpowiednio na uwadze decyzyjne problemy wielomianowe i decyzyjne problemy podlegające wielomianowej weryfikacji, jeśli odpowiedź jest twierdząca.

P vs NP

[edytuj | edytuj kod]

Pytanie, czy klasa P jest tym samym co NP, jest jednym z problemów milenijnych, za których rozwiązanie przewidziano nagrodę w wysokości 1 miliona dolarów. Każdy problem z klasy P jest również w klasie NP, nie wiadomo jednak, czy istnieją problemy klasy NP, które nie są problemami klasy P.

Są trzy możliwe rozwiązania:

Zobacz też

[edytuj | edytuj kod]

Bibliografia

[edytuj | edytuj kod]
  • Christos H. Papadimitriou: Złożoność obliczeniowa, WNT 2002.
  • Christos H. Papadimitriou: Złożoność obliczeniowa, nowy przekład (tłum. Zdzisław Płoski). Helion 2012.
  • T. H. Cormen, C. E. Leiserson, C. Stein i R. L. Rivest, Introduction to Algorithms, The MIT Press/McGraw-Hill Company 1990 (wydanie polskie: Wprowadzenie do algorytmów, WNT 2004).
  • Marek Kubale: Łagodne wprowadzenie do analizy algorytmów, Gdańsk 2004.

Linki zewnętrzne

[edytuj | edytuj kod]