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
bet4/9
Sana21.01.2023
Hajmi0.57 Mb.
#1106215
1   2   3   4   5   6   7   8   9
Bog'liq
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] 



# 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) 



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:
1   2   3   4   5   6   7   8   9




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©fayllar.org 2024
ma'muriyatiga murojaat qiling