تشغيل النمل. يركض

تتناول هذه المقالة عملية إنشاء نموذج محاكاة لسلوك مستعمرة النمل (يمكن قراءتها على ويكيبيديا ) في بيئة المحاكاة "AnyLogic". هذه المقالة عملية. ستنظر في استخدام خوارزمية النمل لحل مشكلة البائع المتجول (يمكنك القراءة هنا ).



باختصار حول الجوهر


جوهر مشكلة البائع المتجول هو أنه يجب على البائع المتجول (البائع) زيارة المدن الشمالية بعد زيارة كل منها مرة واحدة فقط على طول أقصر طريق. نظرًا لأن هذه المهمة معقدة NP ويتم احتساب عدد الخيارات لجميع المسارات الممكنة بين N من المدن على أنها "N!" ، فإن أقصر وقت للبحث عن المسار سيزداد بشكل كبير مع زيادة في N. وبالتالي ، فإن أقصر وقت للبحث عن طريق (الحل) باستخدام الخوارزمية يزداد "البحث الشامل" (الذي يعطي حلاً دقيقًا) مع عدد المدن N> 16 بشكل حاد (أسي). لذلك ، لن نبحث عن أقصر مسار في الطول ، ولكننا نقترب منه (عقلاني) في وقت محدود باستخدام "خوارزمية النمل".

بضع كلمات حول AnyLogic هي أداة قوية تسمح لك بإنشاء نماذج محاكاة متنوعة التعقيد. تنفذ مناهج مختلفة من المحاكاة. سنقوم بتحليل واحد فقط من النهج ، وهي نمذجة "الوكيل". يتم تنفيذه بلغة برمجة Java ، والتي تكمل الأدوات الموجودة. العيب الرئيسي لـ "AnyLogic" هو محدودية النسخة المجانية على عدد الوكلاء الذين تم إنشاؤهم ؛ لا يمكن أن يتجاوز عددهم 50000. "الوكيل" هو الوحدة الأساسية لنظام محاكاة AnyLogic. يمكن العثور على مزيد من المعلومات على موقع www.anylogic.ru

أدوات


1. Anylogic - قم بتنزيل الإصدار المجاني من هنا www.anylogic.ru/downloads
المقدمة الأولية لـ

AnyLogic : تظهر واجهة AnyLogic في الشكل 1. وتتضمن:
  • المنطقة الخضراء هي مساحة العامل الذي سنقوم بإنشائه ؛
  • المنطقة الحمراء - خصائص الكائن الذي يتم التركيز عليه ؛
  • لوحة - الأدوات التي يمكنك استخدامها عند إنشاء نموذج ؛
  • المشاريع - هيكل النموذج المطور.



تين. 1- نافذة منبثقة AnyLogic

إنشاء المشروع


كل شيء بسيط هنا. انقر فوق عنصر القائمة "ملف" بجوار "إنشاء" ثم "نموذج" ، أدخل اسم النموذج وانقر على زر "إنهاء" (الشكل 2).


تين. 2- إنشاء نموذج

إنشاء مدن


حسنًا ، لنبدأ. أول شيء سنفعله هو إنشاء ما يسمى بالمدن (قمم الرسم البياني) التي ستزورها النملة. لماذا نفتح علامة التبويب "الوكيل" في اللوحة واسحب الدائرة الحمراء مع الرجل الصغير إلى العامل "الرئيسي" من هناك ، كما هو موضح في الشكل 3.


الشكل. 3- إنشاء مدن

بعد تحرير زر الماوس ، يظهر مربع حوار ("الخطوة 1") ، يطالبك بإنشاء وكيل. حيث سيكون من الضروري تحديد عنصر "عامل السكان" وانقر على زر "التالي".


تين. 4- إنشاء مدن

يظهر مربع الحوار التالي (الخطوة 2) حيث ستحتاج إلى إدخال اسم نوع الوكيل الجديد واسم مجتمع الوكيل. أدخل نوع "MyTown" واسم السكان "myTowns" وانقر على زر "التالي".


تين. 4 أ - أدخل اسم الوكيل الجديد

ثم ستظهر النافذة التالية (الخطوة 4.). هنا نختار "2D Agent Animation" والرمز الذي يحمل نقش "Plant" وانقر على زر "Finish" (الشكل 5).


تين. 5- أضف رسوم متحركة للوكيل

الآن قم بإنشاء متغير سيحدد العدد الأولي للمدن في نموذجنا. لماذا ، من "لوحة" ، اسحب الرمز مع نقش "متغير" إلى الوكيل "الرئيسي" وأدخل اسمه "numberTown". بعد ذلك ، انقر فوق رمز المتغير الخاص بنا وفي علامة التبويب خصائص ، أدخل قيمته الأولية تساوي ، على سبيل المثال ، 10 وحدد نوعه "int" (الشكل 6).


تين. 6- إنشاء متغير

الآن نقوم بتعيين القيمة الأولية لسكان مدينتنا "myTowns" ، والتي نضغط من أجلها على رمزها وفي علامة التبويب "خصائص" في حقل "العدد الأولي للوكلاء" اكتب اسم المتغير الذي أنشأناه سابقًا (الشكل 7).


تين. 7 - تغيير خصائص سكان "myTowns" بعد ذلك ، سنستخلص

خاتمة مدننا في الوكيل "الرئيسي" في مكان عشوائي. تقتصر المساحة على مربع 400 × 400 بكسل. لماذا ، في علامة التبويب "المشاريع" ، حدد وكيل "الرئيسي" باستخدام الماوس وفي علامة التبويب "الخصائص" ، في الحقل "عند بدء التشغيل" ، أضف رمز جافا التالي (الشكل 7 أ):
for (int i=0; i<myTowns.size(); i++) {
	myTowns.get(i).setXY(uniform(0,400), uniform(0,400));
}

أين:
  • myTowns.size () - عدد المدن التي تم إنشاؤها ؛
  • myTowns.get (i) .setXY (منتظم (0.400) ، منتظم (0.400)) - تعيين إحداثيات X و Y للمدينة i ؛
  • منتظم (0،400) - دالة تُرجع رقمًا عشوائيًا في النطاق من 0 إلى 400 وفقًا لقانون التوزيع المحتمل والمتساوٍ لمتغير عشوائي. تحتوي بيئة AnyLogic على مجموعة أدوات شاملة للعمل مع توزيعات مختلفة من المتغيرات العشوائية. يوجد مُنشئ مدمج للتوزيعات الاحتمالية ، وهو متوفر في شريط الأدوات.

أين:
  • myTowns.size () - عدد المدن التي تم إنشاؤها ؛
  • myTowns.get (i) .setXY (منتظم (0.400) ، منتظم (0.400)) - تعيين إحداثيات X و Y للمدينة i ؛
  • uniform(0,400) – , 0 400 . AnyLogic . .



تين. 7 أ - نقوم بترتيب المدن ،

ثم يمكننا بالفعل رؤية ما قمنا به وبدء نموذجنا. للقيام بذلك ، استخدم المفتاح "F5" ، انقر فوقه وسيتم تشغيل النافذة لبدء التجربة كما هو موضح في الشكل 8.


الشكل. 8 - ابدأ التجربة

بعد ذلك ، انقر على زر "تشغيل" في الزاوية اليسرى السفلية من النافذة وتبدأ التجربة. يجب أن تحصل على نافذة تحتوي على المحتويات على الشاشة كما هو موضح في الشكل 9.


الشكل. 9 - نتيجة التجربة

لذلك قمنا في هذه الخطوة بإنشاء 10 مدن ووضعناها في مكان عشوائي (عشوائي) على شاشتنا. الآن دعنا ننتقل إلى إنشاء "النمل" لدينا

اصنع نملة


لذا ، فإن الوحدة القتالية الرئيسية لنموذجنا ستكون نملة. يجب علينا أولاً أن ننشئها ، ثم نمثل سلوكها.

يشبه إنشاء نملة إنشاء مدينة. في "لوحة" حدد "وكيل" واسحبه إلى "الرئيسي". حدد "تعداد الوكلاء" ، ثم "أريد إنشاء نوع وكيل جديد" ، ثم أدخل "اسم النوع الجديد" و "اسم التعداد السكاني" "MyAnt" و "myAnts" وانقر على "التالي". بعد ذلك نختار الرسوم المتحركة "2D" ، على سبيل المثال ، الرمز الذي يحمل نقش "Fighter" اضغط على "Finish" ويجب أن يظهر كما هو موضح في الشكل 10


. 10 - خلق النمل

موافق ، لا تبدو الطائرة مثل نملة ، لذلك سنصلحها. نذهب إلى محرك البحث بحثًا عن صورة تصور نملة ونغير الطائرة إلى نملة. لماذا نضغط مرتين على الدائرة الحمراء بالقرب من "myAnts". بعد ذلك ستفتح علامة التبويب "myAnt" حيث تحتاج إلى إزالة الطائرة ووضع النملة في مكانها (الشكل 11).


تين. 11 - علامة التبويب MyAnt

حدد الطائرة باستخدام الماوس واضغط على "Del". بعد ذلك ، انتقل إلى علامة التبويب "العرض التقديمي" واسحب عنصر "الصورة" من هناك. بعد ذلك ، سيتم فتح مربع حوار تلقائيًا لتحديد ملف. حدد الملف مع نملة لدينا (الشكل 12) وانقر فوق موافق.


تين. 12 - علامة التبويب MyAnt مع نملة وبالفعل بدون طائرة

استمر. قم بقياس النملة وحركها إلى المكان الذي كانت فيه الطائرة في السابق. يجب أن يتحول كما هو موضح في الشكل 12 أ. يتم تنفيذ جميع هذه العمليات باستخدام الماوس.


تين. 12a - علامة التبويب MyAnt مع نملة

نحيا النملة


الآن نحن بحاجة إلى تعليم نملة المخبوزات الطازجة للزحف بين المدن. صحيح ، حتى الآن دون مراعاة النموذج الرياضي ، ولكن لا يزال يسمح له بالعمل. وهكذا ، افتح الرسم التخطيطي "مخطط الدولة" في "لوحة" والمتابعة. نقوم بنقل الكتل التالية وربطها معًا:
  • بداية مخطط الحالة هو نقطة البداية لدورة حياة نملة لدينا.
  • الحالة - ستميز هذه الكتلة حالة دورة حياة نملة. هذه الكتل مطلوبة في القطع.
  • الانتقال - سهم يربط "ولاياتنا" ببعضنا البعض ويؤدي الانتقال من "ولاية" إلى "دولة" أخرى في ظل ظروف معينة.

ونتيجة لذلك ، يجب أن يتحول إلى شيء مثلما هو موضح في الشكل 13.


الشكل. 13 - منطق سلوك النملة

الآن دعنا نكتب المنطق الأولي لمخطط النملة. نختار بالماوس السهم الذي يخرج من الكتلة تحت اسم "Select City" ونضيف الكود التالي في الحقل "Action" في علامة التبويب "Properties" (الشكل 14):
for (int i=0; i<main.myTowns.size(); i++) {
	if (randomTrue(0.5)) {
		this.moveTo(main.myTowns.get(i));
		break;
	} 
}

هنا كل شيء بسيط للغاية ، نذهب من خلال الدورة في جميع المدن ونرمي عملة معدنية (نولد متغيرًا عشوائيًا باحتمال 0.5) إذا كانت قيمته صحيحة (نسر) ، ثم نرسل النملة إلى هذه المدينة مغادرين الدورة. التعبير "this.moveTo (main.myTowns.get (i))" هو دالة ترسل وكيلًا إلى آخر.


تين. 14 - قم بتعيين المنطق الأولي لحركة النملة

، ثم انقر على السهم الذي يترك كتلة "الحركة" وفي علامة التبويب "الخصائص" في حقل "يحدث" ، واضبط القيمة "عند استلام رسالة" وحدد "عند استلام الرسالة المحددة" في الحقل "يحدث". »كما هو مبين في الشكل 15.


الشكل. 15 - ضبط منطق الانتقال بين "الحركة" و "تجاوز كل شيء"

الآن قم بتكوين آخر سهم يخرج من كتلة "الحركة". نختارها بالماوس وفي علامة التبويب "الخصائص" ، في حقل الانتقال ، نضبط "عند وصول الوكيل". يجب أن تكون الصورة النهائية لـ "مخطط الحالة" كما هو موضح في الشكل 16.


الشكل. 16 - مخطط الحالة مع التحولات

المكونة بين الكتل لذا ، دعونا نلقي نظرة على كيفية عمل "مخطط الحالة" لسلوك النمل:
  1. الحالة الأولى التي تقع فيها النملة هي "Vybor_city" ، حتى الآن لم يتم توضيح أي إجراء.
  2. ثم يذهب إلى الدولة التالية عند الانتقال. في هذا الانتقال ، أضفنا رمزًا يبدأ دورة عبر جميع الجبال ويجعل النمل يجري حول المدن.
  3. كتلة "الحركة" هي المكان الذي توجد فيه النملة حتى تصل إلى المدينة المختارة مسبقًا.
  4. علاوة على ذلك ، لديه طريقتان. أولاً ، يعود إلى الكتلة "City_Choice" ويتكرر كل شيء مرة أخرى. في المسار الثاني سيتعين عليه الذهاب عندما يزور جميع المدن بالفعل. حتى الآن ، لم يتم إنشاء الطريق الثاني معنا. سنتعامل معهم بعد قليل.



تين. 17 - تشغيل مخطط الحالة

الآن يمكننا الضغط على "F5" لمعرفة ما حدث (الشكل 18).


تين. 18- إحياء النمل

حدد المعايير


إذن ، ما هي هذه المعايير (القواعد):
  1. يجب على النملة زيارة كل مدينة مرة واحدة فقط.
  2. النمل ، عندما زار جميع المدن ينهي حركته في المدينة الأخيرة.

تملي علينا هذه المعايير من خلال حالة مشكلة البائع المتجول. سيكون كل نملة معنا نوعًا من البائع المتجول الذي يسافر عبر المدن.

دعونا نعلم النملة أن تلتزم بهذه القواعد. لماذا ، من "لوحة" ، علامة التبويب "وكيل" ، نقل "مجموعة" و "متغير" إلى علامة التبويب "MyAnt" وأطلق عليهم الأول باسم "isVisited" والثاني باسم "المسافة". الأول سيأخذ في الاعتبار المدن التي قمنا بزيارتها بالفعل ، والثاني المسافة التي قطعتها النملة.


تين. 19 - إضافة متغيرات

قم بإعداد مجموعة isVisited. لماذا نختارها بالماوس وفي علامة التبويب "خصائص" ، قم بتعيين "نوع" عناصر "int" كما هو موضح في الشكل 20.
بالنسبة لمتغير "المسافة" في خصائصه ، في حقل "القيمة الأولية" ، قم بتعيين "0" ، ونوع المتغير "مزدوج" ".


تين. 20 - مجموعة من نوع "int"

الآن حدد السهم الذي يغادر كتلة "City_block" وقم بتغيير الشفرة في حقل "الإجراء" إلى الحقل أدناه:
for (int i=0; i<main.myTowns.size(); i++) {
	if (randomTrue(0.9) && isVisited.indexOf(i)==-1) {
		this.moveTo(main.myTowns.get(i));
		distance=distance+this.distanceTo(main.myTowns.get(i));
		isVisited.add(i);
		break;
	} 
}

في الكود أعلاه ، أضفنا شيكًا للمدن التي تمكنا بالفعل من زيارتها ، مع مراعاة المدن التي قمنا بزيارتها ، وكذلك النظر في المسافة المقطوعة. الرمز بسيط للغاية ، أعتقد أنه لن يكون من الصعب عليك فهمه.

يمكنك محاولة إطلاق نموذج "F5" الخاص بنا ومعرفة ما حدث. الآن سيمر النمل عبر جميع المدن مرة واحدة فقط ويكمل حركته في الكتلة.

تغيير الوضع الأولي للنمل


في هذه الخطوة ، سنحدد لكل نملة بشكل عشوائي اختيار المدينة التي سيبدأ منها رحلته. لماذا ، في علامة التبويب "المشاريع" ، حدد وكيل "الرئيسي" باستخدام الماوس ، ثم في علامة التبويب "خصائص" ، أضف التعليمات البرمجية التالية إلى حقل "عند بدء التشغيل" (الشكل 20 أ):
for (int i=0; i<myAnts.size(); i++) {
	//        
	int startTown = uniform_discr(0,myTowns-1);
	//     
	myAnts.get(i).setPosition(myTowns.get(startTown));
	//      
	myAnts.get(i).isVisited.add(startTown);
}



تين. 20 أ - ترتيب النمل حسب المدينة ،

قمت بتطبيق اختيار عشوائي للمدينة الأولية. يمكنك في البداية تحديد جميع النمل في مدينة واحدة فقط.

جعل النمل لا يمكن التنبؤ به


دعونا نقدم الصيغة التالية في نموذجنا:



حيث Pi هو احتمال الانتقال على طول مسار المسار الأول ، li هو طول الانتقال الأول ، fi هو مقدار الفرمون في الانتقال الأول ، q هي القيمة التي تحدد "جشع" الخوارزمية ، ص - القيمة التي تحدد "القطيع" للخوارزمية ، مع q + p = 1.

لقد استعرت هذه الصيغة من الموقع .

بعبارات بسيطة ، تتيح لك هذه الصيغة حساب الاحتمالية التي ستضطر بها النملة إلى الانتقال إلى مدينة معينة.

الآن نحن بحاجة إلى إضافة العديد من المتغيرات التي بدونها لا يمكننا القيام بها. لماذا نعود إلى علامة التبويب "الرئيسية" ، الشكل 21.


الشكل. 21 - علامة تبويب "رئيسية"

لذا ، نضيف المتغير "numberAnt" ، الذي سنخزن فيه حجم مستعمرة النمل. قمنا بتعيين نوعه إلى "int" والقيمة الأولية هي 100.


الشكل 21 - المتغير "numberAnt"

بعد ذلك ، حدد السكان "myAnts" واضبط الحقل "العدد الأولي للوكلاء" على "numberAnt".

المتغير "p" ، الذي سيحدد قطيع الخوارزمية. نوعه مزدوج والقيمة الأولية 0.5.

المتغير "q" ، الذي سيحدد جشع الخوارزمية. نوعه مزدوج والقيمة الأولية 0.5.


تين. 22 - المتغيرات "q and p"

لذا ، سنقوم الآن بتعيين قيمة فرمون عشوائية لكل حافة (طريق) بين المدن. لماذا إنشاء متغير (صفيف ثنائي الأبعاد) "matrixF". ضعه في علامة التبويب "خصائص" في حقل "النوع" ، وحدد القيمة "أخرى" واكتب "مزدوج [] []" في الحقل القيمة الأولية "جديد مزدوج [numberTown] [numberTown]" (الشكل 23).


تين. 23 - إنشاء مصفوفة ثنائية الأبعاد "matrixF". مصفوفة فرمون

بعد ذلك ، نحتاج إلى تهيئة هذه المصفوفة. وبعبارة أخرى ، املأها بقيم عشوائية. نأخذ قيمة الفرمون بشكل عشوائي في النطاق من 0.1 إلى
1. لهذا ، في علامة التبويب "المشاريع" ، حدد العامل "الرئيسي" باستخدام الماوس ثم في علامة التبويب "خصائص" ، أضف التعليمات البرمجية التالية إلى الحقل "عند بدء التشغيل" (الشكل 23 أ):
for (int i=0; i<myTowns.size(); i++) {
	for (int j=0; j<myTowns.size(); j++) {
		matrixF[i][j]=uniform(0.1,1);
	}
} 



تين. 23 أ - كود التهيئة لمصفوفة فرمون

الآن نعود إلى علامة التبويب "MyAnt" ونستمر في حساب احتمال الانتقال وفقًا للصيغة أعلاه. حدد الانتقال بين "City_Choice" و "Motion" وقم بتغيير التعليمات البرمجية في حقل الإجراء إلى ما يلي (الشكل 24):
//       
double denominator=0; 
//          
for (int i=0; i<main.myTowns.size(); i++) {
	if (isVisited.indexOf(i)==-1) {	//     
	    //  i   
		denominator=denominator+(Math.pow(this.distanceTo(main.myTowns.get(i)), main.q)*Math.pow(main.myTowns.get(i).f, main.p));
	} 
}
//      i 
double Pi=0;
//    
double probility=uniform(0,1);
for (int i=0; i<main.myTowns.size(); i++) {
	//        Pi
	if (isVisited.indexOf(i)==-1) {
		//     i-      
		Pi=Pi+(Math.pow(this.distanceTo(main.myTowns.get(i)), main.q)*Math.pow(main.myTowns.get(i).f, main.p))/denominator;
	}
	//      Pi      probility
	if (probility<Pi && isVisited.indexOf(i)==-1) {
		//       i  
		this.moveTo(main.myTowns.get(i));
		//     
		distance=distance+this.distanceTo(main.myTowns.get(i));
		//           
		isVisited.add(i);
		break;
	} 
}



تين. 24- وضعنا سلوك النملة بناءً على التعبير التحليلي لما سبق ،

والآن سأشرح قليلاً ما هو:
  • li - this.distanceTo (main.myTowns.get (i)) ، قيمة الطول بين الوضع الحالي للنمل والمدينة "i" ؛
  • fi - main.matrixF [currentPos] [i] ، قيمة مستوى الفرمون بين المدينة الحالية والمدينة "i" ؛
  • المقام - المقام + (Math.pow (this.distanceTo (main.myTowns.get (i))، main.q) * Math.pow (main.matrixF [currentPos] [i]، main.p))؛ المقام Pi
  • Pi - Pi + (Math.pow (this.distanceTo (main.myTowns.get (i))، main.q) * Math.pow (main.myTowns.get (i) .f، main.p)) / المقام ، احتمالية انتقال النملة من المدينة الحالية إلى المدينة "i".

بعد ذلك ، نختار الانتقال بين الكتل "Motion" و "All-overpassed" بالماوس ونحدد "عندما يتم استيفاء الشرط" في حقل "Occurs" ، وفي حقل الحالة نكتب الشرط حتى يتوقف النملة عن "isVisited.size () == main.myTowns.size ()" (الشكل 25).


تين. 25 - حدد شروط إيقاف النملة ،

ثم يمكنك تشغيل نموذج "F5" ومعرفة ما حدث. سوف يسافر النمل بين المدن مع احتمال محتسب وفقًا للتعبير التحليلي أعلاه.

تحديث قيمة الفرمون


الآن دعونا نفعل شيئين. الإجراء الأول هو زيادة قيمة الفرمون على الحافة بين المدن التي مرت بها النملة. والثاني هو تبخر الفيرومون على الحواف بين المدن ، والذي يتألف من تقليل قيمة الفيرومونات نسبة إلى وقت المحاكاة.

لذا ، لتبدأ بالإجراء الأول ، سنقوم بتحديث قيمة فرمون الضلع بين المدينة التي تقع فيها النملة والتي سيذهب إليها. سيتم حساب القيمة التي سنقوم من خلالها بزيادة القيمة الحالية لحواف الفرمون بين المدن في غاية البساطة. نأخذ أقصى قيمة أولية لقيمة الفيرومون = 1 متر مكعب وتقسمه على المسافة بين المدينة التي تقع فيها النملة والمدينة التي سيذهب إليها. وبناءً على ذلك ، كلما كانت المسافة أصغر بين المدن ، كلما زادت القيمة التي سيتم من خلالها زيادة مستوى فرمون الضلع. لماذا نختار وكيل MyAnt في علامة التبويب "المشاريع" ، واستخدام الماوس لتحديد الانتقال بين كتل "City_title" و "حركة" وإضافة الشفرة التالية إلى حقل الإجراء: "main.matrixF [currentPos] [i] = main.matrixF [currentPos] [i ] + 1 / this.distanceTo (main.myTowns.get (i)؛ ".يجب أن تكون النتيجة كما هو موضح في الشكل 26


تين. 26 - تحديث قيمة مستوى الفيرومونات في الأضلاع التي مرت بها النملة

الآن ننتقل إلى الإجراء رقم 2 وننشئ حدثًا يحاكي تبخر الفيرومون على الحواف بين المدن. لماذا ، في علامة تبويب المشاريع ، حدد الوكيل "الرئيسي" وقم بإنشاء متغيرين إضافيين هناك. الأول هو "الشدة" - سيحدد معدل (شدة) تبخر الفيرومون (القيمة الأولية "0.5" ، اكتب "مزدوج"). "الجزء" الثاني - سيميز الكسر الذي ستنخفض به قيمة الفرمون على الحافة (القيمة الأولية "0.9" ، اكتب "مزدوج").


تين. 27 - إنشاء متغيرات "الشدة" و "الجزء"

بعد ذلك ، نأخذ عنصر "الحدث" من "لوحة" علامة التبويب "الوكيل" وننقله إلى الوكيل "الرئيسي" ونطلق عليه "التبخر" - سيحاكي هذا العنصر تبخر الفرمون على الحواف. نضغط عليها بالماوس وفي "الخصائص" في حقل "نوع الحدث" ، حدد القيمة "بكثافة معينة" في حقل "الكثافة" ، اكتب اسم المتغير الذي يخزن قيمة "الكثافة". زمن الاستجابة ثواني. بعد ذلك ، أضف الرمز أدناه إلى الإجراء:
for (int i=0; i<myTowns.size(); i++) {
	for (int j=0; j<myTowns.size(); j++) {
		matrixF[i][j]=matrixF[i][j]*Part;
		if (matrixF[i][j]<0.1) matrixF[i][j]=0.1;
	}
}

عندما يتم تشغيل حدث "التبخر" ، سيتم تحديث مستويات فرمون في مصفوفة matrixF. ونتيجة لذلك ، يجب أن تكون قادرًا على القيام بذلك كما هو موضح في الشكل 28.


الشكل. 28 - إنشاء حدث "التبخر"

حدد الفائز


في هذه الخطوة ، سنضيف رمزًا يحدد الفائز بماراثون النملة لدينا. سيكون الفائز هو النمل الذي أدار أقصر طريق. بالإضافة إلى كل شيء ، بعد نهاية الماراثون ، نرسم هذا الطريق على الشاشة. لتحقيق ذلك ، سننشئ ثلاثة متغيرات "bestAnt" و "bestDistance" و "numberFinish" في العامل "الرئيسي". في المتغير "bestAnt" سنقوم بتخزين فهرس النملة "الأسرع" ، نوع المتغير سيكون "int" وسيتم تعيين القيمة الأولية على "-1". في المتغير "bestDistance" ، سنقوم بتخزين القيمة الحالية لأفضل طول للمسار بين المدن ، وسيكون نوع المتغير "مزدوجًا" وسيتم تعيين القيمة الأولية على اللانهاية "اللانهاية". في المتغير "numberFinish" سنخزن عدد النمل الذي انتهى في ماراثوننا ،سيكون نوع المتغير "int" والقيمة الأولية هي "0" (الشكل 29).


تين. 29 - إنشاء حدث للمتغيرات

بعد ذلك ، نقوم بإنشاء وظيفة ، بعد الانتهاء من جميع النمل ، سوف ترسم خطوط أفضل مسار بين المدن. لماذا من "لوحة" نسحب إلى العامل "الرئيسي" عنصر بوظيفة الاسم. قم بتعيين اسم الوظيفة إلى drawPath ، وفي علامة التبويب خصائص ، في حقل نص الوظيفة ، أضف التعليمات البرمجية التالية:
//        
for (int i=0; i<myAnts.get(bestAnt).isVisited.size()-1; i++) {
	//    
	ShapeLine myLine = new ShapeLine();
	//            i
	myLine.setX(myTowns.get(myAnts.get(bestAnt).isVisited.get(i)).getX());
	myLine.setY(myTowns.get(myAnts.get(bestAnt).isVisited.get(i)).getY());
	//            i+1
	myLine.setEndX(myTowns.get(myAnts.get(bestAnt).isVisited.get(i+1)).getX());
	myLine.setEndY(myTowns.get(myAnts.get(bestAnt).isVisited.get(i+1)).getY());
	//    ""
	myLine.setColor(blue);
	//   
	myLine.setLineStyle(LINE_STYLE_SOLID );
	//   
	myLine.setLineWidth(1);
	//    
	presentation.add(myLine);	
}
	//           
	ShapeLine myLine = new ShapeLine();
	myLine.setX(myTowns.get(myAnts.get(bestAnt).isVisited.get(myAnts.get(bestAnt).isVisited.size()-1)).getX());
	myLine.setY(myTowns.get(myAnts.get(bestAnt).isVisited.get(myAnts.get(bestAnt).isVisited.size()-1)).getY());
	myLine.setEndX(myTowns.get(myAnts.get(bestAnt).isVisited.get(0)).getX());
	myLine.setEndY(myTowns.get(myAnts.get(bestAnt).isVisited.get(0)).getY());
	myLine.setColor(blue);
	myLine.setLineStyle(LINE_STYLE_SOLID );
	myLine.setLineWidth(1);
	presentation.add(myLine);

ونتيجة لذلك ، يجب أن تكون قادرًا على القيام بذلك كما هو موضح في الشكل 29 أ.


تين. 29 أ - إنشاء وظيفة "drawPath"

الآن نعود إلى النمل ونضيف رمزًا يحدد نملة الفائز وطول أفضل مسار ورسم هذا المسار بين المدن. لماذا ، في علامة التبويب "المشاريع" ، حدد وكيل "MyAnt" ، ثم حدد كتلة "All Bypassed" وقم بإضافة التعليمة البرمجية التالية إلى حقل "Logon Action":
//    
main.numberFinish++;
//      
if (main.bestDistance>distance) {
	//           
	//      
	main.bestDistance=distance;
	//    
	main.bestAnt = this.getIndex();
}
//         Main   
if (main.numberFinish==main.myAnts.size()) main.drawPath();

يجب أن يتحول كما هو موضح في الشكل 30.


الشكل. 30 - إضافة منطق إلى كتلة "تجاوز جميع" ،

ثم يمكنك الضغط على "F5" وتشغيل النموذج. سوف يركض النمل بحثًا عن الطرق ، وعندما تنتهي المدن ، سيتصل الخط الأزرق ، وهو أفضل مسار.

أضف الرسم البياني إلى النموذج


لكي يصبح النموذج أكثر علمية ، يجب عليك إضافة رسم بياني. لذلك ، لن نضيف فقط رسمًا بيانيًا ومخططًا بيانيًا يوضح لنا توزيع طول المسارات التي تغلب عليها النمل. لماذا في علامة التبويب "المشاريع" حدد الوكيل "الرئيسي" وانتقل إلى مساحته. علاوة على ذلك ، في "اللوحة" ، ننتقل إلى علامة التبويب "الإحصائيات" ومن هناك إلى الوكيل "الرئيسي" نقوم بنقل عنصر "بيانات الرسم البياني" مباشرة "الرسم البياني" نفسه. ثم نختار الرسوم البيانية بالماوس وفي علامة التبويب "الخصائص" ، في حقل "البيانات" ، حدد اسم "بيانات الرسم البياني" ، أي "البيانات".

يجب أن يتحول كما هو موضح في الشكل 31


. 31 - بناء جدول زمني

وبعد ذلك سوف نعود مرة أخرى إلى نملة ونجعلها تملأ "الرسم البياني" بقيم طول المسار. لماذا ، في علامة تبويب المشاريع ، حدد الوكيل "MyAnt" وانتقل إلى مساحته. بعد ذلك ، حدد كتلة "All Bypass" وأضف سطرًا واحدًا إليها "main.data.add (المسافة) ؛". يجب أن يتحول كما هو موضح في الشكل 32.


الشكل. 32 - بناء رسم بياني

بعد ذلك ، اضغط على "F5" وتابع دراسة سلوك خوارزمية النمل. يجب أن يتحول إلى شيء ما ، مثل ما هو موضح في الشكل 33.


الشكل. 33 - النمذجة

استنتاج


وفي النهاية ، أوصي بإضافة المزيد من عدم القدرة على التنبؤ بالنموذج. لهذا ، في علامة التبويب "المشاريع" ، حدد عنصر "Simulation: Main" باستخدام الماوس واضبط معلمة "Randomness" على "الرقم الأولي العشوائي (عمليات التشغيل الفريدة)" في علامة تبويب الخصائص - وهذا سيجعل إطلاق كل نموذج فريدًا (الشكل 34).


تين. 34 - الجري العشوائي

شكرا لكم على اهتمامكم! يمكن تنزيل شفرة المصدر من GitHub

All Articles