logo

Genetické algoritmy

Genetické algoritmy (GA) jsou adaptivní heuristické vyhledávací algoritmy, které patří k větší části evolučních algoritmů. Genetické algoritmy jsou založeny na myšlenkách přirozeného výběru a genetiky. Jedná se o inteligentní využití náhodných vyhledávání poskytnutých s historickými daty k nasměrování vyhledávání do oblasti lepšího výkonu v prostoru řešení. Běžně se používají ke generování vysoce kvalitních řešení optimalizačních problémů a problémů s vyhledáváním.

Genetické algoritmy simulují proces přirozeného výběru což znamená, že ty druhy, které se dokážou přizpůsobit změnám ve svém prostředí, mohou přežít a rozmnožovat se a přejít do další generace. Jednoduše řečeno, simulují přežití těch nejschopnějších mezi jednotlivci z po sobě jdoucích generací k vyřešení problému. Každá generace se skládá z populace jednotlivců a každý jednotlivec představuje bod v prostoru hledání a možné řešení. Každý jednotlivec je reprezentován jako řetězec znaků/celého čísla/float/bitů. Tento řetězec je analogický s chromozomem.



Základy genetických algoritmů

Genetické algoritmy jsou založeny na analogii s genetickou strukturou a chováním chromozomů populace. Následuje základ GA založený na této analogii –

  1. Jednotlivci v populaci soutěží o zdroje a páří se
  2. Ti úspěšní (nejzdatnější) jedinci se pak páří, aby vytvořili více potomků než ostatní
  3. Geny od nejschopnějšího rodiče se množí po celou generaci, to znamená, že někdy rodiče vytvoří potomstvo, které je lepší než kterýkoli z rodičů.
  4. Každá následující generace je tak vhodnější pro své prostředí.

Prohledejte prostor

Populace jedinců se udržuje v prostoru hledání. Každý jednotlivec představuje řešení v prostoru hledání daného problému. Každý jedinec je kódován jako vektor konečné délky (analogický k chromozomu) komponent. Tyto proměnné složky jsou analogické s geny. Chromozom (jedinec) je tedy složen z několika genů (proměnných složek).



Fitness skóre

Fitness skóre je přiděleno každému jednotlivci, který ukazuje schopnost jednotlivce soutěžit . Hledá se jedinec s optimálním skóre kondice (nebo téměř optimální).

GA udržuje populaci n jedinců (chromozomů/řešení) spolu s jejich skóre zdatnosti. Jednotlivci s lepším skóre zdatnosti mají větší šanci na reprodukci než ostatní. Jsou vybráni jedinci s lepšími výsledky v kondici, kteří se páří a plodí lepší potomstvo spojením chromozomů rodičů. Velikost populace je statická, takže místnost musí být vytvořena pro nově příchozí. Takže někteří jedinci umírají a jsou nahrazeni novými příchozími, kteří nakonec vytvoří novou generaci, když jsou vyčerpány všechny příležitosti k páření staré populace. Doufáme, že v průběhu následujících generací přijdou lepší řešení, zatímco nejméně fit zemřou.

Každá nová generace má v průměru více lepších genů než jedinec (řešení) předchozích generací. Každá nová generace má tedy lepší dílčí řešení než předchozí generace. Jakmile vyprodukované potomstvo nemá žádný významný rozdíl od potomků vyprodukovaných předchozími populacemi, populace se sblíží. Říká se, že algoritmus je konvergován k sadě řešení problému.



Operátoři genetických algoritmů

Jakmile je vytvořena počáteční generace, algoritmus ji rozvine pomocí následujících operátorů –
1) Operátor výběru: Cílem je upřednostňovat jedince s dobrým kondičním skóre a umožnit jim předat své geny dalším generacím.
2) Crossover Operator: To představuje páření mezi jednotlivci. Dva jedinci jsou vybráni pomocí výběrového operátoru a místa křížení jsou vybrána náhodně. Poté jsou geny na těchto místech křížení vyměněny a vzniká tak zcela nový jedinec (potomek). Například -

3) Operátor mutace: Klíčovou myšlenkou je vložit náhodné geny do potomků, aby se zachovala diverzita v populaci, aby se zabránilo předčasné konvergenci. Například -

trojitá zima

Celý algoritmus lze shrnout takto:

1) Randomly initialize populations p 2) Determine fitness of population 3) Until convergence repeat:  a) Select parents from population  b) Crossover and generate new population  c) Perform mutation on new population  d) Calculate fitness for new population>

Příklad problému a řešení pomocí genetických algoritmů

Zadaný cílový řetězec je cílem vytvořit cílový řetězec počínaje náhodným řetězcem stejné délky. V následující implementaci jsou provedeny následující analogie –

  • Znaky A-Z, a-z, 0-9 a další speciální symboly jsou považovány za geny
  • Řetězec generovaný těmito znaky je považován za chromozom/roztok/jednotlivec

Fitness skóre je počet znaků, které se liší od znaků v cílovém řetězci na konkrétním indexu. Jednotlivci s nižší fitness hodnotou jsou tedy dány větší přednost.

C++




sčítačka plná sčítačka

// C++ program to create target string, starting from> // random string using Genetic Algorithm> > #include> using> namespace> std;> > // Number of individuals in each generation> #define POPULATION_SIZE 100> > // Valid Genes> const> string GENES =>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP'>> 'QRSTUVWXYZ 1234567890, .-;:_!'#%&/()=?@${[]}'>;> > // Target string to be generated> const> string TARGET =>'I love techcodeview.com'>;> > // Function to generate random numbers in given range> int> random_num(>int> start,>int> end)> {> >int> range = (end-start)+1;> >int> random_int = start+(>rand>()%range);> >return> random_int;> }> > // Create random genes for mutation> char> mutated_genes()> {> >int> len = GENES.size();> >int> r = random_num(0, len-1);> >return> GENES[r];> }> > // create chromosome or string of genes> string create_gnome()> {> >int> len = TARGET.size();> >string gnome =>''>;> >for>(>int> i = 0;i gnome += mutated_genes(); return gnome; } // Class representing individual in population class Individual { public: string chromosome; int fitness; Individual(string chromosome); Individual mate(Individual parent2); int cal_fitness(); }; Individual::Individual(string chromosome) { this->chromozom = chromozom; fitness = cal_fitness(); }; // Proveďte páření a zplodte nové potomky Individual Individual::mate(Individual par2) { // chromozom pro potomka string child_chromosom = ''; int len ​​= chromozom.velikost(); for(int i = 0;i { // náhodná pravděpodobnost float p = random_num(0, 100)/100; // pokud je prob menší než 0,45, vložte gen // z rodiče 1 if(p<0.45) child_chromosome += chromosome[i]; // if prob is between 0.45 and 0.90, insert // gene from parent 2 else if(p <0.90) child_chromosome += par2.chromosome[i]; // otherwise insert random gene(mutate), // for maintaining diversity else child_chromosome += mutated_genes(); } // create new Individual(offspring) using // generated chromosome for offspring return Individual(child_chromosome); }; // Calculate fitness score, it is the number of // characters in string which differ from target // string. int Individual::cal_fitness() { int len = TARGET.size(); int fitness = 0; for(int i = 0;i { if(chromosome[i] != TARGET[i]) fitness++; } return fitness; }; // Overloading bool operator<(const Individual &ind1, const Individual &ind2) { return ind1.fitness } // Driver code int main() { srand((unsigned)(time(0))); // current generation int generation = 0; vector population; bool found = false; // create initial population for(int i = 0;i { string gnome = create_gnome(); population.push_back(Individual(gnome)); } while(! found) { // sort the population in increasing order of fitness score sort(population.begin(), population.end()); // if the individual having lowest fitness score ie. // 0 then we know that we have reached to the target // and break the loop if(population[0].fitness <= 0) { found = true; break; } // Otherwise generate new offsprings for new generation vector new_generation; // Perform Elitism, that mean 10% of fittest population // goes to the next generation int s = (10*POPULATION_SIZE)/100; for(int i = 0;i new_generation.push_back(population[i]); // From 50% of fittest population, Individuals // will mate to produce offspring s = (90*POPULATION_SIZE)/100; for(int i = 0;i { int len = population.size(); int r = random_num(0, 50); Individual parent1 = population[r]; r = random_num(0, 50); Individual parent2 = population[r]; Individual offspring = parent1.mate(parent2); new_generation.push_back(offspring); } population = new_generation; cout<< 'Generation: ' << generation << ' '; cout<< 'String: '<< population[0].chromosome <<' '; cout<< 'Fitness: '<< population[0].fitness << ' '; generation++; } cout<< 'Generation: ' << generation << ' '; cout<< 'String: '<< population[0].chromosome <<' '; cout<< 'Fitness: '<< population[0].fitness << ' '; }>

>

>

Jáva




java řetězec na booleovský

import> java.util.ArrayList;> import> java.util.Collections;> import> java.util.List;> import> java.util.Random;> > public> class> GeneticAlgorithm {> >// Number of individuals in each generation> >private> static> final> int> POPULATION_SIZE =>100>;> > >// Valid Genes> >private> static> final> String GENES =>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890, .-;:_!'#%&/()=?@${[]}'>;> > >// Target string to be generated> >private> static> final> String TARGET =>'I love techcodeview.com'>;> > >// Function to generate random numbers in given range> >private> static> int> randomNum(>int> start,>int> end) {> >Random rand =>new> Random();> >return> rand.nextInt(end - start +>1>) + start;> >}> > >// Create random genes for mutation> >private> static> char> mutatedGenes() {> >int> len = GENES.length();> >int> r = randomNum(>0>, len ->1>);> >return> GENES.charAt(r);> >}> > >// Create chromosome or string of genes> >private> static> String createGnome() {> >int> len = TARGET.length();> >StringBuilder gnome =>new> StringBuilder();> >for> (>int> i =>0>; i gnome.append(mutatedGenes()); return gnome.toString(); } // Class representing individual in population private static class Individual implements Comparable { String chromosome; int fitness; Individual(String chromosome) { this.chromosome = chromosome; fitness = calFitness(); } // Perform mating and produce new offspring Individual mate(Individual par2) { StringBuilder childChromosome = new StringBuilder(); int len = chromosome.length(); for (int i = 0; i // random probability float p = randomNum(0, 100) / 100f; // if prob is less than 0.45, insert gene from parent 1 if (p <0.45) childChromosome.append(chromosome.charAt(i)); // if prob is between 0.45 and 0.90, insert gene from parent 2 else if (p <0.90) childChromosome.append(par2.chromosome.charAt(i)); // otherwise insert random gene(mutate), for maintaining diversity else childChromosome.append(mutatedGenes()); } // create new Individual(offspring) using generated chromosome for offspring return new Individual(childChromosome.toString()); } // Calculate fitness score, it is the number of characters in string which differ from target string private int calFitness() { int len = TARGET.length(); int fitness = 0; for (int i = 0; i if (chromosome.charAt(i) != TARGET.charAt(i)) fitness++; } return fitness; } @Override public int compareTo(Individual o) { return Integer.compare(this.fitness, o.fitness); } } // Driver code public static void main(String[] args) { // current generation int generation = 0; List population = new ArrayList(); boolean found = false; // create initial population for (int i = 0; i String gnome = createGnome(); population.add(new Individual(gnome)); } while (!found) { // sort the population in increasing order of fitness score Collections.sort(population); // if the individual having lowest fitness score i.e. 0 then we know that we have reached to the target // and break the loop if (population.get(0).fitness <= 0) { found = true; break; } // Otherwise generate new offsprings for new generation List newGeneration = new ArrayList(); // Perform Elitism, that mean 10% of fittest population goes to the next generation int s = (10 * POPULATION_SIZE) / 100; for (int i = 0; i newGeneration.add(population.get(i)); // From 50% of fittest population, Individuals will mate to produce offspring s = (90 * POPULATION_SIZE) / 100; for (int i = 0; i int len = population.size(); int r = randomNum(0, 50); Individual parent1 = population.get(r); r = randomNum(0, 50); Individual parent2 = population.get(r); Individual offspring = parent1.mate(parent2); newGeneration.add(offspring); } population = newGeneration; System.out.print('Generation: ' + generation + ' '); System.out.print('String: ' + population.get(0).chromosome + ' '); System.out.println('Fitness: ' + population.get(0).fitness); generation++; } System.out.print('Generation: ' + generation + ' '); System.out.print('String: ' + population.get(0).chromosome + ' '); System.out.println('Fitness: ' + population.get(0).fitness); } }>

>

>

Python3




# Python3 program to create target string, starting from> # random string using Genetic Algorithm> > import> random> > # Number of individuals in each generation> POPULATION_SIZE>=> 100> > # Valid genes> GENES>=> '''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP> QRSTUVWXYZ 1234567890, .-;:_!'#%&/()=?@${[]}'''> > # Target string to be generated> TARGET>=> 'I love techcodeview.com'> > class> Individual(>object>):> >'''> >Class representing individual in population> >'''> >def> __init__(>self>, chromosome):> >self>.chromosome>=> chromosome> >self>.fitness>=> self>.cal_fitness()> > >@classmethod> >def> mutated_genes(>self>):> >'''> >create random genes for mutation> >'''> >global> GENES> >gene>=> random.choice(GENES)> >return> gene> > >@classmethod> >def> create_gnome(>self>):> >'''> >create chromosome or string of genes> >'''> >global> TARGET> >gnome_len>=> len>(TARGET)> >return> [>self>.mutated_genes()>for> _>in> range>(gnome_len)]> > >def> mate(>self>, par2):> >'''> >Perform mating and produce new offspring> >'''> > ># chromosome for offspring> >child_chromosome>=> []> >for> gp1, gp2>in> zip>(>self>.chromosome, par2.chromosome):> > ># random probability> >prob>=> random.random()> > ># if prob is less than 0.45, insert gene> ># from parent 1> >if> prob <>0.45>:> >child_chromosome.append(gp1)> > ># if prob is between 0.45 and 0.90, insert> ># gene from parent 2> >elif> prob <>0.90>:> >child_chromosome.append(gp2)> > ># otherwise insert random gene(mutate),> ># for maintaining diversity> >else>:> >child_chromosome.append(>self>.mutated_genes())> > ># create new Individual(offspring) using> ># generated chromosome for offspring> >return> Individual(child_chromosome)> > >def> cal_fitness(>self>):> >'''> >Calculate fitness score, it is the number of> >characters in string which differ from target> >string.> >'''> >global> TARGET> >fitness>=> 0> >for> gs, gt>in> zip>(>self>.chromosome, TARGET):> >if> gs !>=> gt: fitness>+>=> 1> >return> fitness> > # Driver code> def> main():> >global> POPULATION_SIZE> > >#current generation> >generation>=> 1> > >found>=> False> >population>=> []> > ># create initial population> >for> _>in> range>(POPULATION_SIZE):> >gnome>=> Individual.create_gnome()> >population.append(Individual(gnome))> > >while> not> found:> > ># sort the population in increasing order of fitness score> >population>=> sorted>(population, key>=> lambda> x:x.fitness)> > ># if the individual having lowest fitness score ie.> ># 0 then we know that we have reached to the target> ># and break the loop> >if> population[>0>].fitness <>=> 0>:> >found>=> True> >break> > ># Otherwise generate new offsprings for new generation> >new_generation>=> []> > ># Perform Elitism, that mean 10% of fittest population> ># goes to the next generation> >s>=> int>((>10>*>POPULATION_SIZE)>/>100>)> >new_generation.extend(population[:s])> > ># From 50% of fittest population, Individuals> ># will mate to produce offspring> >s>=> int>((>90>*>POPULATION_SIZE)>/>100>)> >for> _>in> range>(s):> >parent1>=> random.choice(population[:>50>])> >parent2>=> random.choice(population[:>50>])> >child>=> parent1.mate(parent2)> >new_generation.append(child)> > >population>=> new_generation> > >print>(>'Generation: {} String: {} Fitness: {}'>.> >format>(generation,> >''.join(population[>0>].chromosome),> >population[>0>].fitness))> > >generation>+>=> 1> > > >print>(>'Generation: {} String: {} Fitness: {}'>.> >format>(generation,> >''.join(population[>0>].chromosome),> >population[>0>].fitness))> > if> __name__>=>=> '__main__'>:> >main()>

>

vznášející se v css

>

C#




using> System;> using> System.Collections.Generic;> using> System.Linq;> > public> class> GeneticAlgorithm> {> >// Number of individuals in each generation> >private> const> int> POPULATION_SIZE = 100;> > >// Valid Genes> >private> const> string> GENES =>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP'> +> >'QRSTUVWXYZ 1234567890, .-;:_!'#%&/()=?@${[]}'>;> > >// Target string to be generated> >private> const> string> TARGET =>'I love techcodeview.com'>;> > >private> static> readonly> Random random =>new> Random();> > >// Function to generate random numbers in given range> >private> static> int> RandomNum(>int> start,>int> end)> >{> >return> random.Next(start, end + 1);> >}> > >// Create random genes for mutation> >private> static> char> MutatedGenes()> >{> >int> len = GENES.Length;> >int> r = RandomNum(0, len - 1);> >return> GENES[r];> >}> > >// Create chromosome or string of genes> >private> static> string> CreateGnome()> >{> >int> len = TARGET.Length;> >char>[] gnome =>new> char>[len];> >for> (>int> i = 0; i { gnome[i] = MutatedGenes(); } return new string(gnome); } // Class representing individual in population private class Individual { public string Chromosome { get; } public int Fitness { get; } public Individual(string chromosome) { Chromosome = chromosome; Fitness = CalculateFitness(); } // Calculate fitness score, it is the number of // characters in string which differ from target string. private int CalculateFitness() { return Chromosome.Zip(TARGET, (a, b) =>a == b? 0 : 1).Součet(); } // Proveďte páření a zplodte nové potomky public Individual Mate(Individual parent2) { char[] childChromozom = new char[Chromozom.Length]; for (int i = 0; i { double p = random.NextDouble(); if (p<0.45) childChromosome[i] = Chromosome[i]; else if (p <0.90) childChromosome[i] = parent2.Chromosome[i]; else childChromosome[i] = MutatedGenes(); } return new Individual(new string(childChromosome)); } } // Overloading private class FitnessComparer : IComparer { public int Compare(Individual ind1, Individual ind2) { return ind1.Fitness.CompareTo(ind2.Fitness); } } // Driver code public static void Main() { // current generation int generation = 0; List population = new List(); bool found = false; // create initial population for (int i = 0; i { string gnome = CreateGnome(); population.Add(new Individual(gnome)); } while (!found) { // sort the population in increasing order of fitness score population.Sort(new FitnessComparer()); // if the individual having lowest fitness score ie. // 0 then we know that we have reached the target // and break the loop if (population[0].Fitness == 0) { found = true; break; } // Otherwise generate new offsprings for new generation List newGeneration = new List(); // Perform Elitism, that means 10% of fittest population // goes to the next generation int s = (10 * POPULATION_SIZE) / 100; for (int i = 0; i newGeneration.Add(population[i]); // From 50% of fittest population, Individuals // will mate to produce offspring s = (90 * POPULATION_SIZE) / 100; for (int i = 0; i { int len = population.Count; int r = RandomNum(0, 50); Individual parent1 = population[r]; r = RandomNum(0, 50); Individual parent2 = population[r]; Individual offspring = parent1.Mate(parent2); newGeneration.Add(offspring); } population = newGeneration; Console.WriteLine('Generation: ' + generation + ' ' + 'String: ' + population[0].Chromosome + ' ' + 'Fitness: ' + population[0].Fitness); generation++; } Console.WriteLine('Generation: ' + generation + ' ' + 'String: ' + population[0].Chromosome + ' ' + 'Fitness: ' + population[0].Fitness); } }>

>

>

Javascript


zpracování řetězců v c++



// Number of individuals in each generation> const POPULATION_SIZE = 100;> > // Valid Genes> const GENES =>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP'> +> >'QRSTUVWXYZ 1234567890, .-;:_!'#%&/()=?@${[]}'>;> > // Target string to be generated> const TARGET =>'I love techcodeview.com'>;> > // Function to generate random numbers in given range> function> RandomNum(start, end) {> >return> Math.floor(Math.random() * (end - start + 1)) + start;> }> > // Create random genes for mutation> function> MutatedGenes() {> >let len = GENES.length;> >let r = RandomNum(0, len - 1);> >return> GENES.charAt(r);> }> > // Create chromosome or string of genes> function> CreateGnome() {> >let len = TARGET.length;> >let gnome =>''>;> >for> (let i = 0; i gnome += MutatedGenes(); } return gnome; } // Class representing individual in population class Individual { constructor(chromosome) { this.Chromosome = chromosome; this.Fitness = this.CalculateFitness(); } // Calculate fitness score, it is the number of // characters in string which differ from target string. CalculateFitness() { let fitness = 0; for (let i = 0; i FitnessComparer.Compare(a, b)); // pokud má jedinec nejnižší skóre fitness, tzn. // 0 pak víme, že jsme dosáhli cíle // a přerušíme smyčku if (populace[0].Fitness === 0) { found = true; přestávka; } // Jinak vygenerujte nové potomky pro novou generaci let newGeneration = []; // Proveďte elitářství, to znamená, že 10 % nejschopnější populace // přejde do další generace let s = Math.floor((10 * POPULATION_SIZE) / 100); for (nechť i = 0; i newGeneration.push(population[i]); // Z 50 % nejschopnější populace se jedinci // spáří za vzniku potomků s = Math.floor((90 * POPULATION_SIZE) / 100); for (ať i = 0; i nechť r = RandomNum(0, 50); nechť rodič1 = populace[r]; r = RandomNum(0, 50); nechť rodič2 = populace[r]; nechť potomek = rodič1.Mate( rodič2); newGeneration.push(potomstvo) = newGeneration; console.log('Generace: ' + generace + ' ' + 'String: ' + populace[0].Chromozom + ); ' ' + 'Fitness: ' + populace[0].Fitness generation++; } console.log('Generace: ' + generace + ' ' + 'String: '); + populace[0].Chromozom + ' ' + 'Fitness: ' + populace[0].Fitness } // Spusťte hlavní funkci Main();

> 

Výstup:

Generation: 1 String: tO{'-?=jH[k8=B4]Oe@} Fitness: 18 Generation: 2 String: tO{'-?=jH[k8=B4]Oe@} Fitness: 18 Generation: 3 String: .#lRWf9k_Ifslw #O$k_ Fitness: 17 Generation: 4 String: .-1Rq?9mHqk3Wo]3rek_ Fitness: 16 Generation: 5 String: .-1Rq?9mHqk3Wo]3rek_ Fitness: 16 Generation: 6 String: A#ldW) #lIkslw cVek) Fitness: 14 Generation: 7 String: A#ldW) #lIkslw cVek) Fitness: 14 Generation: 8 String: (, o x _x%Rs=, 6Peek3 Fitness: 13  .   .   .  Generation: 29 String: I lope Geeks#o, Geeks Fitness: 3 Generation: 30 String: I loMe GeeksfoBGeeks Fitness: 2 Generation: 31 String: I love Geeksfo0Geeks Fitness: 1 Generation: 32 String: I love Geeksfo0Geeks Fitness: 1 Generation: 33 String: I love Geeksfo0Geeks Fitness: 1 Generation: 34 String: I love techcodeview.com Fitness: 0>

Poznámka: Algoritmus pokaždé začíná náhodnými řetězci, takže výstup se může lišit

Jak můžeme vidět z výstupu, náš algoritmus někdy uvízl na lokálním optimálním řešení, což lze dále zlepšit aktualizací algoritmu výpočtu skóre fitness nebo vyladěním operátorů mutace a křížení.

Proč používat genetické algoritmy

  • Jsou Robustní
  • Zajistěte optimalizaci ve stavu velkého prostoru.
  • Na rozdíl od tradiční AI se nerozbijí při nepatrné změně vstupu nebo přítomnosti šumu

Aplikace genetických algoritmů

Genetické algoritmy mají mnoho aplikací, některé z nich jsou –

  • Rekurentní neuronová síť
  • Testování mutací
  • Prolomení kódu
  • Filtrování a zpracování signálu
  • Učení základu fuzzy pravidel atd