Детекција циклуса

С Википедије, слободне енциклопедије

У рачунарској науци, детекција циклуса је алгоритамски проблем проналажења циклуса у секвенци итеративних вредности функције.

За било коју функцију ƒ која мапира коначни скуп S за себе, и било која иницијална вредност x0 у S, секвенца итеративних вредности функције

мора на крају да искористи исту вредност два пута: мора бити неко ij такво да xi = xj. Једном када се то догоди, секвенца мора периодично да се настави, понављајући исте вредности од xi до xj−1. Детекција циклуса је проблем проналажења i и j, за дато ƒ и x0.

Пример[уреди | уреди извор]

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

Фигура показује функцију ƒ која мапира сет S = {0,1,2,3,4,5,6,7,8} за себе. ако нека креће од x0 = 2 и у више наврата примењује ƒ, она види секвенцу вредности

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

Циклус у је у овом случају 6, 3, 1.

Дефиниције[уреди | уреди извор]

Нека S буде било који коначни скуп, ƒ било која функција од S за себе, и x0 било који елемент S. За свако i > 0, нека је xi = ƒ(xi−1). Нека је μ најмањи индекс такав да се вредност xμ поновно појављује бесконачно често унутар секвенце вредности xi, и нека је λ (дужина циклуса) најмањи позитивни цео број такав да xμ = xλ+μ. Проблем детекције циклуса је задатак тражења λ и μ.

Исти проблем можемо гледати из угла теорије графова, конструишући функционални граф (што значи, усмерени граф у којем свако теме има једну одлазну ивицу) чија темена су елементи од S и ивице које пресликавају елемент на одговарајућу вредност функције, као што је приказано. Скуп темена достижних од било којег стартног темена x0 из подграфа облика који личи на грчко слово ро(ρ): пут дужине μ од x0 у циклусу од λ темена.

Рачунарска репрезентација[уреди | уреди извор]

Генерално, ƒ неће бити специфицирано као списак вредности, као што је дато изнад. Него, или нам је дат приступ секвенци вредности xi, или подрутини за рачунање ƒ. Задатак је да се пронађеλ и μ проверавајући што мање вредности из секвенце или извођењем што је могуће мање подрутинских позива. Типично, такође, временска комплексност алгоритма за проблем детекције циклуса није важна: желимо да решимо проблем док користимо меморију знатно мању него што је потребно да се смести цела секвенца.

У неким применама, и у Pollard's rho алгоритму за факторизацију целих бројева, алгоритам има много више ограниченог приступа S и ƒ. У Pollard's rho алгоритму, на пример, S је сет целих бројева модулованих са непознатим простим фактором да би се број факторизовао, тако чак и величина S је непозната алгоритму.

Можемо гледати на алгоритам за детекцију циклуса у овој примени као имање следећих могућности: он иницијално има у својој меморији објекат који репрезентује показивач на почетну вредност x0. У било ком кораку, може извести три акције: може да копира било који показивач који има на други објекат у меморији, може да примени ƒ и замени било који од својих показивача са показивачем на следећи објекат у секвенци, или може да примени подрутину за одређивање да ли два његова показивача представљају исте вредности у секвенци. Акција тестирања једнакости може да укључује неке нетривијалне компутације: у Pollard's rho алгоритму, је то имплементирано тестирањем да ли разлика између две убачене вредности има нетривијални gcd са бројем са којим треба да се факторише. У овом контексту, позваћемо алгоритам који користи само копирање показивача, напредак унутар секвенце, и тестове једнакости с показивачким алгоритмом.

Алгоритми[уреди | уреди извор]

Ако је улаз дат као подрутина за израчунавање ƒ, проблем детекције циклуса може бити тривијално решен коришћењем само λ+μ у функцији, једноставно рачунањем секвенце вредности xi и коришћењем структуре података као што је хеш мапа да се чувају ове вредности и тестира да ли је свака следећа вредност већ сачувана. Међутим, просторна комплексност овог алгоритма је λ+μ, непотребно велика. Додатно, да би се имплементирала ова метода као показивачки алгоритам било би потребно да се примени тест једнакости за сваки пар вредности, резултујући укупном квадратном времену. Тако, истраживање у овој области се концентрисало на два циља: коришћење мање простора него што користи овај наивни алгоритам, и проналажење показивачких алгоритама који користе мање тестова једнакости.

Корњача и зец[уреди | уреди извор]

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

Флојдов алгоритам за проналажење циклуса, такође познат као "алгоритам корњача и зец", алудирајући на Езопову басну о корњачи и зецу, је показивачки алгоритам који користи два показивача, који се померају кроз секвенцу различитим брзинама.

Алгоритам је назван по Robert W. Floyd, који је награђен за свој изум од стране Donald Knuth.[1][2] Међутим, алгоритам се не појављује у Флојдовом објављеном раду, и ово може бити мисатрибуција: Флојд описује алгоритме за слагање свих једноставних циклуса у усмереном графу у објави 1967 године,[3] али ова објава не описује проблем проналажења циклуса у функционалним графовима који су предмет овог чланка. Заправо, Кунтова изјава (у 1969), приписујући је Флојду, без цитата, је прво познато појављивање у штампи, и ово може заправо бити фолкова теорема, неприписива на једног  индивидуалца.[4]

Кључни увид у алгоритам је то да за било којицео број i ≥ μ и k ≥ 0, xi = xi + kλ, где λ је дужина пронађеног циклуса и μ је индекс првог елемента у циклусу. Нарочито, кад год i = kλ ≥ μ, следи да је xi = x2i. Тако, алгоритам треба само да провери понављајуће вредности специјалне форме, једне дупло даље од почетка секвенце него друга, да би пронашли период ν понављања које се множи са λ. Када се ν пронађе, алгоритам се враћа на почетак секвенце да би пронашао своју прву понављајућу вредност  xμ у секвенци, користећи чињеницу да λ дели ν и премда је xμ = xμ + v. Коначно, једном када је вредност μ позната тривијално је пронћи дужину λ најкраћег понављајућег циклуса, проналажењем прве позиције μ + λ за коју је xμ + λ = xμ.

Тако алгоритам одржава два показивача у датој секвенци, једног (корњачу) на xi, и други (зеца) на x2i. На сваком кораку алгориитма, он повећава i за један, померајући корњачу један корак унапред и зеца два корака унапред у секвенци, и онда упоређује вредности секвенце на које показују ова два показивача. Најмања вредност i > 0 за коју и корњача и зец показују исту вредност је жељена вредност ν.

Следећи Python код показује како ова идеја може бити имплементирана као алгоритам.

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

Овај код приступа секвенци само чувајући и копирајући показиваче, евалуациије функције, и тестове једнакости; премда, квалификује се као показивачки алгоритам. Алгоритам користи O(λ + μ) операција ових типова, и O(1) места за чување.

Брентов алгоритам[уреди | уреди извор]

Richard P. Brent је описао алтернативни алгоритам за детекцију циклуса, који као корњача и зец алгоритам, захтева само два показивача у секвенци.[5] Међутим, заснован је на друачијем принципу: тражењем најмањег квадрата 2i који је већи од λ и μ. За i = 0, 1, 2, итд., алгоритам упоређује x2i−1 са сваком следећом вредношћу секвенце до следећег квадрата, стајући када пронађе подударање. Има две предности у односу на алгоритам корњаче и зеца: проналази тачну дужину λ циклуса директно, пре него да треба да га пронађе у наредној фази, и његови кораци укључују само једну евалуацију ƒ пре него три.

Следећи Python код показује како ова техника ради детаљније.

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

Као алгоритам корњача и зец, ово је показивачки алгоритам који користи O(λ + μ) тестова и евалуација функције и O(1) меморије. Није тешко показати да број евалуација функције никада не може да буде већи од Флојдовог алгоритма. Брент тврди да, у просеку, његов алгоритам за проналажење циклуса ради око 36% брже него Флојдов и да убрзава Pollard rho алгоритам за око 24%. Он такође изводи анализу просечног случаја за насумичну верзију алгоритма у којој секвенца индекса праћена од стране споријег од два показивача није квадрат њих двоје, него насумичан садржалац квадрата. Иако је његова главна намеравајућа апликација била у алгоритмима за факторизацију целих бројева, Брент такође дискутује примене у тестирању псеудонасумичних генератора бројева.

Време-простор размене[уреди | уреди извор]

Мноштво аутора су проучавали технике детекције циклуса за детекцију циклуса која користи мање меморије од Флојдовог и Брентовог алгоритма, али да детектују циклус брже. Генерално ове методе чувају неколико претходно израчунатих вредности секвенце, и тестирају да ли је свака нова вредност једнака некој од претходно израчунатих вредности. Да би радили тако брзо, често користе хеш табелеили сличне структуре података за складиштење претходно израчунатих вредности, и премда нису показивачки алгоритми: нарочито, они обично не могу да буду примењени у Pollard's rho алгоритму. Где се ове методе разликују је то како одлучују коју вредност да чувају. Пратећи Nivasch,[6] прегледали смо укратко ове технике.

  • Брент[5] већ описује варијације своје технике у којима се индекси запамћене секвенце где су вредности квадрати броја R различитог од два. Бирајући R да буде број близу јединице, и чувајући вредности секвенце на тим индексима који су близу секвенце узастопних квадрата од R, алгоритам за детекцију циклуса може да користи број евалуација функције које су у арбитрарно малом фактору оптимума λ+μ.[7][8]
  • Sedgewick, Szymanski, и Yao[9] су допринели метод који користи M меморијских ћелија и захтева у најгорем случају само  евалуација функције, за неку константу c, за коју они показују да је оптимална. Техника укључује задржавање нумеричког параметра  d, чувајући у табели само оне позиције у секвенци које су множиоци d, и чишћењем табеле и удвостручавањем d  кад год је превише вредности сачувано.
  • Неколико аутора су описали истакнуте показивачке методе које чувају вредности функције у табели засновано на критеријуму укључујући вредности, пре него (као што је метод Sedgewick et al.) засновано на њиховим позицијама. На пример, вредности једнаке нули по моду неке вредности d могу бити сачуване.[10][11] Једноставније, Nivasch[6] похваљује D. P. Woodruff са сугестијом чувања насумичног примерка претходно виђених вредности, стварајући одговарајући насумични избор на сваком кораку тако да узорак остаје насумичан.
  • Nivasch[6] описује алгоритам који не користи фиксирану количину меморије, али за који је очекивана количина меморије искоришћена (под претпоставком да је улазна функциа насумична) је логаритамска у дужини секвенце. Предмет сачуван у меморијској табели, са овом техником, када ниједан каснији предмет нема мању вредност. Како Nivasch показује, предмети овом техником могу бити одржавани коришћењем стек структуре података, и свака следећа вредност секвенце треба да се упореди са врхом стека. Алгоритам се завршава када се пронађе поновљен елемент секвенце са најмањом вредности. Користећи исти алгоритам са више стекова, користећи насумичне пермутације вредности да би се преместиле вредности у стеку, дозвољава време-простор размену сличну претходним алгоритмима. Међутим, чак и верзије алгоритма са једним стеком није поинтерски алгоритам, због поређења потребног да се одреди која од две вредности је мања.

Било који алгоритам за детекцију циклуса кои чува највише M вредности од улазне секвенце мора да изврши бар евалуација функције.[12][13]

Примене[уреди | уреди извор]

Детекција циклуса се користи у пуно примена.

  • Одређивање дужине циклуса псеудонасумичног генератора бројева је једна мера његове снаге. Ово је примена цитирана од стране Кунта описујући Флојдов метод. Брент[5] описује резултате тестирања  линеарног конгруенцијског генератора у овом погледу; испоставило се да је његов период знатно мањи него што се причало. За комплексније генераторе, секвенца вредности у којој пронађени циклус не мора да репрезентује излаз  генератора, него његово унутрашње стање.
  • Неколико бројно теоретских алгоритама се заснива на детекцији циклуса, укључујући Pollard's rho алгоритам за факторизацију целих бројева[14] и повезан је са кенгур алгоритмом за проблем дискретног логаритма.[15]
  • У криптографијским применама, могућност да се пронађу две сличне вредности xμ−-1 и xλ+μ−-1 пресликаниих уз помоћ неке криптографске функције ƒ за исту вредност xμ може да индикује слабост у ƒ. На пример, Quisquater и Delescaille[11] примењују алгоритме за детекцију циклуса у потрази за поруком и паром Data Encryption Standard кључева који мапирају ту поруку на исту енкриптовану вредност; Kaliski, Rivest, и Sherman[16] такође користе алгоритме за детекцију циклуса да нападну DES. Техника такође може бити искоришћена да се пронађе судар у криптографској хеш функцији.
  • Детекција циклуса може бити од помоћи као начин откривања бесконачних петљи у одређеним типовима рачунарских програма.[17]
  • Периодичне конфигурације у симулирању целуларне аутоматизације могу бити пронађене применом алгоритама за детекцију циклуса на секвенци аутоматонских стања.[6]
  • Анализа облика структуре података повезаних листа је техника за верификовање исправности алгоритма коришћењем ових структура. Ако чвор у листи неправилно показује на претходни чвор у истој листи, структура ће формирати циклус кои може бити детектован од стране ових алгоритама.[18]
  • Teske[8] описује примене у теорији рачунања група: проверавајући структуру Абелове групе из сета његових генератора. Криптографски алгоритми Kaliski et al.[16] могу такође бити посматрани као покушавање  да се закључи структура непознате групе.
  • Fich[12] укратко помиње примену у рачунарској симулацији целестијалне механике, коју она приписује William Kahan. У овој примени, детекција циклуса у фазном простору орбиталног система може бити искоришћена да се одреди да ли је систем периодичан унутар прецизности симулације.
  • У Common Lisp, S-expression штампач, под контролом *print-circle* променљиве, детектује циркуларну структуру листе и штампа је компактно.

Референце[уреди | уреди извор]

  1. ^ Knuth, Donald E. (1969), The Art of Computer Programming, vol. II: Seminumerical Algorithms, Addison-Wesley, стр. 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. ^ а б в Brent, R. P. (1980), „An improved Monte Carlo factorization algorithm” (PDF), BIT, 20 (2): 176—184, doi:10.1007/BF01933190, Архивирано из оригинала (PDF) 24. 09. 2009. г., Приступљено 23. 01. 2016 
  6. ^ а б в г 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. ^ а б 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. ^ а б 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, стр. 429—434 [мртва веза]
  12. ^ а б Fich, Faith Ellen (1981), „Lower bounds for the cycle detection problem”, Proc. 13th ACM Symp. Theory of Computation, стр. 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. ^ а б 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, стр. 37—42 

Спољашње везе[уреди | уреди извор]