الگوریتم تقسیم و حل
|
|
پیشنهاد شده است که روش تقسیم و حل با این مقاله یا بخش ادغام گردد. (بحث) |
در علوم کامپیوتر, الگوریتم تقسیم و حل (چیرگی) (Divide and conquer/D&C) الگو ی طراحیِ الگوریتمِ مهمی بر اساس بازگشت چندانشعابی میباشد. یک الگوریتم تقسیم و حل از طریق تفکیک یک مسئله به دو یا چند زیرمسئله از یک نوع (یا انواع وابسته به هم)، به صورت بازگشتی، کار میکند. این تفکیک تا زمانی ادامه مییابد که زیرمسئلههای حاصله به میزان کافی ساده شده باشند تا بتوان آنها را مستقیماً حل کرد. جواب مسئلهٔ اصلی از ترکیب جوابهای به دست آمده برای زیر مسئلهها به دست میآید.
این تکنیک مبنای الگوریتمهای کارآمدی برای انواع مسئلهها میباشد، به عنوان مثال، مرتبسازی (مثلاً، مرتبسازی سریع و مرتبسازی ادغامی), ضرب اعداد بزرگ (مثلاً، کاراتسوبا), تحلیل ترکیبی (مثلاً، تجزیهکنندههای بالا به پایین)، و محاسبهٔ تبدیل گسستهٔ فوریر (FFTها).
از سوی دیگر، توانایی درک و طراحیِ الگوریتمهای D&C هنری است که کسب مهارت در آن زمان زیادی میطلبد. به هنگام اثبات یک قضیه به کمک استقرا، غالباً نیازمند آنیم که به منظور دستیابی به یک روند بازگشتی، مسئلهٔ اصلی را با یک مسئلهٔ عمومیتر یا پیچیدهتر جایگزین کنیم، و این در حالی است که روش سیستماتیکی برای یافتن تعمیم مناسب وجود ندارد.
گاهی اوقات نام «تقسیم و حل» در مورد الگوریتمهایی که هر مسئله را تنها به یک زیرمسئله تقلیل میدهند نیز به کار میرود، مانند الگوریتم جستجوی دودویی برای یافتن یک پرونده در یک لیست مرتب شده(و یا شبیه آن در الگوریتمهای عددی و محاسباتی؛ الگوریتم دوبخشی برای یافتن ریشه) [۱]. با وجود این تعریف جامع، هر الگوریتمی که از بازگشت و یا حلقه استفاده میکند، از بعضی لحاظ میتواند به عنوان «الگوریتم تقسیم و حل» تلقی شود. از این رو، بعضی از مؤلفان درعوض از نام «کاهش و حل» استفاده میکنند.[۲]. این الگوریتمها میتوانند کارآمدتر از الگوریتمهای تقسیم و حل معمولی، پیادهسازی شوند. به عنوان مثال، در صورت استفاده از بازگشت دنبالهدار، این الگوریتمها میتوانند به حلقههای ساده تبدیل شوند.
معمولاً صحت یک الگوریتم تقسیم و حل، به کمک استقرای ریاضی، اثبات میشود، و هزینهٔ محاسباتی آن نیز معمولاً از طریق حل روابط بازگشتی تعیین میشود.
محتویات |
[ویرایش] مثالهای قدیمی
جستجوی دودویی، الگوریتم تقسیم و حلی که در آن مسئلهٔ اصلی متوالیاً به زیرمسئلههایی یکتا با اندازهٔ تقریبی نصف مسئلهٔ اصلی تفکیک میشود، بیشینهٔ دور و درازی دارد. ایدهٔ استفاده از یک لیست مرتب شده از عناصر به منظور سهولت بخشیدن در جستجو به ۲۰۰ سال پیش از میلاد ,[۳] در بابل باز میگردد، حال آنکه یک توصیف واضح از الگوریتم در کامپیوترها اولین بار در سال ۱۹۴۶ در مقالهای توسط جان مارچلی بیان شد.[۳] الگوریتم تقسیم و حلِ دیگر، با یک زیرمسئلهٔ منحصربهفرد، الگوریتم اقلیدس در محاسبهٔ بزرگترین مقسومعلیه مشترک دو عدد (از طریق کاهش اعداد به زیرمسئلههای کوچکتر، و کوچکتر یا مساوی) میباشد، که به قرنها پیش از میلاد باز میگردد. یک مثال قدیمی از الگوریتم تقسیم و حل با زیرمسئلههای چندگانه، توصیفی بود که گاوس در سال ۱۸۰۵ از چیزی که امروزه الگوریتم Cooley-Tukey fast Fourier transform یا FFT نامیده میشود,[۴] ارایه داد؛ اگرچه او از لحاظ کمّی، شمار عملیات این الگوریتم را تحلیل و بررسی نکرد، و FFTها شایع نشدند مگر یک قرن بعد که مجدداً کشف گردیدند.
یک الگوریتم تقسیم و حلِ دوزیرمسئلهایِ قدیمی که به طور ویژه برای کامپیوترها توسعه یافته، الگوریتم مرتبسازی ادغامی میباشد که توسط جان فون نویمن در سال ۱۹۵۴ ابداع گردید.[۵]
مثال قابل توجه دیگر، الگوریتمای است که توسط کاراتسوبا در سال۱۹۶۰ ابداع گردیده [۶] و میتواند دو عدد nرقمی را با
عمل ضرب کند. این الگوریتم، حدس اندری کولماگوراف 'که در سال 1956 بیان شد و
عمل را برای انجام ضرب مذکور لازم میدانست را رد کرد. به عنوان مثال دیگری از یک الگوریتم تقسیم و حل که در ابتدا کامپیوترها را شامل نمیشد، «ناث» متدی را ارائه داد که به طور نمونه در یک دفتر پست به منظور آدرسدهی نامهها استفاده میشود: نامهها در کیفهای جداگانه برای مناطق مختلف جغرافیایی مرتب میشوند، در هر کدام از این کیفها نیز، نامهها در دستههایی مربوط به نواحی کوچکتر مرتب شدهاند، و به همین ترتیب، تا زمانی که نامهها به مقصد برسند. [۳] این الگوریتم به یک مرتبسازی رقمی، وابستهاست، که در سال ۱۹۲۹ برای ماشینهای مرتبسازی کارت پانچ ارایه شد.[۳]
[ویرایش] مزایا
[ویرایش] حل مسائل دشوار
تقسیم و حل ابزاری است قدرتمند برای حل مسائل دشوار مفهومی، همانند معمای باستانی برجهای هانوی: همهٔ چیزی که حل این مسئله نیاز دارد، پیدا کردن راهی است برای شکستن مسئله به چند زیرمسئله، حل حالات جزیی و ترکیب زیرمسئلهها به مسئلهٔ اصلی.
[ویرایش] کارآیی الگوریتم
الگوی تقسیم و حل، اغلب به یافتن الگوریتمهای کارآمد کمک مینماید. برای مثال، این الگوریتم، راهگشای روشهای ضرب سریع کاراتسوبا، الگوریتمهای مرتبسازی سریع و ادغام، و همچنین تبدیلهای سریع فوریر بود.
در تمام این مثالها، راهبردِ D&C منجر به بهینهسازی هزینهٔ مجانبی راه حل میشود. به عنوان مثال، اگر حالتهای پایه، اندازهٔ ثابت کرانداری داشتهباشند، عمل تفکیک مسئله و ترکیب جوابهای جزیی به نسبت اندازهٔ مسئلهn، بوده، و یک تعداد محدود p از زیرمسئلهها با اندازهٔ n/p~ در هر مرحله وجود دارد، و آنگاه هزینهٔ الگوریتم تقسیم و حل( O(n log n خواهد بود.
[ویرایش] تطابق
الگوریتمهای تقسیم و حل ذاتاً برای اجرا در ماشینهای چندپردازندهای سازگار شدهاند، به ویژه سیستمهای حافظهاشتراکی که ارتباط دادهها بین پردازندهها به برنامهریزی پیشرفته نیازی ندارد، چرا که زیرمسئلههای متمایز قابل اجرا بر روی پردازندههای مختلف میباشند
[ویرایش] دسترسی به حافظه
الگوریتمهای تقسیم و حل ذاتاً به کارآمد ساختن استفاده از حافظههای پنهانگرایش دارند. دلیل آن هم این است که، زمانی که زیرمسئله به اندازهٔ کافی کوچک باشد، آن زیر مسئله و تمام زیرمسئلههای آن میتوانند، به طور کلی، در داخل حافظهٔ پنهان حل شوند، بدون اینکه به حافظهٔ اصلی که کندتر میباشد دسترسی داشته باشند. الگوریتمی که به منظور بهرهکشی اینچنینی از حافظهٔ پنهان طراحی میشود، cache oblivious (بیتوجه به حافظهٔ پنهان)، نامیده میشود، چرا که اندازهٔ حافظهٔ پنهان را به عنوان یک پارامتر آشکار، در بر ندارند.[۷]
علاوه بر این، الگوریتمهای D&C میتوانند برای الگوریتمهای مهم بسیاری، همانند مرتبسازی، FFTها، و ضرب ماتریسها، طراحی شوند، به طریقی مشابه، الگوریتمهای بهینهٔ «بیتوجه به حافظهٔ پنهان»، چنان که میتوان اثبات کرد، به صورت بهینه و از دید مجانبی، صرفنظر از اندازهٔ حافظهٔ پنهان، از آن استفاده میکنند. در مقابل، راهبرد سنتیِ بهکاربستن حافظهٔ پنهان، بلاکبندی میباشد، که در آن، مسئله صریحاً به قطعههایی از اندازههای مقتضی تقسیم میشود—این الگوریتم همچنین میتواند به طور بهینه از حافظهٔ پنهان استفاده کند، ولی فقط زمانی که الگوریتم برای اندازهٔ خاص حافظهٔ پنهان در یک ماشین ویژه مناسبسازی شده باشد.
مزیت مشابهی با درنظر گرفتن سیستمهای حافظهای سلسلهمراتبی دیگر وجود دارد، همانند NUMA یا حافظهٔ مجازی، و نیز برای سطوح چندگانهٔ حافظهٔ پنهان: زمانی که یک زیرمسئله به اندازهٔ کافی کوچک باشد، میتواند، بدون دسترسی به سطوح بالاتر(آهستهتر)، در داخل سطح مفروض از سلسلهمراتب حل شود.
[ویرایش] انواع پیادهسازی
[ویرایش] بازگشتی
الگوریتمهای تقسیم و حل معمولاً به صورت روالهای بازگشتی. پیادهسازی میشوند. در این حالت، زیرمسئلههای جزیی براساس زیرمسئلهای که در حال حل شدن است، به صورت خودکار در پشتهٔ فراخوانی روال ذخیره میشوند.
[ویرایش] پشته کردن صریح
Dالگوریتمهای تقسیم و حل همچنین میتوانند به واسطهٔ یک برنامهٔ غیربازگشتی که زیرمسئلههای جزیی را در بعضی دادهساختارهای صریح همانند پشته, صف، و یا صف اولویتدار، ذخیره میکند، پیادهسازی شوند. این راهبرد آزادی بیشتری در انتخاب زیرمسئلهای که در قرار است در مرحلهٔ بعد حل شود، میدهد، ویژگی ای که در بعضی از برنامههای کاربردی دارای اهمیت میباشد. همانند متد رابطهٔ بازگشتی ابتدا در عرض در انشعاب و تحدید برای بهینهسازی عملکرد. این راهبرد، همچنین راهحل استاندارد زبانهای برنامهنویسیای میباشد که از روالهای بازگشتی پشتیبانی نمیکنند.
[ویرایش] اندازهٔ پشته
در پیادهسازیهای بازگشتیِ الگوریتمهای D&C، باید از وجود حافظهٔ تخصیص دادهشدهٔ مورد نیاز برای پشتهٔ بازگشت اطمینان حاصل شود، درغیراینصورت ممکن است به دلیل سرریز پشته.، اجرا با شکست مواجه شود. خوشبختانه، الگوریتمهای D&Cای که از لحاظ زمانی کارآمد هستند، اغلب، تا حدودی بازگشتی هستند. به عنوان مثال، الگوریتم مرتبسازی سریع میتواند طوری پیادهسازی شود که هرگز به بیشتر از
فراخوانی بازگشتی تودرتو برای مرتب کردن
عنصر نیاز نداشتهباشد.
ممکن است اجتناب از سرریز شدن پشته، به هنگام استفاده از روالهای بازگشتی دشوار باشد، چرا که بسیاری از کامپایلرها فرض میکنند که پشتهٔ بازگشت ناحیهای است مجاور حافظه، و بعضی از آنها یک مقدار ثابت از حافظه را برای آن تخصیص میدهند. همچنین ممکن است کامپایلرها اطلاعاتی بیشتر از آنچه که واقعاً نیاز است را در پشتهٔ بازگشت ذخیره کنند، همانند آدرس برگشت، پارامترهای تغییرناپذیر، و متغیرهای درونی روال. بنابراین، خطر سرریز شدن پشته میتواند با حداقل کردن پارامترها و متغیرهای درونی روال بازگشتی، و یا با استفاده از یک ساختار پشتهٔ صریح، کاهش یابد.
[ویرایش] انتخاب حالات پایه
در هر الگوریتم بازگشتی، آزادی قابل توجهی در انتخاب حالات پایه , (زیرمسئلههای کوچکی که به منظور پایان دادن به بازگشت، مسیقیماً حل میشوند) وجود دارد.
انتخاب کوچکترین یا آسانترین حالت پایهٔ ممکن، مطبوعتر است و معمولاً منجر به برنامههای آسانتر میشود، چرا که حالات کمتری برای رسیدگی وجود دارند که حلشان هم سادهتر است. به عنوان مثال، یک الگوریتم FFT زمانی میتواند به بازگشت پایان دهد که ورودی یک نمونهٔ یکتا باشد، و الگورتیم مرتبسازی لیستِ «مرتبسازی سریع» زمانی پایان مییابد که ورودی، لیست خالی باشد؛ در هر دو مثال تنها یک حالت پایه برای بررسی وجود دارد، که به هیچ پردازشی هم نیاز ندارد.
از سوی دیگر، غالباً، کارآیی، زمانی بهبود مییابد که بازگشت در حالات پایهٔ بزرگ مرتبط پایان یابد، که هرکدام از این حالات به صورت غیربازگشتی حل میشوند. این راهبرد، در مجموع، از فراخوانیهای بازگشتیای که کار اندکی انجام داده و یا اصلاً کاری انجام نمیدهند، اجتناب میورزد، و همچنین ممکن است استفاده از الگوریتمهای غیربازگشتی خاصی که برای آن حالات پایه کارآمدتر از بازگشتِ صِرف میباشند را میسر سازد. از آنجایی که یک الگوریتم D&C، سرانجام، هر نمونه از مسئله یا زیرمسئله را به تعداد زیادی نمونهٔ پایه تقلیل میدهد، این نمونههای پایه هزینهٔ کلی الگوریتم را رقم میزنند، علیالخصوص زمانی که هزینهٔ کلیِ تقسیم و ترکیب پایین باشد. توجه داشته باشید که این ملاحظات به اینکه آیا بازگشت به واسطهٔ کامپایلر پیادهسازی شدهاست یا به کمک یک پشتهٔ صریح، بستگی ندارد.
بنابراین، به عنوان مثال، بسیاری از پیادهسازیهای کتابخانهایِ مرتبسازی سریع، تا زمانی که تعداد عناصری که قرار است مرتب شوند به اندازهٔ کافی کوچک شود، به یک الگوریتم مرتبسازی درجی سادهٔ مبتنی بر حلقه (یا چیزی شبیه آن) سوییچ میکنند. توجه شود که، اگر لیست خالی تنها حالت پایه بود، مرتبسازی یک لیست با n ورودی منجر به n+۱ فراخوانی مرتبسازی سریع خواهدشد که کاری انجام نداده و فوراً برمیگردند. افزایش حالات پایه به لیستهایی با اندازهٔ ۲ یا کمتر، بیشترِ این فراخوانیهایی که کاری انجام نمیدهند را حذف خواهد کرد، و به طور کلی به منظور تقلیل زمان مصرفی برای فراخوانیها یا دستکاریهای پشته، معمولاً از حالت پایهای بزرگتر از ۲ استفاده میشود.
همچنین، میتوان حالات پایهٔ بزرگی را به کار بست که کماکان از الگوریتم تقسیم و حل استتفاده کنند، اما پیادهسازی الگوریتم برای مجموعههای از پیش تعیینشده با اندازهٔ ثابت میتواند کاملاً به کدی بدون هیچگونه بازگشت، حلقه و یا عبارات شرطی (بسته به روش ارزیابی جزئی) تبدیل شود. به عنوان مثال، این راهبرد در بعضی از پیادهسازیهای کارآمد FFT که در آنها حالات پایه، پیادهسازیهای تبدیلشدهٔ الگوریتمهای تقسیم و حل FFT برای یک مجموعه از اندازههای ثابت میباشند، مورد استفاده قرار گرفتهاست..[۸] تعداد زیادِ حالات پایهٔ جدا از همِ درخورِ پیادهسازیِ کارآمدِ این راهبرد، بعضی اوقات با روشهای تولید کد منبع ایجاد میشوند.[۸]
[ویرایش] به اشتراک گذاری زیرمسئلههای تکراری
در بعضی مسائل، بازگشت انشعابی، ممکن است به ارزیابی یک زیرمسئله در دفعات زیاد، پایان دهد. در چنین مواردی ممکن است شناسایی و ذخیرهٔ راه حلهای این زیرمسئلههای مشابه، خالی از لطف نباشد، که این روش به «به خاطرسپاری» معروف بوده و روشی معمول و شناختهشده میباشد. این شیوه به الگوریتمهای تقسیم و حل از پایین به بالا مانند برنامهنویسی پویا و تجزیه و تحلیل نمودار منجر میشود.
[ویرایش] منابع
- ↑ Thomas H. Cormen, Charles E. Leiserson, and Ronald L. Rivest, Introduction to Algorithms (MIT Press, ۲۰۰۰).
- ↑ Anany V. Levitin, Introduction to the Design and Analysis of Algorithms (Addison Wesley, ۲۰۰۲).
- ↑ ۳٫۰ ۳٫۱ ۳٫۲ ۳٫۳ Donald E. Knuth, The Art of Computer Programming: Volume ۳, Sorting and Searching, second edition (Addison-Wesley, ۱۹۹۸).
- ↑ Heideman, M. T., D. H. Johnson, and C. S. Burrus, «Gauss and the history of the fast Fourier transform,» IEEE ASSP Magazine, ۱, (۴), ۱۴–۲۱ (۱۹۸۴)
- ↑ Knuth, Donald. The Art of Computer Programming: Volume ۳ Sorting and Searching. 1998. 159. ISBN 0-201-89685-0.
- ↑ A. Karatsuba and Yu. Ofman, Multiplication of Many-Digital Numbers by Automatic Computers. Doklady Akad. Nauk SSSR, Vol. ۱۴۵ (۱۹۶۲), pp. ۲۹۳–۲۹۴. Translation in Physics-Doklady, ۷ (۱۹۶۳), pp. ۵۹۵–۵۹۶.
- ↑ M. Frigo. C. E. Leiserson, H. Prokop. Proc. ۴۰th Symp. On the Foundations of Computer Science, 1999.
- ↑ ۸٫۰ ۸٫۱ Frigo, M.. Johnson, S. G.. Proceedings of the IEEE 93, no. 2 (February 2005): 216–231.