قدم اول در حل مسئله بهینه سازی مقید با استفاده از الگوریتم رقابت استعماری

این پست در پاسخ سوال یکی از دوستان در مورد نحوه مواجهه با قیود در الگوریتم رقابت استعماری تهیه شده است. مطالعه این پست را به آنهایی که علاقه دارند تا مسائل بهینه سازی مقید خود را با الگوریتم های تکاملی و به طور ویژه با الگوریتم رقابت استعماری حل کنند، توصیه می کنیم. ایده مطرح شده در این پست، کلی بوده و قابل اعمال به همه الگوریتم های تکاملی از جمله الگوریتم های ژنتیک (Genetic Algorithms)، الگوریتم پرندگان یا ازدحام ذرات (Particle Swarm Optimization) و یا کلونی مورچگان (Ant Colony Optimization) می باشد. با ما در ادامه مطلب همراه باشید.

همانگونه که در پست های مختلفی بر روی وبسایت الگوریتم رقابت استعماری و بهینه سازی تکاملی مثلاً در این پست (+) خدمتتان عرض کرده ایم، برای حل مسائل بهینه سازی مقید، اولین قدم، جلوگیری از تولید جوابهای خارج از محدود پذیرفته شده (Feasible Solutions) است. در کدهای الگوریتم رقابت استعماری برای این منظور چه باید کرد؟
اگر شما از کدهای الگوریتم رقابت استعماری استفاده می کنید، سه تابع وجود دارند که باعث ایجاد تغییرات در موقعیت کشورها (تغییر آنها) می شوند. هر یک از این سه بخش باید مورد بررسی قرار گرفته و تغییراتی در آنها ایجاد شود. نکته قابل ذکر این است که اگر قیود ساده و به صورت بازه ثابت برای هر متغیر باشند، نیازی به انجام این تغییرات نیست و نسخه های مختلف کدهای الگوریتم رقابت استعماری بر روی وب بازه اولیه متغیرها را در اول برنامه گرفته و جوابهای نهایی را نیز مطمئناً در این بازه می دهند. پس منظور از قیود، این نوع قیود ساده نیستند. به مثال زیر توجه کنید.

 

فرض کنید می خواهیم در یک مسئله بهینه سازی در حوزه مدیریت مالی، از مجموع یک بودجه برداشتی بهینه داشته باشیم. یک تابع هدف نیز داریم. قیدی داریم که مجموع برداشت ها باید یک (100 درصد) باشد. این قید هم باید در تولید جوابهای اولیه و هم در ایجاد تغییرات آرام (تابع جذب) و هم در تغییرات ناگهانی (تابع انقلاب) لحاظ شود.
در ورژن اولیه کدها که معمولاً استفاده می شود، این سه تابع به ترتیب عبارتند از
  • GenerateNewCountry
  • AssimilateColonies
  • RevolveColonies
در هر سه این توابع باید خطوطی از کد را اضافه کنیم که جمع متغیرهای تولیدی را برابر با یک کند. مثلاً تابع GenerateNewCountry در حالت اولیه به صورت زیر است.
function NewCountry = GenerateNewCountry(NumOfCountries,ProblemParams)
VarMinMatrix = repmat(ProblemParams.VarMin,NumOfCountries,1);
VarMaxMatrix = repmat(ProblemParams.VarMax,NumOfCountries,1);
NewCountry = (VarMaxMatrix – VarMinMatrix) . rand(size(VarMinMatrix)) + VarMinMatrix;
end
با اضافه کردن یک خط می توان مجموع اجزای یک کشور را در مرحله ایجاد برابر با یک کرد. تابع تغییر یافته و خط اضافه شده را در زیر می بینید.
function NewCountry = GenerateNewCountry(NumOfCountries,ProblemParams)
VarMinMatrix = repmat(ProblemParams.VarMin,NumOfCountries,1);
VarMaxMatrix = repmat(ProblemParams.VarMax,NumOfCountries,1);
NewCountry = (VarMaxMatrix – VarMinMatrix) . rand(size(VarMinMatrix)) + VarMinMatrix;
%% Normalizing the sum of population to 1
NewCountry = NewCountry . repmat(sum(NewCountry,2),1,ProblemParams.NPar);
end

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

تغییرات مشابهی در توابع بعدی نیز باید ایجاد شود. دو تابع بعدی را به ترتیب در زیر آورده ایم.

تابع AssimilateColonies در حالت اولیه

function TheEmpire = AssimilateColonies(TheEmpire,AlgorithmParams,ProblemParams)
NumOfColonies = size(TheEmpire.ColoniesPosition,1);
Vector = repmat(TheEmpire.ImperialistPosition,NumOfColonies,1)-TheEmpire.ColoniesPosition;
TheEmpire.ColoniesPosition = TheEmpire.ColoniesPosition + 2 AlgorithmParams.AssimilationCoefficient rand(size(Vector)) . Vector;
MinVarMatrix = repmat(ProblemParams.VarMin,NumOfColonies,1);
MaxVarMatrix = repmat(ProblemParams.VarMax,NumOfColonies,1);
TheEmpire.ColoniesPosition=max(TheEmpire.ColoniesPosition,MinVarMatrix);
TheEmpire.ColoniesPosition=min(TheEmpire.ColoniesPosition,MaxVarMatrix);
end

تابع AssimilateColonies در حالت تغییر یافته

function TheEmpire = AssimilateColonies(TheEmpire,AlgorithmParams,ProblemParams)
NumOfColonies = size(TheEmpire.ColoniesPosition,1);
Vector = repmat(TheEmpire.ImperialistPosition,NumOfColonies,1)-TheEmpire.ColoniesPosition;
TheEmpire.ColoniesPosition = TheEmpire.ColoniesPosition + 2 AlgorithmParams.AssimilationCoefficient rand(size(Vector)) . Vector;
%% Modifying Population according to Conditions
MinVarMatrix = repmat(ProblemParams.VarMin,NumOfColonies,1);
MaxVarMatrix = repmat(ProblemParams.VarMax,NumOfColonies,1);
TheEmpire.ColoniesPosition=max(TheEmpire.ColoniesPosition,MinVarMatrix);
TheEmpire.ColoniesPosition=min(TheEmpire.ColoniesPosition,MaxVarMatrix);
TheEmpire.ColoniesPosition = TheEmpire.ColoniesPosition .      repmat(sum(TheEmpire.ColoniesPosition,2),1,ProblemParams.NPar);
end

تابع RevolveColonies در حالت اولیه

function TheEmpire = RevolveColonies(TheEmpire,AlgorithmParams,ProblemParams)
NumOfRevolvingColonies = round(AlgorithmParams.RevolutionRate numel(TheEmpire.ColoniesCost));
RevolvedPosition = GenerateNewCountry(NumOfRevolvingColonies , ProblemParams);
R = randperm(numel(TheEmpire.ColoniesCost));
R = R(1NumOfRevolvingColonies);
TheEmpire.ColoniesPosition(R,) = RevolvedPosition;
MinVarMatrix = repmat(ProblemParams.VarMin,NumOfColonies,1);
MaxVarMatrix = repmat(ProblemParams.VarMax,NumOfColonies,1);
TheEmpire.ColoniesPosition=max(TheEmpire.ColoniesPosition,MinVarMatrix);
TheEmpire.ColoniesPosition=min(TheEmpire.ColoniesPosition,MaxVarMatrix);
end

تابع RevolveColonies در حالت تغییر یافته

function TheEmpire = RevolveColonies(TheEmpire,AlgorithmParams,ProblemParams)
NumOfRevolvingColonies = round(AlgorithmParams.RevolutionRate numel(TheEmpire.ColoniesCost));
RevolvedPosition = GenerateNewCountry(NumOfRevolvingColonies , ProblemParams);
R = randperm(numel(TheEmpire.ColoniesCost));
R = R(1NumOfRevolvingColonies);
TheEmpire.ColoniesPosition(R,) = RevolvedPosition;
%% Modifying Population according to Conditions
NumOfColonies = size(TheEmpire.ColoniesPosition,1);
MinVarMatrix = repmat(ProblemParams.VarMin,NumOfColonies,1);
MaxVarMatrix = repmat(ProblemParams.VarMax,NumOfColonies,1);
TheEmpire.ColoniesPosition=max(TheEmpire.ColoniesPosition,MinVarMatrix);
TheEmpire.ColoniesPosition=min(TheEmpire.ColoniesPosition,MaxVarMatrix);
TheEmpire.ColoniesPosition = TheEmpire.ColoniesPosition . repmat(sum(TheEmpire.ColoniesPosition,2),1,ProblemParams.NPar);
end

با ایجاد این تغییرات تضمین می شود که جواب بهینه نهایی مسئله مجموع یک خواهد داشت.

در زیر نمودار همگرایی مسئله را می بینیم.

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

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

  1. مسئله من تعداد زیادی قید داره، تا جایی که من کد ها رو بررسی کردم باید اونا رو تو 3 جا اعمال کنیم:      RevolveColonies و GenerateNewCountry و AssimilateColonies. اینا درستن یا جای دیگه ای هم هست؟
  2. بعد از تولید جمعیت اولیه ( یا مراحل بعدی) به صورت اتفاقی، شرایط رو اعمال میکنم و اگر جواب نداد هر مرحله رو از اول تکرار میکنم تا جمعیت ها حتما قیود رو شامل باشن و این کار خیلی سرعت رو پایین میاره آیا راه حلی برای بهبود این وضعیت هست؟

پاسخ ها:

  1. دقیقاً این بخشها هستند که باید تغییر پیدا کنند. تازه اینها بخشهایی هستند در صورت استفاده از “سیاست پیشگیری”، باید تغییر یابند. اگر از سیاست جریمه استفاده شوند، همین ها هم نیازی به تغییر ندارند! در این مورد فرض بر این هست که شما فایل صوتی زیر را مورد استفاده قرار داده اید!
    1. http://www.icasite.info/2010/05/blog-post_1525.html
  2. این بخش نیاز به خلاقیت در هر مسئله دارد. به عنوان یک مثال ساده، مثلاً وقتی قیدها قرار است مجموعشان برابر عدد یک شود، شما می توانید همیشه یکی از متغیرها را برابر یک منهای بقیه تعریف کنید. روش دیگر می تواند، تقسیم همه اعداد به مجموع شان باشد. بسته به شرایط، هر یک از این دو روش می تواند مناسب تر از دیگری باشد. اینکه چه راهی مناسب تر است، نیاز به ایده زنی در آن مسئله دارد. در ضمن اگر دیدید این مسیر سخت می شود، استفاده از متدهای کلی مبتنی بر جریمه پیش روی شماست! در نهایت این را هم در نظر بگیرید که چرخه مورد نظر نباید آنقدر پیچیده و با تغییرات بسیار در جوابها باشد که اطلاعات جواب را از میان ببرد. یعنی فقط به خاطر قیدها آنقدر روی جوابها کار شود که معلوم نشود از کجا آمدند و به کجا رفتند. در این شرایط ممکن است الگوریتم گیج شود. چون کلی انرژی بر روی حرکت در مسیر خاصی گذاشته شده و بعد شما بصورت میانبر آن جواب را وارد حوزه ممکنه جوابها کرده باشید، بدون اینکه الگوریتم بفهمد از چه مسیری به اینجا رسید تا دفعه بعد نیز، حواسش باشد. در حقیقت همان سیستم ماهی و ماهی گیری می شود. باید شما به الگوریتم با قیدهایتان، ماهیگیری یاد دهید.
_____________________________________________
نظرات شما در انتهای این پست برای سایر خوانندگان، بسیار مفید خواهد بود. می توانید نظر خود را با اکانت سرویس های مختلف و یا به عنوان ناشناس در این پست درج نمائید.

صرف زمان برای یادگیری اتلاف زمان نیست. سرمایه گذاری زمانی است.

انواع مسائل بهینه سازی و تقسیم بندی آنها

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

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

بهینه سازی تک بعدی و بهینه سازی چند بعدی
اگر تنها یک متغیر در مسئله بهینه سازی وجود داشته باشد، مسئله بهینه سازی یک مسئله تک بعدی و در غیر این صورت دو بهدی است. مثالی از یک مسئله بهینه سازی یک بعدی به صورت زیر می باشد.

\begin{array}{l}  f(x) = {x^2} + \sin (x) \\   x \in [ - 10,10] \\   \end{array}

یک نمونه از یک مسئله چند یعدی (3 بعدی) به صورت زیر می باشد.

\begin{array}{l}  f(x,y,z) = {x^2} + {y^2} + {z^2} + \sin (x) + \sin (y) + \sin (z) \\   x,y,z \in [ - 10,10] \\   \end{array}

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

\begin{array}{l}  f(x,y) = {x^2} + {y^2} + \sin (x) + \sin (y) \\   x,y \in [ - 10,10] \\   \end{array}

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

\begin{array}{l}  f(x,y,t) = {x^2} + {y^2} + \sin (x/t) + \sin (y/t) \\   x,y \in [ - 10,10] \\   \end{array}

جواب هر دو مسئله بهینه سازی فوق نقطه (0,0) است. حتی تابع دوم نیز که متغیر با زمان می باشد برای هر لطحظه از زمان t به جواب (0,0) می رسد. اما این حالت کلی نمی باشد و در حالت کلی جواب بهینه مسئله پارامتر زمان را نیز با خود خواهد داشت.

بهینه سازی مقید و نا مقید
اگر متغیر های مسئله بهینه سازی به بازه (و یا قید) خاصی محدود باشند، با یک مسئله بهینه سازی مقید (Constrained Optimization) سروکار داریم و در غیر این صورد مسئله بهینه سازی نا مقید است. مثالی از بهینه سازی مقید را در زیر می بینید. در این رابطه موارد بعد از تابع هزینه همگی قیود بهینه سازی هستند. جواب بهینه مسئله باید از میان جوابهایی انتخاب شوند که در هر سه قیود صدق می کنند.

f(x,y) = {x^2} + {y^2} + \sin (x) + \sin (y)
x,y \in [ - 10,10]
{x^2} + {y^2} \le 20
x - y \ge 15

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

بهینه سازی پیوسته و یا گسسته
یک مسئله بهینه سازی گسسته مسئله ای است که در آن متغییر های مسئله در یک بازه معیین تغییرات گسسته دارند. در حالی که در یک مسئله پیوسته مغییرها در بازه معیین تغییرات گسسته دارند. مثالی از یک مسئله بهینه سازی پیوسته به صورت زیر است. این تابع به تابع راسریجین معروف است.

\begin{array}{l}  {f_1} = 20 + {x^2} + {y^2} - 10*(\cos (2\pi x) + \cos (2\pi y)) \\   x,y \in [ - 10,10] \\   \end{array}

این تابع به تابع راسریجین معروف است و نقطه بهینه این تابع نقطه (0,0) است. شکل زیر این تابع را نشان می دهد.

 

\begin{array}{l}  {f_1} = 20 + {n^2} + {m^2} - 10*(\cos (2\pi n) + \cos (2\pi m)) \\   n,m \in [ - 10, - 9, - 8,.\,.\,.\,,8,9,10] \\   \end{array}

به عنوان مثالی از یک مسئله بهینه سازی گسسته، همان تابع فوق را بصورت گسسته در نظر می گیریم.

نقطه بهینه این تابع نقطه (0,0) است. شکل این تابع در زیر نشان داده شده است.

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

بهینه سازی تک معیاره و چند معیاره
یک مسئله بهینه سازی تک معیاره (Single Objective)، دارای تنها یک تابع هدف می باشد. مثالی از این نوع مسئله بهینه سازی به صورت زیر می باشد.

\begin{array}{l}  {f_1} = 20 + {x^2} + {y^2} - 10*(\cos (2\pi x) + \cos (2\pi y)) \\   x,y \in [ - 10,10] \\   \end{array}

اما در یک مسئله چند معیاره (Multi Objective)، تعداد تابع هدف هایی که بطور همزمان بهینه می شوند بیش از یک تا است. مثال از این نوع مسئله بهینه سازی به صورت زیر می باشد.

\begin{array}{l}  {f_1} = 10 + {x^2} + {y^2} - 10*(\cos (\pi x) + \cos (\pi y)) \\   {f_2} = 20 + {x^3} + {y^3} - 20*(\cos (2\pi x) + \cos (2\pi y)) \\   x,y \in [ - 10,10] \\   \end{array}
این مسئله دارای دو تابع هدف می باشد که باید بطور همزمان بهینه شوند. اگر فرض کنیم که توابع فوق مسائل مینیمم سازی هستند، در این صورت به عنوان مثال جواب ({f_1},{f_2}) = (10,11) در مقابل جواب ({f_1},{f_2}) = (20,22) بهتر بوده و انتخاب مناسب تری می باشد. اما در مقابل آن جواب (یعنی ({f_1},{f_2}) = (10,11))، جواب ({f_1},{f_2}) = (9,12) نه بهتر است نه بدتر. در حقیقت از دید {f_2} جواب اول بهتر است و از دید {f_1} جواب دوم. مجموعه جوابهایی که هیچ برتری نسبت به هم ندارند تشکیل یک منحنی را در صفحه می دهند که به نام منحنی پرتو (Pareto) شناخته می شود. شکل زیر یک منحنی پرتو مربوط به یک مسئله بهینه سازی نوعی را نشان می دهد.

 

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

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

——————————————–
مراجع: در تهیه این متن از بخش هایی از سمینار کارشناسی ارشد جناب آقای سید مصطفی کلامی هریس استفاده شده است.

_____________________________________________
نظرات شما در انتهای این پست برای سایر خوانندگان، بسیار مفید خواهد بود. می توانید نظر خود را با اکانت سرویس های مختلف و یا به عنوان ناشناس در این پست درج نمائید.
صرف زمان برای یادگیری اتلاف زمان نیست. سرمایه گذاری زمانی است.