V informatice je časová složitost algoritmu definována jako funkce délky řetězce reprezentujícího vstup, rovné době běhu algoritmu na daném vstupu [1] . Časová složitost algoritmu se obvykle vyjadřuje pomocí velkého zápisu "O" , který bere v úvahu pouze člen nejvyššího řádu a také nebere v úvahu konstantní faktory, tedy koeficienty. Je-li složitost vyjádřena tímto způsobem, hovoříme o asymptotickém popisu časové složitosti, to znamená, že velikost vstupu má tendenci k nekonečnu. Například, pokud existuje takové číslo , že doba běhu algoritmu pro všechny vstupy délky nepřesáhne , pak lze časovou složitost tohoto algoritmu asymptoticky odhadnout jako .
Časová složitost se obvykle odhaduje spočtením počtu elementárních operací, které algoritmus provede. Doba provádění jedné takové operace se bere jako konstanta, to znamená, že se asymptoticky odhaduje jako . V takovém zápisu se celková doba provádění a počet elementárních operací provedených algoritmem liší maximálně o konstantní faktor, který se v O-notaci nezohledňuje. Protože se doba běhu algoritmu může lišit na vstupech stejné velikosti, obvykle se používá nejhorší případ běhu , který se označuje a je definován jako nejdelší doba běhu algoritmu na všech vstupních délkách . Méně často, a to je obvykle specifikováno specificky, se počítá průměrná složitost , tedy matematické očekávání doby běhu pro všechny možné vstupy. Doba běhu algoritmu může být klasifikována podle toho, která funkce je pod O-notací. Například algoritmus s se nazývá algoritmus s lineární dobou běhu a algoritmus s pro některé se nazývá polynom .
Následující tabulka shrnuje nejčastěji se vyskytující třídy složitosti . V tabulce , označuje libovolný polynom v , to je, .
název | Třída obtížnosti | Pracovní doba, | Příklady pracovní doby | Příklady algoritmů |
---|---|---|---|---|
konstantní čas | Určení parity celého čísla (reprezentovaného binárně) | |||
inverzní Ackermannova funkce | Analýza amortizace na operaci pomocí disjunktních sad | |||
iterovaný logaritmický čas | Barvy v distribuovaném cyklu | |||
dvojitě logaritmické | Doba amortizace na operaci při použití fronty s omezenou prioritou [2] | |||
logaritmický čas | DLOGTIME | , | Binární vyhledávání | |
polylogaritmický čas | ||||
sublineární čas | v | , | Hledejte v k-rozměrném stromu | |
lineární čas | Hledání nejmenšího nebo největšího prvku v netříděném poli | |||
"n log-hvězdička n" | Seidelův polygonový triangulační algoritmus . | |||
lineárně-logaritmický čas | , | Nejrychlejší srovnávací řazení | ||
kvadratický čas | Bublinové řazení , řazení vkládání , přímé skládání | |||
krychlový čas | Obvyklé násobení dvou matic. Výpočet parciální korelace . | |||
polynomiální čas | P | .. _ | Karmarkarův algoritmus pro lineární programování , AKS-test jednoduchosti | |
kvazi-polynomiální čas | QP | , | Nejrychlejší známý je aproximační algoritmus pro orientovaný Steinerův problém . | |
subexponenciální čas (první definice) |
SUBEXP | pro všechny | Za předpokladu teoretických hypotéz je BPP obsažen v SUBEXP. [3] | |
subexponenciální čas (druhá definice) |
Nejrychlejší známé algoritmy pro faktoring celých čísel a kontrolu izomorfismu grafu | |||
exponenciální čas (s lineárním exponentem) |
E | , | Řešení problému obchodního cestujícího s dynamickým programováním | |
exponenciální čas | EXPTIME | , | Řešení problému řádu násobení matic pomocí vyčerpávajícího výčtu | |
faktoriální čas | Řešení problému obchodního cestujícího vyčerpávajícím hledáním | |||
dvojnásobně exponenciální čas | 2-EXPTIME | Kontrola správnosti daného tvrzení v Presburgerově aritmetice | ||
1 pro n >= 1 |
O algoritmu se říká, že je to algoritmus s konstantním časem (zapsaný jako time ), pokud je hodnota omezena na hodnotu nezávislou na velikosti vstupu. Například získání jednoho prvku v poli trvá konstantní čas, protože je proveden jediný příkaz k jeho nalezení. Nalezení minimální hodnoty v netříděném poli však není operace s konstantním časem, protože se musíme podívat na každý prvek pole. Tato operace tedy trvá lineárně, . Pokud je počet prvků znám předem a nemění se, lze takový algoritmus označit jako algoritmus s konstantním časem.
Navzdory názvu „konstantní čas“ nemusí být doba běhu nezávislá na velikosti úlohy, ale horní mez doby běhu by měla být. Například problém „výměny hodnot a v případě potřeby získat výsledek “ je považován za problém s konstantním časem, ačkoli doba běhu algoritmu může záviset na tom, zda nerovnost již platí nebo ne. Existuje však určitá konstanta, u které doba provedení úlohy nikdy nepřekročí .
Níže je uveden příklad kódu běžícího v konstantním čase:
int index = 5; int položka = seznam[index]; jestliže (podmínka je pravdivá) pak provádět některé operace s konstantní dobou běhu jiný provádět některé operace s konstantní dobou běhu pro i = 1 až 100 pro j = 1 až 200 provádět některé operace s konstantní dobou běhuPokud je rovno , kde je konstanta, pak je toto ekvivalentní rovno .
Říká se, že algoritmus běží v logaritmickém čase , pokud . Protože počítače používají binární číselný systém , základem logaritmu je (tj. ). Při změně základu logaritmu se však liší pouze konstantním faktorem , který je v O-big notaci vyřazen. Jedná se tedy o standardní zápis pro logaritmické časové algoritmy bez ohledu na základ logaritmu.
Algoritmy běžící v logaritmickém čase se běžně vyskytují v operacích na binárních stromech nebo při použití binárního vyhledávání .
Algoritmy pro práci s poli velikostí dat jsou považovány za vysoce efektivní, protože poměr doby provádění jedné operace k velikosti pole se zvětšováním této velikosti klesá.
Velmi jednoduchým příkladem takového algoritmu je vyhledávání slov ve slovníku. Představte si slovník obsahující slova seřazená abecedně. Zároveň předpokládáme, že všechna slova mají délku a že můžeme přistupovat k libovolnému prvku slovníku indexem v konstantním čase. Nechť je -tý prvek slovníku, pak můžete zkontrolovat, zda je slovo ve slovníku za . Chcete-li to provést, zvažte prvek slovníku , kde označuje zaokrouhlení čísla dolů . Pokud , pak bychom měli jít do pravé poloviny pole, jinak - doleva. Na konci dostaneme index prvního slova, který je roven nebo lexikograficky větší než .
int find ( vector < string > & D , string w ) { int n = D . velikost (); int l = -1 , r = n ; while ( r - l > 1 ) { int m = ( l + r ) / 2 ; if ( D [ m ] < w ) { l = m ; } jinak { r = m ; } } vrátit r ; }Říká se, že algoritmus běží v polylogaritmickém čase , pokud pro některé . Například problém řádu násobení matic lze v takovém čase vyřešit na paralelním stroji RAM [4] .
Říká se, že algoritmus běží v sublineárním čase , pokud . Konkrétně sem patří algoritmy, jejichž časová složitost je výše uvedená, stejně jako například Groverovo hledání se složitostí .
Algoritmy, které jsou sice přesné, ale stále běží v sublineárním čase, obvykle používají paralelismus procesů (stejně jako algoritmus výpočtu determinant matice NC 1 ), neklasické výpočty (jako v Groverově hledání) nebo mají zaručený odhad vstupní struktury (jako binární vyhledávací algoritmy a mnoho algoritmů pro zpracování stromů). Nicméně formální jazyky , jako je jazyk slov, která mají 1 bit na pozici určené prvními bity slova, mohou být rozhoditelné v sublineárním čase, i když jakýkoli bit může být důležitý pro určení, zda slovo patří do jazyka. .
Termín sublineární algoritmus doby běhu se obvykle používá pro algoritmy, které na rozdíl od příkladů výše běží na konvenčních sekvenčních modelech strojů a nevyžadují a priori znalost vstupní struktury [5] . Mohou však používat pravděpodobnostní metody a ještě více, často musí být randomizováni pro jakýkoli netriviální úkol.
Protože takový algoritmus musí dát odpověď bez úplného čtení vstupních dat, je velmi závislý na přístupových metodách povolených ve vstupním toku. Obvykle se pro tok, který je bitovým řetězcem , předpokládá, že algoritmus může požadovat hodnotu pro libovolný .
Algoritmy sublineárního času jsou obvykle pravděpodobnostní a poskytují pouze přibližné řešení. Sublineární runtime algoritmy přirozeně vznikají při zkoumání kontroly vlastností .
Říká se, že algoritmus běží v lineárním čase nebo v čase, pokud je jeho složitost . Neformálně to znamená, že pro dostatečně velkou velikost vstupu se doba běhu lineárně zvyšuje s velikostí vstupu. Například procedura, která sečte všechny prvky seznamu, trvá úměrně délce seznamu. Tento popis není zcela přesný, protože doba běhu se může výrazně lišit od přesné úměrnosti, zejména u malých hodnot .
Lineární čas je často považován za žádoucí atribut algoritmu [6] . Bylo provedeno mnoho výzkumů pro vytvoření algoritmů s (téměř) lineárními nebo lepšími provozními dobami. Tyto studie zahrnovaly jak softwarové, tak hardwarové přístupy. V případě hardwarového provádění mohou některé algoritmy, které z matematického hlediska nikdy nemohou dosáhnout lineárního času provádění ve standardních výpočetních modelech , běžet v lineárním čase. Existují některé hardwarové technologie, které k dosažení tohoto cíle využívají paralelismus . Příkladem je asociativní paměť . Tento koncept lineárního času se používá v problémech se vzorem , jako je Boyer-Mooreův algoritmus a Ukkonenův algoritmus .
Říká se, že algoritmus běží v kvazilineárním čase, pokud pro nějakou konstantu . Když se mluví o lineárně-logaritmickém čase [7] . Z hlediska soft-O se taková doba běhu zapisuje jako . U algoritmů s kvazilineární dobou běhu platí také odhad pro libovolný . Tyto algoritmy jsou tedy rychlejší než jakýkoli polynom v , jehož stupeň je větší než .
Algoritmy běžící v kvazilineárním čase, kromě lineárně-logaritmických algoritmů uvedených výše, zahrnují:
Lineární-logaritmický je speciální případ kvazi-lineárního času s exponentem na logaritmickém faktoru.
Lineárně-logaritmická funkce je funkcí formy (tj. součin lineárního a logaritmického členu). Říká se, že algoritmus běží v lineárně-logaritmickém čase , jestliže [8] . Lineárně-logaritmická funkce tedy roste rychleji než lineární, ale pomaleji než jakýkoli polynom stupně většího než .
V mnoha případech je doba běhu jednoduše výsledkem provedení časové operace na době běhu . Například řazení pomocí binárního stromu vytvoří binární strom tak, že do něj vložíte každý prvek pole velikosti jeden po druhém. Protože operace vložení do vyváženého binárního vyhledávacího stromu zabere čas , bude celková doba provádění algoritmu lineárně-logaritmická.
Jakékoli třídění založené na porovnání vyžaduje alespoň nejhorší případ lineárně-logaritmického počtu srovnání. Jedno z jednoduchých zdůvodnění této skutečnosti z informačně-teoretického hlediska vypadá takto: v důsledku řazení dostaneme permutaci délky , která jednoznačně určuje pořadí prvků. Celkem existují různá řazení, pokud chceme každé z nich jednoznačně zakódovat nějakou posloupností bitů, budeme potřebovat v průměru ne méně než bitů informace na permutaci. V tomto případě je výsledkem párového porovnání dvou prvků pole právě jeden bit informace – buď je první prvek menší než druhý, nebo ne. Pokud tedy pro třídění použijeme pouze párová srovnání, není možné seřadit pole v lepším než nejhorším případě. Zároveň takový odhad pro mnoho rekurzivních druhů, jako je merge sort , často vychází z rekurzivní rovnice .
Říká se, že algoritmus běží v subkvadratickém čase , pokud .
Například jednoduché třídicí algoritmy založené na porovnání (jako je vložení řazení ) jsou kvadratické. Současně lze nalézt pokročilejší algoritmy, které mají subkvadratické běhové prostředí (např. Shell sort ). Žádné obecné druhy nefungují v lineárním čase, ale přechod z kvadratického na podkvadrátový čas má velký praktický význam.
Říká se, že algoritmus běží v polynomiálním čase , pokud je doba běhu shora ohraničena polynomem ve vstupní velikosti algoritmu, tedy pro nějakou konstantu [1] [9] . Problémy , pro které existují deterministické polynomiální algoritmy, představují třídu složitosti P , která je ústředním bodem teorie výpočetní složitosti . Cobhamova teze uvádí, že polynomiální čas je synonymem pro „snadno zpracovatelný“, „schůdný“, „efektivní“ nebo „rychlý“ [10] .
Některé příklady polynomiálních algoritmů:
V některých kontextech, zvláště v optimalizaci , se rozlišuje mezi algoritmy striktního polynomiálního času a slabě polynomiálního času . Tyto dva koncepty platí pouze pro vstupy sestávající z celých čísel.
V aritmetickém modelu výpočtu je definován striktně polynomiální čas. V tomto modelu jsou základní aritmetické operace (sčítání, odčítání, násobení, dělení a porovnávání) brány jako jednotky provedení bez ohledu na délku operandů. Algoritmus pracuje v přísně polynomiálním čase, pokud [11]
Jakýkoli algoritmus s těmito dvěma vlastnostmi může být redukován na polynomiální časový algoritmus nahrazením aritmetických operací odpovídajícími algoritmy pro provádění aritmetických operací na Turingově stroji . Pokud nebude splněn druhý z výše uvedených požadavků, nebude to již pravda. Dané celé číslo (které zabírá paměť úměrnou n v Turingově stroji), to může být počítáno v n operacích používat opakované umocňování . Paměť použitá k reprezentaci je však úměrná a závisí spíše exponenciálně než polynomiálně na paměti použité pro vstup. Tudíž - je nemožné provádět tyto výpočty v polynomiálním čase na Turingově stroji, ale lze je provést v polynomiálním počtu aritmetických operací.
Naopak existují algoritmy, které pracují v počtu kroků Turingova stroje, omezeného polynomickou délkou binárně zakódovaného vstupu, ale nepracují v počtu aritmetických operací, omezeném polynomem v počtu čísel v vstup. Jedním z příkladů je Euklidův algoritmus pro výpočet největšího společného dělitele dvou celých čísel. Pro dvě celá čísla je doba běhu algoritmu omezena kroky Turingova stroje. Toto číslo je polynom ve velikosti binární reprezentace čísel a , který může být zhruba reprezentován jako . Počet aritmetických operací přitom nelze omezit počtem celých čísel na vstupu (což je v tomto případě konstanta – na vstupu jsou pouze dvě čísla). S ohledem na tuto poznámku, algoritmus nefunguje v přísně polynomiálním čase. Skutečná doba běhu algoritmu závisí na hodnotách a , nejen na počtu celých čísel na vstupu.
Jestliže algoritmus běží v polynomiálním čase, ale ne striktně v polynomiálním čase, říká se, že běží ve slabě polynomiálním čase [12] . Známým příkladem problému, pro který je znám slabě polynomiální algoritmus, ale není znám žádný striktně polynomiální algoritmus, je lineární programování . Slabě polynomiální čas by neměl být zaměňován s pseudopolynomiálním časem .
Pojem polynomiálního času vede k několika třídám složitosti v teorii výpočetní složitosti. Některé důležité třídy definované pomocí polynomiálního času jsou uvedeny níže.
P je nejmenší třída časové složitosti na deterministickém stroji, která je stabilní hlediska změny modelu stroje. (Například přechod z jednopáskového Turingova stroje na vícepáskový Turingův stroj může vést ke kvadratickému zrychlení, ale jakýkoli algoritmus, který běží v polynomiálním čase na jednom modelu, bude běžet v polynomiálním čase na jiném.)
Říká se, že algoritmus běží v superpolynomiálním čase , pokud T ( n ) není shora ohraničeno polynomem. Tento čas je ω( n c ) pro všechny konstanty c , kde n je vstupní argument, obvykle počet vstupních bitů.
Například algoritmus, který má 2n kroků, vyžaduje superpolynomiální čas (konkrétněji exponenciální čas) pro vstup o velikosti n .
Je jasné, že algoritmus využívající exponenciální zdroje je superpolynomiální, ale některé algoritmy jsou velmi slabě superpolynomiální. Například Adleman-Pomerance-Rumeliho test primality běží v čase n O(log log n ) na n - bitovém vstupu. Toto roste rychleji než jakýkoli polynom pro dostatečně velké n , ale velikost vstupu se musí stát velmi velkou, aby v něm nedominoval polynom malého stupně.
Algoritmus vyžadující superpolynomiální čas leží mimo třídu složitosti P . Cobhamova teze uvádí, že tyto algoritmy jsou nepraktické a v mnoha případech jsou. Protože problém rovnosti tříd P a NP nebyl vyřešen, nejsou v současné době známy žádné algoritmy pro řešení NP-úplných problémů v polynomiálním čase.
Algoritmy kvazipolynomiálního času jsou algoritmy , které běží pomaleji než polynomiální čas, ale ne tak pomalé jako algoritmy exponenciálního času. Nejhorší případ běhu pro kvazi-polynomiální algoritmus je stejný pro nějaké pevné c . Známý klasický algoritmus pro faktorizaci celého čísla, metoda obecného čísla pole sieve , která běží přibližně v čase , není kvazi-polynomiální, protože dobu běhu nelze reprezentovat jako pro nějaké pevné c . Pokud je konstanta "c" v definici kvazi-polynomiálního časového algoritmu 1, dostaneme polynomiální časový algoritmus, a pokud je menší než 1, dostaneme sublineární časový algoritmus.
Algoritmy kvazi-polynomiálního času obvykle vznikají, když redukujeme NP-těžký problém na jiný problém. Můžete například vzít NP-těžký problém, řekněme 3SAT , a zredukovat ho na jiný problém B, ale velikost problému bude . V tomto případě redukce nedokazuje, že problém B je NP-těžký, taková redukce pouze ukazuje, že neexistuje žádný polynomiální algoritmus pro B, pokud neexistuje kvazi-polynomiální algoritmus pro 3SAT (a pak pro všechny NP -problémy) . Podobně existují některé problémy, pro které známe algoritmy s kvazi-polynomiálním časem, ale pro které neznáme algoritmy s polynomiálním časem. Takové problémy se objevují v aproximačních algoritmech. Slavným příkladem je orientovaný Steinerův problém , pro který existuje přibližný kvazi-polynomiální algoritmus s aproximačním koeficientem (kde n je počet vrcholů), ale existence polynomiálního algoritmu je otevřený problém.
Třída složitosti QP se skládá ze všech problémů, které mají kvazi-polynomiální časové algoritmy. Může být definován z hlediska DTIME takto [13] :
V teorii složitosti se nevyřešený problém rovnosti tříd P a NP ptá, zda všechny problémy z třídy NP mají polynomiální časové algoritmy řešení. Všechny dobře známé algoritmy pro NP-úplné problémy, jako je 3SAT, mají exponenciální čas. Navíc existuje domněnka, že pro mnoho přirozených NP-úplných problémů neexistují žádné algoritmy se subexponenciální dobou provádění. Zde je „subexponenciální čas“ brán ve smyslu druhé definice uvedené níže. (Na druhou stranu, mnoho problémů teorie grafů přirozeně reprezentovaných maticemi sousednosti je řešitelných v subexponenciálním čase jednoduše proto, že velikost vstupu je druhou mocninou počtu vrcholů.) Tato domněnka (pro problém k-SAT) je známá jako exponenciální časová domněnka [14] . Protože předpokládá, že NP-úplné problémy nemají kvazi-polynomiální časové algoritmy, některé výsledky neaproximovatelnosti v oblasti aproximačních algoritmů předpokládají, že NP-úplné problémy nemají kvazi-polynomiální časové algoritmy. Podívejte se například na známé výsledky týkající se nepřiblížení problému zakrytí sady .
Termín subexponenciální čas se používá k vyjádření toho, že doba provádění nějakého algoritmu může růst rychleji než jakýkoli polynom, ale zůstává podstatně kratší než exponenciální. V tomto smyslu jsou problémy se subexponenciálními časovými algoritmy poddajnější než algoritmy s pouze exponenciálním časem. Přesná definice „subexponenciály“ ještě není obecně přijímána [15] a níže uvádíme dvě nejběžnější definice.
Říká se, že problém je vyřešen v subexponenciálním čase, pokud je vyřešen algoritmem, jehož logaritmus doby běhu roste méně než jakýkoli daný polynom. Přesněji řečeno, problém má subexponenciální čas, pokud pro libovolné ε > 0 existuje algoritmus, který problém řeší v čase O(2 n ε ). Množinu všech takových problémů tvoří třída složitosti SUBEXP , kterou lze vyjádřit pomocí DTIME jako [3] [16] [17] [18] .
Všimněte si, že zde ε není součástí vstupních dat a každé ε může mít svůj vlastní algoritmus pro řešení problému.
Někteří autoři definují subexponenciální čas jako průběžný čas 2 o( n ) [14] [19] [20] . Tato definice umožňuje delší dobu běhu než první definice. Příkladem takového sub-exponenciálního časového algoritmu je dobře známý klasický algoritmus pro faktorizaci celých čísel, metoda obecného čísla pole síta , která běží přibližně v čase , kde vstupní délka je n . Dalším příkladem je známý algoritmus pro problém isomorfismu grafu , jehož doba běhu je .
Všimněte si, že je rozdíl, zda je algoritmus subexponenciální v počtu vrcholů nebo v počtu hran. V parametrizované složitosti je tento rozdíl explicitně přítomen zadáním páru , problému řešitelnosti a parametru k . SUBEPT je třída všech parametrizovaných problémů, které běží v subexponenciálním čase v k a v polynomiálním čase v n [21] :
Přesněji řečeno, SUBEPT je třída všech parametrizovaných problémů , pro které existuje vyčíslitelná funkce c a algoritmus, který řeší L v čase .
Exponenciální časová domněnkaExponenciální časový odhad (' ETH ) uvádí, že 3SAT , problém splnitelnosti pro booleovské formule v konjunktivní normální formě s maximálně třemi literály na větu a n proměnnými, nelze vyřešit v čase 2o ( n ) . Přesněji řečeno, domněnka říká, že existuje nějaká konstanta c >0 taková, že 3SAT nelze vyřešit v 2 cn na žádném deterministickém Turingově stroji. Jestliže m označuje počet vět, ETH je ekvivalentní hypotéze, že k -SAT nelze vyřešit v čase 2 o ( m ) pro žádné celé číslo k ≥ 3 [22] . Z exponenciální časové hypotézy vyplývá, že P ≠ NP .
Říká se, že algoritmus běží v exponenciálním čase , pokud je T ( n ) nahoře ohraničeno 2 poly( n ) , kde poly( n ) je nějaký polynom v n . Více formálně, algoritmus běží v exponenciálním čase jestliže T ( n ) je ohraničený O(2 n k ) s nějakou konstantou k . Úlohy, které běží v exponenciálním čase na deterministických Turingových strojích, tvoří třídu složitosti EXP .
Někdy se termín exponenciální čas používá pro algoritmy, pro které T ( n ) = 2 O( n ) , kde exponent je nanejvýš lineární funkcí n . Výsledkem je třída složitosti E .
Říká se, že algoritmus běží ve dvojnásobně exponenciálním čase, pokud je T ( n ) nahoře ohraničeno 2 2 poly( n ) , kde poly ( n ) je nějaký polynom v n . Takové algoritmy patří do třídy složitosti 2-EXPTIME .
Mezi známé dvojitě exponenciální algoritmy patří: