نحوه عملکرد الگوریتم های ایمنی مصنوعی

الگوریتم های مطرح شده در سیستم های ایمنی مصنوعی را می توان به سه دسته تقسیم بندی نمود. دسته اول الگوریتم هایی که بر مبنای انتخاب جامعه سلول های B ایجاد شده اند. دسته دوم الگوریتم هایی که بر مبنای انتخاب معکوس سلول های T ایجاد شده اند. دسته سوم الگوریتم هایی که بر مبنای تئوری شبکه ایمنی بوجود آمده اند.

الگوریتم انتخاب جامعه (Clonal Selection)

این الگوریتم بر مبنای انتخاب جامعه سلول های B ایجاد شده است.بخش های اصلی این الگوریتم شامل شناسایی آنتی ژن، تکثیر و جهش سلول های B (آنتی بادی ها) و ایجاد سلول های حافظه است. در این الگوریتم اکثر سلول ها برای تکثیر انتخاب می شوند اما از همه سلول ها به یک اندازه تکثیر نمی شوند؛ بلکه سلول هایی که میل ترکیبی بیشتری دارند ، بیشتر تکثیر می شوند.

از طرف دیگر سلول هایی که میل ترکیبی کمتری داشته اند بیشتر تغییر می یابند. به بیان دیگر تکثیر نسبت مستقیمی با میل ترکیبی و جهش نسبت عکس با میل ترکیبی دارد. بدین ترتیب میل ترکیبی سلول ها به مرور زمان افزایش یافته و تنوع نیز حفظ می شود.

مراحل الگوریتم انتخاب جامعه

مراحل الگوریتم انتخاب جامعه عبارتند از :

 

 

Code Clonal Selection

 

مراحل الگوریتم انتخاب جامعه

 

الگوریتم انتخاب معکوس (Negative Selection)

این الگوریتم بر مبنای سلول های T ایجاد شده است.سلول های T می توانند سلول های خودی و غیر خودی را از یکدیگر تشخیص دهند.الگوریتم انتخاب معکوس دو مرحله دارد. مرحله اول که مرحله یادگیری است مشابه کار تیموس را انجام می دهد. یعنی سلول هایی که سلول های خودی را شناسایی می کنند را حذف می کند. مرحله دوم، مرحله نظارت یا اجراء است. در این مرحله الگوها (آنتی ژن ها) با سلول های T باقیمانده از مرحله اول مقایسه شده و در صورت شناسایی حذف می شوند. این الگوریتم در شناسایی الگو و امنیت نظارتی کاربرد دارد.

مراحل الگوریتم انتخاب معکوس

فرض می کنیم S مجموعه الگوهای خودی باشد که باید محافظت شده و مجموعه A نیز محافظ ها می باشند.

 

با توجه به مراحل فوق این الگوریتم دارای قابلیت یادگیری است. پس از یادگیری از مجموعه A در مرحله نظارت یا اجراء استفاده می شود.در این مرحله هر الگوی ورودی با الگوهای جدیددر مجموعه A مقایسه می شود و در صورتی که میل ترکیبی آنها از یک حد آستانه ای بیشتر شود ، الگوی ورودی به عنوان یک الگوی غیرخودی حذف می شود.

الگوریتم شبکه ایمنی (Immune Network)

الگوریتم انتخاب جامعه دارای چند مشکل است. اول اینکه آنتی بادی های حاصل از این الگوریتم نسبت به آخرین داده های ورودی یعنی آنتی ژن ها تنظیم می شوند. دوم اینکه آنتی بادی ها تمایل دارند که در نزدیکی یکدیگر تجمع کنند.به بیان دیگر چندین آنتی بادی مقداری نزدیک به هم بدست می آورند. الگوریتم شبکه ایمنی مصنوعی این دو نقص الگوریتم انتخاب جامعه را برطرف می نماید.

در یک شبکه ایمنی مصنوعی ، برای آنتی بادی بجز میل ترکیبی با آنتی ژن ، معیارهای ارزیابی دیگری نیز وجود دارد.معیار ارزیابی اصلی در شبکه ایمنی مصنوعی میزان تحریک شدن آنتی بادی است.میزان تحریک آنتی بادی بر مبنای میل ترکیبی آنتی بادی با آنتی بادی های دیگر و میل ترکیبی سایر آنتی بادی ها با آنتی بادی مورد نظر محاسبه می شود.در صورتیکه یک آنتی بادی ، آنتی بادی دیگر یا آنتی ژن را شناسایی کند ، تحریک می شود اما از طرف دیگر شناسایی شدن یک آنتی بادی توسط آنتی بادی دیگر تاثیر بازدارندگی بر روی آن دارد. میزان تحریک یک آنتی بادی بطور کلی از رابطه زیر بدست می آید:

S = Nt – ct + Ag

Nt : میزان تحریک شدن آنتی بادی توسط شبکه است.
ct : میزان بازدارندگی شبکه ای آنتی بادی می باشد.
A : میزان تحریک آنتی بادی توسط آنتی ژن است.

به دلیل هزینه محاسباتی زیاد رابطه فوق ، الگوریتم های مختلفی برای شبکه ایمنی مصنوعی ارائه شده که از نسخه ساده شده رابطه فوق استفاده می نمایند.

مراحل الگوریتم شبکه ایمنی مصنوعی

الگوریتم شبکه ایمنی مصنوعی را می توان بطور کلی به صورت زیر تعریف کرد:

Code Immune Network

مراحل الگوریتم شبکه ایمنی مصنوعی

الگوریتم aiNET

الگوریتم های متفاوتی برای شبکه ایمنی مصنوعی مطرح شده است که هر یک از آنها بخش های مختلف را به روش خود تعریف کرده اند. یکی از الگوریتم های معروف؛ الگوریتم aiNET می باشد. طبق تعریف aiNET گرافی وزن دار است که ممکن است کاملا همبند نباشد. گره های این گراف را آنتی بادی ها تشکیل می دهند و وزن لبه ها نمایانگر استحکام ارتباط میان دو گره می باشد. مراحل الگوریتم aiNET عبارتند از :

مراحل الگوریتم aiNETمراحل الگوریتم aiNET

مراحل ۱،۲ تا ۸،۲ در الگوریتم فوق انتخاب جامعه می باشد. در مرحله ۴،۲ جهش از رابطه   فرمول جهش   بدست می آید که در آن c’ ماتریس آنتی ژن، c جامعه آنتی بادی ها و ضریب یادگیری یا نرخ جهش است. نرخ جهش در این الگوریتم از حاصل ضرب یک عدد ثابت و یک عدد تصادفی با توزیع یکنواخت در بازه صفرو یک در فاصله آنتی بادی و آنتی ژن بدست می آید.

در الگوریتم فوق، جامعه سازی متناسب با میل ترکیبی باعث می شود که عمل استخراج در نزدیکی پاسخ به خوبی انجام شود زیرا هرچه آنتی بادی به آنتی ژن نزدیک تر باشد، نمونه های مشابه بیشتری تولید می کند و در نتیجه عمل استخراج بهتری انجام می شود.

جهش نیز با توجه به رابطه ای که بیان شد، منتاسب با عکس میل ترکیبی است. یعنی هرچه میل ترکیبی بیشتر باشد (فاصله کمتر)، جهش ها کوچکتر می شود و عمل استخراج صورت می پذیرد و هرچه میل ترکیبی کمتر باشد (فاصله بیشتر) در نتیجه جهش های برزگتری انجام می شود. بدین ترتیب آنتی بادی هایی که از جواب دور هستند عمل اکتشاف و آنتی بادی هایی که نزدیک جواب هستند عمل استخراج را انجام خواهند داد.

مراحل ۹،۲ و ۴ به ترتیب اعمال بازدارندگی جامعه و شبکه را انجام خواهند داد. در مرحله ۹،۲ الگوریتم عمل بازدارندگی روی مجموعه اعضاء جامعه ایجاد شده برای هر آنتی زن جاری انجام می گیرد و در مرحله ۴ این عمل بر روی تمامی آنتی بادی های شبکه انجام می شود. این دو مرحله باعث می شوند آنتی بادی هایی که آنتی ژن های مشابهی را شناسایی می کنند، حذف شوند.

پارامتر حد آستانه، انعطاف پذیری شبکه، دقت خوشه بندی و میزان اختصاص بودن هر یک از آنتی بادی ها را تعیین می کند. هرچه مقدار کوچکتر باشد، آنتی بادی های شبکه می توانند به هم نزدیکتر شوند و در نتیجه دقت خوشه بندی شبکه و میزان اختصاص بودن بیشتر می شود. از طرف دیگر هرچه اتدازه بزرگتر شود، هر آنتی بادی محدوده بزرگتری را شناسایی می کند و در نتیجه شبکه از نظر حاصل از نظر تعداد آنتی بادی کوچک تر می شود و دقت خوشه بندی آن کمتر می شود.

پس از مرحله ۵ الگوریتم، خروجی شبکه به صورت مجموعه ای از آنتی بادی ها (گره های گراف) و میل ترکیبی آنها (لبه های گراف) بدست می آید که یک گراف کامل است. به منظور انجام عمل خوشه بندی، باید تعدادی از یال های گراف حذف شوند تا گراف خوشه های مختلف گراف از یکدیگر جدا شوند. برای این منظور می توان از مقدار آستانه استفاده کرد اما این روش کارایی ندارد.

در سال ۲۰۰۰ میلادی کاسترو در همایش شبکه های عصبی مصنوعی در ریودژانیروی برزیل، روش دیگری ارائه نمود. در روش کاسترو ابتدا درخت پوشای مینیمم گراف محاسبه شده و سپس یال هایی که مقدار آنها از یال های هم جوارشان به صورت مشخصی بیشتر است حذف می شوند. گره های باقیمانده به یک کلاس تعلق دارند.

 

Code aiNET Algorithm

 

معرفی انواع کاربرد سیستم های ایمنی مصنوعی

به طور کلی، سیستم‌های ایمنی مصنوعی جزء الگوریتم‌های الهام گرفته شده از بیولوژی هستند. این نوع الگوریتم‌ها، الگوریتم‍ هایی کامپیوتری هستند که اصول و ویژگی‌های آنها نتیجه بررسی در خواص وفقی و مقاومت نمونه‌ها بیولوژیکی است. سیستم ایمنی مصنوعی نوعی الگو برای یادگیری ماشین است. یادگیری ماشین، توانایی کامپیوتر برای انجام یک کار با یادگیری داده‌ها یا از روی تجربه است. تعریف کاسترو از سیستم ایمنی عبارتست از :

“سيستم هاي وفقي كه با الهام از ايمونولوژي نظري و توابع، اصول و مدل هاي ايمني مشاهده شده به وجود آمده‌اند و برای حل مسائل مورد استفاده قرار می‌گیرند.”

كاسترو و تيميس سه ویژگی زیر را برای الگوريتم ايمني مصنوعي معرفی نموده اند:

۱٫ در هر الگوريتم ايمني مصنوعي، حداقل بايد يك جزء ايمني مانند لنفوسيت ها وجود داشته باشد.
۲٫ در هر الگوريتم ايمني مصنوعي بايد ايده اي برگرفته از بيولوژي نظري يا تجربي استفاده شود.
۳٫ الگوريتم ايمني مصنوعي طراحي شده بايد به حل مسئله اي كمك كند.

بر اساس سه ویژگی فوق، كاسترو و تيميس، اولين الگوريتم هاي ايمني مصنوعي را در سال ۱۹۸۶ طراحي كردند. در همان سال فارمر مدلی برای تئوری شبکه ایمنی ارائه کرد و بر اساس این مدل اعلام کرد که “سیستم ایمنی قادر به یادگیری، به خاطر سپردن و تشخیص الگوست.” بعد از نظر فارمر، توجه به سیستم ایمنی مصنوعی به عنوان یک مکانیزم یادگیری ماشین شروع شد. پس از آن به تدریج سیستم ایمنی مصنوعی ، در زمینه‌های مختلف وفق پذیر و جذاب بودن خود را نشان داد.

سیستم ایمنی علاوه بر توانایی تشخیص الگو، صفات دیگری از قبیل یادگیری، حافظه، خود سازماندهی و از منظر مهندسی، خصوصیات دیگری مانند تشخیص بی‌قاعدگی، تحمل خطا، توزیع‌پذیری و مقاومت بالا دارا می باشد. از زمان آغاز بحث سیستم ایمنی مصنوعی ، این سیستم برای اهداف متنوعی به کار گرفته شده است. این کاربردها را می توان تحت ۹ عنوان کاربردی دسته‌بندی نمود. این عناوین کاربردی عبارتند از :

۱٫ تشخیص عیب (Fault Detection)
۲٫ تشخیص ناهنجاری (Anomaly Detection)
۳٫ تشخیص نفوذ (Intrusion Detection)
۴٫ امنیت اطلاعات (Information Security)
۵٫ مسائل بهینه سازی (Optimization Problems)
۶٫ دسته بندی الگوها (Patterns Classification)
۷٫ زمانبندی (Scheduling)
۸٫ خوشه بندی (Clustering)
۹٫ سیستم های یادگیرنده (Learning Systems)

در ادامه به تشریح دو مثال از کاربردهای سیستم ایمنی مصنوعی می پردازیم.

سیستم ایمنی مصنوعی (AIS) قسمت 1
سیستم ایمنی مصنوعی (AIS) قسمت 2
سیستم ایمنی مصنوعی (AIS) قسمت 3
سیستم ایمنی مصنوعی (AIS) قسمت 4
سیستم ایمنی مصنوعی (AIS) قسمت 5
سیستم ایمنی مصنوعی (AIS) قسمت 6

فرآیند فعال شدن سیستم ایمنی بدن انسان

در بدن انسان برای تولید سلول های B و T از الگوریتم انتخاب منفی استفاده می شود. این سلول ها در مغز استخوان و تیموس به صورت تصادفی ساخته می شوند. در این دو محیط فقط سلول های خودی دیده می شود. این سلول ها اگر با یک سلول خودی منطبق شدند از بین می روند و در غیر این صورت وارد بدن می شوند. این سلول ها دارای ویژگی خود تحمل پذیری کامل می باشند. آین ویژگی بدین معنا است که سلول B یا T تنها با آنتی ژن سلول های غیرخودی منطبق می شوند.سلول های B دارای ویژگی خود تحمل پذیری کامل نمی باشند زیرا نمونه همه سلول های بدن در مغز استخوان وجود ندارد ولی سلول های T به دلیل تکامل و بالغ شدن در تیموس دارای این ویژگی می باشند. اگر آنتی بادی یک سلول B با آنتی ژن یک سلول غیرخودی منطبق شود یک سیگنال اولیه ایجاد می شود.بنابراین اگر یک سلول B با یک سلول غیرخودی مواجه شود آن را می بلعد.اگر گیرنده های TCR موجود بر روی یک سلول T با الگوهای یک سلول B بتواند منطبق شود و در صورتی که سلول T قبلا فعال شده باشد آنگاه سلول T سیگنال دوم یا سیگنال کمک را منتشر می کند. این سیگنال دوم نشان می دهد که یک سلول غیرخودی تشخیص داده شده است و سپس الگوریتم انتخاب با تکثیر آغاز می شود.

 

الگوریتم انتخاب با تکثیر

الگوریتم انتخاب با تکثیر

 

در الگوریتم انتخاب با تکثیر ، بدن شروع به ایجاد سلول های B جدید از روی سلول های B که با آنتی ژن سلول بیگانه جفت شده است ، می کند.سلول های تازه ایجاد شده با سلول قبلی کمی تفاوت دارند و بهتر با آنتی ژن مورد نظر جفت می شوند.تعدادی از این سلول ها به سلول های حافظه تبدیل می شوند و مدت زمان بیشتری در بدن زنده می مانند و می توانند مرحله تشخیص را در حمله های بعدی تسریع نمایند.معمولا برای آغاز شدن الگوریتم انتخاب با تکثیر به هر دو سیگنال اول و دوم نیاز است. البته الگوریتم انتخاب با تکثیر در یک حالت می تواند بدون وجود سیگنال دوم شروع شود. این حالت هنگامی رخ می دهد که میزان تطبیق سلول B و سلول غیرخودی از حد آستانه بیشتر باشد. این مورد در صورتی اتفاق می افتد که جفت شدن با یک سلول حافظه صورت پذیرد.

سلول T در صورتی فعال می شود که یک سیگنال تائید کننده از یک سلول عرضه کننده آنتی ژن دریافت نماید.این سیگنال تائید، سیگنال هم تحریک نامیده می شود. سلول عرضه کننده آنتی ژن در صورتی این سیگنال را می دهد که از یک سلول خودی یا یک سلول امنیتی سیگنال خطر را دریافت نماید. سلول خودی در شرایطی که به خاطر وجود پاتوژن یا سلول غیرخودی بیماری زا احساس خطر نماید این سیگنال را ارسال می کند.

اصلی ترین هدف سیستم ایمنی طبیعی ، تمایز میان خودی و غیر خودی است. با توجه به عملکردها و واکنش های خاص سیستم ایمنی در برخی موارد ، امکان توضیح این واکنش ها با مدل تمایز میان خودی و غیرخودی وجود ندارد. برای توضیح این واکنش ها تئوری خطر مطرح گردید. مبنای تئوری خطر سیگنال های بین سلولی است. سلول T هنگامی فعال می شود که یک سیگنال تائید کننده از سلولی از نوع سلول عرضه کننده آنتی ژن دریافت کند.

سلول عرضه کننده آنتی ژن در صورتی این سیگنال را می دهد که از یک سلول خودی یا یک سلول امنیتی سیگنال خطر دریافت نماید. سلول خودی در شرایطی مانند وجود سلول غیرخودی بیماری زا ، سیگنال خطر را ارسال می نماید. سیگنال خطر هر نوع نشانه ای از مرگ غیر طبیعی سلول های خودی است که به صورت محلی در اطراف سلول مُرده ایجاد می شود.عواملی که توسط سلول های عرضه کننده آنتی ژن به عنوان سیگنال خطر قلمداد می شوند همگی مواد و ترکیبات داخل سلول ها هستند که به دلیل مرگ غیر طبیعی و با پاره شدن غشای سلول بدون حضور سلول بیگانه خوار در محیط اطراف سلول مُرده پخش می شوند.

هر رویداد الکتروشیمیایی که در خارج سلول رخ دهد و توسط گیرنده های سلول به داخل آن منتقل شود و باعث ایجاد رفتاری در سلول شود، یک سیگنال سلولی نامیده می شود.ارتباط سیگنالی بین سلول ها می تواند توسط ارتباط هایی با فواصل طولانی حاصل از ترشح هورمون ها یا ارتباط های محلی میان مولکول های سطح سلول های مجاور ، برقرار گردد.

سیگنال سازی سلول ها به دو دسته هورمونی و فیزیکی تقسیم بندی می شود. سیگنال سازی هورمونی امکان ارتباط بین سلول های دور از هم را بوسیله مولکول های کوچک و قابل حمل فراهم می سازد. سیگنال سازی فیزیکی ارتباط بین سلول ها را به صورت فیزیکی و مستقیم فراهم می سازد. این نوع سیگنال سازی بین سلول های T و سلول های عرضه کننده آنتی ژن امکان پذیر است. این روش با کمک سایتوکین ها صورت می پذیرد.

سایتوکین ها موادی با ساختار پروتئینی هستند که نقش انتقال پیام ها را در سیستم ایمنی برعهده دارند. مبداء سایتوکین یک سلول تحریک شده است. سایتوکین ها پس از انتشار بر روی سلول های مقصد در مجاورت و حتی خود سلول مبداء تاثیر می گذارند. تعداد کمی از انواع سایتوکین ها قابلیت انشار به مقاصد دور و جریان یافت در شریان ها را دارا می باشند.هورمون ها گروه دیگری از مواد شیمیایی هستند که برای انتقال پیام در بدن استفاده می شوند. هومون ها قابلیت بالایی برای انتشار در شریان های بدن و راهیابی به فواصل دور در بدن دارند.

معرفی و تعریف سیستم های ایمنی مصنوعی

سیستم ایمنی مصنوعی به سیستم های سازگار گفته می شود که از ایده مکانیزم دفاعی بدن انسان الهام گرفته و راه حلی برای مسائل پیچیده ارائه نموده اند. کاربرد سیستم ایمنی مصنوعی را می توان به صورت ذیل طبقه بندی نمود:

۱٫ تشخیص عیب (Fault Detection)
۲٫ تشخیص ناهنجاری (Anomaly Detection)
۳٫ تشخیص نفوذ (Intrusion Detection)
۴٫ امنیت اطلاعات (Information Security)
۵٫ مسائل بهینه سازی (Optimization Problems)
۶٫ دسته بندی الگوها (Patterns Classification)
۷٫ زمانبندی (Scheduling)
۸٫ خوشه بندی (Clustering)
۹٫ سیستم های یادگیرنده (Learning Systems)

سیستم ایمنی بدن و بالطبع سیستم ایمنی مصنوعی دارای ویژگی های ذیل است:

1.توازی : این ویژگی بدین معنا است که سیستم ایمنی از جزءهای کوچکی تشکیل شده که با همکاری یکدیگر به حفظ امنیت بدن می پردازند. هرکدام از این اجزاء کوچک توان تشخیص و طول عمر کمی دارند ولی از ترکیب آنها یک سیستم قدرتمند بوجود می آید.

2. توزیع شدگی : توزیع شدگی در سیستم ایمنی بدین معنا است که هر کدام از سلول های ایمنی و در کنار آنها هرکدام از دستگاه های ایمنی ، قدرت تصمیم گیری برای کار خود را دارا می باشند و نیازی به یک مرکز پردازشی وجود ندارد. تمام دستگاه ها و سلول ها با یکدیگر در ارتباط بوده و برای این ارتباط نیازی به سیستمی واحد و متمرکز نیست.

3. تطبیق پذیری : تطبیق پذیری ریشه در یادگیر بودن سیستم ایمنی دارد. بدن انسان با محیط طبیعی خود ارتباط داشته و با آن در تعامل است.بنابراین مواد مفید ، مضر یا بیماری زایی که وارد بدن انسان می شوند نیز متغیر هستند. در ضمن بدن انسان نیز به طور مداوم در حال نوسازی و تغییر است. به همین دلایل سیستم ایمنی به صورتی طراحی شده است که با تغییرات به صورت پویا برخورد نماید و با وجود تغییر ، عوامل بیماری زا را عامل های سالم تشخیص داده و با آنها مبارزه نماید.

4. قابلیت تشخیص الگو : در سیستم ایمنی قابلیت تشخیص الگو توسط آنتی بادی ها وجود دارد. این تشخیص الگو با استفاده از یک سطح آستانه انجام می شود.

5. قابلیت یادگیری : سیستم ایمنی قادر است عوامل بیماری زای جدیدی را که مشاهده می کند به خاطر بسپارد.

6. همکاری گروهی : در سیستم ایمنی سلول ها به صورت گروهی ، موازی و توزیع شده برای تشخیص و انهدام همکاری دارند.

7. چند لایه ای بودن : هیج موجودیتی در سیستم ایمنی و بدن انسان ، یک مکانیزم کامل امنیتی و دفاعی را فراهم نمی کند. بلکه هر لایه سیستم ایمنی به صورت مستقل عمل کرده و و با بقیه لایه ها در ارتباط است.

8. تنوع و گوناگونی : سیستم ایمنی در برابر انواع مختلفی از نفوذها مقاومت کرده و تسلیم نمی شود.

9. بهینه بودن منابع : در سیستم ایمنی با ایجاد مرگ و تکثیر سلولی ، همواره یک نمونه فضای کوچکی از فضای جستجوی آنتی ژن ها در هر زمان نگهداری می شود.

10. پاسخ انتخابی : در سیستم ایمنی ، پس از شناسایی یک آنتی ژن ، پاسخ های متفاوتی داه می شود و همواره به یک شکل عمل نمی شود.

برای حل یک مسئله با استفاده از سیستم ایمنی مصنوعی باید سه مرحله ذیل انجام پذیرد.
(۱) نحوه نمایش داده های مسئله یا تعریف فضای شکل.
(۲) معیار اندازه گیری میل ترکیبی.
(۳) انتخاب یک الگوریتم ایمنی مصنوعی برای حل مسئله.

در سیستم ایمنی همه چیز بر مبنای شناسایی الگو یا شناسایی شکل آنتی ژن است. سیستم ایمنی را می توان به فضایی مملو از شکل های مختلف تشبیه نمود. هدف در این فضا پیدا کردن مکمل شکل ها و شناسایی آنها است. در واقع آنچه سیستم های ایمنی مصنوعی دنبال می کنند پیدا کردن تعدادی شکل بهینه (آنتی بادی) در فضای شکل است که مکمل تمامی شکل های موجود در داده های مسئله (آنتی ژن ها) باشند.
به بیان دیگر در سیستم ایمنی مصنوعی هدف این است که برای N الگو یا آنتی ژن ، M آنتی بادی پیدا شود. البته M خیلی کوچکتر از N است.شکل ها یا آنتی ژن ها به صورت آرایه ای از اعداد نمایش داده می شوند. این آرایه می تواند اعداد باینری ، صحیح یا حقیقی باشد.هر شیوه ای که برای نمایش آنتی ژن استفاده شود برای نمایش آنتی بادی نیز استفاده می شود.

مسئله دیگر نحوه محاسبه میل ترکیبی یک آنتی ژن و آنتی بادی است.عنوان شد که هرچه آنتی بادی میل ترکیبی بیشتری با آنتی ژن داشته باشد ، مکمل بهتری برای آن آنتی ژن است.اگر هر شکل در فضای شکل به صورت صورت یک آرایه از اعداد نمایش داده شود ، میل ترکیبی را می توان معادل شباهت آرایه ها در نظر گرفت. از طرفی هرچه فاصله کمتر شود ، شباهت بیشتر می شود.به بیان دیگر هرچه فاصله انتی بادی با آنتی ژن کمتر شود ، آنتی بادی مکمل بهتری برای آنتی ژن است. بر همین مبنا در الگوریتم های ایمنی مصنوعی از فاصله به عنوان معیار ارزیابی خوب یا بد بودن یک آنتی بادی استفاده می شود.

با توجه به دو تعریف فضای شکل و میل ترکیبی مکمل بودن یک آنتی بادی و یک آنتی ژن ، شناسایی یک آنتی ژن توسط آنتی بادی با استفاده از مقدار آستانه میل ترکیبی تعریف می شود. اگر میزان میل ترکیبی یک آنتی بادی با یک آنتی ژن بیشتر از حد آستانه میل ترکیبی باشد آنگاه آنتی ژن در محدوده شناسایی آنتی بادی قرار گرفته است. به بین دیگر اگر فاصله یک آنتی بادی و یک آنتی ژن از حد آستانه شناسایی کمتر باشد ، آنتی بادی ، آنتی ژن را شناسایی می کند.بنابراین هر آنتی بادی می تواند تعدادی آنتی ژن را که تفاوت های اندکی با یکدیگر دارند شناسایی کند و در نتیجه تعداد آنتی بادی ها می تواند کمتر از آنتی ژن ها باشد.

تاریخچه سیستم های ایمنی مصنوعی

پایه های مدل سازی ریاضی بخش هایی از دستگاه ایمنی بدن در سال ۱۹۷۴ میلادی توسط نیلز جِرن انجام پذیرفته است.اولین ایده استفاده از فرآیندهای دستگاه ایمنی بدن در کاربردهای محاسباتی در سال ۱۹۸۶ میلادی توسط جان فارمر، نورمن پاکارد و آلن پِرِلسون مطرح گردید. آنها رفتار پویای سیستم ایمنی را با معادلات دیفرانسیل مدل کرده و نشان دادند که می توان از این مدل برای یادگیری مسائل استفاده نمود.

تا اوایل دهه ۹۰ میلادی بیشتر کاربردهای دستگاه ایمنی بدن در سیستم های محاسباتی ، شامل یکسری شبیه سازی هایی مانند شبیه سازی بیماری ایدز و مدلسازی ارتباطات سلولی بود و در ادامه با کارهای استفانی فارِست، هوگوس بِرسینی، جاناتان تیمیس، مارک نیل، دیپانکار داسگوپتا، لیندرو دی کاسترو بطور گسترده تری پیگیری شد.

در سال ۱۹۹۰ میلادی هوگوس بِرسینی و فراسیسکو وارِلا ایده شبکه های ایمنی که پیشتر توسط نیلز جِرن و آلن پرلسون در زمینه دستگاه ایمنی مطرح شده بود را برای سیستم های محاسباتی مطرح کردند.

فارِست و داسگوپتا تاکنون مطالعات گسترده ای درباره الگوریتم انتخاب منفی انجام داده اند و دی کاسترو مطالعاتی روی انتخاب مبتنی بر تکثیر انجام داده است. اولین کتاب درباره سیستم های ایمنی مصنوعی نیز در سال ۱۹۹۹ میلادی توسط داسگوپتا منتشر گردید.

در سال ۲۰۰۳ میلادی یووی آیلکین به همراه تیمی از اساتید و دانشجویان رشته های علوم کامپیوتر و ایمنی شناسی دانشگاه ناتینگهام انگلستان نظریه خطر را ارائه نموند که تاکنون این تیم گزارشات و مقالات متعددی در زمینه کاربرد نظریه خطر در سیستم های محاسباتی منتشر نموده اند.
سیستم ایمنی مصنوعی (AIS) قسمت 1
سیستم ایمنی مصنوعی (AIS) قسمت 2
سیستم ایمنی مصنوعی (AIS) قسمت 3
سیستم ایمنی مصنوعی (AIS) قسمت 4
سیستم ایمنی مصنوعی (AIS) قسمت 5
سیستم ایمنی مصنوعی (AIS) قسمت 6

سیستم‌های ایمنی مصنوعی جزء الگوریتم‌های الهام گرفته شده از بیولوژی هستند. این نوع الگوریتم‌ها، الگوریتم هایی کامپیوتری هستند که اصول و ویژگی‌های آنها نتیجه بررسی در خواص وفقی و مقاومت نمونه‌ها بیولوژیکی است. سیستم ایمنی مصنوعی نوعی الگو برای یادگیری ماشین است. یادگیری ماشین، توانایی کامپیوتر برای انجام یک کار با یادگیری داده‌ها یا از روی تجربه است. در این پروژه ابتدا سیستم ایمنی انسان تشریح شده زیرا در سیستم های ایمنی مصنوعی از مدل ایمنی طبیعی پیروی می شود. سپس سیستم ایمنی مصنوعی معرفی و تعریف می گردد. در ادامه به تاریخچه و نحوه عملکرد الگوریتم خواهیم پرداخت و انواع کاربردهای الگوریتم سیستم ایمنی مصنوعی معرفی شده و دو مثال از بین کاربردها تشریح خواهند شد.

سیستم ایمنی بدن انسان

محیط اطراف بدن انسان حاوی انواع عوامل نظیر ویروس ها ، باکتری ها و قارچ ها است. اگر این عوامل وارد بدن انسان یا میزبان شوند و موقعیت تکثیر پیدا نمایند می توانند میزبان را از پا در آورند. البته بیشتر این عوامل به دلیل وجود واکنش‌هایی از طرف بدن میزبان چنین موقعیتی را پیدا نمی کنند و پس از مدت کوتاهی از بین می‌روند.واکنش‌هایی که باعث مبارزه با عوامل ذکر شده می شوند توسط سیستمی یکپارچه به نام دستگاه ایمنی صورت می‌گیرند. در بدن انسان دستگاه ایمنی شامل مولکول‌ها ، سلول ها و بافت هایی است که در برابر عوامل بیماری زا و عفونت حاصله از آنها مقاومت ایجاد نموده و مانع رشد آنها می شود.دستگاه ایمنی بدن انسان دارای پیچیدگی های زیادی است که وجود این پیچیدگی ها منجر به وجود علم ایمنی شناسی شده است. این علم به مطالعه دستگاه ایمنی بدن انسان و پاسخ های آن در برابر عوامل بیماری زا می پردازد.

خطوط دفاعی بدن انسان

اولین خط دفاعی بدن انسان یک حصار فیزیکی مانند پوست است. پس از آن سیستم ایمنی ذاتی است که از هنگام به دنیا آمدن به صورت طبیعی در بدن وجود دارد.خط سوم دفاعی سیستم ایمنی تطبیقی می باشد که قابلیت یادگیری و بهبود مکانیزم دفاعی را دارا می باشد. ایمنی تطبیقی نسبت به ایمنی ذاتی آهسته تر بوجود می آید ولی ایمنی موثرتری را فراهم می نماید.

 

سیستم تطبیقی بدن انسان

سیستم تطبیقی بدن انسان

 

سیستم ایمنی تطبیقی از دو نوع سلول به نام های سلول B و سلول T تشکیل شده است. سطح این سلول ها از پروتئین های آنتی بادی پوشیده شده است. بر روی تمام سلول های دیگر بدن پروتئین های آنتی ژن وجود دارد.آنتی بادی ها با آنتی ژن ها واکنش شیمیایی می دهند و می توانند به هم متصل شوند.

سیستم ایمنی تطبیقی به دو دسته عمده تقسیم می شود : ایمنی همورال و ایمنی با واسطه سلولی.
هریک از این انواع ایمنی تطبیقی ، بوسیله سلول ها و مولکول های متفاوتی اداره می شوند و به ترتیب برای دفاع در برابر میکروب های خارج سلولی و داخل سلولی طراحی شده اند.ایمنی همورال ، با استفاده از پروتئین هایی که آنتی بادی هستند و بوسیله سلول های B ساخته می شوند ، نقش خود را ایفاء می کنند.آنتی بادی ها به درون سیستم گردش خون و ترشحات مخاطی ترشح می شوند و میکروب ها و سموم میکروبی را که به خون و حفرات اندام های مخاطی مانند
مجاری تنفسی و روده ای راه یافته اند را حذف و خنثی می نمایند. یکی از مهمترین وظایف آنتی بادی ها ، مهار دسترسی و متمرکز شدن میکروب هایی است که از سطوح مخاطی و و خون به سلول های میزبان و بافت های همبند حمله ور می شوند.بدین ترتیب آنتی بادی ها از استقرار و ادامه عفونت جلوگیری می نمایند. آنتی بادی ها به به میکروب هایی که درون سلول آلوده وجود دارند و تکثیر می شوند دستیابی ندارند. این مشکل میکروب های درون سلولی توسط ایمنی با واسطه سلولی برطرف می شود. این ایمنی با واسطه سلول های T بوجود می آید.برخی از سلول های T ، سلول های بیگانه خوار را برای از بین بردن میکروب هایی که بوسیله سلول ها بلعیده شده اند را فعال می کند. سلول های بیگانه خوار در اصل گلبول های سفید خون هستند که سلول های تصویر بیگانه موجود در بدن را می بلعند. سایر سلول های T هر نوع سلول میزبان دارای میکروب درون سیتوپلاسم را از بین می برند. بنابراین سلول های B و T به ترتیب برای شناسایی اختصاصی آنتی زن های میکروب های خارج سلولی و درون سلولی طراحی شده اند. تفاوت دیگر این دو سلول در این است که سلول های T فقط آنتی ژن های پروتئینی میکروب ها را شناسایی می کنند اما سلول های B قادر هستند انواع متفاوتی از مولکول های میکروبی را شناسایی نمایند.

سلول B

سلول B

 

آشنایی با مفاهیم اولیه سیستم ایمنی بدن انسان

مهمترین ارگان های سیستم دفاعی بدن انسان عبارتند از : مغز استخوان، تیموس، طحال، رگ های لنفی، گره های لنفی، لوزه و آدونوئید. در تصویر زیر جایگاه هرکدام از ارگان های سیستم دفاعی بدن انسان را مشاهده می نمائید.

 

ارگان های سیستم دفاعی بدن انسان

ارگان های سیستم دفاعی بدن انسان

 

تیموس و مغز استخوان بافت های لنفاوی زاینده نامیده می شوند زیرا در تولید سلول های دستگاه ایمنی (گلبول های سفید) و بلوغ آنها نقش اساسی دارند. این دو ارگان اعضای لنفاوی اصلی نیز نامیده می شوند. تیموس غده ای در اطراف جناغ سینه و گردن انسان است که در بلوغ سلول های T نقش اساسی دارد. این غده تا دوران بلوغ رشد کرده و پس از آن به مرور کوچک تر می شود تا در دوران کهنسالی به غده ای از چربی تبدیل می شود.نقش مهم این غده در آموزش سلول های T برای تشخیص خودی از غیر خودی و ایجاد تحمل ایمنی می باشد. طحال نیز در تولید گلبول های سفید خون نقش دارد و گلبول های قرمز پیر را از بین می برد.

رگ های لنفاوی کانال ارتباطی میان دیگر ارگان ها هستند.گلبول های سفید علاوه بر این که می توانند توسط رگ های خونی در تمام بدن حرکت کنند ، می توانند در سیستمی از رگ های لنفی که به موازات رگ های خونی وجود دارند و به گره های لنفی منتهی می شوند ، نیز حرکت کنند. گره های لنفاوی یکی از مهمترین مولفه های سیستم ایمنی هستند. این گره ها در سرتاسر شریان های لنفی و به تعداد زیاد وجود دارند.گلبول های سفید بالغ به اندام های لنفاوی محیطی رفته و در آنجا به آنتی ژن های خارجی واکنش نشان می دهند و از آنجا وارد خون و رگ های لنفی می شوند. سیستم مخاطی ، طحال و رگ ها و گره های لنفاوی جزء بافت های لنفاوی ثانویه محسوب می شوند.

سلول های B

سلول های B از سلول های ریشه ای مغر استخوان نشات گرفته و در مجاورت سلول های نمدی مغز استخوان مراحل اولیه تکامل را سپری می کنند. سپس از سلول های نمدی جدا شده و مرحله دوم تکامل خود را در مغز استخوان به پایان می رسانند. اگر سلول تشکیل شده ، سلولی سالم باشد و علیه سلول های خودی بدن واکنش نشان ندهد ، از مغز استخوان خارج شده و برای شناسایی و مقابله با آنتی ژن ها وارد بدن می شود.سلول های B پس از تحریک شدن تکثیر یافته و به سلول های حافظه تبدیل می شوند. تحریک سلول های B می تواند در اثر سیگنال های رسیده از جانب سلول های T توسط مولکول های سایتوکین یا مستقیما توسط آنتی ژن ها صورت بپذیرد.

سلول های T

سلول های T دارای نوع های مختلف با عملکردهای متفاوت می باشند.گروهی از سلول های T از طریق واکنش متقابل با سلول های بیگانه خوار تک هسته ای ، به آنها در جهت تخریب عوامل بیماری زای داخل سلولی کمک می کنند.این دسته از سلول های T ، سلول های T کمکی یا TH نامیده می شوند.این گروه از سلول های T می توانند با سلول های B نیز واکنش متقابل داشته و به آنها در جهت تقسیم ، تمایز و تولید آنتی بادی کمک کنند.دسته ای دیگر از سلول هایT وظیفه تخریب آن دسته از سلول های میزبان را که با ویروس یا عوامل بیماری زای داخل سلولی آلوده شده اند را برعهده دارند. این نوع از سلول های T را سلول T کُشنده یا TK می نامند.گروه سوم از سلول های T وظیفه تنظیم پاسخ ایمنی بدن و تعدیل آن پس از برطرف شدن عامل بیماری زا را برعهده دارند.این گروه از سلول های T را سلول T بازدارنده یا TS می نامند.سلول های T در مغز استخوان تولید شده و برای بلوغ و تکامل به تیموس مهاجرت می کنند.سلول های T روی سطح خود دارای مولکول های به عنوان گیرنده هستند که TCR نامیده می شوند.این گیرنده ها با مولکول های دیگری به نام هم گیرنده های TCR، در شناسایی آنتی ژن ها نقش اساسی را ایفا می کنند.

به اجتماع گیرنده ها و هم گیرنده های هر سلول T ، مجموعه TCR گفته می شود. سلول های T در مجموعه TCR متفاوت هستند. به عنوان مثال هم گیرنده های سلول های T کمکی از نوع CD4+ و هم گیرنده های سلول های T کُشنده از نوع CD8+ می باشند. نوع سلول T ، در تیموس و در خلال فرآیندهای انتخاب مشخص می شود. بنابراین یک سلول T هنگامی بالغ است که هم گیرنده آن مشخص شده باشد.گیرنده های TCR ، پیش از بلوغ روی سلول های T قراردارند ولی هم گیرنده آن طی فرآیند بلوغ مشخص می شود.

 

عملکرد سلول T

عملکرد سلول T

آنتی بادی

عنوان شد که پس از تحریک سلول های B توسط آنتی ژن ها و یا سلول های T ، این سلول ها به سلول های حافظه تبدیل می شوند. در این مرحله سلول های حافظه مقادیر زیادی از مولکول های گیرنده از نوع محلول که قابل ترشح است را می سازند.این ماده به عنوان آنتی بادی شناخته می شود زیرا آنتی بادی ها مشابه مولکول اصلی گیرنده هستند و به آنتی ژن هایی که در آغاز سلول B را فعال کرده است متصل می شوند.

آنتی ژن

کلمه آنتی ژن به معنی تولید کننده آنتی بادی است. هر مولکولی که به صورت اختصاصی توسط اجزای سیستم ایمنی مانند سلول های B و T و یا هردو شناسایی شود آنتی ژن محسوب می شود.

انواع مرگ سلول

مرگ برنامه ریزی شده سلول به هر شکلی از مردن یک سلول گفته می شود که بر اساس یک برنامه درون سلولی انجام می شود.مرگ طبیعی سلول راهی کلیدی برای خودپایداری سیستم ایمنی بشمار می رود و عاملی مهم برای تغییرات فیزیولوژیک عمومی سلول مانند تغییرات ریختی و تجزیه سلول به اجزای تشکیل دهنده اش برای ثابت نگاه داشتن حضور خود آنتی ژن ها است. فرآیند مرگ طبیعی سلول ها در طی یک روز برای افراد بالغ حدودا بین پنجاه تا هفتاد میلیارد بار اتفاق می افتد.
شکل دیگری از مرگ برنامه ریزی شده سلول ها ، نکروزیس می باشد که به مرگ غیرطبیعی سلول گفته می شود.نکروزیس باعث ایجاد واکنش های التهابی در اطراف سلول مرده می شود.

پاکسازی سلول های مرده

پاکسازی سلول های مرده توسط سلول های بیگانه خوار انجام می شود.این سلول ها نوعی از سلول های ایمنی هستند که سلول های میکروبی و سلول های مرده را طی فرآیند فاگوسیتوز با بلعیدن و هضم کردن از بین می برند. عوامل زیادی برای جلوگیری از فرآیند فاگوسیتوز بر سلول های سالم و خودی بدن وجود دارد. ساختارهای طبیعی بدن در بافت ها ، سطحی هموار دارند که در برابر سلول های بیگانه خوار مقاوم هستند. اما اگر سطح ذره ای نا هموار باشد احتمال انجام فاگوسیتوز بر روی آن افزایش می یابد. بیشتر مواد طبیعی بدن دارای پوشش حفاظتی پروتئینی هستند که سلول های بیگانه خوار را از خود دور می کنند.بافت های مرده و ذرات خارجی عموما فاقد پوشش حفاظتی هستند که آنها را در معرض سلول های بیگانه خوار قرار می دهد. از طرفی سیستم ایمنی بدن انسان هنگام ورود مواد عفونی نظیر باکتری ها به بدن ، آنتی بادی تولید می کند. آنتی بادی های تولید شده به غشاء باکتری ها چسبیده و و آنها را نسبت به سلول های بیگانه خوار حساس می کنند.
سیستم ایمنی مصنوعی (AIS) قسمت 1
سیستم ایمنی مصنوعی (AIS) قسمت 2
سیستم ایمنی مصنوعی (AIS) قسمت 3
سیستم ایمنی مصنوعی (AIS) قسمت 4
سیستم ایمنی مصنوعی (AIS) قسمت 5
سیستم ایمنی مصنوعی (AIS) قسمت 6

معرفی سیستم ایمنی مصنوعی(Artificial Immune System)

ایمنی از مولکول ها،سلول ها و قوانینی تشکیل شده که از آسیب رساندن عواملی مانند پاتوژن ها(Pathogens) به بدن جلوگیری می کند، قسمتی از پاتوژن به نام آنتی ژن(Antigen) که توسط این سیستم قابل شناسایی و موجب فعال شدن پاسخ سیستم ایمنی می شود. یک نمونه ای از پاسخ سیستم ایمنی ترشح آنتی بادی توسط سلول های B ،که آنتی بادی ها مولکول های شناساگری به شکل Y هستند که به سطح سلول های B متصل است و با یکسری قوانین از پیش تعریف شده آنتی ژن را شناسایی می کنند. مولکول های آنتی بادی قسمتی از آنتی ژن را به نام اپیتوپ شناسایی می کنند،ناحیه ای از آنتی بادی که وظیفه شناسایی و اتصال به آنتی ژن را دارد پاراتوپ گویند که با نام V شناخته می شود، که به منظور ایجاد بیشترین میزان تطابق با آنتی ژن ها می توانند شکل خود را تغییر دهند و به همین دلیل ناحیه متغیر نامیده می شود.

سیستم ایمنی مصنوعی

 

سطوح سیستم ایمنی

     1. اولين سطح – پوست

     2. دومین سطح – ايمني فيزيولوژيکي

  • اشک چشم ، بزاق دهان ، عرق و …

     3. سومین سطح – ایمنی ذاتی

  • پاسخ عمومی به آنتی ژن ها
  • بسیار کند

4. چهارمین سطح – ایمنی اکتسابی

  • پاسخ اختصاصی به آنتی ژن ها
  • بسیار سریع

سیستم ایمنی مصنوعی

ایمنی ذاتی(Innate Immunity)

سیستم ایمنی ذاتی برای تشخیص و حمله تعداد کمی از مهاجمان تنظیم و برنامه ریزی شده که این سیستم پاتوژن ها را در برخورد اولیه نابود می سازد و سیستم ایمنی اکتسابی برای فعال شدن و ایجاد واکنش نیاز به وقت دارد و وظیفه سیستم ایمنی  این است  که به سرعت در برابر مهاجمان واکنش نشان می دهد و حمله را تحت کنترل خود قرار داده تا سیستم ایمنی اکتسابی پاسخ موثرتری را فراهم نماید، هنگامی که ایمنی ذاتی فعال می شود فقط برای چند روزی فعال می ماند.

 

واکنش دستگاه ایمنی ذاتی نسبت به عفونت

واکنش دستگاه ایمنی ذاتی نسبت به عفونت

 

ایمنی اکتسابی (Adaptive Immunity)

این ایمنی هنگامی که فعال می شود برای هفته ها فعال می ماند و وظیفه ایمنی اکتسابی این است زمانی که ایمنی ذاتی به هر دلیلی کارآیی ندارد پاتوژن ها را از بین می برد. و ناکارا بودن ایمنی ذاتی یعنی اینکه نمی تواند پاسخ خاصی را برای پاتوژن مهاجم ایجاد کند و سیستم ایمنی اکتسابی وارد عمل می شود که برخلاف سیستم ایمنی ذاتی پاسخ ایمنی اکتسابی خاص و حافظه دارد و زمانی که یکبار پاتوژن به بدن حمله می کند و سیستم پاسخی را برای آن ایجاد می کند و آنرا به خاطر می سپارد و در برخورد های بعدی پاسخ سریع تری را برای مقابله با پاتوژن تولید می کند.

لنفسیت ها (Lymphocytes)

شناسایی آنتی ژن ها برعهده گلبول های سفید خون که لنفسیت نام دارد و دو نوع لنفسیت B و لنفسیت T داریم و در ادامه در مورد هر کدام توضیح خواهیم داد.

 لنفسیت های نوع B

 سلول های بنیادی که در مغز استخوان تولید می شوند و هر سلول B تعداد گیرنده سلولی (B-Cell Receptor) یا آنتی بادی(Antibody) در سطح خود دارد و هرکدام از این آنتی بادی ها دارای اشکال متفاوتی هستند که هر شکلی شبیه به سلول B را دارند و در نتیجه آنتی بادی هایی که توسط سلول B ساخته شده اند به مجموعه مشابهی از الگوهایی مولکولی متصل می شوند. آنتی بادی های سلول B دو ارزشی و دو عملکردی هستند، دو ارزشی به این دلیل که از طریق دو بازوی Fab به دو آنتی ژن متصل می شوند و از طریق قسمت FC به پذیرنده خاص روی سطح سلول های ایمنی دیگر وصل می شوند. اتصال به آنتی ژن دو نقش را بازی می کند که نقش اصلی آن برچسب زدن به آنتی ژن به عنوان یک مخرب تا مابقی سلول های سیستم ایمنی آن را تخریب کنند به این عملیات آماده مرگ می گویند، این کار با اتصال نواحی Fab آنتی بادی به آنتی ژن صورت می گیرد و ناحیه FC دستنخورده باقی می ماند تا اتصال با سلول های ایمنی دیگر مانند ماکروفاژها(Macrophages) صورت می پذیرد، یک آنتی بادی از دو زنجیره سبک مشابه (L) و دو زنجیره سنگین مشابه (H) تشکیل شده است که در شکل زیر نشان داده شده است.

 

سیستم ایمنی مصنوعی

 

لنفسیت های نوع T

یکی از چالش های سیستم ایمنی تشخیص سلول های خودی از غیر خودی (عوامل بیماری زا) است زیرا در سطح خارجی سلول های خودی آنتی ژن وجود دارد و وظیفه سلول T تشخیص آنتی ژن های سلول های خودی که به آنها آنتی ژن خودی گفته می شود از آنتی ژن های عوامل بیماری زا که به آن آنتی ژن های غیر خودی گفته می شود. سلول های T از سلول های بنیادی مغز استخوان تولید و وارد خون می شوند سلول های T نابالغ گفته می شود که این سلول های نابالغ از طریق جریان خون وارد غده تیموس می شوند و در این غده بخشی محافظت شده وجود دارد که در آن تنها سلول های خودی وجود دارد که نمی تواند هیچ عامل بیماری زایی در بدن وجود داشته باشد.

سلول های T به چند دسته تقسیم می شوند: دسته اول سلول های T کشنده، زمانی که سلولی را شناسایی می کنند آن را از بین می برند. دسته دیگر سلول های T کمکی، آنتی بادی ها به سلول های B متصل هستند اما سلول های B آنتی ژن های خودی را از آنتی ژن های غیرخودی تشخیص نمی دهند به سلول T احتیاج دارند و پاسخ ایمنی سلول های B زمانی تولید می شود که سلول B و یک سلول T کمکی به طور همزمان یک آنتی ژن را شناسایی می کنند.

لنفسیت های نوع T

ویژگی های سیستم ایمنی بدن

سیستم ایمنی بدن شامل خصوصیاتی که بالطبع سیستم ایمنی مصنوعی از آن پیروی می کند که به صورت خلاصه در مورد هر کدام توضیح داده شده است:

1- قابلیت تشیخص الگو توسط آنتی بادی ها: این تشخیص الگو با استفاده از یک آستانه انجام می شود و زمانی که تحریک الگویی از یک آستانه بالاتر رفت به عنوان یک سلول خودی شناخته می شود.

2- تطبیقی بودن سیستم ایمنی با رخدادها و محیط: بدن انسان با محیط طبیعی خود در ارتباط است و همچنین مواد مفید یا مضر (عوامل بیماری زا) که وارد بدن انسان می شوند متغیر هستند به همین دلیل سیستم ایمنی به صورت پویا با تغییرات برخورد می کند و با وجود تغییر عوامل بیماری زا را تشخیص داده و با آنها مبارزه می کند.

3- قابلیت یادگیری: سیستم ایمنی بدن قادر است که ویروس های جدیدی را که مشاهده می کند به خاطر می سپارد.

4- همکاری گروهی: در سیستم ایمنی سلول ها به صورت گروهی، موازی و توزیع شده برای تشخیص و انهدام همکاری دارند.

5- چند لایه ای بودن: هیچ موجودیتی در سیستم ایمنی بدن انسان یک مکانیزم کامل امنیتی و دفاعی را فراهم نمی کند بلکه هر لایه سیستم ایمنی به صورت مستقل عمل کرده و با بقیه لایه ها در ارتباط است.

6- تنوع و گوناگونی: سیستم ایمنی بدن در برابر انواع مختلفی از نفوذها مقاومت کرده و تسلیم نمی شود.

7- بهینه بودن منابع: در سیستم ایمنی با ایجاد مرگ سلولی و تکثیر سلولی، یک نمونه فضای کوچکی از فضای جستجوی آنتی ژن ها در هر زمان نگه داری می کنند.

8- پاسخ انتخابی: در سیستم ایمنی بدن پس از شناسایی یک آنتی ژن پاسخ های متفاوتی داده می شود که به یک شکل عمل نمی کنند.

9- تنظیم تعداد سلول های ایمنی توسط سیستم ایمنی

 سیستم ایمنی مصنوعی

یک الگویی برای یادگیری ماشین است و یادگیری ماشین یعنی توانایی کامپیوتر برای انجام یک کار با یادگیری داده ها از روی تجربه است.

کاربردهای سیستم ایمنی مصنوعی

AIS یکی از الگوریتم های الهام گرفته از سیستم ایمنی بدن انسان است و راه حل هایی را برای مسائل پیچیده ارائه داده اند و از جمله کاربردهای آن عبارتند از:

خوشه بندی (Clustering)

زمانبندی (Scheduling)

تشخیص عیب (Fault Detection)

تشخیص ناهنجاری (َAnomaly Detection)

امنیت اطلاعات (Security Infrmation)

مسائل بهینه سازی (Optimization problems)

دسته بندی الگوها (Patterns Classification)

سیستم های یادگیرنده (Learning system)

تشخیص نفوذ (Intrusion Detection)

مراحل سیستم ایمنی مصنوعی

 برای حل مساله با استفاده از  AIS باید 3 مرحله زیر انجام پذیرد:

1- نحوه نمایش داده های مساله (تعریف فضای شکل)

2- معیار اندازه گیری میل ترکیبی

3-انتخاب یک الگوریتم ایمنی مصنوعی برای حل مساله

فضای شکل (Shape Space)

سیستم ایمنی بر مبنای شناسایی الگو یا شناسایی شکل آنتی ژن است و می توان این سیسستم را فضایی مملوء از اشکال مختلف تشبیه کرد و هدف پیدا کردن مکمل اشکال و در نتیجه شناسایی آنها است، یعنی پیدا کردن تعدادی شکل بهینه یا آنتی بادی در فضای شکل که مکمل تمامی شکل های موجود در داده های مسئله آنتی ژن است. آنتی ژن ها به صورت آرایه ای از اعداد نمایش داده می شود و هر شیوه های که برای نمایش آنتی ژن استفاده می شود برای نمایش آنتی بادی هم نیز استفاده می شود (نحوه نمایش آنتی بادی و آنتی ژن یکسان است).

نحوه محاسبه و میل ترکیبی آنتی بادی با آنتی ژن

هر چه آنتی بادی میل ترکیبی بیشتری با آنتی ژن داشته باشد یعنی هر چه فاصله آنتی بادی و آنتی ژن کمتر شود مکمل بهتری برای آنتی ژن است و میل ترکیبی را می توان به صورت شباهت آرایه ها در نظر گرفت. که بر همین اساس در الگوریتم AIS از فاصله به عنوان معیار ارزیابی خوب یا بد بودن یک آنتی بادی استفاده می شود.

الگوریتم های AIS

الگوریتم های AIS به 3 دسته تقسیم می شوند:

1- دسته اول الگوریتم هایی که بر مبنای انتخاب کلونی سلول های B ایجاد شده اند.

2- دسته دوم الگوریتم هایی که بر مبنای انتخاب معکوس سلول های T ایجاد شده اند.

3- دسته سوم بر مبنای تئوری شبکه ایمنی ایجاد شده اند.

انتخاب کلونی (Clonal Selection)

زمانی که سلول B آنتی ژن را شناسایی می کند و سلول های B شروع به تکثیر شدن می کنند و تعداد زیادی سلول B یکسان و مشابه تولید می شود، 12 ساعت طول می کشد که یک سلول B رشد کرده و به دو سلول تبدیل شود و بعد از تحریک شدن دوره تکثیر حدودا یک هفته طول می کشد و از یک سلول 2 به توان 14 (16000) سلول مشابه تولید می شود و هر چه میل پیوندی بین سلول B و آنتی ژن بیشتر شود نرخ تکثیر بیشتر خواهد شد، در نتیجه سلول های B با میل پیوندی بالاتر، کلونی بیشتری تولید می کنند که اصل انتخاب کلونی نام دارد.

اصل انتخاب کلونی در AIS الگوریتم خاص خودش را دارد که بعد از تکثیر شدن سلول های B شروع به بالغ شدن می کنند که این فرایند در 3 مرحله صورت می پذیرد:

1- دگرگونی ایزوتایپ

2- بلوغ میل پیوندی

3- تصمیم گیری بین حافظه یا پلاسما شدن سلول B

AIS با دگرگونی ایزوتوپ در گیر نیست ولی دو مرحله بعدی در AIS مهم می باشند. ابرجهش سومانیک قسمتی از بلوغ میل پیوندی که قسمت مهمی در AIS بشمار می آید و جهش میل پیوندی آنتی بادی را می تواند کاهش یا افزایش می دهد.

سلول B در صورتی که به تکثیر ادامه می دهد که جهش باعث افزابش  میل پیوندی شده باشد و آنتی بادی به طور مداوم توسط آنتی ژن تحریک می شود و تلاش برای ایجاد سلول های B بهتری دارد که فرایند بلوغ پیوندی نام دارد.گام بعدی فرایند بلوغ پیوندی انتخاب بین حافظه یا پلاسما شدن سلول B است که سلول های پلاسما سازندگان آنتی بادی هستند و در حجم زیادی آنتی بادی ترشح می کنند و عمر زیادی ندارند و حالت دیگر تبدیل سلول های B به سلول های حافظه که این سلول ها میل پیوندی زیادی با آنتی ژن دارند و هدف بخاطر سپردن این آنتی ژن برای آینده است. سلول های حافظه علاوه بر تنظیم شدن به یک نوع خاص آنتی ژن، در آینده هم برای فعال شدن نیاز به تحریک شدن کمتری دارند و در نتیجه سرعت و کارآیی پاسخ ایمنی را زمانی که پاتوژن برای بار دوم به بدن حمله می کند زیاد می شود.

انتخاب کلونی (Clonal Selection)

انتخاب معکوس (Negative Selection)

میل ترکیبی سلول های T نابالغ با سلول های موجود در تیموس بررسی می شود و هرکدام از سلول های T نابالغ میل ترکیبی زیادی با یکی از سلول ها داشته باشند حذف می شوند و سایر سلول های T وارد جریان خون می شوند که  به این گونه انتخاب در آن برای حدف شدن انتخاب می شود انتخاب معکوس گویند.

 

انتخاب معکوس (Negative Selection)

 

تئوری شبکه ایمنی (Immune Network Theory)

آنتی بادی های موجود بر روی B-Cell ها می توانندعلاوه بر تشخیص آنتی ژن، آنتی بادی را هم می توانند تشخیص بدهند و باعث می شود سیستم ایمنی رفتاری پویا داشته که از آن در AIS استفاده می شود، و بر اساس این تئوری هر آنتی بادی قسمتی به نام ایدوتوپ دارد که توسط آنتی بادی دیگر قابل شناسایی است که در نتیجه آنتی بادی ها با شناسایی کردن یکدیگر سیگنال هایی را ارسال می کنند که می توانند یکدیگر را تحریک کنند و بدین ترتیب این شناسائی و تاثیر گذاری بر روی یکدیگر باعث پویایی شبکه ایمنی مصنوعی می شود. به مجموعه آنتی بادی ها که یکدیگر را شناسایی می کنند شبکه ایمنی یا ایدوتوپی گفنه می شود.

 

تئوری شبکه ایمنی (Immune Network Theory)

 

در هر الگوریتم AIS باید به 3 نکته توجه داشت:

1- در هر الگوریتم AIS باید حداقل یک جزء ایمنی مانند لنفسیت باشد.

2- در هر الگوریتم AIS باید ایده ای برگرفته از بیولوژی نظری یا تجربی باشد.

3- الگوریتم AIS که طراحی می شود باید به حل مسئله کمک کند.

مقایسه سیستم ایمنی طبیعی و الگوریتم های ایمنی مصنوعی

 

مقایسه سیستم ایمنی طبیعی و الگوریتم های ایمنی مصنوعی

 

برگرفته از پایان نامه بنت الهدی حلمی – دانشگاه علم و صنعت – تحت عنوان استخراج قوانین انجمنی با استفاده از سیستم ایمنی مصنوعی

استخراج قوانین انجمنی با استفاده از سیستم ایمنی مصنوعی

2.برگرفته از مقاله سید امیر احسانی ، امیر مسعود افتخاری مقدم – دانشگاه آزاد اسلامی واحد قزوین – تحت عنوان کاهش معناگری داده با استفاده از سیستم های ایمنی مصنوعی

کاهش معناگری داده با استفاده از سیستم های ایمنی مصنوعی

 

منبع

به عنوان یک قانون کلی که در مقالهOptimum population size and mutation rate for a simple real genetic algorithm that optimizes array factors  به آن اشاره شده (لینک مقاله در انتها آورده شده) اندازه جمعیت به تعداد ژن ها بستگی دارد. بنابراین ۹ ژن  به ۱۶ کروموزوم نیاز دارد و ۱۶ ژن به ۳۲ کروموزوم. معمولا با انتخاب اندازه حمعیتی معادل با ۱٫۵ تا ۲ برابر تعداد ژن ها شروع می شود تا به ماکزیمم اندازه جمعیت ۱۰۰ برسیم.

برای فضاهای حالت پیچیده احتمال crossover بالاتر (بیش از ۰٫۵) به جستجو در ابتدای کار کمک می کند. با این وجود در ادامه باید به مقادیری نزدیک به ۰٫۱ یا ۰٫۲ کاهش یابد. احتمال میوتیشن باید پایین نگه داشته شود (۰٫۰۱ – ۰٫۱). در غیر اینصورت همگرایی بی دلیل به تعویق می افتد.

پس برای مسائل مختلف و نحوه پیاده سازی مختلف الگوریتم ها تنظیم پارامترها متفاوت است و نمی توان به یک روال خاص در رابطه با کوچک یا بزرگ در نظر گرفتن جمعیت یا احتمالات میوتیشن و crossover اکتفا کرد. و بهترین راه تنظیم این پارامترها معمولا سعی و خطا و بازی با پارامترهاست.

ولی به عنوان یک قانون کلی:

اگر احتمال میوتیشن بسیار کوچک باشد: جمعیت بیش از حد زود همگرا می شود

اگر احتمال crossover بسیار بزرگ باشد: جمعیت هیچ گاه همگرا نمی شود

در ادامه الگوریتم مورد استفاده برای مسئله ۸ وزیر بارها وبارها با پارامترهای مختلف اجرا شده است تا بهترین پارامترها در نظر گرفته شود.

به این صورت عمل شده است که از آنجایی که تعداد ژن ها برابر با ۸ است ابتدا از ۱٫۵ برابر آن یعنی ۱۲ شروع شده است. یعنی مقدار جمعیت برای بار اول برابر با ۱۲ قرار داده شده است. تعداد نسل ها برابر با تعداد تکرار است. تعداد نسل را نصف تعداد جمعیت قرار می دهیم و از احتمال میویتش ۰٫۰۱ و احتمال crossover 0.5 استفاده می کنیم. لینک دانلود مرجع کد برنامه در انتها آورده شده است.

همان طور که مشاهده می شود نتیجه خوب نیست

تغییر تعداد جمعیت به دو برابر تعداد ژن ها:

هنوز به فیتنس ۲۸ یعنی تعداد برخوردهای ۰ نرسیده ایم.

در محله بعدی تکرار افزایش می یابد:

حال برای مقایسه مقدار crossover افزایش می یابد:

در این حالت هم به global maximum نرسیدیم و در دام بهینه محلی افتادیم.

مقدار crossover را مجددا کمتر کرده و مقدار میوتیشن را کمی افزایش می دهم:

نتیجه بدتر شد. مجددا به حالت قبل بر می گردانیم:

مشاهده می شود این بار نتیجه از بار قبل که با همین مقادیر اجرا شد بهتر است. چون الگوریتم ژنتیک احتمالاتی است هر بار اجرای آن نتیجه متفاوتی دارد. مثلا ژنی که برای میوتیشن انتخاب می شود تغییر می کند و کروموزوم حاصل در نسل بعدی نتیجه را تغییر می دهد.

در مرحله بعد تعداد جمعیت را به ۲۰ افزایش میدهیم:

نتیجه تغییر چندانی ندارد.

همان طور که در شکل بالا مشاهده می شود اندازه نسل نیز افزایش یافت ولی تغییر چندانی حاصل نشد.

به نظر می رسد تعداد جمعیت باید تغییر زیادی داشته باشد تا نتیجه بیشتر تغییر کند:

در این مرحله تعداد جمعیت را برابر با تعداد ژنها به توان ۲ در نظر می گیریم (در تحقیقی ثابت شده بهتر است همواره جمعیت بیشتر از دوبرابر تعداد ژنها باشد که این طور که از نتایج مشخص است این روش خوبی است).

حال می توان میتویشن و crossover را تغییر داد:

کاهش crossover در این حالت نتیجه را خراب کرد

در حالت فوق میوتیشن کمی افزایش داده شد

در حالت فوق جمعیت و تکرار را افزایش می دهیم که ابتدا به دو راه حل بهینه می رسد و البته سرعت اجرا بسیار کند می باشد ولی بعد از افزایش میوتیشن تعداد راه حل های بهینه افزایش پیدا کرده و سرعت کندتر می شود. یعنی هزینه اجرایی بالا می رود.

در تصویر فوق به علت قرار دادن یک عدد بزرگ برای میوتیشن فقط یک جواب بهینه پیدا کرد و سریع در دام بهینه های محلی افتاد.

در تصویر فوق مشاهده می شود که به علت قرار گیری عدد بزرگ در crossover به هیچ وجه همگرا نمی شود

تا کنون بهترین حالتی که مشاهده شد تصویر فوق است. که با در نظر گرفتن جمعیت نرمال ۱۰۰ ، تعداد تکرار نصف جمعیت یعنی ۵۰ و مقدار احتمال میوتیشن ۰,۰۱ و crossover برابر با ۰٫۰۷ به ۶ جواب بهینه رسیدیم. یعنی ۶ کروموزومی پیدا شدند که فیتنس ۲۸ و ماکزیمم دارند.

اجرای ۸ وزیر در متلب:

در کد زیر که با الهام از الگوریتم تپه نوردی نوشته شده پس از اجرا برای جمعیت برابر با ۱۰۰۰ و تعداد تکراری برابر با ۱۰۰ به ۲۰ جواب بهینه رسیدیم. در اینجا نیز تنظیم پارامترها دست شما است و می توان به جواب بهتری رسید


pop=1000;                                         %total population always

gen=100;                                           %total generations

n=8;

max_fitness=(((n-1)*n)/2);

initpop=zeros(pop,n);                            %initial population

pop_fitness=zeros(pop,1);                        %population fitness matrix

pop_fitness_sorted=zeros(pop,1);                 %for sorted fitness

fitness_temp=0;                                  %fitness temporary variable used in fitness loops between k and j

actual_pop_temp=zeros(1,n);

actual_pop_sorted=zeros(pop,n);

z=0;                                             %temporary variable used for simplicity

s=1;

w=0;

solution=zeros(1000,n);                           % solution matrix

cross_over_temp_mat=zeros(pop/2,n);              %cross-over variables

cross_over_ready_pop=zeros(pop,n);

cross_over_pop_final=zeros(pop,n);

cross_over_point=0;

cross_over_pop_temp_one=zeros(1,n);

cross_over_pop_temp_two=zeros(1,n);

cross_over_pop_temp_adjust=0;

cross_over_child_two_flipped=zeros(1,n);

cross_over_child_one=zeros(1,n);

cross_over_child_two=zeros(1,n);

mutation_temp_one=0;                             %mutation variables

mutation_temp_two=0;

mutation_temp_data=0;

for i=1:pop

initpop(i,:)=randperm(n);   %random initial population –indicates queen position on board

end;

actual_pop=initpop;                                 %duplication for working on this variable and keeping initial population intact

%generations loop

for q=1:gen

%for one generation

for i = 1:pop

fitness_temp=0;

%fitness calculation loop

for k=1:(n-1)                                               %calculates fitness by position manipulation

for j=k+1:n                                         %queen movements have been covered using j and k manipulation

z=abs(actual_pop(i,k)-actual_pop(i,j));          % for example   : when one queen is at (3,1)–(row,column)

if (ne(z,0)&& ne(z,(j-k)))                      %                next queens cant be at {(2,2),(3,2),(4,2) } {(1,3),(3,3),(5,3)}

fitness_temp=fitness_temp+1;               %                now you can observe that subtraction of each queen position and next

end                                             %                column queen position tells us a lot of information.

end                                                 %                remember the actual pop contains queen position dont confuse them with ‘i’ & ‘j’

end

pop_fitness(i,1)=fitness_temp;

end

%sort for individuals with good fitness

pop_fitness_sorted=pop_fitness;

actual_pop_sorted=actual_pop;

for i=1:(pop-1)

for j=i+1:pop

if(pop_fitness_sorted(i,1)<pop_fitness_sorted(j,1))

fitness_temp=pop_fitness_sorted(i,1);

pop_fitness_sorted(i,1)=pop_fitness_sorted(j,1);

pop_fitness_sorted(j,1)=fitness_temp;

actual_pop_temp(1,:)=actual_pop_sorted(i,:);

actual_pop_sorted(i,:)=actual_pop_sorted(j,:);

actual_pop_sorted(j,:)=actual_pop_temp(1,:);

end

end

end

% for unique solution gathering

%specified a vector of 100 rows ‘n’ columns

for i=1:pop

if(pop_fitness_sorted(i,1)==max_fitness)

for j=1:s

if actual_pop_sorted(i,:)==solution(j,:)

w=w+1;

else

w=w;

end

end

if w==0

solution(s,:)=actual_pop_sorted(i,:);

s=s+1;

else

continue;

end

end

w=0;

end

%selection

for i=1:(pop/2)

cross_over_temp_mat(i,:)=actual_pop_sorted(i,:);

end

cross_over_ready_pop=repmat(cross_over_temp_mat,2,1);

cross_over_pop_final=cross_over_ready_pop;

%cross over part begins

%for detail explaination cross over logic refer to the pdf attached

%logic—get random crossover point–then cross over at that point

%if two same values of rows in one individual..then adjust crossover

%according to the logic give in the pdf

while 1,

cross_over_point=floor(n*rand(1));

if cross_over_point~=0

break;

end

end

i=1;

while i<(pop-1),

cross_over_pop_temp_one(1,:)=cross_over_ready_pop(i,:);         %copied parents

cross_over_pop_temp_two(1,:)=cross_over_ready_pop(i+1,:);       %copied parents

%for child one

for j=1:cross_over_point

for k=j:n

if (cross_over_pop_temp_one(1,j)==cross_over_pop_temp_two(1,k))

cross_over_pop_temp_adjust=cross_over_pop_temp_two(1,j);

cross_over_pop_temp_two(1,j)=cross_over_pop_temp_two(1,k);

cross_over_pop_temp_two(1,k)=cross_over_pop_temp_adjust;

break;

end

end

end

for j=1:cross_over_point

cross_over_child_one(1,j)=cross_over_pop_temp_one(1,j);

end

for j=cross_over_point:n

cross_over_child_one(1,j)=cross_over_pop_temp_two(1,j);

end

%for child two

cross_over_pop_temp_two(1,:)=cross_over_ready_pop(i,:);         %copied parents

cross_over_pop_temp_one(1,:)=cross_over_ready_pop(i+1,:);       %copied parents

for j=1:cross_over_point

for k=j:n

if (cross_over_pop_temp_one(1,j)==cross_over_pop_temp_two(1,k))

cross_over_pop_temp_adjust=cross_over_pop_temp_two(1,j);

cross_over_pop_temp_two(1,j)=cross_over_pop_temp_two(1,k);

cross_over_pop_temp_two(1,k)=cross_over_pop_temp_adjust;

break;

end

end

end

for j=1:cross_over_point

cross_over_child_two(1,j)=cross_over_pop_temp_one(1,j);

end

for j=cross_over_point:n

cross_over_child_two(1,j)=cross_over_pop_temp_two(1,j);

end

cross_over_pop_final(i,:)=cross_over_child_one(1,:);

cross_over_child_two_flipped=wrev(cross_over_child_two);                 %flipped

cross_over_pop_final(i+1,:)=cross_over_child_two_flipped(1,:);

i=i+2;

end

%mutation introduced

%mutation occours  :at every 5th individual..swapping of two random

%                   column values(that is queen positions)

i=5;

while i<pop,

mutation_temp_one=floor(rand(1)*n/2);

mutation_temp_two=floor(2*(rand(1)*n/2));

if (mutation_temp_one==0 || mutation_temp_two==0)

continue;

else

mutation_temp_data=cross_over_pop_final(i,mutation_temp_one);

cross_over_pop_final(i,mutation_temp_one)=cross_over_pop_final(i,mutation_temp_two);

cross_over_pop_final(i,mutation_temp_two)=mutation_temp_data;

end

i=i+5;

end

i=0;

actual_pop=cross_over_pop_final;%the most important statement for my code

end

f=figure(‘Position’,[50 100 1000 600]);

cnames = {‘1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′,’10’,’11’,’12’};

rnames = {‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,’solution’,…

‘solution’,’solution’,’solution’,’solution’};

t = uitable(‘Parent’,f,’Data’,solution,’ColumnName’,cnames,…

‘RowName’,rnames,’Position’,[10 100 1000 500]);

 
 

با تغییر جمعیت به ۱۰۰ و تکرار به ۵۰:

به ۳ جواب بهینه رسیدیم:

با اجرای کد زیر ۹۲ کروموزوم به عنوان خروجی برگردانده می شود یعنی ۸ وزیر ۹۲ جواب دارد که ۱۲ جواب آن منحصر به‌فرد است یعنی بقیه جواب‌ها از تقارن جواب‌های اصلی به‌دست می‌آید.


function queen

clc;

counter = 0;

n = 8;

board = zeros(1,n);

[board,counter] = back(1, board,counter);

fprintf(‘Solution count: %d\n’,counter);

%%

function value =  isSolution(board)

for  i = 1:length(board)

for  j = (i+1): length(board)

if abs(board(i) – board(j)) == abs(i-j)

value = false;

return;

end

end

end

value = true;

%%

function [board,counter] =  back(depth, board,counter)

if  (depth == length(board)+1) && isSolution(board)

counter = counter + 1;

disp(board);

end

if ( depth <= length(board))

for  i = 1:length(board)

if ~any(board==i)

board(1,depth) = i;

[~,counter] = back(depth+1, board,counter);

end

end

end

 

بخشی از جواب ها بصورت زیر است:

۱     ۵     ۸     ۶     ۳     ۷     ۲     ۴

۱     ۶     ۸     ۳     ۷     ۴     ۲     ۵

۱     ۷     ۴     ۶     ۸     ۲     ۵     ۳

۱     ۷     ۵     ۸     ۲     ۴     ۶     ۳

۲     ۴     ۶     ۸     ۳     ۱     ۷     ۵

۲     ۷     ۵     ۸     ۱     ۴     ۶     ۳

۲     ۸     ۶     ۱     ۳     ۵     ۷     ۴

۳     ۱     ۷     ۵     ۸     ۲     ۴     ۶

۳     ۵     ۲     ۸     ۱     ۷     ۴     ۶

۳     ۵     ۲     ۸     ۶     ۴     ۷     ۱

۳     ۵     ۷     ۱     ۴     ۲     ۸     ۶

۳     ۵     ۸     ۴     ۱     ۷     ۲     ۶

۳     ۶     ۲     ۵     ۸     ۱     ۷     ۴

۳     ۶     ۲     ۷     ۱     ۴     ۸     ۵

۳     ۶     ۲     ۷     ۵     ۱     ۸     ۴

۳     ۶     ۴     ۱     ۸     ۵     ۷     ۲

۳     ۶     ۴     ۲     ۸     ۵     ۷     ۱

۳     ۶     ۸     ۱     ۴     ۷     ۵     ۲

۳     ۶     ۸     ۱     ۵     ۷     ۲     ۴

۳     ۶     ۸     ۲     ۴     ۱     ۷     ۵

۳     ۷     ۲     ۸     ۵     ۱     ۴

Solution count: 92

منبع

مسئله چند وزیر قسمت 1
مسئله چند وزیر قسمت 2
مسئله چند وزیر قسمت 3
مسئله چند وزیر قسمت 4

فانکش استفاده از میوتیشن برای نسل فعلی:

ابتدا یک کروموزوم رندوم انتخاب می شود (کروموزومی به غیر از بهترین کروموزومی که در صدر لیست قرار دارد). سپس دو ژن رندوم از این کروموزوم انتخاب می شود و با هم جابجا می شود. افزایش تعداد میوتیشن ها آزادی الگوریتم را در جستجو خارج از فضای حالات کروموزوم ها بیشتر می کند.

همان طور که گفته شد ژن عددی از ۰ تا ۷ است که به معنی شماره سطری است که وزیر در آن قرار گرفته است. موقعیت ژن در یک کروموزوم به معنی شماره ستون قرار گیری وزیر است. مشخص کردن مکان قرار گیری هر وزیر را باید حتما در هر سطر و ستون مشخص کرد.

کروموزوم نیز مجموعه ای از ۸ ژن است. و این طور فرض می شود که هیچ ژنی در یک کروموزوم دوبار تکرار نشود. برای مثال اگر کروموزوم ما ۰|۱|۴|۲|۳|۶|۷|۵ باشد یعنی ۸ وزیر در خانه های زیر از ماتریس قرار گرفته اند.

(۰,۰), (۱,۱), (۲,۴), (۳,۲), (۴,۳), (۵,۶), (۶,۷), (۷,۵)

در اینجا میوتیشن با swap کردن ژنی که باید mutate شود با یک ژن تصادفی (به جز ژنی که می خواهیم میوتیشن را روی آن انجام دهیم) از همان کروموزوم انجام می شود.

در crossover ژن ها از کروموزوم های دو والدین با احتمال ۰٫۵ گرفته می شود. یک ژن از یکی از والدین گرفت می شود و به کروموزوم فرزند اضافه می شود. ژنی که تولید می شود در پرنت دیگر پاک می شود. این مرحله انقدر ادامه می یابد تا کروموزوم های پدر و مادر هر دو، خالی شود و فرزند آنها همه ژن ها را داشته باشد.

تابع فیتنس: زمانی که دو وزیر طوری قرار بگیرند که یکدیگر را تهدید کنند یعنی در یک سطر، ستون یا قطر مشابه باشند. از آنجایی که کروموزوم ها ژن های تکراری ندارند بنابراین این اطمینان وجود دارد که هیچ دو وزیری در یک ستون قرار نمی گیرند. پس تنها باید برخوردهای قطری را بررسی و محاسبه کرد. بنابراین ماکزیمم تعداد برخوردها می تواند ۲۸ باشد. تابع فیتنس مقدارش هر چه بیشتر باشد بهتر است بنابراین اگر یک راه حل ۰ برخورد (تهدید دو وزیر) داشته باشد فیتنس آن ۲۸ است که با تفریق مقدار برخوردهایی که در حالت فعلی رخ می دهند از ۲۸ به دست می آید.

در کد c# مورد استفاده :

class GeneticAlgo: کلاسی است که مسئولیت همه عملیات الگوریتم ژنتیک را بر عهده دارد.

class FitnessComparator: یک کلاس مقایسه کننده است که کروموزوم ها را با fitness value مرتب می کند تا جمعیت نهایی را در جدول نشان دهد. بیشترین فیتنس در بالای جدول قرار می گیرد و کمترین آنها در پایین جدول.

struct Chromosome: ساختاری است که کروموزومی که حاوی ژنهااست، فیتنس و مجموع میانگین فیتنس ها را نشان می دهد.

class MainFrame: این کلاس موظف به کنترل اینترفیس کاربر و ایجاد جمعیت اولیه به منظور انتقال آن به الگوریتم ژنتیک است.

class Board: این کلاس گرافیک و عملیات صفحه شطرنج را بر عهده دارد.

متغیر private const int MAX_FIT = ۲۸ بیشترین مقدار فیتنس را دارد.

توابع:


private List<chromosome> GetInitialPopulation(int population)

{

List<chromosome> initPop = new List<chromosome>();

GeneticAlgo RandomGen = new GeneticAlgo();

for (int i = 0; i < population; i++)

{

List<int> genes = new List<int>(new int[] {0, 1, 2, 3, 4, 5, 6, 7});

Chromosome chromosome = new Chromosome();

chromosome.genes = new int[8];

for (int j = 0; j < 8; j++)

{

int geneIndex = (int)(RandomGen.GetRandomVal

(۰,genes.Count-1)+0.5);//randomly select a gene

chromosome.genes[j] = genes[geneIndex];

genes.RemoveAt(geneIndex);//remove selected gene

}

initPop.Add(chromosome);

}

return initPop;

}

 

تابع فوق اندازه جمعیت را به صورت پارامتر می گیرد و لیستی از کروموزوم هایی که دربردارنده ژن های تولید شده تصادفی هستند را بر می گرداند. مقدار ژن ها بصورت تصادفی از لیستی که شامل اعداد ۰ تا ۷ است انتخاب می شود. در حین اینکه مقادیر از لیست انتخاب می شوند، مقادیر انتخاب شده پاک می شوند تا از تکراری شدن ژن ها در کروموزوم جلوگیری شود. اندازه لیست مساوی با اندازه جمعیت است. پس از ایجاد جمعیت اولیه با استفاده از این تابع، لیست کروموزوم هایی که برمیگرداند به تابع DoMating داده می شود.


public void DoMating(ref List<Chromosome> initPopulation,

int generations, double probCrossver, double probMutation)

{

int totalFitness = 0;

CalcFitness(ref initPopulation, ref totalFitness);

for (int generation = 0; generation < generations; generation++)

{

PrepareRuletteWheel(ref initPopulation,totalFitness);

Crossover(ref initPopulation, probCrossver);

Mutate(ref initPopulation, probMutation);

CalcFitness(ref initPopulation, ref totalFitness);

if (initPopulation[initPopulation.Count – 1].fitness == 28)

break;

if (progress != null)

{

progress(generation + 1);

}

}

initPopulation.Sort(new FitnessComparator());

}
 

این تابع لیست کروموزوم ها را به عنوان جمعیت اولیه ، تعداد نسل هایی که می خواهیم در الگوریتم پخش شوند، احتمال crossover و احتمال mutation را به عنوان پارامتر می گیرد. مسئولیت این تابع هندل کردن پخش جمعیت به نسل مورد نیاز با فراخوانی توابع CalcFitness،PrepareRuletteWheel،CrossoverوMutate است.

 

public void CalcFitness(ref List<Chromosome> chromosome, ref int totalFitness)

{

int collisions = 0;

totalFitness = 0;

for (int k = 0; k < chromosome.Count; k++)

{

for (int i = 0; i < chromosome[k].genes.Length – 1; i++)

{

int x = i;

int y = chromosome[k].genes[i];

for (int j = i + 1; j < chromosome[k].genes.Length; j++)

{

if (Math.Abs(j – x) == Math.Abs

(chromosome[k].genes[j] – y))

collisions++;

}

}

Chromosome temp = chromosome[k];

temp.fitness = MAX_FIT – collisions;

chromosome[k] = temp;

totalFitness += chromosome[k].fitness;

collisions = 0;

}

}

این تابع فیتنس هر کروموزوم را اندازه می گیرد و fitness value را به مشخصه fitness  هر کروموزوم تخصیص می دهد. فیتنس با محاسبه تعداد برخوردها و کم کردن آن از ماکزیمم تعداد برخورد ها محاسبه می کند. در این کد فیتنس تابعی است که هرچه مقدارش بیشتر باشد بهتر است. علاوه بر محاسبه فیتنس هر کروموزوم، این تابع می تواند فیتنس کلی جمعیت را نیز محاسبه کند زیرا در مرحله بعدی برای محسابه نرخ فیتنس هر کروموزوم به آن نیاز داریم.


private void PrepareRuletteWheel(ref List<Chromosome> parents,int total)

{

int currentTotalFitness=0;

for (int i = 0; i < parents.Count; i++)

{

currentTotalFitness += parents[i].fitness;

Chromosome temp = parents[i];

temp.cumAvgFitness = currentTotalFitness / (double)total;

parents[i] = temp;

}

}

rulette wheel که بر مبنای فیتنس کروموزوم است برای انتخاب والدین برای جفت گیری برای ایجاد نسل جدید استفاده می شود. این تابع مسئول آماده سازی rulette wheel بوده و لیستی از کروموزوم ها را به عنوان جمعیت فعلی و فیتنس کلی جمعیت می گیرد. این تابع نرخ فیتنس هر کروموزوم تا فیتنس کلی را محاسبه می کند سپس مجموع آن را برای اختصاص به مشخصه cumAvgFitness  کروموزوم محاسبه می کند.

با تابع RuletteWheel می توان احتمال انتخاب را بر اساس نرخ فیتنس تعیین کرد. با این روش کروموزم هایی با fitness value بالاتر احتمال بیشتری برای انتخاب در ساخت نسل بعدی دارند در حالی که کروموزم هایی با fitness value پایین تر با احتمال کمتری شرکت داده می شوند


public void Crossover(ref List<Chromosome> parents, double probability)

{

List<Chromosome> offspring = new List<Chromosome>();

for (int i = 0; i < parents.Count; i++)

{

if (Assay(probability)) //if the chance is to crossover

{

Chromosome parentX = AssayRuletteWheel(parents);

Chromosome parentY = AssayRuletteWheel(parents);

List<int> child = new List<int>();

for (int j = 0; j < 8; j++)

{

if (Assay(0.5)) //select from parentX

{

for (int k = 0; k < parentX.genes.Length; k++)

{

if (!child.Contains

(parentX.genes[k]))//instead of

//deleting the similar genes

//from parents select the

//next non-contained number

{

child.Add(parentX.genes[k]);

break;

}

}

}

else //select from parentY

{

for (int k = 0; k < parentY.genes.Length; k++)

{

if (!child.Contains

(parentY.genes[k]))//instead of

//deleting the similar genes from

//parents select the next

//non-contained number

{

child.Add(parentY.genes[k]);

break;

}

}

}

}

Chromosome offSpr = new Chromosome();

offSpr.genes = child.ToArray();

offspring.Add(offSpr);

}

else //else the chance is to clone

{

Chromosome parentX = AssayRuletteWheel(parents);

offspring.Add(parentX);

}

}

while (offspring.Count > parents.Count)

{

offspring.RemoveAt((int)GetRandomVal(0, offspring.Count – 1));

}

parents = offspring;

}

 

تابع فوق مسئول انجام عمل cross over است. تابع لیستی از کروموزم ها را به عنوان جمعیت فعلی و احتمال crossover را به عنوان پارامتر می گیرد. تابع Assay(int probability) با احتمال داده شده true بر می گرداند بنابراین با احتمال crossover برای تعیین اینکه عملیات crossover است یا cloning استفاده می شود.

if (Assay(probability)) //if the chance is to crossover

{

Chromosome parentX = AssayRuletteWheel(parents);

Chromosome parentY = AssayRuletteWheel(parents);

List<int> child = new List<int>();

for (int j = 0; j < 8; j++)

{

if (Assay(0.5)) //select from parentX

{

for (int k = 0; k < parentX.genes.Length; k++)

{

if (!child.Contains(parentX.genes[k]))//instead of

//deleting the similar genes from parents

//select the next non-contained number

{

child.Add(parentX.genes[k]);

break;

}

}

}

else //select from parentY

{

for (int k = 0; k < parentY.genes.Length; k++)

{

if (!child.Contains(parentY.genes[k]))//instead of

//deleting the similar genes from parents

//select the next non-contained number

{

child.Add(parentY.genes[k]);

break;

}

}

}

}

Chromosome offSpr = new Chromosome();

offSpr.genes = child.ToArray();

offspring.Add(offSpr);

}

این بخش از کد مسئول crossover دو پرنت parentX  و parentY می باشد. به منظور ایجاد فرزند، ژنها از دو والدین با احتمال ۰٫۵ انتخاب می شوند در حالیکه از تکرار ژنها در کروموزوم ها اجتناب می شود. در عملیات cloning یکی از والدین مستقیما به نسل بعدی آورده می شود.


public void Mutate(ref List&amp;lt;Chromosome&amp;gt; parents, double probability)

{

List&amp;lt;Chromosome&amp;gt; offsprings = new List&amp;lt;Chromosome&amp;gt;();

for (int i = 0; i &amp;lt; parents.Count; i++)

{

Chromosome offspring = parents[i];

for (int mutatePosition = 0; mutatePosition &amp;lt; 8; mutatePosition++)

{

if (Assay(probability)) //if the chance is to mutate

{

int newGeneIndex = (int)(GetRandomVal(0,6)+0.5);

if (newGeneIndex&amp;gt;=mutatePosition)

{

newGeneIndex += 1;

}

int swapTemp = offspring.genes[mutatePosition];

offspring.genes[mutatePosition] =

offspring.genes[newGeneIndex];

offspring.genes[newGeneIndex] = swapTemp;

}

}

offsprings.Add(offspring);

}

parents = offsprings;

}
 

این تابع اپراتور mutation را با احتمال داده شده استفاده می کند. این تابع تغییر میوتیش را در حین انتقال ژن ها در جمعیت فعلی بررسی می کند. اگر باید برای ژنی از میوتیشن استفاده شود آنگاه مقدار آن با یک ژنی که بصورت تصادفی انتخاب شده در همین کروموزوم (ژنی به جز خود ژنی که می خواهیم روی آن میوتیشن انجام دهیم)  swap می شود.

زمانی که به یک راه حل می رسیم آرایه ژن های کروموزومی که شامل راه حل هستند را میتوان به پراپرتی به نام Genes  در کلاس Board اختصاص داد.

این برنامه این امکان را می دهد که اندازه جمعیت، تعداد نسل ها، احتمال crossover و احتمال mutation را مشخص کنید.

تمام کروموزوم های نسل آخر در جدول نشان داده می شوند و بهترین نتیجه در صفحه شطرنج گرافیکی نمایش داده می شود.

هیچ محدودیتی برای تعداد نسل ها وجود ندارد تازمانی که از ماکزیمم مقداری که یک متغیر اینتیجر می تواند بگیرد بیشتر نشود. از آنجایی که این الگوریتم بر اساس فرایند احتمالاتی است نمی توان همیشه انتظار پاسخ صحیح را داشت. به عبارت دیگر از آنجایی که این روش احتمالاتی است می توان با تکرار اجرای آن به راه حل های مختلفی دست یافت.

این سوال ها سالها مطرح بوده است که بین crossover و mutation کدامیک بهتر است؟ کدامیک لازم است؟ کدامیک اصلی است؟ پاسخی که تاکنون بیشتر از بقیه پاسخها مورد قبول بوده این است که هر کدام نقش مخصوص خود را دارد. در حالت کلی بهتر است از هر دو استفاده شود. میتوان الگوریتمی داشت که فقط از mutation استفاده کند ولی الگوریتمی که فقط ازcrossover   استفاده کند کار نخواهد کرد. Crossover خاصیت جستجوگرانه و یا explorative دارد. میتواند با انجام پرشهای بزرگ به محل هائی دربین والدین رفته و نواحی جدیدی را کشف نماید. Mutation خاصیت گسترشی و یا  exploitive  دارد. میتواند با انجام تغییرات کوچک تصادفی به نواحی کشف شده وسعت ببخشد.  Crossoverاطلاعات والدین را ترکیب میکند درحالیکه mutation  میتواند اطلاعات جدیدی اضافه نماید. رسیدن به یک پاسخ بهینه در mutation شانسی است.

نتایج اجرای این الگوریتم نشان می دهد که جمعیت عامل بسیاری مهمی بوده و تاثیر زیادی دارد و crossover probability و mutation rate تاثیر غیر قابل انکاری بر اجرای الگوریتم ژنتیک دارند زیرا با هر بار تغییر در هر یک از این پارامترها نتایج به شدت تغییر می کند. در حقیقت نحوه انتخاب اپراتورهای GA یک تریدآف بین همگرایی سریع تر و حفظ قابلیت اکتشافی بودن الگوریتم (برای جلوگیری از همگرایی اشتباه) است. Crossover پارامتری است که به تنظیم رفتار الگوریتم ژنتیک کمک می کند. کم کردن احتمال crossover باعث می شود در نسل بعدی افراد بیشتری بدون تغییر باقی بمانند. بسته به مسئله کاهش یا افزایش مقدار احتمال crossover می تواند تاثیر مثبت یا منفی داشته باشد.

پس از اجراهای متوالی الگوریتم می توان دید که هیچ جوابی وجود ندارد گه به طور قطع بتوان گفت از بقیه بهتر است و بتوان گفت که مقدار تنظیم شده برای پارامترهای الگوریتم ژنتیک در این حالت از همه بهتر است. این بهترین مقادیر به عوامل زیادی وابسته هستند. برای مثال اگر الگوریتم شما generational است میخواهید احتمالی را برای این در نظر بگیرید که برخی از والدین بدون تغییر باقی بمانند. در غیر اینصورت برخی راه حل های خوب را از دست خواهید داد. بنابراین بهتر است crossover rate را نزدیک به ۰٫۷ تنظیم کرد. برخی از الگوریتم ها نیز هستند که به طور کامل به mutation وابسته اند و برای آنها crossover rate مساوی با ۰ در نظر گرفته می شود. اگر crossover probability برابر با ۱۰۰درصد باشد همه فرزندان توسط crossover ایجاد می شوند. اگر ۰ درصد باشد همه نسل جدید کپی دقیقی از کروموزوم فعلی جمعیت قدیمی است ولی به این معنی نیست که نسل جدید دقیقا همان نسل قبلی است.

انتخاب اپراتورهای الگوریتم توازنی میان سرعت و دقت همگرایی است یعنی exploration در مقابل exploitation.

اینطور که گفته شده بهتر است mutation بین ۰٫۰۱۵ تا ۰٫۰۲ باشد. چرا؟

Exploration یعنی جستجوی فضای حالت در حد امکان در حالی که exploitation یعنی تمرکز بر یک نقطه که امیدواریم global optimum باشد.

در GA اپراتورهای mutation اغلب برای exploration و اپراتور های Crossover اغلب برای exploitation یعنی هدایت جمعیت به سوی همگرایی به یک راه حل خوب استفاده می شوند. در نتیجه وقتی Crossover سعی در همگرایی به یک نقطه مشخص دارد mutation سعی خود را می کند که همگرایی صورت نگیرد و فضای بیشتری کاوش شود.

در ابتدای فرایند جستجو ترجیح ما بر این است که جستجوی بیشتری به منظور اکتشاف فضا صورت گیرد. از طرف دیگر در انتهای فرایند جستجو exploitations بیشتری ترجیح داده می شود که همگرایی جمعیت به سمت global optimum تضمین شود. تنها یک استثناء وجود دارد؛ زمانی که جمعیت به سمت بهینه محلی همگرا می شود اگر بتوانیم باید پراکندگی حمیت را افزایش دهیم تا فضای بیشتری جستجو شود و در دام بهینه محلی نیفتد. با توجه به این نکته mutation rate بالا باعث افزایش احتمال جستجوی فضای بیشتری از فضای جستجو می شود با این حال از همگرایی جمعیت به یک جواب بهینه جلوگیری می کند. از طرف دیگر اگر mutation rate خیلی کوچک باشد باعث همگرایی زودهنگام و نارس می شود و به حای رسیدن به global optimum در دام بهینه محلی گرفتار می شود.مقداری که انتخاب می شود به ماهیت مسئله و نحوه پیاده سازی الگوریتم بستگی دارد. پس mutation rate های بسیار بالا از همگرایی الگوریتم جلوگیری کرده و رسیدن به راه حل بهینه را تضمین نمی کنند. بنابراین عاقلانه تر این است که از mutation rate های کوچک تر استفاده شود. مقدار کوچک برای mutation rate تضمین می کند که میوتیشن های زیادی در آن واحد اتفاق نیفتد ولی این نیز به تعداد ژن های موجود در هر کروموزوم از جمعیت بستگی دارد. بهتر این است که با مقادیر کم شروع کرده و به تدریج آنها را افزایش داد و کارایی هر یک را بررسی کرد مثلا به ترتیب: ۰٫۰۰۱، ۰٫۰۱، ۰٫۰۵، ۰٫۱، ۰٫۲ و … . در رابطه با جستجو در فضای حالت در مقایسه با mutation rate بالاتر، جمعیت بزرگتر ترجیح داده می شود.

در مقابل استفاده از mutation rate مناسب منجر به رسیدن سریع به نتایج خوب می شود و استفاده از mutation rate های بیش از حد کوچک فرایند را بسیار کند می کند زیرا کوناگونی را کم کرده و در نهایت ممکن است حتی همگرایی به درستی صورت نگیرد. mutation rate های بسیار بزرگ نیز همگرا شدن را بسیار سخت می کنند زیرا باعث می شوند جواب صحیح به راحتی از دست برود. بهترین راه تغییر تدریجی mutation rate است. مثلا به عنوان راه حل دیگر می توان با mutation rate های بزرگ شروع کرد تا گوناگونی بیشتری تزریق کرده از افتادن در دام بهینه محلی جلوگیری کرد سپس با انتها رسیدن الگوریتم یعنی تکرار آخر، این مقدار را کاهش داده و بهترین راهکار پیدا شود.

Exploitation = (crossover +  انتخاب بر اساس فیتنس) ما را به جواب بهینه نهایی می رساند.

این طور گفته می شود که اندازه جمعیت کوچکتر سرعت همگرایی بیشتری به الگوریتم می دهد ولی الگوریتم راحتتر در بهینه محلی گرفتار می شود. احتیاط بر این است که از جمعیت های بیش از حد کوچک استفاده نشود. معمولا به احتمال crossover و mutation بسیار بزرگ نیاز نخواهید داشت و جمعیتی با اندازه متوسط مناسب است.

است.
مسئله چند وزیر قسمت 1
مسئله چند وزیر قسمت 2
مسئله چند وزیر قسمت 3
مسئله چند وزیر قسمت 4

الگوریتم ژنتیک

  • نحوه نمایش مسئله:

می‌دانیم اگر دو وزیر در یک ستون قرار گیرند قطعاً به جواب نخواهیم رسید. بنابراین قرار دادن دو وزیر در یک ستون باعث غیرامیدبخش شدن جواب مسئله می‌شود.

برای نمایش مسئله در کروموزوم‌ها از این ویژگی استفاده کرده و به صورت زیر عمل می‌کنیم:

یک آرایه تک بعدی ایجاد می‌کنیم که به تعداد ستون‌های صفحه شطرنج عنصر دارد. هر عنصر از این آرایه نشان می‌دهد که وزیر در کدام سطر از آن ستون قرار دارد. به عنوان مثال اگر مسئله ۸ وزیر را در نظر بگیریم، آرایه تک بعدی باید دارای ۸ عنصر باشد. فرض کنید آرایه دارای مقادیر زیر باشد:

۸ , ۷ , ۶ , ۵ , ۴ , ۳ , ۲ , ۱

مقدار ۸ در اولین عنصر آرایه گویای این مطلب است که در ستون اول صفحه شطرنج وزیری در سطر هشتم قرار داده‌ایم.

  • تولید جمعیت اولیه:

الگوریتم‌های ژنتیک ابتدا جمعیت اولیه‌ای تولید کرده و سپس سعی در بهبود بخشیدن این جمعیت دارند. برای مسئله n وزیر تولید جمعیت به صورت تصادفی خواهد بود. بدین صورت که وزیرها به‌طور تصادفی روی صفحه شطرنج قرار می‌دهیم.

برای محاسبه میزان بهینگی جواب تعداد جفت وزیرهایی را که به هم گارد می‌دهند، محاسبه می‌کنیم. برای مسئله ۸ وزیر در بدترین حالت هر وزیر با همه وزیرهای دیگر گارد می‌دهد (فرض کنید همه وزیرها در یک سطر قرار گیرند). در این حالت حداکثر تعداد جفت وزیرهایی که به همگدیکر کارد می‌دهند ۲۸ جفت است:

۷ + ۶ + ۵ + ۴ +۳ + ۲ + ۱

در حالت کلی برای مسئله n وزیر حداکثر تعداد جفت وزیرهایی که به همدیگر گارد می‌دهند به صورت زیر محاسبه می‌شود:

۱+ ۲ +.. +(n-۱) = (n * (n-۱)) /۲
  • برای محاسبه میزان بهینگی هر کروموزوم از فرمول زیر استفاده می‌کنیم:
Fitness[i] =1 – (Guard(chromosome[i])) / MaxGuards
  • حداکثر تعداد گاردها:
MaxGuards
  • تعداد جفت وزیرهایی که در کروموزوم ام همدیگر را گارد می‌دهند:
 Guard(chromosome[i])

 

منبع

 


پیاده سازی الگوریتم ۸ وزیر با استفاده از الگوریتم ژنتیک

راهکاری که برای حل یک مسئله با الگوریتم ژنتیک استفاده می شود تکامل می یابد. الگوریتم ژنتیک مثل هر الگوریتم بهینه سازی دیگر با تعریف متغیرهای بهینه سازی آغاز می شود و مانند الگوریتم های بهنیه سازی دیگر نیز خاتمه می یابد یعنی با تست همگرایی.

یک الگوریتم GA دارای پارامترهای زیر است:

  • : Fitnessتابعی برای ارزیابی یک فرضیه  که مقداری عددی به هر فرضیه نسبت میدهد
  • : Fitness_threshold مقدار آستانه که شرط پایان را معین میکند
  • : population تعداد فرضیه هائی که باید در جمعیت در نظر گرفته شوند
  • : crossover rate  در صدی از جمعیت که در هر مرحله توسط الگوریتم crossover  جایگزین میشوند
  • :mutation rate  نرخ mutation

الگوریتم GA  به صورت زیر کار می کند:

  • : Initializeجمعیت را با تعداد population فرضیه بطور تصادفی مقدار دهی اولیه کنید.
  • : Evaluateبرای هر فرضیه h در population مقدار تابع Fitness(h) را محاسبه نمائید.
  • تا زمانیکه[maxh Fitness(h)] < Fitness_threshold یک جمعیت جدید ایجاد  کنید.
  • فرضیه ای که دارای بیشترین مقدار Fitness است را برگردانید.

روش های مختلف crossover:

Single-point crossover

  • یک نقطه تصادفی در طول رشته انتخاب میشود.
  • والدین در این نقطه به دوقسمت میشوند.
  • هر فرزند با انتخاب تکه اول از یکی از والدین و تکه دوم از والد دیگر بوجود میاید.

روشهای دیگر Crossover

در crossover یکنواخت بیتها بصورت یکنواخت از والدین انتخاب می شوند.

اپراتورهای ژنتیکی Mutation :

  • اپراتور mutation برای بوجود آوردن فرزند فقط از یک والد استفاده میکند. اینکار با انجام تغییرات کوچکی در رشته اولیه  بوقوع میپیوندد.
  • با استفاده از یک توزیع یکنواخت یک بیت بصورت تصادفی اتنخاب و مقدار آن تغییر پیدا میکند.
  • معمولا mutation بعد از انجام crossover اعمال میشود.

تابع fitness  معیاری برای رتبه بندی فرضیه هاست که کمک میکند تا فرضیه های برتر برای نسل بعدی جمعیت انتخاب شوند. نحوه انتخاب این تابع بسته به کاربر مورد نظر دارد

در روش معرفی شده در الگوریتم ساده GA احتمال انتخاب یک فرضیه برای استفاده در جمعیت بعدی بستگی به نسبت fitness  آن به fitness  بقیه اعضا دارد. این روش Roulette Wheel selectionنامیده میشود.

روش جستجوی GA با روشهای دیگر مثل شبکه های عصبی تفاوت دارد:

در شبکه عصبی روش Gradient descent بصورت  هموار از فرضیه ای به فرضیه  مشابه دیگری حرکت میکند در حالیکه GA  ممکن است بصورت ناگهانی فرضیه والد را با فرزندی جایگزین نماید که تفاوت اساسی با والد آن داشته باشد.از اینرو احتمال گیر افتادن GA در مینیمم محلی کاهش می یابد. با این وجود GA با مشکل دیگری روبروست که crowding  نامیده میشود crowding پدیده ای  است که در آن  عضوی که سازگاری بسیاربیشتری از بقیه افراد جمعیت دارد بطور مرتب تولید نسل کرده و با تولید اعضای مشابه درصد عمده ای از جمعیت را اشغال میکند. راه حل رفع مشکل Crowdingاستفاده از ranking  برای انتخاب نمونه ها است، با اختصاص رتبه به فرضیه ای که بسیار بهتر از بقیه عمل میکند.

مسئله ۸ وزیر:

بدین ترتیب دیدیم که مسیر میان اجزای الگوریتم ژنتیک به ترتیب زیر است:

  1. تعریف توابع و متغیرها
  2. تولید جمعیت اولیه
  3. دیکد کردن کروموزوم ها
  4. پیدا کردن هزینه برای هر کروموزوم
  5. انتخاب جفت ها
  6. جفت گیری
  7. میوتیشن
  8. بررسی همگرایی
  9. خاتمه یا بازگشت به مرحله دیکد کردن کروموزوم ها

ژن عددی از ۰ تا n-1 است در ۸ وزیر n برابر با ۸ است بنابراین ژن عددی از ۰ تا ۷ می شود و کروموزوم آرایه ای از ژن هاست. که می تواند پاسخ مسئله باشد.

جمعیت هر نسل می تواند  تعداد کروموزوم ها را تعیین کند.

جمعیت اولیه از انتخاب رندومی از کروموزوم ها ایجاد می شود. تعداد نسل هایی که برای همگرایی مورد نیاز است به جمعیت تصادفی اولیه بستگی دارد.

برای پیدا کردن هزینه مربوط به هر کروموزوم یک تابع هزینه تعریف می شود. نتیجه تابع هزینه یک cost value است که در نهایت میانگین cost valueهای هر نسل به نتیجه مطلوب نزدیک می شود.

کروموزوم هایی که فیتنس بالاتری (هزینه پایین تر) دارند برای تولید نسل بعدی استفاده می شوند.

در فرایند cross over فرزندان توسط والدین تولید می شوند که ترکیب آنها شامل ترکیب ژن های آنهاست. اگر نسل جدید حاوی کروموزومی باشد که نزدیک یا برابر با نتایج مطلوب باشد آنگاه مسئله حل شده است. در غیر اینصورت فرایند قبلی در نسل جدید هم پیاده سازی می شود مانند فرایندی که برای والدین آنها اتفاق افتاد. تا زمانی که به راه حل مناسب برسیم این روال ادامه دارد.

در شطرنج وزیر می تواند هر طور که مایل بود حرکت کند افقی عمودی یا در قطر. صفحه شطرنج ۸ در ۸ است یعنی ۸ سطر و ۸ ستون دارد . در مسئله ۸ وریز استاندارد به دنبال این هستیم که چگونه ۸ وزیر در خانه های جدول به گونه ای قرار بگیرند که هیچ یک دیگری را تهدید نکنند. در اینجا با الگوریتم ژنتیک این کار را انجام می دهیم.

برای تولید فرزندان از والیدن نیاز به crossover داریم که تصمیم می گیرد از دو والدین کدام ژن باید انتخاب شود.

 

مسئله چند وزیر قسمت 1
مسئله چند وزیر قسمت 2
مسئله چند وزیر قسمت 3
مسئله چند وزیر قسمت 4

مسئله چند وزیر یک معمای شطرنجی و ریاضیاتی است که بر اساس آن باید n وزیر شطرنج در یک صفحه n×n شطرنج به‌گونه‌ای قرار داده شوند که هیچ‌یک زیر ضرب دیگری نباشند. با توجه به اینکه وزیر به‌صورت افقی، عمودی و اُریب حرکت می‌کند، باید هر وزیر را در طول، عرض و قطر متفاوتی قرار داد.

اولین و مشهورترین شکل این مسئله معمای هشت وزیر است که برای حل آن باید ۸ وزیر را در یک صفحهً معمولی (۸×۸) شطرنج قرار داد. این مسئله ۹۲ جواب دارد که ۱۲ جواب آن منحصر به‌فرد است یعنی بقیه جواب‌ها از تقارن جواب‌های اصلی به‌دست می‌آید.

مسئله n وزیر در صورتی جواب دارد که n مساوی ۱ یا بیشتر از ۳ باشد. یعنی مسئله دو وزیر و سه وزیر راه حلی ندارند.

تاریخچه

این مسئله در سال ۱۸۴۸ توسط شطرنج بازی به نام Max Bezzel عنوان شد و ریاضی دانان بسیاری ازجمله Gauss و Georg Cantor بر روی این مسئله کار کرده و در نهایت آن را به n وزیر تعمیم دادند. اولین راه حل توسط Franz Nauck در سال ۱۸۵۰ ارائه شد که به همان مسئله n وزیر تعمیم داده شد. پس از آن Gunther راه حلی با استفاده از دترمینان ارائه داد که J.W.L. Glaisher آن را کامل نمود. در سال ۱۹۷۹، Edsger Dijkstra Nauck این مسئله را با استفاده از الگوریتم عقب‌گرد حل کرد.

حل مسئله

هشت وزیر را می‌توان با الگوریتم‌های مختلفی مانند تپه نوردی و روش ارضای محدودیت(csp) حل کرد که در زیر روش ارضای محدودیت را بررسی می‌کنیم. هر وزیری در هر ستونی هدفی دارد که همان مکانش در هرستون می‌شود یک گره .در کد زیر تعریف مکان‌ها را داریم:

Variables: { Q1, Q2, Q3, Q4 }

Domain: { (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4) }

Constraints: Alldifferent( Q1, Q2, Q3, Q4 ) and 
for i = 0...n and j = (i+1)...n, k = j-i, Q[i] != Q[j] + k and Q[i] != Q[j] - k

و این الگوریتم که برای جواب هر خانه‌است به دست می‌آید که یک csp است

min-conflicts(csp, max):
initial := complete assignment ;jamiyate avaliye
for 1..max do: ;az 1 .. akharin khane
if initial is a solution: ;if jamiyate tolide javab bod 
return initial ;barmigardanad
var := nextVar() ;da ghire indorat yek motaghair be jelo
value := leastConflicts( var ) ;taeein meghdar
var := value in initial ;gharar dadan meghdar dar motaghair
return failure ;bargash be ebtedaye algoritm

صورت مسئله

هدف از مسئله n وزیر، چیدن n مهره وزیر در یک صفحه شطرنج(n*n) است، به‌طوری‌که هیچ دو وزیری یکدیگر را گارد ندهند، یعنی هیچ دو مهره‌ای نباید در یک سطر، ستون یا قطر یکسان باشند. وزیر در خانه‌های شطرنج به صورت عرضی، طولی و قطری می‌تواند حرکت کند. مسئله n وزیر از جمله مسائل NP در هوش مصنوعی است که روش‌های جستجوی معمولی قادر به حل آن‌ها نخواهد بود

شمردن تعداد جواب‌ها

جدول زیر تعداد راه حل‌ها برای قرار دادن n وزیر بر روی صفحه n × nنشان می‌دهد. هر دو منحصر به فرد و متمایز، برای تعداد ۱-۱۴،۲۴-۲۶ است.

مسئله ی چند وزیر

  • توجه:

حالت شش وزیر جواب‌های کمتری نسبت به پنج وزیر دارد و فرمول صریحی برای یافتن تعداد جواب‌ها وجود ندارد.

روش‌های حل مسئله

الگوریتم عقبگرد

از تکنیک عقبگرد Backtracking برای حل مسائلی استفاده می‌شود که در آن‌ها دنباله‌ای از اشیاء از یک مجموعه مشخص انتخاب می‌شود، به‌طوری‌که این دنباله، ملاکی را در بر می‌گیرد. عقبگرد حالت اصلاح شدهٔ جستجوی عمقی یک درخت است. این الگوریتم همانند جستجوی عمقی است، با این تفاوت که فرزندان یک گره فقط هنگامی ملاقات می‌شوند که گره امید بخش باشد و در آن گره حلی وجود نداشته باشد. با توجه به اینکه هیچ ۲ وزیری نباید همدیگر را گارد کنند و در یک سطر نمی‌توانند باشند، تعداد کل حالت‌ها برای n=۴ برابر ۴*۴*۴*۴=۲۵۶ است. در شطرنج یک وزیر می‌تواند به مهره‌هایی که در خانه‌های عمود یا مورب به وی قرار دارند حمله کند. یا به عبارت ریاضی، اگر ردیفها و ستونهای شطرنج را از یک تا هشت شماره‌گذاری کنیم و وزیر در خانه (i، j) قرار داشته باشد، مهره‌هایی که در خانه‌های (i، m) یا (m، j) یا (i ± m، j ± m) قرار دارند توسط وزیر تهدید می‌شوند.

برای سادگی تشریح این مسئله با استفاده از روش بازگشت به عقب، فرض می‌کنیم که خانه‌های شطرنج ۴x۴ و تعداد وزیرها نیز ۴ باشد. سپس بعد از یافتن راه حل برای این مسئله ساده شده، اقدام به نوشتن الگوریتم برای مسئله اصلی می‌کنیم.

مراحل جستجو برای یافتن جواب را به این صورت دنبال می‌کنیم که: وزیر اول را در ردیف اول و ستون اول قرار می‌دهیم.

در ردیف دوم از اولین ستون به جلو رفته و به دنبال خانه‌ای می‌گردیم که مورد تهدید وزیر اول نباشد و وزیر دوم را در این خانه قرار می‌دهیم.

همانند قبل، در ردیف سوم از اولین ستون به جلو رفته و به دنبال خانه‌ای می‌گردیم که مورد تهدید وزیران اول و دوم نباشد. می‌بینیم که چنین خانه‌ای موجود نیست. پس به عقب یعنی ردیف دوم برگشته و وزیر دوم را به خانه‌ای دیگر از ردیف دوم منتقل می‌کنیم که مورد تهدید وزیر اول نباشد.

دوباره در ردیف سوم اولین خانه‌ای را میابیم که مورد تهدید دو وزیر قبلی نباشد. این بار خانه را می‌یابیم و وزیر سوم را در آن قرار می‌دهیم.

همانند قبل، در ردیف چهارم به دنبال اولین خانه‌ای می‌گردیم که مورد تهدید وزیران پیشین نباشد. چنین خانه‌ای موجود نیست. به ردیف قبل یعنی ردیف سوم باز می‌گردیم تا خانه‌ای دیگر برای وزیر سوم بیابیم. خانه دیگری وجود ندارد. به ردیف قبل یعنی ردیف دوم بر می‌گردیم تا خانه دیگری برای وزیر دوم پیدا کنیم. به آخرین ستون رسیده‌ایم و خانه دیگری نیست. به ردیف قبل یعنی ردیف اول بر می‌گردیم و وزیر اول را یک ستون به جلو می‌بریم.

در ردیف دوم اولین خانه‌ای را میابیم که مورد تهدید وزیر اول نباشد و وزیر دوم را در آن خانه قرار می‌دهیم.

در ردیف سوم اولین خانه‌ای را میابیم که مورد تهدید وزیران اول و دوم نباشد و وزیر سوم را در آن خانه می‌گذاریم.

در ردیف چهارم اولین خانه‌ای را میابیم که مورد تهدید وزیران پیشین نباشد. این بار خانه را می‌یابیم و وزیر چهارم را در آن خانه قرار می‌دهیم.

به یک جواب می‌رسیم. حال اگر فرض کنیم که این خانه جواب نیست و به مسیر خود ادامه دهیم، احتمالاً” می‌توانیم جوابهای دیگری نیز بیابیم.

شبه کد پیاده‌سازی الگوریتم عقبگرد برای مسئله n وزیر

void queens (index i)
{
	index j;
	if (promising(i))
		if (i == n)
			cout &amp;amp;amp;amp;lt;&amp;amp;amp;amp;lt; col[1] through col[n];
		else
			for (j = 1; j &amp;amp;amp;amp;lt;= n; j++) {
				col[i + 1] = j;
				queens(i + 1);
			}
}
bool promising (index i)
{
	index k;
	bool Switch;
	k = 1;
	Switch = true ;
	while (k &amp;amp;amp;amp;lt; i &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; switch) {
		if (col[i] == col[k] || abs(col[i] – col[k] == i - k))
			switch = false;
		k++;
	}
	return Switch;
}

برنامه زبان C به صورت غیر بازگشتی

# include &amp;amp;amp;amp;lt;stdio.h&amp;amp;amp;amp;gt;

int b[8];

inline static int unsafe(int y) {
        int i, t, x;
        x = b[y];
        for (i = 1; i &amp;amp;amp;amp;lt;= y; i++) {
                t = b[y - i];
                if ((t == x) ||
                     (t == x - i) ||
                     (t == x + i)) {
                        return 1;
               }
       }

        return 0;
}

static void putboard(void) {
        static int s = ۰;
        int x, y;
        printf("\n\nSolution #٪i\n", ++s);
        for (y = 0; y &amp;amp;amp;amp;lt; 8; y++) {
                for (x = 0; x &amp;amp;amp;amp;lt; 8; x++) {
                        printf((b[y] == x) ? "|Q": "|_");
               }
                printf("|\n");
       }
}

int main(void) {
        int y = ۰;
        b[۰] = -۱;
        while (y &amp;amp;amp;amp;gt;= ۰) {
                do {
                        b[y]++;
               } while ((b[y] &amp;amp;amp;amp;lt; 8) &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; unsafe(y));
                if (b[y] &amp;amp;amp;amp;lt; 8) {
                        if (y &amp;amp;amp;amp;lt; 7) {
                                b[++y] = -۱;
                       } else {
                                putboard();
                       }
               } else {
                        y--;
               }
       }

        return 0;
}

برنامه زبان ++C به صورت بازگشتی

  • برنامه زیر برای هشت وزیر نوشته شده‌است با انتخاب اعداد دیگر به جای هشت در define MAXSIZE 8 # می‌توان برای تعداد دیگری وزیر نیز استفاده کرد.
# include &amp;amp;amp;amp;lt;assert.h&amp;amp;amp;amp;gt;
# include &amp;amp;amp;amp;lt;stdio.h&amp;amp;amp;amp;gt;

# define MAXSIZE 8
class EightQueens
{
    int m_size;				
    int m_solution_count;		
    int m_attempt_count;		
    int m_queen[MAXSIZE];		
    bool m_row_inuse[MAXSIZE]; 		
    bool m_diag_rise[MAXSIZE*2];	
    bool m_diag_fall[MAXSIZE*2];	

public:

    EightQueens(int size, bool is_alt) {

	assert(size &amp;amp;amp;amp;lt;= MAXSIZE);

	m_size = size;
	m_solution_count = 0;
	m_attempt_count = 0;

	for (int i = 0; i &amp;amp;amp;amp;lt; m_size; i++) {
	    m_queen[i] = i;
	    m_row_inuse[i] = 0;
	}

	for (int j = 0; j &amp;amp;amp;amp;lt; m_size*2; j++) {
	    m_diag_rise[j] = 0;
	    m_diag_fall[j] = 0;
	}

	if (is_alt) SearchAlt(0);
	else        Search(0);

   }

    int GetSolutionCount() {
	return m_solution_count;
   }

    int GetAttemptCount() {
	return m_attempt_count;
   }

private:

    void SearchAlt(int col){

	if (col == m_size) {
	    m_solution_count++;
	    return;
	}

	for (int row = 0; row &amp;amp;amp;amp;lt; m_size; row++) {
	    m_attempt_count++;
	    if (m_row_inuse[row] == 0 &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; IsDiagValid(col, row)) {
		m_queen[col] = row;
		m_row_inuse[row] = 1;
		SetDiags(col, 1);
		SearchAlt(col+1);
		SetDiags(col, 0);
		m_row_inuse[row] = 0;
		m_queen[col] = -1;
	   }
	}

   }

    void Search(int col) {
	if (col == m_size) {
	    m_solution_count++;
	    return;
	}

	for (int i = col; i &amp;amp;amp;amp;lt; m_size; i++) {
	    if (SwapQueenIfDiagValid(col, i)) {
		Search(col+1);
		UnSwapQueen(col, i);
	   };
	}
   }

    void SwapQueenBasic(int i, int j) {
	    int hold = m_queen[i];
	    m_queen[i] = m_queen[j];
	    m_queen[j] = hold;
   }

    void SetDiags(int col, int val) {
	assert(m_diag_rise[m_queen[col] + col]!= val);
	       m_diag_rise[m_queen[col] + col] =  val;
	assert(m_diag_fall[m_queen[col] - col + m_size]!= val);
	       m_diag_fall[m_queen[col] - col + m_size] =  val;
   }

    bool IsDiagValid(int col, int row) {
	return (m_diag_rise[row + col] == 0 &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;
		m_diag_fall[row - col + m_size] == 0);
   }

    bool SwapQueenIfDiagValid(int i, int j) {
	m_attempt_count++;
	if (IsDiagValid(i, m_queen[j])) {
	    SwapQueenBasic(i, j);
	    SetDiags(i, 1);
            return true;
	}
        return false;
   }

    void UnSwapQueen(int i, int j) {
	SetDiags(i, 0);
	SwapQueenBasic(i, j);
   }

};

void
do_work(bool is_alt)
{
    int size = 8;

    EightQueens puzzle(size, is_alt);
    int soln = puzzle.GetSolutionCount();
    int attempt = puzzle.GetAttemptCount();
    assert(size!= 8 || soln == 92);
    const char* style = is_alt ? "cartesian": "permutation";
    printf("EightQueens[%d] has %d solutions found in %5d attempts using %s search. \n", size, soln, attempt, style);
}

int main()
{
    printf("We should have 92 solutions for 8x8. \n");
    do_work(0);
    do_work(1);
}

انیمیشن روش بازگشتی

 

مسئله چند وزیر

 

الگوریتم مونت کارلو

از الگوریتم مونت کارلو برای برآورد کردن کارایی یک الگوریتم عقبگرد استفاده می‌شود. الگوریتم‌های مونت کارلو، احتمالی هستند، یعنی دستور اجرایی بعدی گاه به‌طور تصادفی تعیین می‌شوند. در الگوریتم قطعی چنین چیزی رخ نمی‌دهد. الگوریتم مونت کارلو مقدار مورد انتظار یک متغیر تصادفی را که روی یک فضای ساده تعریف می‌شود، با استفاده از مقدار میانگین آن روی نمونه تصادفی از فضای ساده بر آورد می‌کند. تضمینی وجود ندارد که این برآورد به مقدار مورد انتظار واقعی نزدیک باشد، ولی احتمال نزدیک شدن آن، با افزایش زمان در دسترس برای الگوریتم، افزایش می‌یابد.

شبه کد پیاده‌سازی الگوریتم مونت کارلو برای الگوریتم عقبگرد مسئله n وزیر

  int ostimate _ n_ queens (int n)
   {
          index i , j , col [1..n];
          int m , mprod , numnodes ;
          set _of_ index  prom _children;
          i = ۰;
          numnodes =۱ ;
          m = ۱;

        mprod  = ۱ ;
        while  (m!= 0 &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; i!= n) {
        mprod = mprod * m ;
        numnodes  = numnodes + mprod * n;
        i ++;
        m = ۰ ;
        prom_childern  = Ø;
        for (j = 1 ; j ≤ n ; j++;) {
                col [i]  = j ;
                if (promising(i)) {

         m++;
         prom_children = prom _ children U {i};
                }
            }
             if (m!= ۰)  {
                 j = random selection from prom _childeren;
                 col [i];
             }
        }
         return numnodes;
     }

روش مکاشفه‌ای

برای حل این مسئله که دارای ۹۲ جواب است، باید تکنیکهایی جهت کاهش حالات، روش Brute Force یا امتحان تک تک جواب‌ها انجام شود. تعداد همه حالاتی که می‌تواند در روش Brute Force چک شود برابر ۱۶٬۷۷۷٬۲۱۶ یا هشت به توان هشت است! یکی از روش‌های حل این مسئله برای n>=4 یا n=1 استفاده از روش مکاشفه‌ای ( heuristic)است:

1- عدد n را بر عدد ۱۲ تقسیم کن و باقی‌مانده را یادداشت کن

۲- به ترتیب اعداد زوج ۲ تا n را در لیستی بنویس

۳- اگر باقی‌مانده ۳ یا ۹ بود، عدد ۲ را به انتهای لیست انتقال بده.

۴- به لیست اعداد فرد ۱ تا n را به ترتیب اضافه کن، اما اگر باقی‌مانده ۸ بود اعداد را دو به دو باهم عوض کند (مثلاً ۱و۳و۵و۷و۹ تبدیل به ۳و۱و۷و۵و۹ میشه)

۵- اگر باقی‌مانده ۲ بود جای ۱ و۳ را با هم عوض کن و ۵ را به انتهای لیست ببر.

۶- اگر باقی‌مانده ۳ یا ۹ بود، اعداد ۱ و ۳ را به انتهای لیست ببر.

۷- حال با استفاده از لیست بدست آمده وزیرها در صفحه شطرنج چیده می‌شوند، به‌طوری‌که جای وزیر ستون اول، اولین عدد لیست، جای وزیر ستون دوم، دومین عدد لیست و…

این الگوریتم یک راه حل برای حل این مسئله‌است، برای بدست آوردن همه حالات از روش‌های دیگری می‌توان استفاده کرد. روش حل مسئله ۱۲ راه حل یکتا دارد که با در نظرگیری تقارن و چرخش به ۹۲ حالت قابل تبدیل است.

روش‌های جستجوی محلی

می‌توان به مسئله ۸ وزیر به عنوان یک مسئله بهینه‌سازی نیز نگریست که در آن هدف بهینه کردن تعداد گاردهای جفت وزیرها می‌باشد.

به عنوان مثال فرض کنید در صفحه شطرنج معمولی، ۸ وزیر را به دو روش زیر قرار دهیم:

مسئله ی چند وزیرمسئله ی چند وزیر

در روش چینش سمت چپ ۳ وزیر و در روش چینش سمت راست ۴ وزیر همدیگر را گارد می‌دهند. بنابراین روش چینش قبلی بهینه تر از روش چینش فعلی است. در واقع می‌توان مسئله بهینه‌سازی را به صورت زیر تعریف کرد. فرض کنید S مجموعه همه جواب‌های ممکن برای مسئله باشد. در صورتی S* می‌تواند جواب مسئله باشد که به ازای همه جواب‌های موجود در S، S* بهینه تر از دیگر جواب‌ها باشد. در مسئله ۸ وزیر دیدیم که جوابی بهینه‌است که تعداد گاردهای جفت وزیر آن کمتر باشد.

روش‌های جستجوی محلی همگی حالت‌های همسایه حالت فعلی را برای رسیدن به بهینه‌ترین جواب بررسی می‌کنند. از این رو وجود دو تابع در همه این روش‌های جستجو الزامی است. اولین تابع میزان بهینگی جواب مسئله ارزیابی می‌کند و تابع دوم یکی از حالت‌های همسایه حالت فعلی را انتخاب می‌کند.

نحوه پیاده‌سازی و طراحی الگوریتم برای انتخاب حالت هسایه در این روش‌های جستجو از اهمیت ویژه‌ای برخوردار است. به عنوان مثال برای مسئله ۸ وزیر می‌توان به شکل‌های زیر حالت‌های همسایگی را تولید کرد:

۱) دو وزیر به تصادف انتخاب شده و جای آن دو باهم عوض گردد.

۲) یکی از وزیرها به تصادف انتخاب شده و شماره سطر آن به تصادف تغییر کند.

۳) ویزیری به تصادف انتخاب شده و یک خانه به سمت بالا یا پایین حرکت کند

مسئله چند وزیر قسمت 1
مسئله چند وزیر قسمت 2
مسئله چند وزیر قسمت 3
مسئله چند وزیر قسمت 4

الگوریتم های فرا ابتکاری یا فرا تکاملی یا فرا اکتشافی نوعی از الگوریتم‌ های تصادفی هستند که برای یافتن پاسخ بهینه به کار می‌روند.

روش‌ها و الگوریتم‌های بهینه‌سازی به دو دسته الگوریتمهای دقیق (exact) و الگوریتم‌های تقریبی (approximate algorithms) تقسیم‌بندی می‌شوند. الگوریتم‌های دقیق قادر به یافتن جواب بهینه به صورت دقیق هستند اما در مورد مسائل بهینه‌سازی سخت کارایی کافی ندارند و زمان اجرای آن‌ها متناسب با ابعاد مسائل به صورت نمایی افزایش می‌یابد. الگوریتم‌های تقریبی قادر به یافتن جواب‌های خوب (نزدیک به بهینه) در زمان حل کوتاه برای مسائل بهینه‌سازی سخت هستند.

الگوریتم‌های تقریبی نیز به سه دسته الگوریتم‌های ابتکاری (heuristic) و فراابتکاری (meta-heuristic) و فوق ابتکاری (hyper heuristic) بخش‌بندی می‌شوند. دو مشکل اصلی الگوریتم‌های ابتکاری، گیر افتادن آنها در نقاط بهینه محلی، همگرایی زودرس به این نقاط است. الگوریتم های فراابتکاری برای حل این مشکلات الگوریتم‌های ابتکاری ارائه شده‌اند. در واقع الگوریتم های فراابتکاری، یکی از انواع الگوریتم‌های بهینه‌سازی تقریبی هستند که دارای راهکارهای برونرفت از نقاط بهینه محلی هستند و قابلیت کاربرد در طیف گسترده‌ای از مسائل را دارند. رده‌های گوناگونی از این نوع الگوریتم در دهه‌های اخیر توسعه یافته‌است که همه این ها زیر مجموعه الگوریتم فراابتکاری می باشند.

دسته‌بندی الگوریتم های فرا ابتکاری

معیارهای مختلفی می‌توانند برای طبقه‌بندی الگوریتم های فراابتکاری استفاده شوند:

  • مبتنی بر یک جواب و مبتنی بر جمعیت: الگوریتم‌های مبتنی بر یک جواب در حین فرایند جستجو یک جواب را تغییر می‌دهند، در حالی که در الگوریتم‌های مبتنی بر جمعیت در حین جستجو، یک جمعیت از جواب‌ها در نظر گرفته می‌شوند.
  • الهام گرفته شده از طبیعت و بدون الهام از طبیعت: بسیاری از الگوریتم های فراابتکاری از طبیعت الهام گرفته شده‌اند، در این میان برخی از الگوریتم های فراابتکاری نیز از طبیعت الهام گرفته نشده‌اند.
  • با حافظه و بدون حافظه: برخی از الگوریتم های فراابتکاری فاقد حافظه می‌باشند، به این معنا که، این نوع الگوریتم‌ها از اطلاعات بدست آمده در حین جستجو استفاده نمی‌کنند (به طور مثالتبرید شبیه‌سازی شده). این در حالی است که در برخی از الگوریتم های فراابتکاری نظیر جستجوی ممنوعه از حافظه استفاده می‌کنند. این حافظه اطلاعات بدست آمده در حین جستجو را در خود ذخیره می‌کند.
  • قطعی و احتمالی: یک الگوریتم فراابتکاری قطعی نظیر جستجوی ممنوعه، مسئله را با استفاده از تصمیمات قطعی حل می‌کند. اما در الگوریتم های فراابتکاری احتمالی نظیر تبرید شبیه‌سازیشده، یک سری قوانین احتمالی در حین جستجو مورد استفاده قرار می‌گیرد.

الگوریتم های فراابتکاری بر پایه جمعیت

از الگوریتم‌های شناخته شده فراابتکاری بر پایه جمعیت می‌توان الگوریتم‌های تکاملی (الگوریتم ژنتیک، برنامه‌ریزی ژنتیک، …)، بهینه‌سازی کلونی مورچگان، کلونی زنبورها، روش بهینه‌سازی ازدحام ذرات، الگوریتم قهرمانی در لیگهای ورزشی، بهینه‌سازی ملهم از فیزیک نور، الگوریتم ریشه-پاجوش و الگوریتم چکه آبهای هوشمند را نام برد.

در سالهای اخیر الگوریتم های فراابتکاری جدیدی با توجه به موجودات زنده موجود در طبیعت توسعه داده شده اند که از معروف ترین آنها میتوان به الگوریتم بهینه سازی گرگ خاکستری ، الگوریتم بهینه سازی سنجاقک ، الگوریتم بهینه سازی گرده افشانی گل ها، الگوریتم بهینه سازی نهنگ یا وال ، الگوریتم بهینه سازی ملخ نام برد.

الگوریتم‌های متداول فراابتکاری مبتنی بر یک جواب

از الگوریتم‌های متداول فراابتکاری مبتنی بر یک جواب می‌توان الگوریتم جستجوی ممنوعه و الگوریتم تبرید شبیه‌سازی شده را نام برد.

پیاده‌سازی الگوریتم های فراابتکاری

فرایند طراحی و پیاده‌سازی الگوریتم های فراابتکاری دارای سه مرحلهٔ متوالی است که هر کدام از آن‌ها دارای گام‌های مختلفی هستند. در هر گام فعالیت‌هایی باید انجام شود تا آن گام کامل شود. مرحلهٔ ۱ آماده‌سازی است که در آن باید شناخت دقیقی از مسئله‌ای که می‌خواهیم حل کنیم بدست آوریم، و اهداف طراحی الگوریتم فراابتکاری برای آن باید با توجه به روش‌های حل موجود برای این مسئله به طور واضح و شفاف مشخص شود. مرحلهٔ بعدی، ساخت نام دارد.

مهمترین اهداف این مرحله انتخاب استراتژی حل، تعریف معیارهای اندازه‌گیری عملکرد، و طراحی الگوریتم برای استراتژی حل انتخابی می‌باشد. آخرین مرحله پیاده‌سازی است که در آن پیاده‌سازی الگوریتم طراحی شده در مرحلهٔ قبل، شامل تنظیم پارامترها، تحلیل عملکرد، و در نهایت تدوین و تهیه گزارش نتایج باید انجام شود.

منبع


خلاصه ای در مورد الگوریتم های متاهیوریستیک

اکنون تعداد زیادی از مسائل بهینه سازی در پیرامون ما وجود دارد که به روش دقیق یا اصلاً قابل حل نیستند و یااین که در زمان معقول انجام این امر امکان پذیر نیست. بعضی از این چنین مسائلی را که عمدتاً جزء مسائل بهینه سازی هستند، مسائل NP-Hard می نامند. این خانواده بزرگ از مسائل، خواص بسیار جالبی دارند که سبب شده است تا کنون روش های تقریبی متعددی برای حل هر کدام از آنها در طول زمان ارائه شود. الگوریتم های فراابتکاری (متاهیوریستیک) جزء این دسته از روش ها هستند.

البته در مواقعی که در یک مسئله بهینه سازی، پارامتر یا محدودیت تصادفی، چند تابع هدف متضاد و امثالهم هم وجود داشته باشد، استفاده از الگوریتم های فراابتکاری بسیار موفقیت آمیزتر از سایر روش ها گزارش شده است. از طرف دیگر تنها تعداد معدودی از این الگوریتم ها اثبات شده اند که در حل بعضی از مسائل خاص حتماً به ازای هر مقدار از پارامترهای ورودی به جواب بهینه همگرا می شوند. عیب عمده این روش ها هم در همین مورد است. اما قابلیت مانور فراوان، طراحی ساده و بسیار سریع بودن آنها در کفه دیگر ترازو قرار دارد.

تعداد الگوریتم های فراابتکاری بسیار زیاد است اما ساختار منطق حاکم بر آنها معمولا جزء چند دسته از ساختارهای شناخته شده قرار می گیرد. از این رو با شناخت این منطق ها می توان الگوریتم های هیبریدی جدیدی را برای حل مسائلی را که با آنها سر و کار داریم، به وجود آورد. این روند همچنان ادامه دارد و هر روز الگوریتم های جالبی متولد می شوند و عده ای از الگوریتم ها نیز به تدریج منسوخ می شوند و تنها ارزش گزارش شدن در تاریخچه الگوریتم ها را به خود می گیرند. به عبارت دیگر، یکی از اهداف این دوره، آشنایی با دنیای زنده و پر تکاپوی موجودات الگوریتمی برای مهندسین صنایع است تا در مطالعات علمی خود از آنها استفاده کنند.

منبع


در چند دهه اخیر، دسته‌ای از الگوریتم‌های تقریبی توسعه داده شده‌اند که سعی دارند با ترکیب اصول اولیه روش‌های ابتکاری (هیوریستیک) روشی را برای جستجوی مؤثر و کارای فضای جواب پیدا کنند. امروزه این روش‌ها به روش‌های فرا ابتکاری (متاهیوریستیک) مشهورند. اصطلاح متاهیوریستیک اولین بار توسط Glover در سال 1993 و به هنگام معرفی روش جستجوی ممنوع به عنوان یک روش ابتکاری جدید به کار برده شد.
پیش از این، روش‌های فرا ابتکاری، روش‌های ابتکاری نوین نامیده می‌شدند. الگوریتم‌های تکاملی نظیر الگوریتم ژنتیک، الگوریتم بهینه‌سازی مورچگان، روش شبیه‌سازی تبرید، جستجوی ممنوع و شبکه‌های عصبی مصنوعی نمونه‌هایی از این روش‌ها می‌باشند.
تا به امروز تعریف مشخص و جامعی از اصطلاح متاهیوریستیک یا فرا ابتکاری صورت نگرفته است و تعاریف مختلفی برای این اصطلاح ارائه شده است. اما به طور خلاصه می‌توان مشخصات اصلی روش‌های فرا ابتکاری را به صورت زیر بیان نمود.

  • برخلاف روش‌های ابتکاری، هدف اصلی این روش‌ها، جستجوی مؤثر و کارای فضای جواب به جای یافتن صرف جواب‌های بهینه یا نزدیک بهینه می‌باشد؛
  • روش‌های فرا ابتکاری سیاست‌ها و راهکارهایی هستند که فرآیند جستجو را هدایت می‌کنند؛
  • روش‌های فرا ابتکاری تقریبی بوده و اغلب غیر قطعی(تصادفی) می‌باشند؛
  • این روش‌ها ممکن است با استفاده از مکانیزم‌هایی از به دام افتادن فرآیند جستجو در بهینه‌های موضعی جلوگیری کنند؛
  • الگوریتم های فراابتکاری، برخلاف روش‌های ابتکاری وابسته به نوع مساله نیستند، به عبارت دیگر می‌توان آنها را برای حل طیف گسترده‌ای از مسائل بهینه‌سازی مورد استفاده قرار داد؛
  • روش‌های فرا ابتکاری پیشرفته‌تر، از تجربیات و اطلاعات به دست آمده در طول فرآیند جستجو به شکل حافظه برای هدایت جستجو به نواحی پرامیدتر فضای جواب استفاده می‌کنند؛

به طور خلاصه می‌توان گفت که الگوریتم های فراابتکاری، راهکارهای پیشرفته و کلی جستجو می‌باشند و گام‌ها و معیارهایی را پیشنهاد می‌کنند که در فرار از دام بهینه‌های موضعی بسیار مؤثر هستند. عامل مهم در این روش‌ها، تعادل پویا بین استراتژی‌های تنوع بخشی و پرقدرت سازی است. تنوع بخشی به جستجوی گسترده در فضای جواب اشاره دارد و پرقدرت سازی به معنی بهره‌برداری از تجربیات به دست آمده در فرآیند جستجو و تمرکز بر نواحی پرامیدتر فضای جواب می‌باشد.
بنابراین با ایجاد تعادل پویا بین این دو استراتژی از یک طرف، جستجو به سمت محدوده‌هایی از فضای جواب سوق داده می‌شود که جواب‌های بهتری در آنها یافت شده است و از طرف دیگر موجب عدم اتلاف زمان بیشتر در بخشی از فضای جواب می‌شود که پیش از این بررسی شده و یا شامل جواب‌های نامرغوب‌تری است.
یکی از شاخص‌های تقسیم‌بندی الگوریتم های فراابتکاری، تعداد جواب‌هایی است که آنها در هر تکرار، تولید و مورد بررسی قرار می‌دهند. بر این اساس روش‌های فر ا ابتکاری به دو گروه روش‌های تک نقطه‌ای و روش‌های جمعیتی تقسیم‌بندی می‌شوند که در اینجا شرح مختصری از هر کدام از این روش‌ها آورده می‌شود.

منبع


الگوریتم های فراابتکاری

ردپای بهینه سازی تقریبا در همه بخش های زندگی ما وجود دارد. از طراحی مهندسی گرفته تا بازارهای مالی، از فعالیت های روزمره تا برنامه ریزی تعطیلات و از علوم کامپیوتری تا کاربردهای صنعتی. در حقیقت ما به طور پیوسته به دنبال راه حل های بهینه برای مسائلی که با آن ها روبرو می شویم، هستیم.
توسعه تکنیک های بهینه سازی از سال ها پیش همچنان ادامه دارد و در نیم قرن اخیر پیشرفت های فراوانی در زمینه روش های بهینه سازی صورت گرفته است. روش ها و الگوریتم های بهینه سازی به دو دسته کلی الگوریتم های قطعی و الگوریتم های احتمالی یا تقریبی تقسیم بندی می شوند. الگوریتم های قطعی قادر به یافتن جواب بهینه به صورت دقیق هستند اما در مورد مسائل بهینه سازی سخت کارایی آن ها به شدت کاهش می یابد.
الگوریتم های تقریبی قادر به یافتن جواب های نزدیک به بهینه در زمان حل کوتاه برای مسائل بهینه سازی سخت هستند. الگوریتم های تقریبی به دو دسته الگوریتم های ابتکاری و فرا ابتکاری بخش بندی می شوند. دو مشکل اصلی الگوریتم های ابتکاری قرار گرفتن در بهینه محلی و نا توانی برای کاربرد در مسائل گوناگون است.
الگوریتم های فراابتکاری برای رفع مشکلات الگوریتم های ابتکاری ارائه شدند. درواقع این الگوریتم ها یکی از انواع الگوریتم های بهینه سازی احتمالی هستند که دارای راهکارهای برون رفت از بهینه محلی می باشند و برای طیف گسترده ای از مسائل کاربرد دارند. در این بخش مهمترین مباحث مربوط به ر الگوریتم های فراابتکاری در چندین سرفصل مهم و جامع برای پژوهشگران جمع آوری و طبقه بندی شده است.

دسته‌بندی الگوریتم های فراابتکاری  

معیارهای مختلفی می‌تواند برای طبقه‌بندی الگوریتم های فراابتکاری استفاده شود.
-1مبتنی بر یک جواب و مبتنی بر جمعیت: الگوریتم‌های مبتنی بر یک جواب در حین فرآیند جستجو یک جواب را تغییر می‌دهند، در حالی که در الگوریتم‌های مبتنی بر جمعیت در حین جستجو، یک جمعیت از جواب‌ها در نظر گرفته می‌شوند    .
 -2الهام گرفته شده از طبیعت و بدون الهام از طبیعت: بسیاری از الگوریتم های فراابتکاری از طبیعت الهام گرفته شده‌اند، در این میان برخی از الگوریتم های فراابتکاری نیز از طبیعت الهام گرفته نشده اند   .
3-با حافظه و بدون حافظه: برخی از الگوریتم های فراابتکاری فاقد حافظه می‌باشند، به این معنا که، این نوع الگوریتم‌ها از اطلاعات بدست آمده در حین جستجو استفاده نمی‌کنند (به طور مثال تبرید شبیه‌سازی شده). این در حالی است که در برخی از الگوریتم های فراابتکاری نظیر جستجوی ممنوعه از حافظه استفاده می‌کنند. این حافظه اطلاعات بدست آمده در حین جستجو را در خود ذخیره می‌کند.
-4قطعی و احتمالی: یک الگوریتم فراابتکاری قطعی نظیر جستجوی ممنوعه، مسئله را با استفاده از تصمیمات قطعی حل می‌کند. اما در الگوریتم های فراابتکاری احتمالی نظیر تبرید شبیه سازی شده، یک سری قوانین احتمالی در حین جستجو مورد استفاده قرار می‌گیرد.

الگوریتم های مبتنی بر یک جواب

-الگوریتم تبرید شبیه سازی شده simulated annealing
-جست وجوی ممنوعه tabu search
-جست و جوی حریصانهGRASP search  
-جست و جوی همسایگی متغیرvariable neighborhood search  
-جست و جوی محلی هدایت شدهguided local search  
-جست و جوی محلی تکرار شوندهinterated local search 

الگوریتم های مبتنی بر جمعیت

الگوریتم ژنتیک Genetic Algorithm 
-الگوریتم رقابت استعماری Imperialist Competitive Algorithm 
الگوریتم بهینه سازی کلونی مورچگان Ant Colony Optimization Algorithm  
الگوریتم کلونی زنبور عسل Bee Colony Algorithm 
-الگوریتم کرم شب تاب Firefly Algorithm
-الگوریتم سیتم ایمنی مصنوعی Artificial Immune System Algorithm
-الگوریتم جستجوی هارمونی Harmony Search Algorithm 
الگوریتم بهینه سازی تجمعی ذرات Particle Swarm Optimization Algorithm

 

منابع

1.https://fa.wikipedia.org

2.http://eyvazian.ir

3.http://www.papyrus.ir

4.http://www.ariamodir.com

 

روابط پوشانندگی در مسئلهٔ کوله پشتی بیکران

در حل مسئلهٔ کوله پشتی بیکران، با کنار گذاشتن اشیایی که هیچوقت مورد استفاده قرار نمی‌گیرند، می‌توان مسئله را ساده‌تر کرد. برای مثال، فرض کنید برای شی ای مانند i، می‌توان زیر مجموعه از اشیا به نام J یافت طوری‌که ارزش مجموع آن‌ها بزرگتر از ارزش i و وزن مجموع آن‌ها کمتر از وزن i باشد؛ بنابراین، i نمی‌تواند در جواب بهینه بیاید. در این هنگام مجموعهٔ J را پوشاننده ی iمی‌گوییم. (توجه کنید این استدلال برای مسئلهٔ کوله پشتی کراندار نمی‌تواند مورد استفاده قرار گیرد. زیرا ممکن است قبلاً از اشیا سازندهٔ مجموعهٔ J استفاده کرده باشیم و تمام شده باشند)

پیدا کردن روابط پوشانندگی، به ما کمک می‌کند تا تا حجم فضای جستجو را در حد قابل توجهی کاهش دهیم. انواع مختلفی از روابط پوشانندگی وجود دارند، که همگی در نامساوی زیر صدق می‌کنند:

{\displaystyle \qquad \sum _{j\in J}w_{j}\,x_{j}\ \leq \alpha \,w_{i}}, and {\displaystyle \qquad \sum _{j\in J}v_{j}\,x_{j}\ \geq \alpha \,v_{i}\,} for some {\displaystyle x\in Z_{+}^{n}}

که: {\displaystyle \alpha \in Z_{+}\,,J\subseteq N} و {\displaystyle i\not \in J}. و x_{j} تعداد انتخاب‌های شی نوع j را نشان می‌دهد. (دقت کنید این j‌ها، اعضای مجموعهٔ J هستند)

پوشانندگی انتخابی

شی {\displaystyle i} ام، به‌طور انتخابی توسط {\displaystyle J} پوشانده شده، اگر جمع وزن تعدادی از اعضای مجموعهٔ {\displaystyle J}، کمتر از {\displaystyle w_{i}} باشد و جمع ارزش آن‌ها بیشتر از {\displaystyle v_{i}}. به بیان ریاضی:

{\displaystyle \qquad \sum _{j\in J}w_{j}\,x_{j}\ \leq w_{i}} و {\displaystyle \qquad \sum _{j\in J}v_{j}\,x_{j}\ \geq v_{i}} درصورتی که {\displaystyle x\in Z_{+}^{n}} که {\displaystyle \alpha =1}.

بررسی این نوع پوشانندگی، از لحاظ پیچیدگی محاسباتی چندان ساده نیست، بنابراین از بهترین روش‌ها، راه حل پویاست. در واقع این مسئله، یک مسئله کوله پشتی، اما با پارامترهای کوچکتر، مطابق زیر است:

{\displaystyle V=v_{i}} ، {\displaystyle W=w_{i}} و اشیا محدود به مجموعهٔ {\displaystyle J} هستند.

نماد ریاضی پوشانندگی انتخابی به صورت {\displaystyle i\ll J} است.

پوشانندگی حدی

شی {\displaystyle i} ام، به‌طور حدی توسط {\displaystyle J} پوشانده شده، اگر تعدادی از اشیا نوع {\displaystyle i} توسط {\displaystyle J} پوشانده شوند. به بیان ریاضی:

{\displaystyle \qquad \sum _{j\in J}w_{j}\,x_{j}\ \leq \alpha \,w_{i}} و {\displaystyle \qquad \sum _{j\in J}v_{j}\,x_{j}\ \geq \alpha \,v_{i}\,} در صورتی که {\displaystyle x\in Z_{+}^{n}} و {\displaystyle \alpha \geq 1}.

این نوع پوشانندگی، نمایش کلی تری از پوشانندگی انتخابی نیست که برای اولین بار در معرفی شد و در الگوریتم EDUK مورد استفاده قرار گرفت. کوچکترین \alpha  ممکن، حد i نامیده می‌شود. به بیان ریاضی: {\displaystyle t_{i}=(\alpha -1)w_{i}}. در این هنگام، پاسخ بهینه حد اکثر می‌تواند به تعداد {\displaystyle \alpha -1} شی، از نوع i را شامل شود.

پوشانندگی چندگانه

شی {\displaystyle i}، به‌طور چندگانه توسط شی {\displaystyle j} پوشانده شده، اگر {\displaystyle i} توسط تعدادی از شی نوع {\displaystyle j} پوشانده شود. (یعنی شی{\displaystyle i}، فقط توسط تعدادی شی از نوع {\displaystyle j} پوشانده شود و نیازی به استفاده از اشیا دیگر نباشد). به بیان ریاضی:

{\displaystyle \qquad w_{j}\,x_{j}\ \leq w_{i}} و {\displaystyle \qquad v_{j}\,x_{j}\ \geq v_{i}} برای {\displaystyle x_{j}\in Z_{+}}

که{\displaystyle J=\{j\},\alpha =1,x_{j}=\lfloor {\frac {w_{i}}{w_{j}}}\rfloor }.

این پوشانندگی می‌تواند برای بهینه کردن پروسهٔ حل مورد استفاده قرار گیرد، زیرا تشخیص روابط پوشانندگی از این نوع، به محاسبات زیادی نیاز ندارد و نسبتاً ساده است.

نماد ریاضی پوشانندگی انتخابی به صورت {\displaystyle i\ll _{m}j} است.

پوشانندگی ماژولار

فرض کنیم {\displaystyle b} بهترین شی باشد، یعنی برای تمام {\displaystyle i} ها، {\displaystyle {\frac {v_{b}}{w_{b}}}\geq {\frac {v_{i}}{w_{i}}}\,}{\displaystyle b} شی ای با بیشترین چگالی است.

شی {\displaystyle i} ام، به‌طور ماژولار توسط شی {\displaystyle j} پوشانده شده، اگر توسط {\displaystyle j} و تعدادی شی از نوع {\displaystyle b} پوشانده شود. (یعنی شی {\displaystyle i}، فقط توسط {\displaystyle j} و تعدادی شی از نوع {\displaystyle b} پوشانده شود و نیازی به استفاده از اشیا دیگر نباشد) به بیان ریاضی:

{\displaystyle w_{j}+tw_{b}\leq w_{i}} و {\displaystyle v_{j}+tv_{b}\geq v_{i}}

که {\displaystyle J=\{b,j\},\alpha =1,x_{b}=t,x_{j}=1}.

نماد ریاضی پوشانندگی ماژولار به صورت {\displaystyle i\ll _{\equiv }j} است.

الگوریتم کوله پشتی با استفاده از روش حریصانه

void Greedy Knapsack(w,n)
{
//W is the knapsack and the n objects
sort (p,w)//Pi/Wi  &gt;  =  Pi+1/Wi+1
for(i=0;i  &lt;  n;i++)
    x[i]=۰
    U=W
    for(i=0;i  &lt; n;i++) if(W[i] &gt;  u);
break ;
[
x[i]=1;
u=u-[wi] 
}
if(i  &lt;  n)
    x[i]=u/w 
}

شبه کد عقبگرد برای مسئله کوله پشتی ۰و۱

از انجاییکه این مسئله بهینه‌سازی است، ما رد بهترین مجموعه کنونی کالاها و مجموع ارزش آن‌ها را نگه می‌داریم که اینکار توسط ارائه bestset و و یک متغیر maxprofit انجام می‌شود. این مسئله را برای یافتن اولین جواب بهینه مطرح می‌کنیم

مسئله:n کالا داریم که هر کدام از آن‌ها دارای ارزشی و وزنی دارند. ارزش‌ها و وزن ها، اعدادی صحیح و مثبت هستند. مجموعه‌ای از کالاها با حداکثر مجموع ارزش را طوری تعیین کنید که مجموع اوزان آن‌ها بیش از عدد صحیح مثبت w نشود

ورودی:اعداد صحیح مثبت nوw,ارایه‌های wوpکه از ۱ تاn شاخص دهی شده و هر یک شامل اعداد صحیح و مثبتی هستند که بترتیب غیر نزولی بر اساس مقادیر [p[i]/w[i مرتب شده‌اند

خروجی:مقدار صحیح maxprofit که ماکزیمم ارزش است، ارائه bestset که از ۱ تا n شاخص دهی شده و در مقادیر bestsetو “yes”است اگر کالای iام در مجموعه بهینه قرار داشته باشد در غیر اینصورت مقدار ان “no” می‌باشد

void knapsack (index I ,
             int profit , int weight)
 {
    if (weight  &lt; = W &amp;&amp; profit &gt;  maxprofit){
      maxprofit=profit;
      numbest=i;
      bestset=include;
    }
   if(promising(i)){
   include[i+1]=”yes”;
 knapsack(i+1,profit+p[i+1],weight+w[i+1]);
 include[i+1]=”no”
 knapsack(i+1,profit,weight);
 }
 }
 bool promising(index i)
 {
 index j,k;
 int totweight;
 float bound;
 if(weight  &gt; =  W)
 return false;
 else {
 j=i+1;
 bound=profit;
 totweight=weight;
 while(j  &lt; = n &amp;&amp; totweight + w[j]  &lt; = W){
 totweight=totweight+w[j];
 bound=bound+p[j];
 j++;
 }
 k=j;
 if(k  &lt; = n) bound=bound+(W-totweight)*p[k]/w[k]; return bound &gt;  maxprofit;
 }
 }

طبق قرار دادn,w,p,W ,numbest , bestset , include , maxprofit ورودیهای روتین نیستند. اگر این متغیرهای را به صورت سراسری تعریف می‌کردیم، شبه کد زیر ماکزیمم ارزش و مجموعه دارای این ارزش را تولید می‌کرد:

 numbest=0;
maxprofit = 0 ;
knapsack(0,0,0);
cout  &lt;&lt; maxprofit;      // نوشتن ماکزیمم ارزش
for (j=i ; j &lt; = numbest ; j++)     //نمایش مجموعه بهینه کالاها
cout &lt;&lt; bestset[i];

کاربردها

مسئلهٔ کوله پشتی می‌تواند در تصمیم‌گیری‌هایی که در دنیای واقعی با آن‌ها روبرو هستیم، مورد استفاده قرار گیرد. مانند بریدن کالا به‌طوری‌که کمترین مقدار به هدر رود، انتخاب سرمایه‌گذاری‌هاو سبد سهام، انتخاب دارایی‌ها برای مسئلهٔ امنیت دارایی‌های قبلی و ساختن کلیدها برای سیستم رمزنگاری کوله پشتیِ مرکل-هلمن.

== یکی از کاربردهای اولیهٔ مسئلهٔ کوله پشتی، طراحی و بارم بندی آزمون است به نحوی که آزمون دهنده در پاسخگویی به سؤالات حق انتخاب داشته باشد. چنانچه بارم بندی سؤالات همگن باشد، مسئله بسیار ساده خواهد شد. برای مثال، اگر آزمون دارای 12 سؤال، هر سؤال به ارزش 10 نمره باشد، آزمون دهنده باید فقط 10 سؤال را پاسخ دهد تا به بیشینه نمره ممکنِ 100 برسد. اما برای آزمون‌هایی با بارم بندی نایکسان، مسئله کمی سخت‌تر می‌شود. Feuerman و Weiss سیستمی ارائه دادند که در آن دانش آموزان با آزمونی با بارم بندی ناهمگن، با جمع بارم 125 روبرو هستند. از دانش آموزان خواسته می‌شود با توجه به توانایی‌های خود به سؤالات پاسخ دهند. در اینجا با مسئلهٔ کوله پشتی روبرو هستیم. چه زیر مجموعه‌هایی، جمع نمره‌ای برابر با 100 خواهند داشت؟ برای هر دانش آموز، پاسخ گویی به کدام زیر مجموعه از سؤالات، نمرهٔ بیشتری را به ارمغان می‌آورد؟

یک مثال از مسئله کوله پشتی

صورت مسئله: دزدی قصد سرقت از مغازه‌ای را دارد و حداکثر وزن w از اجناس را که می‌تواند بدزد در این مغازه n نوع جنس وجود دارد. اگر وزن جنس iام wi و قیمت آن vi باشد بیشینه سودی که بدست می‌آورد چقدر است؟

این مسئله به دو صورت تعریف می‌شود: 1- صفر و یک در حالت صفر و یک مسئله به این صورت تعریف می‌شود که دزد یا یک جنس را برمی‌دارد یا برنمی‌دارد و حق برداشتن تکه‌ای از یک جنس را ندارد. برای این مسئله راه حل حریصانه‌ای وجود ندارد و به ارائه یک راه حل پویا خواهیم پرداخت.

ایده حل این مسئله در حالت پویا یه ابن صورت هست که دزد یا جنس iام را برمی‌دارد یا برنمی‌دارد و براساس این دو حالت سود زیرمسئله ایجاد شده محاسبه می‌شود و از مسیری که جواب بیشینه را داده پیش خواهیم رفت. به عبارتی:

کد c[i,w] = c[i-1, w]

 if wi  ≥  0
 max [vi + c[i-1, w-wi], c[i-1, w]}
 if i &gt; 0 and w  ≥  wi

شبه کد Dynamic-0-1-knapsack (v, w, n, W)

 for w = 0 to W
 do c[0, w] = 0
 for i = 1 to n
 do c[i, 0] = 0
 for w = 1 to W
 do if wi  ≤  w
 then if vi + c[i-1, w-wi]
 then c[i, w] = vi + c[i-1, w-wi]
 else c[i, w] = c[i-1, w]
 else
 c[i, w] = c[i-1, w]

۲-کسری در این حالت از مسئه دزد می‌تواند قسمتی از یک جنس را بردارد و مثل حالت قبل ۰ و ۱ی نمی‌باشد. برای این مسئله راه حال حریصانه وجود داره و به این شکل هست که دزد تا می‌تواند جنس پرارزش تر را برداشته و درصورتی که نتوانست بیشترین کسر ممکن آن را برمی‌دارد.

تاریخچه

مسئلهٔ کوله پشتی بیش از یک قرن مورد مطالعه قرار گرفته و اولین بررسی در سال ۱۸۹۷ انجام گرفته‌است. هر چند اولین داده‌های ثبت شده در این مورد، به کارهای ریاضیدانی به نام (1884–1956) Tobias Dantzig برمی گردد، چیزی با عنوان مسئلهٔ کوله پشتی قبلاً در میان عامهٔ مردم وجود داشته‌است.

مسئلهٔ کوله پشتی درجه دوم، اولین بار توسط Hammer، Gallo و Simeone در سال ۱۹۶۰ مطرح شد.

در سال ۱۹۸۸، تحقیقی از دانشگاه استونی بروک بر روی مجموعه‌ای از الگوریتم‌ها، نشان داد که از میان ۷۵ مسئلهٔ الگوریتمی، مسئلهٔ کوله پشتی، ۱۸ امین مسئلهٔ معروف و ۴ امین مسئلهٔ پرکاربرد بعد از درخت کی دی، درخت پیشوندی و bin packing problem است.

منبع


تعریف سوال

شما یک کوله پشتی دارید که حجم ثابتی دارد. همچنین تعدادی وسیله نیز دارید که حجم هر کدام را به شما داده اند. می‌خواهید تعدادی از این وسیله‌ها را در کوله پشتی بریزید به طوری که بیشترین حجم ممکن از کوله پشتی اشغال شود. (فرض کنید شکل وسایل طوری است که فضای بی‌استفاده بین آن‌ها باقی نمی‌ماند.)

الگوریتم

این مسئله یکی از پایه‌ای‌ترین مسائل برنامه‌ریزی پویا است و صورت‌های مختلفی دارد که در انتها به آن‌ها و ایده‌ی اثبات‌شان اشاره می‌شود.
برای حل مدل ساده‌ی سوال، یک آرایه دوبعدی به نام d به ابعاد(n+1)×(W+1) را در نظر بگیرید که در آن n تعداد وسایل مختلفی که می‌توانیم در کوله‌پشتی بگذاریم وW حجم کوله‌پشتی است.
مقدارdi,j برابر یک است اگر و تنها اگر بتوان فقط با استفاده از i وسیله‌ی اول، دقیقا حجم j از کوله‌پشتی را پر کرد. یعنی یک زیرمجموعه‌ از i عضو اول وجود دارد که مجموع وزن‌شان j است. در غیر اینصورت، مقدارش برابر صفر است.
جواب مسئله بزرگترین اندیس j است که dn,j برابر یک باشد.
مقداردهی اولیه: با استفاده از ۰ وسیله‌ی اول (استفاده نکردن از وسایل) فقط می‌توان حجم ۰ را تولید کرد (کوله‌پشتی خالی) پس تمام خانه‌های به صورت d0,j برابر صفر اند به جز d0,0 که برابر ۱ است.
به روز رسانی: برای به دست آوردن di,j دو حالت وجود دارد این که خود وسیله‌ی i ام در کوله‌پشتی نباشد که در این صورت باید برای این که مقدار یک شود، مقدار di1,j برابر ۱ باشد. حالت دیگر این است که خود وسیله در کوله پشتی باشد. پس در این حالت مقدار در صورتی یک می‌شود که (مقدار حجم وسیله‌ی i ام را ai بگیریم) di۱,jai با فرض jai برابر یک باشد.

شبه کد:

d = {0} 
d[0][0] = 1 

for i from 1 to n 
	for j from 0 to W 
		d[i][j] = d[i-1][j] 
		if j   &gt;  = a[i]  and  d[i-1][j-a[i]] == 1
			d[i][j] = 1

اگر دقت کنید می‌بینید احتیاج خاصی به نگه داشتن یک آرایه‌ی دوبعدی نداریم چون برای محاسبه‌ی هر ستون، فقط به ستون قبلی احتیاج داریم و فقط باید ۲ ستون را نگه‌داریم. اما حتی می‌توانیم از این هم جلوتر برویم و فقط یک ستون داشته باشیم. اما در اینجا باید حواس‌مان باشد که اشتباه زیر را انجام ندهیم.
شبه کد با آرایه‌ی یک بعدی (اشتباه):

d = {0} 
d[0] = 1 

for i from 1 to n 
	for j from 0 to W 
		if j   &gt; =  a[i] and d[j-a[i]] == 1
			d[j] = 1

کد بالا یک مشکل دارد. به نظرتان مشکلش چیست؟
فرض کنید در فقط یک وسیله داریم مثلا با حجم ۲ واحد و حجم کوله‌پشتی برابر ۴ است. پس فقط می‌توان ۲ واحد از کوله‌پشتی را پر کرد. اما اگر شبه کد بالا را برای آن اجرا کنید، می‌بینید که مقدار d4d4 برابر یک است. چون با استفاده از وسیله‌ی اول که حجم دو واحد داشت، مقدار d2d2 را یک کردیم، اما بعد از این متوقف نشدیم بلکه چون مقدار d2d2 برابر یک بود، مقدار d4d4 را نیز برابر یک قرار دادیم. پس انگار بیش از یک وسیله با حجم دو داشتیم. در واقع این کد جواب مسئله‌ی دیگری به نام خرد کردن پولاست که در آن به تعداد نامتناهی از هر کدام از وسایل داریم.
حال بیایید سعی کنیم مشکل کد بالا را حل کنیم. مشکل این بود که اول با استفاده از وسیله‌ی اول (یا بقیه‌ی وسایل) مقدار خانه‌های پایین جدول را به روز رسانی کردیم و سپس دوباره با استفاده از همان وسیله، مقادیر خانه‌های بالاتر را نیز به روز رسانی کردیم. چطور می‌شود اگر خانه‌ها را به ترتیب دیگری پیمایش کنیم تا این مشکل پیش نیاید؟ حجم وسایل که نمی‌تواند منفی باشد. پس اگر بالا به پایین آرایه را به روز رسانی کنیم، این مشکل پیش نمی‌آید. خودتان هم کمی فکر کنید که چرا این روش درست است.
بر همین اساس کد را تغییر می‌دهیم. شبه کد با آرایه‌ی یک بعدی (درست):

d = {0} 
d[0] = 1 

for i from 1 to n 
	for j from W to 0 
		if j   &gt; =  a[i] and d[j-a[i]] 
			d[j] = 1

پیچیدگی‌ الگوریتم

پیچیدگی زمانی که در تمام حالت‌ها از O(n×W) است. مقدار حافظه‌ی مورد نیاز نیز O(W) است.

صورت‌های مختلف سوال

مثال: فرض کنید وسایلی که می‌خواهید در کوله‌پشتی بگذارید، علاوه‌بر حجم، ارزش نیز داشته باشند و هدف شما فقط بردن وسایلی باشد که در مجموع ارزش‌شان بیشترین مقدار ممکن باشد. الگوریتمی از O(n×W) برای حل این سوال بدهید.

پاسخ

تعریف آرایه‌ی dd را به این صورت تغییر دهید که di,jdi,j یعنی با استفاده از ii وسیله‌ی اول و حجم jj حداکثر مجموع ارزش وسایل در کوله‌پشتی چقدر است. شیوه‌ی به روز رسانی شبیه سوال اصلی است و به خواننده محول می‌شود.

پیاده‌سازی اولیه

#include   &lt; iostream &gt; 
using namespace std; 
 
const int MAXN = 10*1000; 
const int MAXW = 100*1000; 
 
bool d[MAXW+10]; 
int p[MAXW+10]; 
int a[MAXN+10]; 
 
int main() 
{ 
	ios::sync_with_stdio(false); 
	int n, w; 
	cin   &gt;&gt;   n   &gt;&gt;   w; 
	for(int i=0; i  &lt; n; i++) cin &gt;&gt;   a[i]; 
 
	d[0] = 1; 
	for(int i=0; i  &lt; n; i++) for(int j=w; j &gt;  =a[i]; j--) 
			if( d[j] == 0 &amp;&amp; d[j-a[i]] == 1 ) 
			{ 
				d[j] = 1; 
				p[j] = a[i]; 
			} 
 
	int out = w; 
	for(; out  &gt; =  0; out--) 
		if( d[out] ) 
			break; 
 
	cout   &lt;&lt;   out   &lt;&lt;   endl; 
	while( out != 0 ) 
	{ 
		cout   &lt;&lt;   p[out]   &lt;&lt;   " "; 
		out -= p[out]; 
	} 
	cout   &lt;&lt;   endl; 
	return 0; 
}

منبع 

مسئله کوله پشتی قسمت 1
مسئله کوله پشتی قسمت 2