Ovozlar_soni: 5 ovoz beradigan shaxslarning soni bizda 33 mln bo’lishi mumkin
Tuzmoqchi bo’lgan dasturimiz quyidagicha ishlashi kerak
./saylov Mirziyoyev Saidov Narimanov // dasturning cosole da ishlash jarayoni
Ovozlar_soni: 5
Ovoz: Narimanov
Ovoz: Saidov
Ovoz: Mirziyoyev
Ovoz: Mirziyoyev
Ovoz: Mirziyoyev
Mirziyoyev // g’alaba qozongan nomzod nomi
Dastur implementatsiyasi
#include
#include
#include
//Nomzodlarning maksimal soni
#define MAX 5
//Nomzodlarning ismi va ular to’plagan ovozlarini yozish uchun o’zgaruvchilar
typedef struct
{
string name;
int votes;
}
candidate;
// Nomzodlar massivi
candidate candidates[MAX];
// Nomzodlar soni
int candidate_count;
// Funksiya prototipi asl funksiya pastda yozilgan
bool vote(string name);
void print_winner(void);
int main(int argc, string argv[])
{
// Dastur ishga tushirilganda uning to’g’ri ishlashini tekshirish
if (argc < 2)
{
printf("To’g’ri qiymat kiriting: saylov [Nomzodlar...]\n");
return 1;
}
// Nomzodlar quyidagilar
candidate_count = argc - 1;
if (candidate_count > MAX)
{
printf("Saylovdagi mavjud nomzodlarnning umumiy soni %i\n", MAX);
return 2;
}
for (int i = 0; i < candidate_count; i++)
{
candidates[i].name = argv[i + 1];
candidates[i].votes = 0;
}
int voter_count = get_int("Ovozlarning umumiy soni: ");
// ovozlar bo’yicha yurib chiqish
for (int i = 0; i < voter_count; i++)
{
string name = get_string("Ovoz: ");
// Ovozni tekshirish
if (!vote(name))
{
printf("Noto’g’ri ovoz kiritfingiz.\n"); }
}
// Saylov g’olibi
print_winner(); }
// Berilgan ovoz bilan umumiy ovozlarni yangilash
bool vote(string name)
{
bool exist = false;
for (int i = 0; i < candidate_count; i++)
{
//Kiritilgan nomzodning ismi bazadagisi bilan solishtirish
if (strcmp(name, candidates[i].name) == 0)
{
candidates[i].votes += 1;
exist = true;
break; }
}
return exist;
}
void print_winner(void)
{
//o’zgaruvchilarga boshlang’ich qiymat berish
int most = 0;
string winner;
//Eng ko’p ovozni aniqlash
for (int y = 0; y < candidate_count; y++)
{
if(candidates[y].votes >= most )
{
most = candidates[y].votes;
winner = candidates[y].name;
}
}
printf("Nomzod %s %i ovoz bilan g’olib bo’ldi\n", winner , most);
}
Amaliy topshiriqlar
Men ushbu vazifa uchun Олдга йўналтирилган қисман танлов алгоритми (Алгоритм последовательно селекция в перед); ya’ni ushbu algoritmning ikkinchi nomi Genetik algoritm ni blok-sxemalar asosida implementatsiyani namoyish qilmoqchiman. Genetik algoritm birinchi navbatda evolyutsion algoritmdir, boshqacha aytganda, algoritmning asosiy xususiyati bu kesishish (birlashtirish). Siz osongina taxmin qilishingiz mumkin bo'lganidek, algoritm g'oyasi tabiatdan bilan olingan va unga "kombinatsiyani" tanlash orqali erishiladi.
Umuman olganda ushbu algoritm quyidagi 3ta bosqichda amalga oshiriladi
Chatishtirish
Tanlash (tanlash)
Yangi avlodning shakllanishi
Agar natija bizni qoniqtirmasa, natijalar bizni qoniqtira boshlaguncha yoki quyidagi shartlardan biri paydo bo'lmaguncha ushbu amallar takrorlanadi:
Avlodlar (tsikllar) soni oldindan tanlangan maksimal darajaga etadi
Mutatsiya vaqti tugadi
Yuqoridagi bosqichlarni batafsil yoritishga harakat qilaman.
Yangi populyatsiyaning vujudga kelishi. (Создание новой популяции. ) Ushbu bosqichda boshlang'ich populyatsiya yaratiladi, ehtimol bu unchalik katta bo'lmaydi, lekin algoritm bu muammoni hal qilishi mumkin. Asosiysi shundaki, ular "format" ga mos keladi va "ko'paytirishga moslashadi".
Ko'paytirish. Xo'sh, barchasi odamlarga o'xshaydi, farzand ko'rish uchun ikkita ota-ona kerak. Asosiysi, avlod (bola) ularning xususiyatlarini ota-onadan meros qilib olishi mumkin edi. Bunday holda, nafaqat omon qolganlar, balki ko'payadilar (bu ibora ayniqsa bema'ni, lekin bizda hamma narsa sharsimon bo'shliqda bo'lganligi sababli hamma narsani qilish mumkin), aks holda bitta alfa erkak ajralib chiqadi, ularning genlari boshqalarga to'g'ri keladi, ammo bu biz uchun mutlaqo nomaqbuldir.
Mutatsiyalar. Mutatsiyalar ko'payish bilan o'xshashdir, mutantlardan ma'lum miqdordagi shaxslar tanlanadi va oldindan belgilangan operatsiyalarga muvofiq o'zgartiriladi.
Tanlash. Bu erda eng shirin boshlanadi, biz aholidan "oldinga boradiganlar" ni tanlashni boshlaymiz. Shu bilan birga, biz tanlanganimizdan so'ng, "omon qolganlar" ning ulushini parametr shaklida ko'rsatamiz. Afsuski, qolgan odamlar o'lishi kerak
Diofantin tenglamalarimning (Диофантовых уравнений) misolini ko'rib chiqamiz (butun sonlar ildizlari bilan tenglamalar).
Tenglama ko’rinishi
a+2b+3c+4d=30;
Ushbu tenglamaning ildizlari [1; 30] oraliqda yotganligini taxmin qilamiz va shuning uchun biz 5 ni olamiz
a, b, c, d tasodifiy qiymatlari. (30-ning chegarasi, masalani soddalashtirish uchun maxsus qabul qilinadi).
Shunday qilib, bizda birinchi avlod bor:
(1,28,15,3)
(14,9,2,4)
(13,5,7,3)
(23,8,16,19)
(9,13,5,2)
Omon qolish darajasini (коэффициенты выживаемости),hisoblash uchun biz har bir echimni ifodaga almashtiramiz. Olingan qiymatdan 30 gacha bo'lgan masofa kerakli qiymatga ega bo'ladi.
|114-30|=84
|54-30|=24
|56-30|=26
|163-30|=133
|58-30|=28
Kichikroq qiymatlar mos ravishda 30 ga yaqinroq, ular ko'proq istalgan. Aniqlanishicha, katta qiymatlar omon qolish darajasi past bo'ladi. Tizimni yaratish uchun har birini (xromosoma) tanlash ehtimolini hisoblaymiz. Ammo echim koeffitsientlarning teskari qiymatlari yig'indisini olish va shu asosda foizlarni hisoblashdir. (0.135266 bet - teskari koeffitsientlar yig'indisi)
(1/84)/0.135266 = 8.80%
(1/24)/0.135266 = 30.8%
(1/26)/0.135266 = 28.4%
(1/133)/0.135266 = 5.56%
(1/28)/0.135266 = 26.4%
Keyinchalik, biz bitta bolaga ega bo'lgan beshta ota-onani tanlaymiz. Imkoniyatdan ozod bo'lish uchun biz besh marta beramiz, har safar ota-ona bo'lish imkoniyati bir xil bo'ladi va tirik qolish imkoniyatiga teng bo'ladi.
3-1, 5-2, 3-5, 2-5, 5-3
Yuqorida ta'kidlab o'tilganidek, avlod ota va onaning genlari haqida ma'lumotni o'z ichiga oladi. Bunga turli yo'llar bilan erishish mumkin, ammo bu holda "krossover" ishlatiladi. (| = ajratuvchi chiziq)
X.-otasi: a1 | b1, c1, d1 X.-onasi: a2 | b2, c2, d2 X.-avlodlari: a1, b2, c2, d2 yoki a2, b1, c1, d1
X.-otasi: a1, b1 | c1, d1 X.-onasi: a2, b2 | c2, d2 X.-avlodlari: a1, b1, c2, d2 yoki a2, b2, c1, d1
X.-otasi: a1, b1, c1 | d1 X.-onasi: a2, b2, c2 | d2 X.-avlodi: a1, b1, c1, d2 yoki a2, b2, c2, d1
Ma'lumotni naslga etkazishning ko'p usullari mavjud va o'zaro kelishib olish bu ko'pchilikning biridir. Ajratuvchining joylashuvi butunlay o'zboshimchalik bilan bo'lishi mumkin, shuningdek, ota yoki onasi chiziqning chap tomonida bo'ladi.
Endi avlodlar bilan ham shunday qilaylik:
Х.-otasi: (13 | 5,7,3) Х.-otasi: (1 | 28,15,3) Х.-avlodi: (13,28,15,3)
Х.-otasi: (9,13 | 5,2) Х.-otasi: (14,9 | 2,4) Х.-otasi: (9,13,2,4)
Х.-otasi: (13,5,7 | 3) Х.-otasi: (9,13,5 | 2) Х.-otasi: (13,5,7,2)
Х.-otasi: (14 | 9,2,4) Х.-otasi: (9 | 13,5,2) Х.-otasi: (14,13,5,2)
Х.-otasi: (13,5 | 7, 3) Х.-otasi: (9,13 | 5, 2) Х.-otasi: (13,5,5,2)
Endi biz avlodlarning yashash darajalarini hisoblaymiz.
(13,28,15,3) — |126-30|=96(9,13,2,4) — |57-30|=27
(13,5,7,2) — |57-30|=22
(14,13,5,2) — |63-30|=33
(13,5,5,2) — |46-30|=16
Afsuski, naslning o'rtacha moslashuvchanligi 38,8, ota-onalar uchun bu koeffitsient 59,4 edi. Ayni paytda mutatsiyani qo'llash maqsadga muvofiqdir, buning uchun biz bir yoki bir nechta qiymatlarni tasodifiy raqam bilan 1 dan 30 gacha o'zgartiramiz.
Omon qolish darajasi nolga teng kelmasa, algoritm ishlaydi. I.e. tenglamaga yechim hisoblanadi. Aholisi ko'p bo'lgan tizimlar (masalan, 5 o'rniga 50 ta) kerakli darajaga (0) tez va barqaror o'tishadi.
Ushbu tenglama misollarni dasturda ko’ramiz
Bu erda 5 qiymat talab qiladi: 4 koeffitsient va natija. Yuqoridagi misol uchun u quyidagicha bo'ladi:
CDiofantine dp (1,2,3,4,30); // yaratilgan klass nomi
Keyin, tenglamani yechish uchun Solve () funktsiyasini chaqiramiz, bu eritma o'z ichiga olgan allelni qaytaradi. a, b, c, d qiymatlarini to'g'ri olish uchun GetGene () ni chaqiramiz. Ushbu klassdan foydalanadigan standart main.cpp protsedurasi quyidagicha bo'lishi mumkin:
#include ""
#include "diophantine.h"
void main() {
CDiophantine dp(1,2,3,4,30);
int ans; ans = dp.Solve();
if (ans == -1) {
cout << "No solution found." << endl;
} else
{
gene gn = dp.GetGene(ans);
cout << "The solution set to a+2b+3c+4d=30 is:\n";
cout << "a = " << gn.alleles[0] << "." << endl;
cout << "b = " << gn.alleles[1] << "." << endl;
cout << "c = " << gn.alleles[2] << "." << endl;
cout << "d = " << gn.alleles[3] << "." << endl; }
}
Endi Cdiofantine klassini ko’rib chiqamiz
#include
#include
#define MAXPOP 25
struct gene {
int alleles[4];
int fitness;
float likelihood;
// Test for equality.
operator==(gene gn) {
for (int i=0;i<4;i++) {
if (gn.alleles[i] != alleles[i]) return false;
}
return true;
}
};
class CDiophantine {
public:
CDiophantine(int, int, int, int, int);// Constructor with coefficients for a,b,c,d.
int Solve();// Solve the equation.
// Returns a given gene.
gene GetGene(int i) { return population[i];}
protected:
int ca,cb,cc,cd;// The coefficients.
int result;
gene population[MAXPOP];// Population.
int Fitness(gene &);// Fitness function.
void GenerateLikelihoods(); // Generate likelihoods.
float MultInv();// Creates the multiplicative inverse.
int CreateFitnesses();
void CreateNewPopulation();
int GetIndex(float val);
gene Breed(int p1, int p2);
};
CDiophantine::CDiophantine(int a, int b, int c, int d, int res) : ca(a), cb(b), cc(c), cd(d), result(res) {}
int CDiophantine::Solve() {
int fitness = -1;
// Generate initial population.
srand((unsigned)time(NULL));
for(int i=0;i// Fill the population with numbers between
for (int j=0;j<4;j++) {// 0 and the result.
population[i].alleles[j] = rand() % (result + 1);
}
}
if (fitness = CreateFitnesses()) {
return fitness;
}
int iterations = 0;// Keep record of the iterations.
while (fitness != 0 || iterations < 50) {// Repeat until solution found, or over 50 iterations.
GenerateLikelihoods();// Create the likelihoods.
CreateNewPopulation();
if (fitness = CreateFitnesses()) {
return fitness;
}
iterations++;
}
return -1;
}
int CDiophantine::Fitness(gene &gn) {
int total = ca * gn.alleles[0] + cb * gn.alleles[1] + cc * gn.alleles[2] + cd * gn.alleles[3];
return gn.fitness = abs(total - result);
}
int CDiophantine::CreateFitnesses() {
float avgfit = 0;
int fitness = 0;
for(int i=0;i
fitness = Fitness(population[i]);
avgfit += fitness;
if (fitness == 0) {
return i;
}
}
return 0;
}
float CDiophantine::MultInv() {
float sum = 0;
for(int i=0;i
sum += 1/((float)population[i].fitness);
}
return sum;
}
void CDiophantine::GenerateLikelihoods() {
float multinv = MultInv();
float last = 0;
for(int i=0;i
population[i].likelihood = last = last + ((1/((float)population[i].fitness) / multinv) * 100);
}
}
int CDiophantine::GetIndex(float val) {
float last = 0;
for(int i=0;i
if (last <= val && val <= population[i].likelihood) return i;
else last = population[i].likelihood;
}
return 4;
}
gene CDiophantine::Breed(int p1, int p2) {
int crossover = rand() % 3+1;// Create the crossover point (not first).
int first = rand() % 100;// Which parent comes first?
gene child = population[p1];// Child is all first parent initially.
int initial = 0, final = 3;// The crossover boundaries.
if (first < 50) initial = crossover; // If first parent first. start from crossover.
else final = crossover+1;// Else end at crossover.
for(int i=initial;i// Crossover!
child.alleles[i] = population[p2].alleles[i];
if (rand() % 101 < 5) child.alleles[i] = rand() % (result + 1);
}
return child;// Return the kid...
}
void CDiophantine::CreateNewPopulation() {
gene temppop[MAXPOP];
for(int i=0;i
int parent1 = 0, parent2 = 0, iterations = 0;
while(parent1 == parent2 || population[parent1] == population[parent2]) {
parent1 = GetIndex((float)(rand() % 101));
parent2 = GetIndex((float)(rand() % 101));
if (++iterations > 25) break;
}
temppop[i] = Breed(parent1, parent2);// Create a child.
}
for(i=0;i
}
Topshiriqni bajarishda foydalanilgan manbalar ro’yxati:
https://habr.com/en/post/128704/
http://algolist.manual.ru/
https://en.wikipedia.org/wiki/Genetic_algorithm
Do'stlaringiz bilan baham: |