Detekcija ciklusa

S Vikipedije, slobodne enciklopedije

U računarskoj nauci, detekcija ciklusa je algoritamski problem pronalaženja ciklusa u sekvenci iterativnih vrednosti funkcije.

Za bilo koju funkciju ƒ koja mapira konačni skup S za sebe, i bilo koja inicijalna vrednost x0 u S, sekvenca iterativnih vrednosti funkcije

mora na kraju da iskoristi istu vrednost dva puta: mora biti neko ij takvo da xi = xj. Jednom kada se to dogodi, sekvenca mora periodično da se nastavi, ponavljajući iste vrednosti od xi do xj−1. Detekcija ciklusa je problem pronalaženja i i j, za dato ƒ i x0.

Primer[uredi | uredi izvor]

A function from and to the set {0,1,2,3,4,5,6,7,8} and the corresponding functional graph

Figura pokazuje funkciju ƒ koja mapira set S = {0,1,2,3,4,5,6,7,8} za sebe. ako neka kreće od x0 = 2 i u više navrata primenjuje ƒ, ona vidi sekvencu vrednosti

2, 0, 6, 3, 1, 6, 3, 1, 6, 3, 1, ....

Ciklus u je u ovom slučaju 6, 3, 1.

Definicije[uredi | uredi izvor]

Neka S bude bilo koji konačni skup, ƒ bilo koja funkcija od S za sebe, i x0 bilo koji element S. Za svako i > 0, neka je xi = ƒ(xi−1). Neka je μ najmanji indeks takav da se vrednost xμ ponovno pojavljuje beskonačno često unutar sekvence vrednosti xi, i neka je λ (dužina ciklusa) najmanji pozitivni ceo broj takav da xμ = xλ+μ. Problem detekcije ciklusa je zadatak traženja λ i μ.

Isti problem možemo gledati iz ugla teorije grafova, konstruišući funkcionalni graf (što znači, usmereni graf u kojem svako teme ima jednu odlaznu ivicu) čija temena su elementi od S i ivice koje preslikavaju element na odgovarajuću vrednost funkcije, kao što je prikazano. Skup temena dostižnih od bilo kojeg startnog temena x0 iz podgrafa oblika koji liči na grčko slovo ro(ρ): put dužine μ od x0 u ciklusu od λ temena.

Računarska reprezentacija[uredi | uredi izvor]

Generalno, ƒ neće biti specificirano kao spisak vrednosti, kao što je dato iznad. Nego, ili nam je dat pristup sekvenci vrednosti xi, ili podrutini za računanje ƒ. Zadatak je da se pronađeλ i μ proveravajući što manje vrednosti iz sekvence ili izvođenjem što je moguće manje podrutinskih poziva. Tipično, takođe, vremenska kompleksnost algoritma za problem detekcije ciklusa nije važna: želimo da rešimo problem dok koristimo memoriju znatno manju nego što je potrebno da se smesti cela sekvenca.

U nekim primenama, i u Pollard's rho algoritmu za faktorizaciju celih brojeva, algoritam ima mnogo više ograničenog pristupa S i ƒ. U Pollard's rho algoritmu, na primer, S je set celih brojeva modulovanih sa nepoznatim prostim faktorom da bi se broj faktorizovao, tako čak i veličina S je nepoznata algoritmu.

Možemo gledati na algoritam za detekciju ciklusa u ovoj primeni kao imanje sledećih mogućnosti: on inicijalno ima u svojoj memoriji objekat koji reprezentuje pokazivač na početnu vrednost x0. U bilo kom koraku, može izvesti tri akcije: može da kopira bilo koji pokazivač koji ima na drugi objekat u memoriji, može da primeni ƒ i zameni bilo koji od svojih pokazivača sa pokazivačem na sledeći objekat u sekvenci, ili može da primeni podrutinu za određivanje da li dva njegova pokazivača predstavljaju iste vrednosti u sekvenci. Akcija testiranja jednakosti može da uključuje neke netrivijalne komputacije: u Pollard's rho algoritmu, je to implementirano testiranjem da li razlika između dve ubačene vrednosti ima netrivijalni gcd sa brojem sa kojim treba da se faktoriše. U ovom kontekstu, pozvaćemo algoritam koji koristi samo kopiranje pokazivača, napredak unutar sekvence, i testove jednakosti s pokazivačkim algoritmom.

Algoritmi[uredi | uredi izvor]

Ako je ulaz dat kao podrutina za izračunavanje ƒ, problem detekcije ciklusa može biti trivijalno rešen korišćenjem samo λ+μ u funkciji, jednostavno računanjem sekvence vrednosti xi i korišćenjem strukture podataka kao što je heš mapa da se čuvaju ove vrednosti i testira da li je svaka sledeća vrednost već sačuvana. Međutim, prostorna kompleksnost ovog algoritma je λ+μ, nepotrebno velika. Dodatno, da bi se implementirala ova metoda kao pokazivački algoritam bilo bi potrebno da se primeni test jednakosti za svaki par vrednosti, rezultujući ukupnom kvadratnom vremenu. Tako, istraživanje u ovoj oblasti se koncentrisalo na dva cilja: korišćenje manje prostora nego što koristi ovaj naivni algoritam, i pronalaženje pokazivačkih algoritama koji koriste manje testova jednakosti.

Kornjača i zec[uredi | uredi izvor]

Floyd's "tortoise and hare" cycle detection algorithm, applied to the sequence 2, 0, 6, 3, 1, 6, 3, 1, ...

Flojdov algoritam za pronalaženje ciklusa, takođe poznat kao "algoritam kornjača i zec", aludirajući na Ezopovu basnu o kornjači i zecu, je pokazivački algoritam koji koristi dva pokazivača, koji se pomeraju kroz sekvencu različitim brzinama.

Algoritam je nazvan po Robert W. Floyd, koji je nagrađen za svoj izum od strane Donald Knuth.[1][2] Međutim, algoritam se ne pojavljuje u Flojdovom objavljenom radu, i ovo može biti misatribucija: Flojd opisuje algoritme za slaganje svih jednostavnih ciklusa u usmerenom grafu u objavi 1967 godine,[3] ali ova objava ne opisuje problem pronalaženja ciklusa u funkcionalnim grafovima koji su predmet ovog članka. Zapravo, Kuntova izjava (u 1969), pripisujući je Flojdu, bez citata, je prvo poznato pojavljivanje u štampi, i ovo može zapravo biti folkova teorema, nepripisiva na jednog  individualca.[4]

Ključni uvid u algoritam je to da za bilo kojiceo broj i ≥ μ i k ≥ 0, xi = xi + kλ, gde λ je dužina pronađenog ciklusa i μ je indeks prvog elementa u ciklusu. Naročito, kad god i = kλ ≥ μ, sledi da je xi = x2i. Tako, algoritam treba samo da proveri ponavljajuće vrednosti specijalne forme, jedne duplo dalje od početka sekvence nego druga, da bi pronašli period ν ponavljanja koje se množi sa λ. Kada se ν pronađe, algoritam se vraća na početak sekvence da bi pronašao svoju prvu ponavljajuću vrednost  xμ u sekvenci, koristeći činjenicu da λ deli ν i premda je xμ = xμ + v. Konačno, jednom kada je vrednost μ poznata trivijalno je pronći dužinu λ najkraćeg ponavljajućeg ciklusa, pronalaženjem prve pozicije μ + λ za koju je xμ + λ = xμ.

Tako algoritam održava dva pokazivača u datoj sekvenci, jednog (kornjaču) na xi, i drugi (zeca) na x2i. Na svakom koraku algoriitma, on povećava i za jedan, pomerajući kornjaču jedan korak unapred i zeca dva koraka unapred u sekvenci, i onda upoređuje vrednosti sekvence na koje pokazuju ova dva pokazivača. Najmanja vrednost i > 0 za koju i kornjača i zec pokazuju istu vrednost je željena vrednost ν.

Sledeći Python kod pokazuje kako ova ideja može biti implementirana kao algoritam.

def floyd(f, x0):
    # Main phase of algorithm: finding a repetition x_i = x_2i
    # The hare moves twice as quickly as the tortoise and
    # the distance between them increases by 1 at each step.
    # Eventually they will both be inside the cycle and then,
    # at some point, the distance between them will be
    # divisible by the period λ.
    tortoise = f(x0) # f(x0) is the element/node next to x0.
    hare = f(f(x0))
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(f(hare))
  
    # At this point the tortoise position, ν, which is also equal
    # to the distance between hare and tortoise, is divisible by
    # the period λ. So hare moving in circle one step at a time, 
    # and tortoise (reset to x0) moving towards the circle, will 
    # intersect at the beginning of the circle. Because the 
    # distance between them is constant at 2ν, a multiple of λ,
    # they will agree as soon as the tortoise reaches index μ.

    # Find the position μ of first repetition.    
    mu = 0
    tortoise = x0
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(hare)   # Hare and tortoise move at same speed
        mu += 1
 
    # Find the length of the shortest cycle starting from x_μ
    # The hare moves one step at a time while tortoise is still.
    # lam is incremented until λ is found.
    lam = 1
    hare = f(tortoise)
    while tortoise != hare:
        hare = f(hare)
        lam += 1
 
    return lam, mu

Ovaj kod pristupa sekvenci samo čuvajući i kopirajući pokazivače, evaluaciije funkcije, i testove jednakosti; premda, kvalifikuje se kao pokazivački algoritam. Algoritam koristi O(λ + μ) operacija ovih tipova, i O(1) mesta za čuvanje.

Brentov algoritam[uredi | uredi izvor]

Richard P. Brent je opisao alternativni algoritam za detekciju ciklusa, koji kao kornjača i zec algoritam, zahteva samo dva pokazivača u sekvenci.[5] Međutim, zasnovan je na druačijem principu: traženjem najmanjeg kvadrata 2i koji je veći od λ i μ. Za i = 0, 1, 2, itd., algoritam upoređuje x2i−1 sa svakom sledećom vrednošću sekvence do sledećeg kvadrata, stajući kada pronađe podudaranje. Ima dve prednosti u odnosu na algoritam kornjače i zeca: pronalazi tačnu dužinu λ ciklusa direktno, pre nego da treba da ga pronađe u narednoj fazi, i njegovi koraci uključuju samo jednu evaluaciju ƒ pre nego tri.

Sledeći Python kod pokazuje kako ova tehnika radi detaljnije.

def brent(f, x0):
    # main phase: search successive powers of two
    power = lam = 1
    tortoise = x0
    hare = f(x0)  # f(x0) is the element/node next to x0.
    while tortoise != hare:
        if power == lam:  # time to start a new power of two?
            tortoise = hare
            power *= 2
            lam = 0
        hare = f(hare)
        lam += 1

    # Find the position of the first repetition of length λ
    mu = 0
    tortoise = hare = x0
    for i in range(lam):
    # range(lam) produces a list with the values 0, 1, ... , lam-1
        hare = f(hare)
    # The distance between the hare and tortoise is now λ.

    # Next, the hare and tortoise move at same speed till they agree
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(hare)
        mu += 1
 
    return lam, mu

Kao algoritam kornjača i zec, ovo je pokazivački algoritam koji koristi O(λ + μ) testova i evaluacija funkcije i O(1) memorije. Nije teško pokazati da broj evaluacija funkcije nikada ne može da bude veći od Flojdovog algoritma. Brent tvrdi da, u proseku, njegov algoritam za pronalaženje ciklusa radi oko 36% brže nego Flojdov i da ubrzava Pollard rho algoritam za oko 24%. On takođe izvodi analizu prosečnog slučaja za nasumičnu verziju algoritma u kojoj sekvenca indeksa praćena od strane sporijeg od dva pokazivača nije kvadrat njih dvoje, nego nasumičan sadržalac kvadrata. Iako je njegova glavna nameravajuća aplikacija bila u algoritmima za faktorizaciju celih brojeva, Brent takođe diskutuje primene u testiranju pseudonasumičnih generatora brojeva.

Vreme-prostor razmene[uredi | uredi izvor]

Mnoštvo autora su proučavali tehnike detekcije ciklusa za detekciju ciklusa koja koristi manje memorije od Flojdovog i Brentovog algoritma, ali da detektuju ciklus brže. Generalno ove metode čuvaju nekoliko prethodno izračunatih vrednosti sekvence, i testiraju da li je svaka nova vrednost jednaka nekoj od prethodno izračunatih vrednosti. Da bi radili tako brzo, često koriste heš tabeleili slične strukture podataka za skladištenje prethodno izračunatih vrednosti, i premda nisu pokazivački algoritmi: naročito, oni obično ne mogu da budu primenjeni u Pollard's rho algoritmu. Gde se ove metode razlikuju je to kako odlučuju koju vrednost da čuvaju. Prateći Nivasch,[6] pregledali smo ukratko ove tehnike.

  • Brent[5] već opisuje varijacije svoje tehnike u kojima se indeksi zapamćene sekvence gde su vrednosti kvadrati broja R različitog od dva. Birajući R da bude broj blizu jedinice, i čuvajući vrednosti sekvence na tim indeksima koji su blizu sekvence uzastopnih kvadrata od R, algoritam za detekciju ciklusa može da koristi broj evaluacija funkcije koje su u arbitrarno malom faktoru optimuma λ+μ.[7][8]
  • Sedgewick, Szymanski, i Yao[9] su doprineli metod koji koristi M memorijskih ćelija i zahteva u najgorem slučaju samo  evaluacija funkcije, za neku konstantu c, za koju oni pokazuju da je optimalna. Tehnika uključuje zadržavanje numeričkog parametra  d, čuvajući u tabeli samo one pozicije u sekvenci koje su množioci d, i čišćenjem tabele i udvostručavanjem d  kad god je previše vrednosti sačuvano.
  • Nekoliko autora su opisali istaknute pokazivačke metode koje čuvaju vrednosti funkcije u tabeli zasnovano na kriterijumu uključujući vrednosti, pre nego (kao što je metod Sedgewick et al.) zasnovano na njihovim pozicijama. Na primer, vrednosti jednake nuli po modu neke vrednosti d mogu biti sačuvane.[10][11] Jednostavnije, Nivasch[6] pohvaljuje D. P. Woodruff sa sugestijom čuvanja nasumičnog primerka prethodno viđenih vrednosti, stvarajući odgovarajući nasumični izbor na svakom koraku tako da uzorak ostaje nasumičan.
  • Nivasch[6] opisuje algoritam koji ne koristi fiksiranu količinu memorije, ali za koji je očekivana količina memorije iskorišćena (pod pretpostavkom da je ulazna funkcia nasumična) je logaritamska u dužini sekvence. Predmet sačuvan u memorijskoj tabeli, sa ovom tehnikom, kada nijedan kasniji predmet nema manju vrednost. Kako Nivasch pokazuje, predmeti ovom tehnikom mogu biti održavani korišćenjem stek strukture podataka, i svaka sledeća vrednost sekvence treba da se uporedi sa vrhom steka. Algoritam se završava kada se pronađe ponovljen element sekvence sa najmanjom vrednosti. Koristeći isti algoritam sa više stekova, koristeći nasumične permutacije vrednosti da bi se premestile vrednosti u steku, dozvoljava vreme-prostor razmenu sličnu prethodnim algoritmima. Međutim, čak i verzije algoritma sa jednim stekom nije pointerski algoritam, zbog poređenja potrebnog da se odredi koja od dve vrednosti je manja.

Bilo koji algoritam za detekciju ciklusa koi čuva najviše M vrednosti od ulazne sekvence mora da izvrši bar evaluacija funkcije.[12][13]

Primene[uredi | uredi izvor]

Detekcija ciklusa se koristi u puno primena.

  • Određivanje dužine ciklusa pseudonasumičnog generatora brojeva je jedna mera njegove snage. Ovo je primena citirana od strane Kunta opisujući Flojdov metod. Brent[5] opisuje rezultate testiranja  linearnog kongruencijskog generatora u ovom pogledu; ispostavilo se da je njegov period znatno manji nego što se pričalo. Za kompleksnije generatore, sekvenca vrednosti u kojoj pronađeni ciklus ne mora da reprezentuje izlaz  generatora, nego njegovo unutrašnje stanje.
  • Nekoliko brojno teoretskih algoritama se zasniva na detekciji ciklusa, uključujući Pollard's rho algoritam za faktorizaciju celih brojeva[14] i povezan je sa kengur algoritmom za problem diskretnog logaritma.[15]
  • U kriptografijskim primenama, mogućnost da se pronađu dve slične vrednosti xμ−-1 i xλ+μ−-1 preslikaniih uz pomoć neke kriptografske funkcije ƒ za istu vrednost xμ može da indikuje slabost u ƒ. Na primer, Quisquater i Delescaille[11] primenjuju algoritme za detekciju ciklusa u potrazi za porukom i parom Data Encryption Standard ključeva koji mapiraju tu poruku na istu enkriptovanu vrednost; Kaliski, Rivest, i Sherman[16] takođe koriste algoritme za detekciju ciklusa da napadnu DES. Tehnika takođe može biti iskorišćena da se pronađe sudar u kriptografskoj heš funkciji.
  • Detekcija ciklusa može biti od pomoći kao način otkrivanja beskonačnih petlji u određenim tipovima računarskih programa.[17]
  • Periodične konfiguracije u simuliranju celularne automatizacije mogu biti pronađene primenom algoritama za detekciju ciklusa na sekvenci automatonskih stanja.[6]
  • Analiza oblika strukture podataka povezanih lista je tehnika za verifikovanje ispravnosti algoritma korišćenjem ovih struktura. Ako čvor u listi nepravilno pokazuje na prethodni čvor u istoj listi, struktura će formirati ciklus koi može biti detektovan od strane ovih algoritama.[18]
  • Teske[8] opisuje primene u teoriji računanja grupa: proveravajući strukturu Abelove grupe iz seta njegovih generatora. Kriptografski algoritmi Kaliski et al.[16] mogu takođe biti posmatrani kao pokušavanje  da se zaključi struktura nepoznate grupe.
  • Fich[12] ukratko pominje primenu u računarskoj simulaciji celestijalne mehanike, koju ona pripisuje William Kahan. U ovoj primeni, detekcija ciklusa u faznom prostoru orbitalnog sistema može biti iskorišćena da se odredi da li je sistem periodičan unutar preciznosti simulacije.
  • U Common Lisp, S-expression štampač, pod kontrolom *print-circle* promenljive, detektuje cirkularnu strukturu liste i štampa je kompaktno.

Reference[uredi | uredi izvor]

  1. ^ Knuth, Donald E. (1969), The Art of Computer Programming, vol. II: Seminumerical Algorithms, Addison-Wesley, str. 7,exercises 6 and 7 
  2. ^ Handbook of Applied Cryptography, by Alfred J. Menezes, Paul C. van Oorschot, Scott A. Vanstone, .com/books?id=nSzoG72E93MC&pg=PA125 pp. 125], describes this algorithm and others
  3. ^ Floyd, R.W. (1967), „Non-deterministic Algorithms”, J. ACM, 14 (4): 636—644, doi:10.1145/321420.321422 
  4. ^ The Hash Function BLAKE, by Jean-Philippe Aumasson, Willi Meier, Raphael C.-W. Phan, Luca Henzen (2015), .com/books?id=nhPmBQAAQBAJ&pg=PA21 pp. 21], footnote 8
  5. ^ a b v Brent, R. P. (1980), „An improved Monte Carlo factorization algorithm” (PDF), BIT, 20 (2): 176—184, doi:10.1007/BF01933190, Arhivirano iz originala (PDF) 24. 09. 2009. g., Pristupljeno 23. 01. 2016 
  6. ^ a b v g Nivasch, Gabriel (2004), „Cycle detection using a stack”, Information Processing Letters, 90 (3): 135—140, doi:10.1016/j.ipl.2004.01.016 
  7. ^ Schnorr, Claus P.; Lenstra, Hendrik W. (1984), „A Monte Carlo Factoring Algorithm With Linear Storage”, Mathematics of Computation, American Mathematical Society, 43 (167): 289—311, JSTOR 2007414, doi:10.2307/2007414 
  8. ^ a b Teske, Edlyn (1998), „A space-efficient algorithm for group structure computation”, Mathematics of Computation, 67 (224): 1637—1663, doi:10.1090/S0025-5718-98-00968-5 
  9. ^ Sedgewick, Robert; Szymanski, Thomas G.; Yao, Andrew C.-C. (1982), „The complexity of finding cycles in periodic functions”, SIAM Journal on Computing, 11 (2): 376—390, doi:10.1137/0211030 
  10. ^ van Oorschot, Paul C.; Wiener, Michael J. (1999), „Parallel collision search with cryptanalytic applications”, Journal of Cryptology, 12 (1): 1—28, doi:10.1007/PL00003816 
  11. ^ a b Quisquater, J.-J.; Delescaille, J.-P., „How easy is collision search? Application to DES”, Advances in Cryptology – EUROCRYPT '89, Workshop on the Theory and Application of Cryptographic Techniques, Lecture Notes in Computer Science, 434, Springer-Verlag, str. 429—434 [mrtva veza]
  12. ^ a b Fich, Faith Ellen (1981), „Lower bounds for the cycle detection problem”, Proc. 13th ACM Symp. Theory of Computation, str. 96—105, doi:10.1145/800076.802462 
  13. ^ Allender, Eric W.; Klawe, Maria M. (1985), „Improved lower bounds for the cycle detection problem”, Theoretical Computer Science, 36 (2–3): 231—237, doi:10.1016/0304-3975(85)90044-1 
  14. ^ Pollard, J. M. (1975), „A Monte Carlo method for factorization”, BIT, 15 (3): 331—334, doi:10.1007/BF01933667 
  15. ^ Pollard, J. M. (1978), „Monte Carlo methods for index computation (mod p)”, Math. Comp., American Mathematical Society, 32 (143): 918—924, JSTOR 2006496, doi:10.2307/2006496 
  16. ^ a b Kaliski, Burton S., Jr.; Rivest, Ronald L.; Sherman, Alan T. (1988), „Is the Data Encryption Standard a group? (Results of cycling experiments on DES)”, Journal of Cryptology, 1 (1): 3—36, doi:10.1007/BF00206323 
  17. ^ Van Gelder, Allen (1987), „Efficient loop detection in Prolog using the tortoise-and-hare technique”, Journal of Logic Programming, 4 (1): 23—31, doi:10.1016/0743-1066(87)90020-3 
  18. ^ Auguston, Mikhail; Hon, Miu Har (1997), „Assertions for Dynamic Shape Analysis of List Data Structures”, AADEBUG '97, Proceedings of the Third International Workshop on Automatic Debugging, Linköping Electronic Articles in Computer and Information Science, Linköping University, str. 37—42 

Spoljašnje veze[uredi | uredi izvor]