Автор работы: Пользователь скрыл имя, 24 Сентября 2009 в 18:16, Не определен
Данная работы состоит в изучении теоретического аспекта использования генетических алгоритмов, а так же в практической реализации задачи с использованием генетического алгоритма
| 
 | 
Таблица 
5: Кроссоверы между родителями 
 
Есть достаточно много путей передачи информации потомку, и кроссовер - только один из них. Расположение разделителя может быть абсолютно произвольным, как и то, отец или мать будут слева от черты.
     А 
теперь попробуем проделать это 
с нашими потомками 
 
| 
 | 
Таблица 
6: Симуляция кросс-оверов хромосом родителей 
Теперь мы можем вычислить коэффициенты выживаемости (fitness) потомков.
| 
 | 
Таблица 
7: Коэффициенты выживаемости потомков 
(fitness) 
Средняя приспособленность (fitness) потомков оказалась 38.8, в то время как у родителей этот коэффициент равнялся 59.4. Следующее поколение может мутировать. Например, мы можем заменить одно из значений какой-нибудь хромосомы на случайное целое от 1 до 30.
Продолжая таким образом, одна хромосома в конце концов достигнет коэффициента выживаемости 0, то есть станет решением.
     Системы 
с большей популяцией (например, 
50 вместо 5-и сходятся к желаемому 
уровню (0) более быстро и стабильно.27 
1.1 
 Принцип работы программы 
Oбранимся к теоретическим пояснениям в практической реализации данной задачи в среде программирования С++ :
Первым делом 
посмотрим на заголовок класса:  
#include <stdlib.h> 
#include <time.h> 
#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); 
      
int Solve(); 
      
// Returns a given gene. 
      
gene GetGene(int i) { return population[i];} 
   protected: 
      
int ca,cb,cc,cd; 
      
int result; 
      
gene population[MAXPOP]; 
 
      
int Fitness(gene &); 
      
void GenerateLikelihoods(); 
      
float MultInv();inverse. 
      
int CreateFitnesses(); 
void CreateNewPopulation();
      
int GetIndex(float val); 
 
      
gene Breed(int p1, int p2); 
 
}; 
     Существуют 
две структуры: gene и класс CDiophantine. 
gene используется для слежения за различными 
наборами решений. Создаваямая популяция 
- популяция ген. Эта генетическая структура 
отслеживает свои коэффициенты выживаемости 
и вероятность оказаться родителем. Также 
есть небольшая функция проверки на равенство.  
Теперь 
по функциям:  
Fitness function 
     Вычисляет 
коэффициент выживаемости (приспособленности 
- fitness) каждого гена. В нашем случае это 
- модуль разности между желаемым результатом 
и полученным значением. Этот класс использует 
две функции: первая вычисляет все коэффициенты, 
а вторая – поменьше - вычисляет коэффициент 
для какого-то одного гена.  
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<MAXPOP;i++) 
{ 
      
fitness = Fitness(population[i]); 
      
avgfit += fitness; 
      
if (fitness == 0) { 
         
return i; 
      
} 
   } 
   return 0; 
} 
 
Заметим, что если fitness = 0, то найдено решение - возврат. После вычисления приспособленности (fitness) нам нужно вычислить вероятность выбора этого гена в качестве родительского.
Likelihood functions
Как и было объяснено, вероятность вычисляется как сумма обращенных коэффициентов, деленная на величину, обратную к коэффициенту данному значению. Вероятности кумулятивны (складываются), что делает очень легким вычисления с родителями. Например:
| 
 | 
     В 
программе, при одинаковых начальных 
значениях, вероятности сложатся: представьте 
их в виде кусков пирога. Первый ген 
- от 0 до 8.80%, следующий идет до 39.6% (так 
как он начинает 8.8). Таблица вероятностей 
будет выглядеть приблизительно так: 
| 
 | 
     Последнее 
значение всегда будет 100. Имея в нашем 
арсенале теорию, посмотрим на код. 
Он очень прост: преобразование к float 
необходимо для того, чтобы избегать 
целочисленного деления. Есть две функции: 
одна вычисляет smi, а другая генерирует 
вероятности оказаться родителем.  
float CDiophantine::MultInv() 
{ 
   float sum = 0; 
   for(int i=0;i<MAXPOP;i++) 
{ 
      
sum += 1/((float)population[i].
}
   return sum; 
}
void CDiophantine::
   float multinv 
= MultInv(); 
   float last = 0; 
   for(int i=0;i<MAXPOP;i++) 
{ 
      
population[i].likelihood = last  
      
= last + ((1/((float)population[i].
   } 
} 
Итак, у нас есть и коэффициенты выживаемости (fitness) и необходимые вероятности (likelihood). Можно переходить к размножению (breeding).
Breeding Functions
     Функции 
размножения состоят из трех: получить 
индекс гена, отвечающего случайному 
числу от 1 до 100, непосредственно 
вычислить кроссовер двух генов 
и главной функции генерации 
нового поколения. Рассмотрим все эти 
функции одновременно и то, как они друг 
друга вызывают. Вот главная функция размножения:  
void CDiophantine::
   gene temppop[MAXPOP]; 
   for(int i=0;i<MAXPOP;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 > (MAXPOP * MAXPOP)) break;
}
      
temppop[i] = Breed(parent1, parent2);  // Create a child. 
}
   for(i=0;i<MAXPOP;i++) 
population[i] = temppop[i]; 
} 
     Итак, 
первым делом мы создаем случайную 
популяцию генов. Затем делаем цикл 
по всем генам. Выбирая гены, мы не хотим, 
чтобы они оказались одинаковы (ни к чему 
скрещиваться с самим собой,  и вообще 
- нам не нужны одинаковые гены (operator = в 
gene). При выборе родителя, генерируем случайное 
число, а затем вызываем GetIndex. GetIndex использует 
идею кумулятивности вероятностей (likelihoods), 
она просто делает итерации по всем генам, 
пока не найден ген, содержащий число:  
   int CDiophantine::GetIndex(float 
val) { 
   float last = 0; 
   for(int i=0;i<MAXPOP;i++) 
{ 
      
if (last <= val && val <= population[i].likelihood) return 
i; 
      
else last = population[i].likelihood; 
}
   return 4; 
} 
     Возвращаясь 
к функции CreateNewPopulation(): если число 
итераций превосходит MAXPOP2, она выберет 
любых родителей. После того, как 
родители выбраны, они скрещиваются: 
их индексы передаются вверх на функцию 
размножения (Breed). Breed function возвращает 
ген, который помещается во временную 
популяцию. Вот код:  
gene CDiophantine::Breed(int p1, int p2) {
   int crossover 
= rand() % 3+1; 
   int first = rand() 
% 100; 
   gene child = population[p1]; 
   int initial = 
0, final = 3; 
   if (first < 
50) initial = crossover; 
   else final = crossover+1; 
   for(int i=initial;i<final;i++) 
{ 
      
child.alleles[i] = population[p2].alleles[i]; 
      
if (rand() % 101 < 5) child.alleles[i] = rand() % (result + 1); 
Информация о работе Генетические алгоритмы и их практическое применение