8-laboratoriya mashg’uloti. Matematik funksiylarning optimal qiymatini genetik algoritmlar yordamida aniqlashning dasturiy ta’minoti Klassik genetik algoritm va uning asosiy bosqichlari
Download 0.57 Mb. Pdf ko'rish
|
8-Lab.mash. (Genetik algoritm) (1)
parents = numpy.empty((num_parents, pop.shape[1]))
Joriy populyatsiyani aylanib chiqqach, funksiya eng yuqori MosF qiymati indeksini oladi, chunki bu chiziq bo'yicha tanlangan eng yaxshi yechim: max_fitness_idx = numpy.where (fitness == numpy.max (fitness)) Ushbu indeks ushbu qator yordamida moslik qiymatiga mos keladigan yechimni olish uchun ishlatiladi: parents[parent_num, :] = pop[max_fitness_idx, :] Bunday yechimni qayta tanlamaslik uchun uning yaroqliligi juda kichik qiymatga o'rnatiladi, bu katta ehtimollik bilan endi tanlanmaydi, bu 99999999999, ota- onalar. Oxirida quyidagi ko'rinishdagi massiv qaytariladi: [[-0.63698911 -2.8638447 2.93392615 -1.40103767 -1.20313655 0.30567304] [ 3.00912373 -2.745417 3.27131287 -0.72163167 0.7516408 0.00677938] [1.96561297 0.51030292 0.52852716 -1.56909315 -2.35855588 2.29682254] [2.12480298 2.97122243 3.60375452 3.78571392 0.28776565 3.5170347]] E'tibor bering, bu uchta ota-ona mos ravishda 18,24112489, 17,0688537, 15,99527402 va 14,40299221 bo'lgan jismoniy tayyorgarlik ko'rsatkichlariga ko'ra hozirgi popylyarsiyaning eng yaxshi odamlari hisoblanadi. Keyingi qadam - bu tanlangan juftlashuvchi ota-onalardan nasl berish uchun foydalanishdir. Juftlash ga.krossover funksiyasiga ko‘ra chatishtiruv operatsiyasidan boshlanadi. Bu funksiya ota-onalarni va naslning o'lchamini qabul qiladi. Bu ota- onalardan olingan nasllarning sonini bilish uchun naslning o'lchamidan foydalanadi. Ushbu funksiya GA modulida quyidagicha amalga oshiriladi: def crossover(parents, offspring_size): offspring = numpy.empty(offspring_size) # Ikki ota-ona o'rtasida chatishtiruv sodir bo'ladigan nuqta. Odatda, u markazda joylashgan. crossover_point = numpy.uint8 (offspring_size[1]/2) for k in range(offspring_size[0]): # Birinchi juftlik uchun ota-onaning indeksi. parent1_idx = k% parents.shape[0] # Ulanish uchun ikkinchi ota-onaning indeksi. parent2_idx = (k+1) % parents.shape[0] 6 # Yangi nasl genlarining birinchi yarmini birinchi ota-onadan oladi. offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point] # Yangi nasl genlarining ikkinchi yarmini ikkinchi ota-onadan oladi. offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:] return offspring Funksiya naslning o'lchamiga qarab bo'sh massiv yaratish bilan boshlanadi, ya’ni quyidagi qatorda keltirilganidek: offspring = numpy.empty(offspring_size) Biz bitta nuqta kesishmasidan foydalanayotganimiz sababli, kesishish sodir bo'lgan nuqtani ko'rsatishimiz kerak. Ushbu chiziqqa muvofiq echimni ikkita teng yarmiga bo'lish nuqtasi tanlangan: crossover_point = numpy.uint8(offspring_size[1]/2) Keyin chatishtiruv uchun ikkita ota-onani tanlashimiz kerak. Ushbu ota- onalarning indekslari ushbu ikki qatorga muvofiq tanlanadi: parent1_idx = k% parents.shape [0] parent2_idx = (k+1)% parents.shape [0] Ota-onalar uzuk kabi tanlanadi. Boshida birinchisi 0 va 1 indekslari bilan ikkita avlod hosil qilish uchun tanlanadi. Agar hali ham nasl tug'ilishi kerak bo'lsa, biz yana ikkita nasl berish uchun ota-ona 1ni ota-ona 2 bilan tanlaymiz. Agar bizga ko'proq nasl kerak bo'lsa, unda biz 2 va 3 indekslari bilan keyingi ikkita ota-onani tanlaymiz. 3- indeksda biz oxirgi ota-onaga erishdik. Agar biz ko'proq nasllarni qoldirishni xoxlasak,, u holda biz 3 indeksdagi ota-onani tanlaymiz va 0 indeksdagi ota-onaga qaytamiz va hokazo. Ota-ona chatishtiruvini (krossoverini) qo'llashdan keyin qabul qilingan qarorlar nasl o'zgaruvchilarida saqlanadi va ular quyidagilar: [[-0.63698911 -2.8638447 2.93392615 -0.72163167 0.7516408 0.00677938] [3.00912373 -2.745417 3.27131287 -1.56909315 -2.35855588 2.29682254] [ 1.96561297 0.51030292 0.52852716 3.78571392 0.28776565 3.5170347 ] [ 2.12480298 2.97122243 3.60375452 -1.40103767 -1.20313655 0.30567304]] Keyinchalik, GA moduli ichidagi ga.mutation funksiyasidan foydalanib, nasl o'zgaruvchisida saqlangan chatishtiruv natijalariga ikkinchi GA variantini, mutatsiyani qo'llaymiz. Bu funksiya chatishtiruvning avlodlarini oladi va bir xil mutatsiyani qo'llaganidan keyin ularni qaytaradi. Bu xususiyat quyidagicha amalga oshiriladi: def mutation(offspring_crossover): # Mutatsiya har bir nasldagi bitta genni tasodifiy o'zgartiradi. for idx in range(offspring_crossover.shape[0]): # Genga qo'shiladigan tasodifiy qiymat. random_value = numpy.random.uniform(-1.0, 1.0, 1) offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_value return offspring_crossover U har bir naslni takrorlaydi va shu qatorga muvofiq -1 dan 1 gacha bo'lgan bir xilda yaratilgan tasodifiy sonni qo'shadi: random_value = numpy.random.uniform(-1.0, 1.0, 1) 7 Keyin bunday tasodifiy raqam ushbu chiziqqa muvofiq 4 nasl indeksiga ega bo'lgan genga qo'shiladi: offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_valut Bunda indeksni istalgan boshqa indeksga o'zgartirish mumkin. Mutatsiyani qo'llaganidan keyin avlodlar quyidagi ko’rinishda bo’ladi: [[-0.63698911 -2.8638447 2.93392615 -0.72163167 1.66083721 0.00677938] [3.00912373 -2.745417 3.27131287 -1.56909315 -1.94513681 2.29682254] [1.96561297 0.51030292 0.52852716 3.78571392 0.45337472 3.5170347 ] [2.12480298 2.97122243 3.60375452 -1.40103767 -1.5781162 0.30567304]] Bunday natijalar offspring_crossover o'zgaruvchisiga qo'shiladi va funksiya tomonidan qaytariladi. Ayni damda 4 ta tanlab olingan ota-onadan 4 ta naslni muvaffaqiyatli hosil qildik va kelgusi avlod uchun yangi populyatsiyani yaratishga tayyormiz. Ta’kidlaymizki GA tasodifiy optimallashtirish usuli hisoblanadi. U joriy echimlarni ularga tasodifiy o'zgarishlarni qo'llash orqali yaxshilashga harakat qiladi. Ushbu o'zgarishlar tasodifiy bo'lgani uchun, ular yaxshiroq echimlarga olib kelishiga ishonchimiz komil emas. Shu sababli yangi populyatsiyada oldingi eng yaxshi echimlarni (ota-onalarni) saqlab qolish afzaldir. Eng yomon holatda, barcha yangi avlodlar bunday ota-onalardan yomonroq bo'lsa ham, biz bunday ota-onalardan foydalanishni davom ettiramiz. Natijada, biz yangi avlod hech bo'lmaganda avvalgi yaxshi natijalarni saqlab qolishini va yomonlashmasligini ta'minlaymiz. Yangi populyatsiya oldingi ota-onalarning dastlabki 4 ta echimiga ega bo'ladi. Oxirgi 4 ta yechim chatishtiruv va mutatsiyani qo'llashdan keyin yaratilgan nasldan olingan: new_population[0:parents.shape[0], :] = parents new_population[parents.shape[0]:, :] = offspring_mutation Birinchi avlodning barcha echimlarining (ota-onalar va avlodlar) muvofiqligini hisoblashda ularning muvofiqligi quyidagicha ko'rinadi: [18.24112489 17.0688537 15.99527402 14.40299221 -8.46075629 31.73289712 6.10307563 24.08733441] Ilgari eng yuqori yaroqlilik 18,24112489 edi, ammo hozir u +31,7328971158. Bu tasodifiy o'zgarishlar yaxshiroq yechim tomon siljiganligini anglatadi. Bu yaxshi. Ammo bunday natijalarni bir necha avlodlar davomida yaxshilash mumkin. Quyida yana 4 avlod uchun har bir bosqich natijalari keltirilgan: Download 0.57 Mb. Do'stlaringiz bilan baham: |
Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling
ma'muriyatiga murojaat qiling