Так же, как я собирался предложить алгоритм определения цикла Флойда, пост Ричи побил меня до этого. Тем не менее, все это можно сделать более практичным путем ускорения сравнения полных состояний.
Узким местом предлагаемого алгоритма было бы сравнение полного состояния. Эти сравнения обычно не заканчиваются, а заканчиваются рано - при первом различии. Одна оптимизация заключается в том, чтобы вспомнить, где произошли прошлые различия, и сначала проверить эти части состояния. Например, ведите список местоположений и просмотрите этот список, прежде чем проводить полное сравнение. Когда местоположение из этого списка показывает разницу, остановите сравнение (с ошибкой) и переместите местоположение в начало списка.
Другой (и потенциально более масштабируемый) подход заключается в использовании добавочного хеширования. Выберите функцию полного состояния так, чтобы значения хеш-функции легко настраивались в O (1) при изменении какой-либо части состояния. Например, возьмите взвешенную сумму слов состояния mod для некоторого большого простого числа и объедините с невзвешенной суммой mod для некоторого другого большого простого числа (можно также добавить модульную взвешенную сумму квадратов слов с различным весом и модулем). Таким образом, обновления хеша будут занимать O (1) времени на каждом шаге выполнения, а сравнение будет занимать O (1) времени, пока вы не получите попадание. Вероятность ложного положительного результата (т. Е. Совпадения хэшей, в то время как состояния различаются) очень мала, и даже если это когда-либо произойдет, амортизируется большое количество истинных отрицаний (ложные отрицания невозможны).
Конечно, на практике кажется более вероятным попасть в такие ситуации, как генерация цифр числа pi - вещи продолжают изменяться, но никогда не заканчиваются. Другая частая возможность состоит в том, что бесконечный цикл выделяет память, и в этом случае он быстро исчерпывает всю доступную память.
В моем курсе по алгоритмам и структурам данных наш автогрейдер должен иметь дело с представлениями студентов, которые иногда попадают в бесконечные циклы. Это обеспечивается 30-секундным тайм-аутом и определенным ограничением памяти. И то, и другое намного слабее, чем бюджеты времени выполнения и памяти, которые мы накладываем как часть оценки. Я не уверен, что реализация истинного обнаружения бесконечного цикла будет иметь большой смысл в этом контексте, потому что такие программы будут работать немного медленнее (именно здесь может помочь аппаратная поддержка хеширования состояний, но опять же вам потребуются дополнительные применения для оправдать это). Когда студенты знают, что их программа истекла, они обычно могут найти бесконечный цикл.