شناسایی دور
در علوم کامپیوتر تشخیص دور یا یافتن دور مسئله‌ای الگوریتمی است که به بررسی پیدا کردن یک دور (تکرار) در توالی مقادیر یک تابع می‌کند.
برای هر تابع f که یک مجموعه متناهی S را به خودش، و هر مقدار اولیه در S را، با توالی مقادیر تابع به صورت زیر نگاشت می‌کند در نهایت مجبور به دو بار استفاده کردن از یک مقدار هستیم: باید جفت اندیس‌های مجزایی وجود داشته باشد به صورت i و j به‌طوری‌که . هنگامی که این اتفاق می‌افتد، توالی باید همچنان به صورت دوره‌ای، با همان دنباله‌ای از مقادیر از تا تکرار شود. شناسایی دور مسئله پیدا کردن i و j با دانستن f و می‌باشد.
چندین الگوریتم برای پیدا کردن دور به سرعت و با استفاده از حافظه اندک شناخته شده‌است. الگوریتم «لاک‌پشت و خرگوش» فلوید، الگوریتم حرکت دو اشاره گر در توالی مقادیر تابع با دو سرعت متفاوت می‌باشد تا در نهایت هر دو اشاره‌گر به یک مقدار برابر اشاره کنند. الگوریتم «برنت» بر اساس ایده جستجوی نمایی برقرار است. هر دو الگوریتم فلوید و برنت از تعداد ثابتی از سلول‌های حافظه استفاده می‌کنند، و هم چنین تعدادی از مقایسه و ارزیابی میان مقادیر تابع که متناسب با فاصله اولین تکرار از شروع توالی می‌باشد. دیگر الگوریتم‌ها استفاده بیشتر از حافظه در مقابل مقایسه‌های کمتر را پیشنهاد می‌دهند.
شناسایی دور شامل تست کیفیت مولد اعداد شبه تصادفی و تابع درهمساز رمزنگارانه، الگوریتم های نظریه اعداد رایانشی، تشخیص حلقه بی‌نهایت در برنامه‌های کامپیوتری و پیکربندی‌های متناوب در اتوماتای سلولی،و داده ساختارهای لیست پیوندی است.
این شکل یک تابع f که مقادیر مجموعه را می‌نگارد نشان می‌دهد
را به خود. اگر یک‌نفر از شروع کند و مکرراً f را مورد اعمال قرار دهد دنباله‌ای از مقادیر زیر را مشاهده می‌کند
S را مجموعه متناهی دلخواهی فرض کنید، f تابعی دلخواه از S به خودش، و هر عنصر دلخواه از Sباشد. برای هر ، فرض می‌کنیم . فرض می‌کنیم μ کوچکترین اندیسی باشد به‌طوری‌که مقدار به‌طور بینهایت در دنباله مقادیر ظاهر شود، و فرض می‌کنیم λ (طول دور) باشد کوچکترین عدد صحیح مثبت باشد به‌طوری‌که . تشخیص دور مسئله یافتن λ و μ می‌باشد.
همین مسئله را در نظریه گراف،با ساخت یک گراف تابع (که یک گراف جهت دار خوانده می‌شودد که در آن هر راس دارای یک یال خارج شونده است) که رئوس آن عناصر S و یال‌های آن یک عنصر را به مقدار تابع مربوط به آن نگاشت می‌کنند، همان‌طور که در شکل نشان داده شده‌است. مجموعه رئوس قابل دسترسی با شروع از راس از یک زیر گراف با یک شکل شبیه رو (ρ): یک مسیر با طول μ از به یک دور با λ راس.
به‌طور کلی، f را نمی‌توان به صورت جدولی از مقادیر، طوری‌که در شکل بالا نشان داده شده نمایش داد. بلکه، یک الگوریتم تشخیص دور ممکن است یا با دنباله مقادیر ، یا یک تابع برای محاسبه f داده شود. هدف پیدا کردن λ و μ با بررسی چند مقدار از دنباله یا پیدا کردن مقدار تابع در چند مرتبه با کمترین استفاده از سلول‌های حافظه می‌باشد. به‌طور معمول، پیچیدگی فضا در مسئله تشخیص دور اهمیت دارد: ما مایل به حل این مسئله با استفاده ماز مقداری از حافظه هستیم که کمتر از حافظه مورد نیاز برای ذخیره کل دنباله اعداد می‌باشد.
در برخی از برنامه‌ها، و به ویژه در الگوریتم رو پولارد برای تجزیه اعداد طبیعی،الگوریتم دسترسی محدودتری به S و f دارد. در الگوریتم پولارد، به عنوان مثال، S مجموعه‌ای از اعداد صحیح می‌باشد که عامل اول عدد مورد تجزیه به آن بخشپذیر است، بنابراین حتی اندازه S هم نامعلوم است. برای اینکه تشخیص دور با چنین اطلاعات محدودی قابل استفاده باشد، باید براساس توانایی‌های زیر بنا شوند. در ابتدا فرض می‌شود الگوریتم حافظه مخصوص به خود را دارد که یک نشانگر به مقدار شروع یعنی دارد. در هر مرحله ممکن است یکی از سه عمل زیر را انجام دهد: ممکن است هر نشانگری را به شئ دیگری کپی کند، ممکن است f را اعمال کند و هرکدام از نشانگرهایش را با یک نشانگر به شئ بعدی جایگزین کند یا ممکن است با اجرای یک تابع تشخیص دهد که دو نشانگر به یک مقدار برابر در دنباله اشاره دارند یا نه. آزمون برابری می‌تواند بعضی از محاسبات غیربدیهی دربرداشته باشد: برای مثال، در الگوریتم پولارد رو، این عملیات این‌گونه پیاده می‌شود که آیا اختلاف بین دو مقدار ذخیره شده بزرگترین مقسوم علیه مشترک بغیر بدیهی با عدد مورد تجزیه دارد یا خیر. در این زمینه، با قیاس با مدل محاسباتی ماشین اشاره گر، یک الگوریتم که تنها از کپی کردن یک اشاره گر، پیشروی در دنباله، و آزمون‌های برابری استفاده می‌کند، الگوریتم اشاره‌گری نامیده می‌شود. اگر ورودی به عنوان یک رابطه برای محاسبه f داده شده باشد، مسئله تشخیص چرخه ممکن است به‌طور بدیهی با تنها اجرای تابع حل شود، به سادگی با محاسبه دنباله‌ای از مقادیر و با استفاده از یک ساختار دادهمانند یک جدول درهم ساز برای ذخیره این مقادیر و تست اینکه آیا هر مقدار در حال حاضر ذخیره شده‌است یا خیر. اما پیچیدگی فضایی این الگوریتم متناسب با ، به‌طور بی‌ارزشی بزرگ است. علاوه بر این برای اجرای این روش به عنوان یک الگوریتم اشاره‌گر، نیاز به استفاده از آزمون برابری برای هر جفت از مقادیر و در نتیجه به زمان از مرتبه دو می‌انجامد؛ بنابراین تحقیقات در این زمینه بر روی دو هدف متمرکز شده: استفاده از فضای کمتر از این الگوریتم ساده، و پیدا کردن الگوریتم‌های اشاره‌گری که با استفاده از آزمون برابری کمتر.
الگوریتم یافتن دور فلوید الگوریتمی است که از دو اشاره‌گر استفاده می‌کند، که با سرعت‌های متفاوت در دنباله حرکت می‌کنند. همچنین به نام «الگوریتم لاک‌پشت و خرگوش» نامیده می‌شود با اشاره به حکایت لاک‌پشت و خرگوش از ازوپ.
الگوریتم پس از نام رابرت فلوید با اعتبار اختراع آن توسط دانلد کنوت نام‌گذاری شد. با این حال به نظر نمی‌رسد این الگوریتم در کارهای منتشر شده از فلوید باشد، و این ممکن است یک سوءتفاهم باشد: فلوید توصیف الگوریتم را با لیست کردن تمامی دورها در یک گراف جهت دار سال ۱۹۶۷ سال در یک مقاله انجام داد، اما این مقاله مسئله یافتن دور در یک گراف تابعی که موضوع این مقاله است را شرح نداد. در واقع بیانیه کنوت (در سال ۱۹۶۹)، و نسبت دادن آن به فلوید، بدون استناد، اولین ظهور آن به‌طور چاپی است و آن را در نتیجه ممکن است یک قضیه منتسب به یک فرد است.
نکته اصلی در درک این الگوریتم این است که، برای هر عدد صحیح و داریم که در آن λ طول حلقه یافت شده و μ اندیس اولین عنصر چرخه است. به‌طور خاص، اگر و تنها اگر . این الگوریتم تنها نیاز به بررسی مقادیر تکراری این فرم خاص، تا آنجا که یکی از مقادیر پس از شروع دنباله تکرار شود، برای یافتن دوره تناوبv برای تکرار که مضربی از λ می‌باشد. به محض اینکه v یافت شد، الگوریتم دنباله را دوباره از آغاز بررسی می‌کند تا اولین مقدار تکراری ، با توجه به این مسئله کهv بر λ بخشپزیر است به همین دلیل . سرانجام پس از یافتن مقدار μ به‌طور بدیهی به دنبال طول λ می‌گردیم که کوچکترین طول دور می‌باشد، با یافتن اولین مکان که در آن .
این الگوریتم در نتیجه دو اشاره گر را در طول دنباله داده شده حفظ می‌کند، یکی (لاک‌پشت) در و دیگری (خرگوش) در . در هر مرحله از الگوریتم،i را با حرکت لاک‌پشت یک گام به جلو یک واحد افزایش می‌دهد و خرگوش دو گام به جلو در دنباله، و سپس مقدار دنباله در این دو اشاره گر را مقایسه می‌کند. کوچکترین مقدار که در آن نقطه مقدار لاک‌پشت و خرگوش برابر است که مقدار ν مورد نظر ماست.
کد پایتون زیر این ایده به عنوان یک الگوریتم پیاده‌سازی می‌شود: def floyd(f, x0):
این کد تنها به دنباله با ذخیره‌سازی و کپی کردن اشاره گرها، مقداریابی تابع و آزمون برابری دسترسی دارد؛ بنابراین، آن را به عنوان یک الگوریتم اشاره‌گری می‌نامیم. این الگوریتم از عملیات از این نوع و فضای ذخیره‌سازی استفاده می‌کند.
ریچارد پیرس برنت یک الگوریتم یافتن دور جایگزین را توصیف می‌کند، که همانند الگوریتم لاک‌پشت و خرگوش تنها نیاز به دو اشاره گر در دنباله دارد. با این حال، بر اساس اصل مختلف دیگری بنا شده‌است: جستجو برای کوچکترین توان دو که بزرگتر از هر دو λ و μ باشد. برای ، الگوریتم را با هر یک از مقادیر پس از آن دنباله مقایسه می‌کند، و هر گاه عدد مورد نظر را یافت متوقف می‌شود. این الگوریتم نسبت به الگوریتم لاک‌پشت و خرگوش دو مزیت دارد: مقدار صحیح λ برای دور را به‌طور مستقیم می‌یابد به جای اینکه نیاز به جستجو برای آن در مرحله بعدی داشته باشد، و مراحل آن شامل تنها یک مقداریابی از f می‌باشد.
کد پایتون زیر با جزییات نشان می‌دهد این تکنیک چگونه کار می‌کند.
def brent(f, x0):
مانند الگوریتم لاک‌پشت و خرگوش، این یک الگوریتم اشاره‌گری است که از تست و مقدار یابی تابع و فضای ذخیره‌سازی استفاده می‌کند.
سخت نیست که نشان دهیم تعداد مقداریابی‌های تابع نسبت به الگوریتم فلوید هیچگاه بیشتر نمی‌شود. برنت ادعا می‌کند که به‌طور متوسط الگوریتم یافتن دور او حدود ۳۶ درصد سریعتر از الگوریتم فلوید می‌باشد و الگوریتم پولارد رو را تا حدود ۲۴٪ تسربع می‌کند. او همچنین یک آنالیز حالت متوسط برای یک نسخه تصادفی الگوریتم اجرا کرد که در آن دنباله‌ای از شاخض‌های دنبال شده خود توانی از ۲ نبودند اما یک مضربی از توان دو به صورت تصادفی بودند. اگرچه برنامه اصلی او در رابطه با تجزیه عوامل اول اعداد صحیح بود، برنت همچنین در رابطه با برنامه تست کردن اعداد شبه تصادفی نیز بحث کرد.
الگوریتم گسپر دوره تناوب را می‌یابد اما نقطه شروع اولین پریود را مشخص نمی‌کند. از ویژگی‌های اصلی آن است که هیچ‌گاه برای مقداریابی تابع مولد بر نمی‌گردد که این عمل از نظر زمانی و حافظه بهینه است.
برخی از نویسندگان روش‌هایی را مورد بررسی قرار داده‌اند که نسبت به الگوریتم فلوید و برنت حافظهٔ بیشتری نیاز دارد اما دور را سریعتر شناسایی می‌کند. به‌طور کلی این روش‌ها دنباله‌ای از مقادیر از پیش محاسبه‌شده را ذخیره می‌کنند، و بررسی می‌کنند که آیا مقادیر جدید ما مقادیر قبلاً محاسبه شده برابرند یا خیر. به منظور انجام سریع آن‌ها، به‌طور معمول از یک جدول درهم‌سازی یا یک داده ساختار مشابه برای ذخیره مقادیر از قبل محاسبه شده‌استفاده می‌شود، و در نهایت هیچ الگوریتم اشاره‌گری در کار نیست: به‌طور خاص آن‌ها قابل پیاده شدن به روی الگوریتم پولارد نیستند. تفاوتی که این الگوریتم‌ها دارند در این است که کدام مقادیر برای ذخیره شدن انتخاب شوند. ما به بررسی این روش‌ها به‌طور خلاصه می‌پردازیم: هر الگوریتم شناسایی دور که اقدام به ذخیره M مقدار از دنباله ورودی در حافظه می‌کند، حداقل نیاز به اجرای formula_3 مقداریابی تابع دارد.
شناسایی دور در بسیاری از برنامه‌ها استفاده شده‌است.