Właśnie gdy miałem zasugerować algorytm wykrywania cyklu Floyda, post Rici mnie pobił. Jednak całość można uczynić bardziej praktyczną poprzez przyspieszenie porównań pełnych stanów.
Wąskim gardłem proponowanego algorytmu byłoby porównywanie stanu pełnego. Te porównania zwykle się nie kończą, ale kończą wcześnie - przy pierwszej różnicy. Jedną z optymalizacji jest zapamiętanie, gdzie wystąpiły różnice w przeszłości i sprawdzenie najpierw tych części stanu. Na przykład prowadź listę lokalizacji i przejrzyj ją przed wykonaniem pełnego porównania. Gdy lokalizacja z tej listy ujawnia różnicę, zatrzymaj porównanie (z błędem) i przenieś lokalizację na początek listy.
Innym (i potencjalnie bardziej skalowalnym) podejściem jest stosowanie przyrostowego mieszania. Wybierz funkcję pełnego stanu, aby wartości skrótu były łatwe do dostosowania w O (1), gdy zmieni się jakaś część stanu. Na przykład weź ważoną sumę słów stanu mod jakąś dużą liczbę pierwszą i połącz z nieważoną sumą mod inną dużą dużą liczbą pierwszą (możesz również wrzucić modułową sumę ważoną kwadratów słów o różnej wadze i module). W ten sposób aktualizacje skrótów zajmą czas O (1) na każdym etapie wykonania, a porównania potrwają czas O (1), aż do uzyskania trafienia. Prawdopodobieństwo fałszywie dodatniego (tzn. Skrótu dopasowania, podczas gdy stany się różnią) jest bardzo niskie, a nawet jeśli tak się stanie, amortyzuje się w stosunku do dużej liczby prawdziwych negatywów (fałszywe negatywy są niemożliwe).
Oczywiście w praktyce wydaje się, że bardziej prawdopodobne jest popadnięcie w takie sytuacje, jak generowanie cyfr liczby pi --- rzeczy ciągle się zmieniają, ale nigdy się nie kończą. Inną częstą możliwością jest to, że nieskończona pętla przydziela pamięć, w którym to przypadku szybko wyczerpuje całą dostępną pamięć.
W moim kursie na temat algorytmów i struktur danych nasz autograder musi zajmować się zgłoszeniami uczniów, które czasami wpadają w nieskończone pętle. Zajmuje się tym 30-sekundowy limit czasu i pewien limit pamięci. Oba są znacznie luźniejsze niż budżety czasu wykonywania i pamięci, które nakładamy w ramach oceniania. Nie jestem pewien, czy wdrożenie prawdziwego wykrywania pętli nieskończonej miałoby sens w tym kontekście, ponieważ takie programy będą działały nieco wolniej (w tym przypadku pomocna może być sprzętowa obsługa haszowania stanu, ale ponownie potrzebne będą dodatkowe zastosowania, aby uzasadnij to). Kiedy uczniowie wiedzą, że upłynął limit czasu ich programu, zwykle mogą znaleźć nieskończoną pętlę.