View Full Version : معرفی الگوریتم ژنتیک
whitehat
سه شنبه 07 اسفند 1386, 23:17 عصر
با توجه به اینکه سوال در موزد این الگوریتم زیاد شده کمی در مورد این الگوریتم در این تاپیک بحث می کنیم ، و به تدریج بحثهای قبلی را با این تاپیک ادغام خواهم کرد. عمده مطالب از دو مرجع زیر انتخاب شده اند :
سهراب امینی ، بهینه سازی ماشینهای DC مغناطیس دائم با جاروبک با استفاده از روشهای هوشمند ; دانشگاه صنعتی شریف، دانشکده برق ، پائیز 1377
رضا کیانی نژاد . جستاری در الگوریتم ژنی ; سمینار کارشناسی ارشد , دانشگاه تربیت مدرس , دانشکده مهندسی , گروه برق , قدرت 1 , پائیز 1373 .
-------------------------------
معرفی الگوریتم ها ژنتیک
الگوریتم ژنتیک، الگوریتم مبتنی بر تکرار است و اصول اولیه آن از علم ژنتیک اقتباس گردیده است. این الگوریتم که با تقلید از تعدادی فرایندهای مشاهده شده در تکامل طبیعی اختراع شده است، به طور مؤثری از دانش قدیمی موجود در یک جمعیت استفاده می کند، تا حلهای جدید و بهبود یافته ایجاد کند. این الگوریتم در مسائل متنوعی نظیر بهینه سازی، شناسایی و کنترل سیستم، پردازش تصویر و مسائل ترکیبی، تعیین توپولوژی و آموزش شبکههای عصبی مصنوعی و سیستم های مبتنی بر تصمیم و قاعده به کار میرود. الگوریتم ژنتیک به دلیل تقلید نمودن از طبیعت دارای چند اختلاف اساسی با روشهای جستجوی مرسوم میباشد که در زیر به تعدادی از آنها اشاره میکنیم:
1-الگوریتم ژنتیک با رشتههای بیتی کار میکند که هر کدام از این رشتهها کل مجموعه متغیرها را نشان میدهد. حال آنکه بیشتر روشها به طور مستقل با متغیرهای ویژه برخورد میکنند.
2-الگوریتم ژنتیک در هر تکرار چند نقطه از فضای جستجو را در نظر میگیرد.
3-الگوریتم ژنتیک برای راهنمایی جهت جستجو، انتخاب تصادفی انجام میدهد که به این ترتیب اطلاعات مشتق نیاز ندارد. مکانیسمهایی که تکامل روی موجود زنده را انجام میشوند تا کنون به طور کامل فهمیده نشدهاند. اما تعدادی از ویژگیهای این مکانیسم شناخته شده است.
در اینجا تعدادی از ویژگیهای یکی از تئوریهای بسیار پذیرفته شده است آورده میشود.
1- تکامل، فرایندی است که روی رشتهها صورت میگیرد، نه روی موجود زندهای که معرف آن رشته است.
2- انتخاب طبیعی، پیوندی ما بین رشتههای و عملکرد ساختمانهای رمزگشایی شده آنها میباشد.
3- فرایند تولید مثل، نقطهای است که تکامل صورت میگیرد. تکامل ممکن است سبب شود که فرزند بیولوژیکی با والدین خود متفاوت میباشد.
الگوریتم ژنتیک الگوریتم جستجویی است که از ویژگیهای ذکر شده برای تئوری تکامل، الهام گرفته است. همان گونه جان هلند مبتکر الگوریتم ژنتیک اعتقاد داشت، این الگوریتم به همان روشی که طبیعت، فرایند تکامل را انجام میدهد، تکامل را روی نمادهای ژنی مربوط به حلهای یک مسأله بهینهسازی انجام میدهد.
الگوریتم ژنتیک چندین نقطه از فضای جستجو را به صورت همزمان در نظر میگیرد و بنابر این شانس اینکه به یک بیشینه محلی همگرا شود، کاهش مییابد. در بیشتر روشهای جستجو مرسوم، قاعده تصمیم حاکم به این صورت عمل میکند که از یک نقطه به نقطه دیگر حرکت میکند این روشها میتوانند در مسئلههای جستجو دارای چند بیشینه خطرناک باشند. زیرا ممکن است آنها به یک بیشینه محلی همگرا شوند. لیکن الگوریتم ژنتیک جمعیتهای کاملی از نقاط ( رشتهها ) را تولید میکند سپس هر نقطه را به صورت انفرادی امتحان میکند و با ترکیب کیفیتهای ( محتویات ) نقاط موجود، یک جمعیت جدید را که شامل نقاط بهبود یافته است تشکیل می دهد. صرف نظر از انجام یک جستجو، ملاحظه همزمان تعدادی نقطه در الگوریتم ژنتیک، آن را با ماشینهای موازی قابل تطبیق میسازد، زیرا در اینجا تکامل هر نقطه یک فرایند مستقل است. لذا الگوریتم ژنتیک فقط نیاز به اطلاعاتی در مورد کیفیت حلهای ایجاد شده به وسیله هر مجموعه از متغیرها دارد. در صورتی که بعضی از روشهای بهینه سازی نیاز به اطلاعات مشتق یا حتی نیاز به شناخت کاملی از ساختمان مسأله و متغیرها دارند. چون الگوریم ژنتیک نیاز به چنین اطلاعات مشخصی از مسأله ندارد بنابراین قابل انعطافتر از بیشتر روشهای جستجو است. همچنین الگوریتم ژنتیک از روشهای جستجوی نوعی، که برای راهنمایی جهت روشهای جستجویشان از انتخاب تصادفی استفاده میکنند، متفاوت میباشد. زیرا اگر چه برای تعریف روشهای تصمیمگیری از تصادف و شانس استفاده میکند، ولی در فضای جستجو به صورت تصادفی قدم نمیزند. الگوریتم ژنتیک از تصادف به طور مناسب برای بهرهبرداری از معرفت پیشینی استفاده میکنند تا به سرعت به حلهای نزدیک بهینه برسد.
در ادامه به اصطلاحات موجود در این الگوریتم ها می پردازیم
whitehat
پنج شنبه 09 اسفند 1386, 09:35 صبح
اصطلاحالت الگوریتم ژنتیک
1- رشته ( کروموزوم) : آرایهای از اعداد صحیح است که مقادیر عناصر این آرایه با توجه به نوع رشته تعیین میشود. مثلاً در رشته بیتی این عناصر فقط صفر و یک می توانند باشند. این رشتهها مشخص کننده مجموعه متغیر های بهینه سازی مسأله مورد نظر هستند.
2- ژن : بخشی از رشته که خصوصیات ویژهای را معین میکند.
3- نماد ژنی : به ترکیب ژنتیکی یا همان رشته گفته میشود.
4- نماد معرف : به خصوصیات قابل مشاهده یک جاندار گفته میشود و در مسائل بهینه سازی به بردار حقیقی حاصل از رمزگشایی یک رشته گفته میشود.
5- نسل : یک دوره از زاد و ولد اعضاء یک جمعیت را یک نسل میگویند. به عبارت دیگر هر جایگزینی از جمعیت قدیمی به وسیله جمعیت جدید یک نسل ( زاد و ولد ) نامیده میشود.
6- شایستگی : در طبیعت به مقدار سازگاری و تطابق یک جاندار با محیط گفته میشود و در بهینهسازی به مقدار ارزیابی تابع هدف یا مقداری متناظر با آن به ازای یک رشته خاص، گفته میشود که نشان دهنده میزان مطلوب بودن آن رشته برای آن مسأله خاص ( تابع هدف ) میباشد.
7- تبادل ژنی : به جا به جایی و مبادله قسمتهای متناظر از دو رشته گفته میشود.
8- جهش : به تغییر تصادفی و ناگهانی یکی از عناصر در یک رشته گفته میشود.
whitehat
پنج شنبه 09 اسفند 1386, 09:44 صبح
در حالت کلی هر الگوریتم ژنتیک دارای سه جزء اساسی زیر است:
1- جزء ارزیابی 2- جزء جمعیت 3- جزء تولید مثل
---------------------------------------------------------------
1- جزء ارزیابی : شامل یک تابع ارزیابی است که درستی هر رشتهای که در جمعیت وجود دارد را اندازه گیری میکند. در مورد این جزء نکته مهم این است که چیز مخصوصی درباره تابع ارزیابی، که آن را با الگوریتم ژنتیک گره بزند، وجود ندارد و به راحتی میتوان هر تابع دیگری را به جای آن تابع به کار برد. البته مادامی که تعداد متغییرهای دو تابع و محدوده تغییرات متغییرها و دقت مورد نیاز آنها یکسان باشند. به عبارت دیگر، در الگوریتم ژنتیک هیچ اطلاعاتی درباره مسألهای که باید حل شود، وجود ندارد و تا آنجایی که به الگوریتم ژنتیک مربوط میشود، صرفاً تولید مثل میکند و رشتههای جدید تولید میکند و روی رشتههای بیتی تولید شده به گونهای عمل میکند که آنهایی که دارای ارزیابی بالاتری هستند، بیشتر اوقات تولید مثل کنند. فرایند رمز گشایی و تابع ارزیابی به راحتی میتوانند جایگزین شوند. این تغییرات، تا مادامی که تعداد بیتهای رشتهها ثابت بماند به تغییر اجزای دیگر الگوریتم ژنتیک نیاز ندارد.
2- جزء جمعیت : شامل جمعیتی از رشتهها و تکنیکهاست که این تکنیکها برای ایجاد و دستکاری آن جمعیت استفاده می شود.
3- جزء تولید مثل : شامل روش هایی برای ایجاد رشتههای جدید طی تولید مثل است.
تداخل بین سه جزء یک الگوریتم ژنتیک موقعی که در حال اجراست، به این صورت میباشد که جزء جمعیت از جزء تولید مثل، جمعیت جدید را میخواهد. جزء تولید از جزء جمعیت، والدینی که باید در رخداد تولید مثل به کار برده شوند را طلب میکند. در هر رخداد تولید مثل، دو والد از جزء جمعیت گرفته شده و روی آنها عملگرهای تبادل و جهش اعمال میشود تا دو فرزند تولید شود. همچنین موقعی که یک مجموعه جدید از فرزندان تولید شدند، جزء جمعیت از جزء ارزیابی برای ارزیابی فرزندان جدید ( رشتههای جدید ) استفاده میکند.
whitehat
جمعه 10 اسفند 1386, 13:18 عصر
یک تشریح کلی از الگوریتم ژنتیک را میتوان به صورت زیر در نظر گرفت :
1- جمعیتی از رشتهها را به صورت تصادفی بسازید.
2- هر رشته داخل جمعیت را ارزیابی کنید.
3- رشتههای جدید را با ترکیب رشتههای جاری ایجاد کنید. برای ترکیب رشتههای والد از عملگرهای جهش و تبادل استفاده کنید.
4- اعضایی از جمعیت را برای ایجاد فضایی برای رشتههای جدید حذف کنید.
5- رشتههای جدید را ارزیابی نموده و آنها را داخل جمعیت قرار دهید.
6- اگر زمان اجرا تمام شده است توقف نمایید و بهترین رشته را باز گردانید. در غیر این صورت به مرحله سه بازگردید.
روند ذکر شده در بالا متداولترین روش الگوریتم ژنتیک را تشریح میکند. اما محققین مختلف، آن را به روشهای متفاوت پیاده سازی کردهاند.
(دو روش متداول دیگر برای اختتام: همگرا شدن الگوریتم، تولید تعداد خاص نسل میباشد )
whitehat
دوشنبه 13 اسفند 1386, 22:50 عصر
اغلب نام الگوریتم ژنتیک متداول در مقابل الگوریتم ژنتیک ترکیبی آورده میشود. در الگوریتم ژنتیک متداول معمولاً از سه عملگر انتخاب، تبادل و جهش استفاده میشود. این سه عملگر معمولاً عملگرهای اساسی همه روشهای الگوریتم ژنتیک هستند که از رشتههای بیتی استفاده میکنند. با توجه به اینکه روش رمز کنندگی با استفاده از رشتههای بیتی میتوان با طیف وسیعی از مسائل روبرو شد؛ می توان گفت این سه عملگر و روش رمزکنندگی رشته بیتی باعث مقاوم شدن الگوریتم ژنتیک خواهد شد که در این مورد در بخش بعد توضیحات بیشتری داده خواهد شد.
1- عملگر انتخاب
هدف از انتخاب والدین در الگوریتم ژنتیک دادن شانس تولید مثل بیشتر به آن اعضایی است که برازندگی بالاتری داشته باشند. چندین روش برای انجام این کار وجود دارد.
یک روش که به طور معمول استفاده میشود، روش انتخاب با استفاده از چرخ گردان است. روند اجرای این روش به صورت زیر میباشد:
الف – برازندگی همه اعضای جمعیت را جمع کنید و نتیجه را برازندگی کل بنامید
ب- عدد n را به صورت تصادفی تولید کنید، به طوری که آن عددی بین صفر و برازندگی کل باشد. ج- اولین عضو از جمعیت را که برازندگی آن به اضافه برازندگی اعضای پیشین جمعیت بزرگتر یا مساوی n باشد را بازگردانید.
اثر انتخاب والدین به روش چرخ گردان بازگردان یک والد میباشد که به صورت تصادفی انتخاب شده است. اگر چه این فرایند انتخاب، تصادفی است، شانس هر والدی که انتخاب میشود مستقیماً متناسب با برازندگی آن است. به طور متعادل در روی تعدادی از نسلها این الگوریتم ژنتیک اعضای با کمترین برازندگی را دفع میکند و به انتشار مواد ژنتیکی در برازندهترین اعضای جمعیت کمک میکند. البته ممکن است بدترین عضو جمعیت بتواند به وسیله این الگوریتم انتخاب شود ( زیرا به هر حال در روند این الگوریتم عنصر تصادف نیز وجود دارد. ) اتفاقاتی از این دست در جمعیتی با هر اندازه، قابل صرفنظر هستند و به فرض انتخاب چنین اعضایی در یک نسل، احتمال دفع آنها در نسلهای بعدی بسیار بیشتر است. به هر حال، با گذشت چند نسل، این اعضا از جمعیت دفع میشوند. در به کار بردن روش انتخاب والدین باید دقت شود که مقادیر برازندگی رشتهها باید اعداد مثبت باشند.
2- عملگر تبادل
عملکرد این عملگر و عملگر جهش باعث میشود که رشته های تولید شده طی تولید مثل، از رشتههای والدینشان متفاوت باشند. در طبیعت، این عملگر موقعی رخ میدهد که دو والد قسمتهایی از رشتههای متناظرشان را معاوضه کنند و در الگوریتم ژنتیک، عملگر تبادل، مواد ژنتیکی دو رشته والد را مبادله میکند تا دو فرزند ( رشته جدید ) ایجاد شود. چندین نوع عملگر تبادل وجود دارد. ولی معروفترین عملگر تبادل به کار رفته در الگوریتم ژنتیک عملگر یک نقطهای میباشد.
در الگوریتم ژنتیک این عملگر به صورتی که در زیر تشریح میشود، اعمال میگردد. برای اینکه بتوانیم از این عملگر استفاده کینم نیاز به دو رشته داریم. بنابراین با دوبار اعمال عملگر انتخاب روی جمعیت جاری دو رشته از آن را انتخاب میکنیم سپس یک آزمون احتمال انجام میدهیم تا مشخص شود که عملگر تبادل روی دو رشته اعمال بشود یا نشود. این آزمون با استفاده از یک سکه نا همگن صورت میگیرد به این صورت که سکه با احتمال (Pcross) شیر و با احتمال (1- Pcross) خط میآید. به عنوان مثال، اگر قرار باشد با شیر آمدن سکه عملگر تبادل بر روی رشته اعمال گردد، فرض میکنیم سکه را پرتاب کردهایم و شیر آمده است. سپس وارد مرحله بعدی یعنی اجرای عملگر تبادل میشویم یک عدد تصادفی بین یک و طول رشته تولید میشود.پس از مشخص شدن این عدد صحیح که نشان دهنده مکان تبادل روی رشتهها است, هر دو رشته از محلی که این عدد مشخص میکند شکسته میشوند و قسمتهای انتهایی آنها با همدیگر معاوضه میشوند. اکنون قسمتهای جدا شده به همدیگر متصل میشوند، تا دو رشته جدید حاصل شود
3-عملگر جهش
این عملگر نیز یکی از عملگرهای الگوریتم ژنتیک است و به کارگیری آن قابلیت الگوریتم ژنتیک را برای یافتن حلهای نزدیک بهینه افزایش میدهد. جهش، تغییر اتفاقی در مقدار یک وضعیت ویژه رشته میباشد. با به کارگیری این عملگر مشخصه هایی که در جمعیت والدین وجود ندارد، ایجاد میشود. زیرا جهش باعث تغییر مقدار یک ژن میشود یعنی اگر یک باشد صفر میشود و بالعکس اگر صفر باشد یک میشود. لذا همین موضوع باعث تغییر مشخصههای یک رشته میشود و برای اینکه جمعیت پیش از موعد همگرا نشود، مناسب میباشد. زیرا یکی از دلایل همگرایی پیش از موعد یکسان بودن اعضاء جمعیت می باشد که عملگر جهش باعث می شود احتمال یکسان شدن اعضاء در جمعیت های جدید بسیار کاهش یابد. روش پیاده سازی این عملگر در زیر توضیح داده می شود.
این عملگر بر خلاف عملگر تبادل که به دو رشته نیاز داشت، به یک رشته نیاز دارد، پس از اینکه عملگر تبادل روی دو رشته اعمال شد و دو رشته جدید به دست آمد، عملگر جهش به این دو رشته به صورت مجزا اعمال می شود. روش اعمال به این صورت است که برای تک تک عناصر یک رشته، آزمون احتمال جهش صورت میگیرد. در صورتی که این آزمون با موفقیت انجام شود، مقدار آن وضعیت از یک به صفر یا از صفر به یک تغییر میکند و به اصطلاح جهش میکند. انجام آزمون احتمال نیز با استفاده از یک سکه نا همگن که با احتمال (Pcross) شیر و با احتمال (1- Pcross) خط میآید، صورت میگیرد و در صورتی که با پرتاب سکه شیر آمده باشد مقدار بیت مربوط جهش میکند.
همانطور که در بالا گفته شد بایستی آزمون احتمال برای تک تک وضعیتهای یک رشته صورت گیرد. به عبارت دیگر برای هر جهش یک بار سکه ناهمگن رها میشود و با توجه به نتیجه، مقدار بیت جهش مییابد یا جهش نمییابد.
whitehat
پنج شنبه 23 اسفند 1386, 11:31 صبح
در این قسمت نکاتی درباره پیادهسازی الگوریتم ژنتیک دودوئی مانند تشکیل رشتهها، تعداد بیتهای متناظر با هر متغییر، رمزگشائی، انواع روشهای تشکیل رشته، تعداد بیتهای متناظر با هر متغییر و چگونگی تشکیل رشتهها توضیح داده میشود. به دلیل وجود فرمول از pdf استفاده شده
Alireza_Salehi
پنج شنبه 23 اسفند 1386, 19:16 عصر
خیلی ممنون
پیشنهاد:
1. بهتر بود معادل انگلیسی کلمات کلیدی متن (عناوین) را به صورت زیر نویس قرار می داید.
2. این کتاب خیلی زیبا ، روان و کاربردی الگوریتم ژنتیک را تشریح کرده:
Genetic Algorithms and Engineering Design (http://eu.wiley.com/WileyCDA/WileyTitle/productCd-0471127418.html)
hasankhaksar
چهارشنبه 28 فروردین 1387, 10:35 صبح
سلام. موضوع پایان نامه من بهینه سازی شبکه اتوبوسرانی شهری با استفاده از ژنتیکه. آیا کسی هست که برنامه نویسی و کدینگ ژنتیک رو بدونه و بتونه کمکم کنه؟؟
meytim
دوشنبه 14 مرداد 1387, 19:04 عصر
براي الگوريتم ژنتيك زيربخش آخر از آخرين بخش كتاب "شگردهاي عددي" رو هم ميتونيد بخونيد. موقعي كه من اون كتاب رو نوشتم، هنوز شركت MathWorks جعبهابزار الگوريتم ژنتيك رو ارائه نداده بود، واسه همين برنامهها رو خودم نوشتم. برنامههاي كتاب رو ميتونيد از لينك زير دانلود كنيد.
http://mmnrecipes.blogspot.com (http://mmnrecipes.blogspot.com/)
زيربخش آخر از بخش آخر كتاب من در مورد الگوريتم ژنتيك هست. احتمالاً اولين كتاب فارسي در مورد الگوريتم ژنتيك همين است كه من نوشتهام (سال 1381). آن موقع شركت MathWorks هنوز Toolbox براي الگوريتم ژنتيك نداده بود، براي همين برنامههاي الگوريتم ژنتيك آن كتاب را خودم نوشتم، و مطمئناً سادهتر از آني هست كه شركت MathWorks داده؛ اين طبيعي است، چون يك نفر كجا و يك تيم كجا؟ اما در هر صورت مفاهيم آن را داخل كتاب توضيح دادم و برنامههايش هم قبل از اينكه كتاب رو چاپ كنم حداقل براي 20 تا پروژة ليسانس و فوق ليسانس تست شده. به نظر من پيشنياز نميخواد، چون مفاهيمش خيلي ساده هست. البته بعضيها يك سري مفاهيم پيچيده رو به هر مبحثي اضافه ميكنن؛ من اين كار رو نكردم. فقط بايد متلب بلد باشيد، كه اون رو هم در بخش اول كتاب به طور خلاصه گفتم.
afabahar
دوشنبه 11 آذر 1387, 18:39 عصر
باز هم کارتون عالی بود.
به زودی نتیجه این تحقیقاتم رو در زمینه الگوریتم ژنتیک در اختیار سایرین قرار میدهم.
با تشکر
majidshe
جمعه 12 فروردین 1390, 21:03 عصر
با الگوریتم ژنتیک مسئله 8 وزیر را در متلب و ی شارپ لازم دارم لطفا کمک کنید
mjal146
جمعه 12 فروردین 1390, 21:35 عصر
اگر ممکنه یه مثال خیلی ساده از الگوریتم ژنتیک بزنید (فروشنده و 8وزیر و مینیمم تابع نباشد) مثلا حل معادله درجه 2 با کدش به زبان سی یا سی پلاس پلاس:قلب:
خیلی لازم دارم:افسرده:
mjal146
جمعه 12 فروردین 1390, 21:57 عصر
با الگوریتم ژنتیک مسئله 8 وزیر را در متلب و ی شارپ لازم دارم لطفا کمک کنید
آموزش پیاده سازی گرافیکی هشت وزیر با C#
گام نخست : پیاده سازی مهره و کاشی بازی
مهره نشان دهنده وزیر
را ایجاد کنید.eight_queen ای به نام Windows Application برنامه Visual C# را اجرا کنید و از قسمت Visual Studio
SquareControl.cs به نام User Control یک Add new item بر روی پروژه یتان کلیک راست کنید و از قسمت
کاشی صفحه شطرنج ما را می سازدUser control را ایجاد کنید.در واقع این
این کنترل را به 32, 32 تغییر می دهیم.حالا کاشی تخته یمان آماده شد!size
تخته یمان که به شکل دایره است می رسد(Discs)نوبت به طراحی مهره های
این مهره ها را می توان به 2 صورت پیاده سازی کرد:
با قرار دادن عکس وزیر درون کاشی های شطرنج .1
با کشیدن دایره درون کاشی های شطرنج. .2
که در این مقاله راه دوم را برگزیدیم.یعنی با کد زیر دایره ای با رنگ سفید یا سیاه درون کاشی هایمان رسم می کنیم.
e.Graphics.DrawEllipse(SquareControl.pen, left, top, width, height);
را حذف کردیم و آنرا به گام های بعدی محول کرده ایم.shadow و animationدر این گام ما قسمت
گام دوم : تعریف پارامترها و نام دامنه برای User Control ها
نام دامنه
پارامتر
اضافه می کنیم:User controlدر ابتدای کار نام دامنه زیر را
using System.Drawing.Drawing2D;
سپس رنگ کاشی خود را تعیین می کنیم:
public static Color NormalBackColor= Color.Green;
باید متغیری برای ذخیره کردن ردیف و ستون مهره ها ایجاد کنیم.به این دلیل که کدمان حرفه ای تر بشود ، آنها را تعریف کرده ایم:propertyمستقیمان به صورت
// These reflect the position of the square on the board.
Public int col{get;set;}
public int row{get;set;}
در انتها هم رنگ و قلم موی خود را انتخاب می کنیم:
// Drawing tools.
Private static Pen pen = new Pen(Color.Black);
private static SolidBrush solidBrush = new SolidBrush(Color.Black);
گام سوم : تابع تنظیم ردیف و ستون
ما در این گام باید تابعی را بسازیم که بتوانیم از بیرون از این کلاس، ردیف و ستون مهره هایمان را تنظیم کنیم.
در گام پیشین تعریف propertyبا این کار ما میتوانیم وضعیت ردیف و ستون مهره هایمان را که به صورت
کردیم را دریافت کنیم و پس از محاسبه حرکت صحیح توسط هوش مصنوعی برنامه یمان بوسیله ی این تابع
از دوباره ردیف و ستون مهره هایمان را مقدار دهی کنیم.
Public SquareControl(int row, int col)
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
this.Contents = Board.Empty;
this.row = row;
this.col = col;
// Prevent the control from receiving focus via the TAB key.
This.TabStop = false;
// Set the background color.
This.BackColor = SquareControl.NormalBackColor;
}
گام چهارم : ایجاد و نابود سازی User Control ها
ن مقاله موزیرود در محیط های مختلف طراحی و پیاده سازی کنند.گوریتم هشت وزیر را تحلیل کرده و بازگشتی و غیر بازگشتی نوشته
انحدام
ایجاد
InitializeComponent()تابعی ای که شاید در گام قبل برای برخی ها نا آشنا به نظر برسد تابع
ما را می سازد. و در بطن کد نویسی ما دخالتیuser controlمی باشد.این تابع در واقع اجزای اصلی
ندارد:
private void InitializeComponent()
{
// SquareControl
this.Name = “SquareControl”;
this.Size = new System.Drawing.Size(32, 32);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Square Control_Paint);
}
می باشد.همانگونه که می دانید دات نت دارای خواصیتی به نامuser controlتابع بعدی ما برای نابود سازی
خود خارج می شود.scoop می باشد .به این معنا است که هنگامی که کنترل ما از Garbage collector
دات نت بصورت خودکار آن شئی را نابود می کند.این خواصیت دات نت باعث بهبود عملکرد برنامه می شود.
Protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
بصورت خودکار توسط ویژاوال استدیوdispose و InitializeComponent تابع
ایجاد می شود،بنابرین نیاز به حفظ کردن و توضیحات در این باره نمی باشد.
فقط نکته ای که در این بین هست، ما برای سحولت و داکیومنت کردن این پروژه
SquareControl.cs در قسمت SquareControl.Designer.csآنرا از قسمت
نوشته ایم.به این دلیل که هر دوی آنها درون یک کلاس می باشند.در کد نویسی
آن تفاوتی بوجود نمی آید.
گام پنجم : چیدن مهره ها در صفحه شطرنج
حالا به مهم ترین قسمت طراحیمان که همان طراحی مهره ها می باشد میرسیم.در این مرحله ما باید هر دفعه که
ما فراخوانی می شود، مهرهایمان ها را بچینیم.
می باشد. SquareControl_Paint ای که می توانیم برای اینکار فراخوانی کنیم،eventبهترین
ما فراخوانی میشود. کد های درونUser controlحالا با قرار دادن کدهایمان درون این تابع هربار که
آن اجرا می شود.
برای اینکه ما بهترین حالت نمایش مهره هایمان را داشته باشیم،باید قطعه کدی را بنویسیم که به رایانه بگوییم هدف ما یک گرافیک خوب می باشد نه یک طراحی سریع و یا بدون لرزش. قطعه کد زیر اختیاری است به این معنی که اگر قطعه کد زیر را وارد نکینم، باز هم برنامه ما اجرا می شود ولی گرافیک برنامه ما پایین می آید:
// Set drawing options.
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
حالا ما با دستور شرطی حالتی را میسنجیم که در صورت برقرار بودن هر یک از 2 شرط زیر دستور مربوطه اجرا شود:
1. کاشی ما در حال حاضر دارای هیچ مهر ای نباشد
2. محتویات جدید کاشی ما مهره سیاه باشد.
if (this.Contents != Board.Empty)
در مرحله بعد،باید مکان مهره را درون صفحه شطرنج مشخص کنیم. همانگونه که از قبل به یاد دارید مهره های ما بصورت یک دایره بوسیله کد زیر روی کاشی هایمان رسم
رسم میکنیم:
e.Graphics.FillEllipse(SquareControl.solidBrush, left, top, width, height);
) مهره هایمان روی کاشی از کد زیر استفاده می کنیمpositionخوب،برای تعیین مکان (
// Get size and position parameters based on the control size.
Int size = (int) (this.Width * (0.80));
int offset = (int) ((this.Width – size) / 2);
int thickness = (int) (size * 0.08);
int width = size;
int height = size;
int left = offset;
int top = offset + (int) Math.Round((double) (size – height) / 2.0);
حالا درون شرط بالا، شرط دیگری را اضافه میکنیم.در این شرط بررسی می کنیم که آیا
کاشی قبلی خالی بوده است یا خیر.این شرط را به این دلیل بررسی می کنیم که
اگر مهره ای قرار نگرفته بود آنرا بسازیم.
If (this.PreviewContents == Board.Empty)
{
SquareControl.solidBrush.Color = Color.Black;
else
{
}
e.Graphics.FillEllipse(SquareControl.solidBrush, left, top, width, height);
}
mjal146
جمعه 12 فروردین 1390, 21:59 عصر
گام ششم : کشیدن حاشیه بین کاشی ها.باشد.
برای اینکه کاشی ها از هم جدا شوند،ما مجبوریم بین آنها خطی را به عنوان فصل ممیز کاشی ها رسم کنیم.این کار هم بسیار ساده می باشد.فقط با کشیدن 4 خط که رنگی متفاوت با کاشی ها دارند در سمت راست و چپ و بالا و پایین کاشی ها می توانیم آنها را از هم جدا کنیم.
// Draw the border.
Point topLeft = new Point(0, 0);
Point topRight = new Point(this.Width – 1, 0);
Point bottomLeft = new Point(0, this.Height – 1);
Point bottomRight = new Point(this.Width - 1, this.Height - 1);
SquareControl.pen.Color = Color.Moccasin;
SquareControl.pen.Width = 1;
e.Graphics.DrawLine(SquareControl.pen, bottomLeft, topLeft);
e.Graphics.DrawLine(SquareControl.pen, topLeft, topRight);
SquareControl.pen.Color = Color.Navy;
e.Graphics.DrawLine(SquareControl.pen, bottomLeft, bottomRight);
e.Graphics.DrawLine(SquareControl.pen, bottomRight, topRight);
گام هفتم : نگاه کلی بر کلاس SquareControl
فصل دوم : پیاده سازی محیط بازی
گام هشتم : تعریف متغییر های تخته بازی
تخته بازی
<-متغییر ها در
در پیاده سازی بازی هشت وزیر از متغییر های زیر استفاده شده است :
private Board board;
private eightQueen queen;
private Boolean[, ,] memory;
private Int32 moveNumber;
در اینجا کلاس eighteQueen در واقع نشان دهنده کلاسی است که الگوریتم بازی در آن نوشته شده است.
آرایه سه بعدی memory هم نشان دهنده مکان 8 وزیر در 92 حالت ممکن است.اندیس اول و دوم این آرایه مختص ردیف و ستون بازی می باشد و اندیس سوم این آرایه برای نگه داری 92 حالت ممکن بازی می باشد.این آرایه به صورت Boolean نمایش داده شده است.به این معنا که محتویات این ارایه می تواند True یا False باشد.در صورتی که مهره ای درون صفحه نباشد،مقدار این متغییر False میشود و در صورتی که بر اساس الگوریتم،مهره وزیری در این مکان وجود داشته باشد،مقدار این متغییر True می شود.
متغییر سراسری moveNumber هم در واقع اندیس سوم آرایه memory می باشد.در بازی شما می توانید با کلیک کردن بر روی دکمه next و previous می توانید مقدار این متغییر را زیاد یا کم کنید.
گام نهم : پیاده سازی تابع سازنده تخته بازی
در این متد ،ما با 2 حلقه for در 64 آرایه جستجو می کنیم،در صورت وجود وزیر در هر یک از خانه ها،آن را در خانه مرتبطش در صفحه شطرنج قرار می دهیم
private void UpdateBoardDisplay()
{
// Map the current game board to the square controls.
SquareControl squareControl;
for (int row = 0; row < 8; row++)
{
for (int col = 0; col < 8; col++)
{
squareControl = (SquareControl)this.squaresPanel.Controls[row * 8 + col];
if (memory[row, col, this.moveNumber] == true)
{
squareControl.Contents = 1;
}
else squareControl.Contents = 0;
}
}
// Redraw the board.
this.squaresPanel.Refresh();
}
در آخر هم صفحه ای که خانه های شطرنج در آنها وجود دارد،refresh می شود.با اینکار رنگ مناسب هر خانه در صفحه ترسیم می شود.
گام دهم : ذخیره 92 حالت مختلف
private void btnNext_Click(object sender, EventArgs e)
{
if (moveNumber < 93 && moveNumber > -1)
{
this.moveNumber++;
this.UpdateBoardDisplay();
}
else
MessageBox.Show("You are at end move");
}
همانطور که بسیار روشن است، ابتدا بررسی می کنیم که آیا شماره حرکت ما در دامنه مجاز وجود دارد یا خیر، سپس یک واحد به شمارنده حرکت اضافه می کنیم.و متد UpdateBoardDisplay برای نشان دادن،شماره حالت مورد نظر در الگوریتم هشت وزیر استفاده می کنیم.
private void btn_previous_Click(object sender, EventArgs e)
{
if (moveNumber < 93 && moveNumber > 0)
{
this.moveNumber--;
this.UpdateBoardDisplay();
}
else
MessageBox.Show("You are at firs move");
}
این متد هم عکس متد پیشین را انجام می دهد.
فصل سوم : الگوریتم هشت وزیر به روش غیر بازگشتی
گام یازدهم : معرفی الگوریتم
در این الگوریت به طور سری وار از ردیف صفر،تمام هشت ستون 92 حالت موجود را برسسی می کند، و سپس به ردیف دوم می رود و تمام ستون های 92 حالت ممکن را حساب می کند.ان الگوریتم تا ردیف هشتم تمام هشت ستون نود و دو حالت ممکن را جستجو می کند و سپس در همه آنها را در آرایه سه بعدی ما قرار می دهد و آنرا را به برنامه اصلی بر می گرداند،به این دلیل که این الگوریتم هیچگاه متد خودش را به صورت تو درتو راخوانی نکرده است،به آن بدون بازگشتی می گویند.
public Boolean[, ,] calculate()
{
board = new Boolean [8,8];
memory = new Boolean[8, 8, 92];
for ( int a = 0 ; a < 8 ; a++ )
if(test( 0 , a ))
for ( int b = 0 ; b < 8 ; b++ )
if(test( 1 , b ))
for ( int c = 0 ; c < 8 ; c++ )
if(test( 2 , c ))
for ( int d = 0 ; d < 8 ; d++ )
if(test( 3 , d ))
for ( int e = 0 ; e < 8 ; e++ )
if(test( 4 , e ))
for ( int f = 0 ; f < 8 ; f++ )
if(test( 5 , f ))
for ( int g = 0 ; g < 8 ; g++ )
if(test( 6 , g ))
for ( int h = 0 ; h < 8 ; h++ )
if (test(7, h))
{
for ( int m = 0 ; m < 8 ; m++ ) {
for (int n = 0; n < 8; n++)
memory[m, n, BoardNO] = board[m,n];
}
BoardNO++;
}
return memory;
}
گام دوازدهم : روش بررسی صحّت قرار گیری مهره
همانگونه که می دانید ، حرکت مجاز برای وزیر، به صورت مورب و بعلاوه است،درست شبیه همان چیزی که در بازی Reversi دیده ایم . برای بررسی کردن 8 جهت هر وزیر ما باید با کم کردن و زیاد کردن ردیف و ستون ، آن را آزمایش کنیم :
Boolean test( int i , int j )
if ( board[i - b,j] != false )
if (board[i - b, j - b] != false)
if (board[i - b, j + b] != false)
به این دلیل که هنوز وزیر های ردیف های بعدی ساخته نشده اند]مراجعه شود به گام قبل[ردیف های بعدی را اعتبار سنجی نمی کنیم.در آخر کد زیر را داریم:
Boolean test( int i , int j )
{
for ( int a = 0 ; a < 8 ; a++ )
board[i, a] = false;
for ( int b = 1 ; b < 8 ; b++ )
if ( i - b >= 0 ) {
if ( board[i - b,j] != false )
return false;
if ( j - b >= 0 )
if (board[i - b, j - b] != false)
return false;
if ( j + b <= 7 )
if (board[i - b, j + b] != false)
return false ;
}
board[i,j]= true ;
return true ;
}
فصل چهارم : الگوریتم هشت وزیر به روش بازگشتی
گام سیزدهم : معرفی الگوریتم
همانگونه که می دانید استفاده از الگوریتم بازگشتی دارای مزیت بسیار بزرگی است ، و آن خوانایی ودرک راحت تر آن می باشد . از اینرو است که بیشتر برنامه نویسان از الگوریتم های بازگشتی برای حل مسائلاش استفاده می کنند..
در الگوریتم بازگشتی هشت وزیر که در زیر آورده شده است. روش محاسبه آن بصورت زیر می باشد.
/**
* Place a queen in a row and check its validity. If valid then place it in the
* next row else backtrack.
*
* @param row
*/
public void place(int row) {
if (row == 8) {
for (int r = 0; r< 8; r++)
{
for (int c = 0; c < 8; c++)
{
if (board[r] == c){
memory[r, c, number] = true;
// MessageBox.Show(r.ToString()+"/"+c.ToString()+"/"+number.ToString());
}else
memory[r, c, number] = false;
}
}
this.number++;
return;
} else {
for (int i = 0; i < 8; i++) {
board[row] = i;
if (valid(row)) place(row + 1);
}
}
}
در این الگوریتم، وزیر ها بصورت بازگشتی از ستون اول به در ردیف مناسب قرار میگیرند.در هر ستون،هشت ردیف آن مورد بررسی قرار می گیرد،در صورت مجاز بودن ردیف برای آن ستون،آنرا بوصیله تابع بازگشتی درون صفحه قرار می دهیم.
در آخر هم که تمام مهره ها در ستون و ردیف مناسب قرار گرفتند،آنرا داخل آرایه قرار می دهیم.
گام چهاردهم : روش بررسی صحّت قرارگیری مهره
در این متد روشی جالب برای مجاز بودن حرکت استفاده شده است.
در این متد،اگر مقدار ردیف و ستون و یا مورب ردیف و ستون ردیف های پیشین وزیر یکسان بود،مقدار false را بر می گرداند،ردیف و ستون مفعلی و مورب مهره یکسان نبود،مقدار false را برمی گرداند.
/**
* Checks the validity of a position. If valid returns true else returns false.
*
* @param row
* @return
*/
public Boolean valid(int row) {
for (int i = 0; i < row; i++) {
if ((board[i] == board[row]) || Math.Abs(board[row] - board[i]) == (row - i)) {
return false;
}
}
return true;
}
منبع:
پروژه درس هوش مصنوعی
نوشته: شریفی
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.