/// <summary> /// Konstruktor /// </summary> /// <param name='size'>Größe der Population</param> /// <param name='genomeSize'>Größe des einzelnen Genomes</param> public Population(int size, int genomeSize, double minAllelValue, double maxAllelValue, Helper.Enums.Encryption encryption) { _encryption = encryption; // Erzeuge Listen mit fester Kapazität curGeneration = new List<Genome>(size); oldGeneration = new List<Genome>(size); totalSize = size; Genome tmp; for(int i = 0; i < size; i++) { if (_encryption == Helper.Enums.Encryption.None) throw new NotImplementedException(); //todo Genome mit Integerwerten // else if (_encryption == Helper.Enums.Encryption.Binary) // { // throw new NotImplementedException(); //todo // } // else if (_encryption == Helper.Enums.Encryption.Real) else { tmp = new GenomeReal(genomeSize, minAllelValue, maxAllelValue); // um Duplikate bei der Erzeugung der Population zu vermeiden while(curGeneration.Contains(tmp)) { //Console.WriteLine(String.Format("Duplikat: {0}\r\ni = {1}", tmp.AsString(),i)); tmp = new GenomeReal(genomeSize, minAllelValue, maxAllelValue); } curGeneration.Add(tmp); } } }
protected void OnBtnStart10Clicked(object sender, System.EventArgs e) { //Mal ne Exception, will ich eh alles anders machen statusbar.Push(1,"Ditt jeht noch nich, keule."); Problem bin = new Griewank(); bin.countIndividuals = (int)txt_countIndividuals.Value; Genome a = new GenomeReal(5,-50,50); Genome b = new GenomeReal(5,-50,50); List<Genome> childs = new List<Genome>(2); childs.Add(a); childs.Add(b); Console.WriteLine(a.AsString()); Console.WriteLine(b.AsString()); bin.MutateBinary(childs); }
/// <summary> /// Der eigentliche evolutionäre Algorithmus - entspricht doc/EvoAlgTSP.pdf. /// </summary> public void Compute() { int countGeneration = 0; int c; // child-counter bestFitness = double.MaxValue; averageFitness = double.MaxValue; bestFitnessGeneration = 0; Genome bestGenome; sb.AppendLine("Compute:"); // 1. Initialisiere Population P(0) mit zufälligen Genomen Population p = new Population(countIndividuals, countGene, minAllelValue, maxAllelValue, Encryption); // 2. Berechne die Fitnesswerte von P(0) foreach (Genome genome in p.curGeneration) { CalcFitness(genome); } // Ermittel beste Lösung von P(0) bestGenome = Helper.Fitness.GetBestGenome(p.curGeneration); while(countGeneration < maxGenerations && stableGenerations < 1000) { //Event für Fortschritt feuern if (OnProgress != null) { double percentage = ((double)(countGeneration + 1) / (double)maxGenerations); OnProgress(percentage); } //Sagt dem Betriebssystem das es seine Evenets abarbeiten soll. //Das verhindert (u.A.) das einfrieren der GUI while (Application.EventsPending ()) Application.RunIteration (); // Fitness des besten Genoms, ist hoeher als bisherige beste Fitness if (bestGenome.Fitness < bestFitness) { bestFitness = bestGenome.Fitness; bestFitnessGeneration = countGeneration + 1; bestList.Add(bestGenome.Copy()); } else { // Zähle stableGenerations hoch, wenn sich bester Fitnesswert nicht geändert hat stableGenerations++; } //alte Generation merken p.SaveAsOldGen(); switch(SelPropType) { case Helper.Enums.SelPropType.Fitness : Helper.Selection.CalcSelPropByFitness(p.oldGeneration); break; case Helper.Enums.SelPropType.Ranking : Helper.Selection.CalcSelPropByRanking(p.oldGeneration); break; } // 3. Erzeuge Kinder und füge sie P' hinzu c = 0; Random rnd = new Random(Guid.NewGuid().GetHashCode()); while (c < countChilds) { if (rnd.NextDouble() <= recombinationProbability) { // I. Rekombination zweier Individuen A und B aus Population P(0) //todo: Genom aus der Populationsklasse liefern lassen damit der Genom-Typ immer passt Genome mama = new GenomeReal(); Genome papa = new GenomeReal(); bool equals = true; while (equals) { switch (SelType) { case main.Helper.Enums.SelType.Roulette : mama = Selection.Roulette(p.oldGeneration); papa = Selection.Roulette(p.oldGeneration); break; case main.Helper.Enums.SelType.SingleTournament : mama = Selection.SingleTournament(p.oldGeneration, TournamentMemberCount); papa = Selection.SingleTournament(p.oldGeneration, TournamentMemberCount); break; case main.Helper.Enums.SelType.MultiTournament : mama = Selection.MultiTournament(p.oldGeneration, TournamentMemberCount); papa = Selection.MultiTournament(p.oldGeneration, TournamentMemberCount); break; } //Mama und Papa dürfen nicht die selben sein, sonst evtl. Duplikat if (!mama.IsEqual(papa)) equals = false; } //Rekombinieren und Fitness berechnen List<Genome> childs = Recombine(mama,papa); // II. Mutiere Kind c if (Encryption != Helper.Enums.Encryption.Binary) Mutate(childs); foreach (Genome genome in childs) CalcFitness(genome); // III. Füge Kinder C zu P' hinzu //todo: Binäre Rekombination liefert 2 Kinder zurück if (!p.ContainsGenome(childs[0]) || ((childs.Count > 1)? !p.ContainsGenome(childs[1]) : false)) // if (!p.ContainsGenome(childs[0]) ) { p.curGeneration.AddRange(childs); if (Encryption == Helper.Enums.Encryption.Binary) c += 2; else c++; } } } // 5. Erzeuge Kind-Population -> die besten Individuen aus Kind- + Eltern-Generation if (Encryption != Helper.Enums.Encryption.Binary) Selection.Plus(p, countIndividuals); else { int perc = (int)Math.Round((double)p.curGeneration.Count * 0.3); // perc = countIndividuals - perc; List<Genome> lst = new List<Genome>(); Random rnd1 = new Random(Guid.NewGuid().GetHashCode()); for (perc = countIndividuals - perc; perc <= p.oldGeneration.Count; perc++) { lst.Clear(); lst.Add(p.oldGeneration[rnd1.Next(0,p.oldGeneration.Count)]); Mutate(lst); p.curGeneration[perc-1] = lst[0]; } foreach (Genome genome in p.curGeneration) CalcFitness(genome); p.curGeneration.Sort((a,b) => a.Fitness.CompareTo(b.Fitness)); } bestGenome = p.curGeneration[0]; countGeneration++; } //Ausgabe der letzten Generation // sb.AppendLine("Letzte Generation"); // foreach (Genome genome in p.curGeneration) // sb.AppendLine(genome.AsString()); // Ausgabe der besten Lösungen sb.AppendLine("\r\nBestenliste"); int counter = 1; for (int i = bestList.Count-1; i >= 0; i--) { sb.AppendLine(counter + ".\t" + bestList[i].AsString()); counter++; } // Speichere den besten Fitnesswert und die Generation in der er aufgetreten ist zur späteren Auswertung (Evolutioniere x 10) bestSolutions.Add(bestFitness); bestSolutionsGeneration.Add(bestFitnessGeneration); }
public override List<Genome> RecombineDefault(Genome genomeA, Genome genomeB) { //Fehler, wenn Genome null if (genomeA == null || genomeB == null) { throw new ArgumentNullException(); } //Fehler, wenn Längen der Genome unterschiedlich if (genomeA.Count != genomeB.Count) { throw new ArgumentException("Cant recombine genomes with a different count of values."); } //Kinder-List mit Startallel initialisieren Genome childs = new GenomeReal(); childs.Add(genomeA[0]); //Nachbarn für alle Allele ermitteln Dictionary<int, Genome> neighbours = new Dictionary<int, Genome>(); foreach (int gene in genomeA) { neighbours.Add(gene, GetNeighboursOfValue(gene, genomeA,genomeB)); } //Kind ermitteln int tempAllel = 0; //Alle Allele durchgehen int j = 0; int g = 1; while (j < genomeA.Count - 1) { int minLength = int.MaxValue; foreach (int i in neighbours[g]) { Genome subNeighbours = neighbours[i].Copy(); subNeighbours.RemoveAll(s => childs.Contains(s)); //Immer wenn eine kürzere Nachbarmenge gefunden wurde -> das zugehörige Allel merken, insofern noch nicht im Kind vorhanden if (subNeighbours.Count < minLength && !childs.Contains(i)) { tempAllel = i; //Neue kürzeste Länge merken die es zu unterbieten gilt minLength = subNeighbours.Count; } } //Ermitteltes Allel zum Kind hinzufügen childs.Add(tempAllel); g = tempAllel; j++; } List<Genome> result = new List<Genome>(); result.Add(childs); return result; }
/// <summary> /// Kopiert ein Genom /// </summary> public override Genome Copy() { Genome result = new GenomeReal (this.ToArray()); result.Fitness = this.Fitness; return result; }