public Tierchen InzestMutation() { Random randomizer = new Random(); var AllelSize = GenCode.Select(allel => allel.Size).Distinct(); var InterValList = GenCode.Select(allel => allel.Interval).ToList(); if (AllelSize.Count() == 1) { var allelLenght = AllelSize.FirstOrDefault(); var gencode = CompleteGenCode; int Stelle1 = randomizer.Next(gencode.Count); int Stelle2 = Stelle1; if (Stelle1 < gencode.Count - 1) { Stelle2 = randomizer.Next(Stelle1 + 1, gencode.Count); } var tmpValue = gencode[Stelle1]; gencode[Stelle1] = gencode[Stelle2]; gencode[Stelle2] = tmpValue; // gesamtliste wieder trennen var newTier = new Tierchen(this.Problem, GenCode); newTier.CompleteGenCode = gencode; return(newTier); } else { return(this); } }
public Tierchen Mutation() { /* Führe eine Mutation aus * Bestimme dazu die Allelmenge * */ Random randomizer = new Random(); var AllelSize = GenCode.Select(allel => allel.Size).Distinct(); var InterValList = GenCode.Select(allel => allel.Interval).ToList(); if (AllelSize.Count() == 1) { var allelLenght = AllelSize.FirstOrDefault(); var gencode = CompleteGenCode; int Stelle1 = randomizer.Next(gencode.Count); int Stelle2 = Stelle1; if (Stelle1 < gencode.Count - 1) { Stelle2 = randomizer.Next(Stelle1 + 1, gencode.Count); } gencode.Reverse(Stelle1, Stelle2 - Stelle1); // gesamtliste wieder trennen var newTier = new Tierchen(this.Problem, GenCode); newTier.CompleteGenCode = gencode; return(newTier); } else { return(this); } }
private void button2_Click(object sender, EventArgs e) { Random randomizer = new Random(); Elterngeneration.Clear(); Kindgeneration.Clear(); TierchenHistory.Clear(); BesteFitness.Clear(); DurchschnittsFitness.Clear(); BesterDerHistoryFitness.Clear(); // erzeuge Elterngeneration Int32.TryParse(textBox1.Text, out elternSize); Int32.TryParse(textBox5.Text, out binärStringLenght); Int32.TryParse(textBox3.Text, out gene); problem = new Problem(Int32.Parse(comboBox1.SelectedItem.ToString().Substring(1, 1))); var matches = Regex.Matches(textBox2.Text, @"\[(.*?)\]"); intervalle.Clear(); foreach (Match m in matches) { Intervall intervall; Intervall.TryParse(m.Groups[1].Value, out intervall); intervalle.Add(intervall); } if (checkBox1.Checked && intervalle.Count() == 1) { while (intervalle.Count() < gene) { intervalle.Add(intervalle[0]); } } progressBar1.Enabled = true; progressBar1.Value = 0; while (Elterngeneration.Count < elternSize) { Elterngeneration.Add(Tierchen.RandomTier(randomizer, binärStringLenght, intervalle, gene, problem)); /* * ### Wie kommt das mit dem Distinct zustande ? ### * ### Ist ToList() eine Methode einer über TierchenComparer liegenden Klasse ? ### * ### Welche voraussetzungen müssen erfüllt sein ? ### * !!! Hatten wir ja geklärt, oder? */ Elterngeneration = Elterngeneration.Distinct(new TierchenComparer()).ToList(); progressBar1.Value = Elterngeneration.Count() * 100 / elternSize; } SaveGeneration("last.xml"); progressBar1.Enabled = false; m_Generator = new generator(Elterngeneration, Kindgeneration, TierchenHistory, problem, BesteFitness, DurchschnittsFitness, BesterDerHistoryFitness); }
public static List <Tierchen> NPunktRekombination(Random randomizer, int recombinations, int pointOfRecombination, List <Tierchen> kindGen, List <Tierchen> elternGen) { // Füge zur Kindgeneration zwei Kinder über eine Ein-Punkt-Rekombination hinzu // Wiederhole solange bis die Anzahl der Rekombinationen erreicht bool verbieteDoppelte = true; int lastCount = 0; int versuchsZähler = 0; while (kindGen.Count() < recombinations) { var index1 = randomizer.Next(0, elternGen.Count); var index2 = index1; while (index2 == index1) { index2 = randomizer.Next(0, elternGen.Count); } Tierchen Kind1; Tierchen Kind2; Tierchen.NPointRecombination(randomizer, elternGen[index1], elternGen[index2], out Kind1, out Kind2, pointOfRecombination); kindGen.Add(Kind1); kindGen.Add(Kind2); if (verbieteDoppelte) { kindGen = kindGen.Distinct(new TierchenComparer()).ToList(); if (kindGen.Count() == lastCount) { if (versuchsZähler <= MAX_VERSUCHE_ZUM_FINDEN_NICHT_DOPPELTEN) { versuchsZähler++; } else { verbieteDoppelte = false; } } else { versuchsZähler = 0; } } lastCount = kindGen.Count(); } return(kindGen); }
public static Tierchen RandomTier(Random randomizer, int AllelLenght, List <Intervall> interval, int GenLenght, Problem problem) { var genCode = new List <Allel>(); for (int i = 0; i < GenLenght; i++) { var allel = new Allel(AllelLenght, interval[i]); var allelVal = new List <byte>(); for (int j = 0; j < AllelLenght; j++) { allelVal.Add((byte)randomizer.Next(0, 2)); } allel.Add(allelVal); genCode.Add(allel); } var tier = new Tierchen(problem, genCode); tier.Bewerte(); return(tier); }
public static bool OnePointRecombination(Random randomizer, Tierchen mutter, Tierchen vater, out Tierchen kind1, out Tierchen kind2) { /* Ein-Punkt-Rekombination wählt zwei Tierchen sowie zufällig je ein Allel ihres Gens. * Kinder setzen sich aus einem Teil der Mutter/Vater sowie einem Teil des Vaters zusammen. * Übergeben den Kindern zunächst den vollständigen Gencode und Entferne anschließend * an einer zufälligen Stelle den übergebliebenen Code, füge anschließend einen anderen Code * (des Vaters/Mutter) in das gleiche Tierchen ein. */ kind1 = null; kind2 = null; if (mutter.GenCode.Count() == vater.GenCode.Count() && mutter.GenCode.Count() > 0 && mutter.CompleteGenCode.Count() == vater.CompleteGenCode.Count() && mutter.CompleteGenCode.Count() > 0) { // Gib eine Folge von eindeutigen (unsortierten?) Allelen des jew. Tierchens aus // mehrere Allele in einem Tierchen sind möglich - müssen aber extra berücksichtigt werden var AllelSizeMutter = mutter.GenCode.Select(allel => allel.Size).Distinct(); var AllelSizeVater = mutter.GenCode.Select(allel => allel.Size).Distinct(); if (AllelSizeMutter.Count() == 1 && AllelSizeVater.Count() == 1) { var genCodeKind1 = mutter.CompleteGenCode; var genCodeKind2 = vater.CompleteGenCode; int splitIndex = randomizer.Next(0, genCodeKind1.Count()); int GenCodeSize = genCodeKind1.Count(); genCodeKind1.RemoveRange(splitIndex, GenCodeSize - splitIndex); genCodeKind1.AddRange(vater.CompleteGenCode.GetRange(splitIndex, GenCodeSize - splitIndex)); genCodeKind2.RemoveRange(splitIndex, GenCodeSize - splitIndex); genCodeKind2.AddRange(mutter.CompleteGenCode.GetRange(splitIndex, GenCodeSize - splitIndex)); kind1 = new Tierchen(mutter.Problem, mutter.GenCode); kind1.CompleteGenCode = genCodeKind1; kind2 = new Tierchen(vater.Problem, vater.GenCode); kind2.CompleteGenCode = genCodeKind2; } } return(false); }
static void Main(string[] args) { while (restart) { restart = false; repeat = true; Console.Clear(); TierchenHistory = new List <Tierchen>(); intervalle = new List <Intervall>(); bool couldParsed = false; bool loadDocument = false; int gene = 0; // Überspringe, falls keine start Generation übergeben wurde if ((args.Length > 0)) { Console.WriteLine("Soll das übergebenene Dokument geladen werden? (y/n)"); string answer = Console.ReadLine(); if (answer == "y") { loadDocument = true; try { // Elterngeneration einladen XDocument doc = XDocument.Load(args[0]); Elterngeneration = // lade alle "tier"-Elemente doc.Root.Descendants("tier").Select(tier => // erzeuge für jedes ein Tierchen Object new Tierchen( // lade Problem new Problem(int.Parse(tier.Attribute("problemType").Value)), // lade innerhalb des "tier"-Elementes alle "gen"-Elemente tier.Descendants("gen").Select(gen => // erzeuge für jedes ein Allel new Allel( // lade innerhalb des "gen"-Elementes alle "allel"-Elemente gen.Descendants("allel").Select(allel => // parse den bool-Wert bool.Parse(allel.Value)).ToList(), // Intervall steht als Attribut innerhalb des "gen"-Elementes new Intervall( int.Parse(gen.Attribute("interval_start").Value), int.Parse(gen.Attribute("interval_end").Value)) ) ).ToList() ) ).ToList(); elternSize = Elterngeneration.Count(); Console.WriteLine("gelesene Größe der Elterngeneration:"); Console.WriteLine(elternSize); } catch (Exception) { loadDocument = false; } } } /* * Programmbereiche auskommentiert um die Parametereingabe zu vereinfachen */ if (!loadDocument) { // Problem abfragen couldParsed = false; while (!couldParsed) { Console.WriteLine("Welches Problem soll gelöst werden?\r\n" + "[1] lineares Gleichungssystem\r\n" + "[2] Griewank-Funktion\r\n" + "[3] Ackley-Funktion\r\n" + "[4] C-Funktion\r\n" + "[5] Nullstellen-Funktion"); string lenght = Console.ReadLine(); couldParsed = Problem.TryParse(lenght, out problem); } } if (!loadDocument) { couldParsed = false; while (!couldParsed) { Console.WriteLine("Größe der Elterngeneration?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out elternSize); } //elternSize = 100; Console.WriteLine("Größe Elterngeneration = {0}", elternSize); } couldParsed = false; while (!couldParsed) { Console.WriteLine("Wie viele werden davon Rekombiniert?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out countOfRecombinations); couldParsed = couldParsed ? countOfRecombinations < elternSize : false; } //countOfRecombinations = 50; Console.WriteLine("Anzahl Rekombinationen = {0}", countOfRecombinations); couldParsed = false; /* * Für N-Punkt-Rekombination die Anzahl der Rekombinationspunkte */ while (!couldParsed) { Console.WriteLine("Wie viele Rekombinationspunkte sollen verwendet werden?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out pointOfRecombination); } couldParsed = false; /* * gibt die Anzahl der stellen innerhalb eines Allels an * Bsp: Länge = 6 -> Gen: [001001] [011011] [010010] */ if (!loadDocument) { while (!couldParsed) { Console.WriteLine("Länge des Binärstrings?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out binärStringLenght); } // binärStringLenght = 9; // Console.WriteLine("Binärstringlänge = {0}", binärStringLenght); } couldParsed = false; if (!loadDocument) { while (!couldParsed) { Console.WriteLine("Anzahl der Gene?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out gene); } //gene = 1; //Console.WriteLine("Anzahl der Gene = {0}", gene); } couldParsed = false; if (!loadDocument) { Console.WriteLine("Möchten Sie verschiedene Intervalle für jedes Gen angeben? [y/n]"); string input = Console.ReadLine(); if (input == "y") { while (!couldParsed) { Console.WriteLine("Größe des {0}. Intervals?", (intervalle.Count() + 1)); string lenght = Console.ReadLine(); Intervall actInterval; couldParsed = Intervall.TryParse(lenght, out actInterval); if (couldParsed) { intervalle.Add(actInterval); couldParsed = (intervalle.Count() >= gene); } } } else { while (!couldParsed) { Console.WriteLine("Größe aller Intervalle?"); string lenght = Console.ReadLine(); Intervall actInterval; couldParsed = Intervall.TryParse(lenght, out actInterval); if (couldParsed) { while (intervalle.Count() < gene) { intervalle.Add(actInterval); } } } } //Intervall actIntervall; //couldParsed = Intervall.TryParse("3", out actIntervall); //intervall.Add(actIntervall); //couldParsed = Intervall.TryParse("3", out actIntervall); //intervall.Add(actIntervall); //couldParsed = Intervall.TryParse("3", out actIntervall); //intervall.Add(actIntervall); // ### hier funktioniert noch die Ausgabe nicht richtig ### // !!! liegt daran, dass interval ein Object ist und c# keine automatische object ausgabe hat // !!! lösung wäre entweder die toString Methode im Object zu deklarieren oder per hand den Start und das ende auszugeben // !!! HINWEIS: die Methode TryParse in der Intervall Klasse versucht aus einem String wie: "[-1,1]" oder "-1,1" ein Intervall auszulesen //couldParsed = Intervall.TryParse("3,5", out actIntervall); //intervall.Add(actIntervall); Console.WriteLine("Intervalle = {0}", String.Join(",", intervalle.Select(o => o.ToString()).ToArray())); } couldParsed = false; while (!couldParsed) { Console.WriteLine("Größe der History?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out historySize); } couldParsed = false; /* * ### Wie definiert sich die Größe? Sind es Mengen von Tierchen oder Mengen von Generationen? ### * !!! Größe der History bestimmt, wie viel besten Tierchen gesoeichert werden sollen, damit die History nicht unnötig voll läuft * !!! Beispiel: Größe der History auf 10 gesetzt bewirkt, dass die History ( nach Wertigkeit sortiert ) die besten 10 Tierchen enthält */ //historySize = 2; while (!couldParsed) { Console.WriteLine("Generationen die erzeugt werden sollen?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out countOfGenerations); } // es wurde keine Anfangs-Generation übergeben if (!loadDocument) { Elterngeneration = new List <Tierchen>(); // erzeuge Elterngeneration while (Elterngeneration.Count < elternSize) { Elterngeneration.Add(Tierchen.RandomTier(binärStringLenght, intervalle, gene, problem)); /* * ### Wie kommt das mit dem Distinct zustande ? ### * ### Ist ToList() eine Methode einer über TierchenComparer liegenden Klasse ? ### * ### Welche voraussetzungen müssen erfüllt sein ? ### * !!! Hatten wir ja geklärt, oder? */ Elterngeneration = Elterngeneration.Distinct(new TierchenComparer()).ToList(); } try { // Elterngeneration im Programm Verzeichnis unter dem Namen "last.xml" speichern // xml-Dokument erzeugen XDocument doc = new XDocument( // erzeuge des Wurzelelement "generation" new XElement("generation", // für jedes tier in der Generation Elterngeneration.Select(tier => // erzeuge "tier"-Element new XElement("tier", // erzeuge Problem-Attribute new XAttribute("problemType", (int)(tier.Problem.ProblemType) ), // für jedes gen im tierchen tier.GenCode.Select(gen => // erzeuge "gen"-Element new XElement("gen", // füge "interval_start"-Attribut hinzu new XAttribute("interval_start", gen.Interval.start ), // füge "interval_end"-Attribut hinzu new XAttribute("interval_end", gen.Interval.end ), // für jedes allel (Bit) im Gen gen.BinärCode.Select(allel => // speichere bool'schen Wert new XElement("allel", allel.ToString() ) ) ) ) ) ) ) ); // dokument speichern doc.Save("last.xml"); } catch (Exception) { } } foreach (var tier in Elterngeneration) { Console.WriteLine("Tier: {0} | Wert:\t{1}", tier.ToString(), tier.Wert.ToString("####0.#####")); } /* * Ab hier beginnen die Methoden * Zunächst wird Selektiert */ Random randomizer = new Random(); int counter = 0; while (repeat) { repeat = false; // Sichere die aktuelle Elterngeneration in die History TierchenHistory.AddRange(Elterngeneration); //Eliminiere die Doppelten TierchenHistory = TierchenHistory.Distinct(new TierchenComparer()).OrderBy(tier => tier.Wert).Take(historySize).ToList(); Kindgeneration = new List <Tierchen>(); //Rufe Ein-Punkt-Rekombination auf Kindgeneration = EvolutionAlgorithms.NPunktRekombination(randomizer, countOfRecombinations, pointOfRecombination, Kindgeneration, Elterngeneration); Kindgeneration = EvolutionAlgorithms.mutiereKinder(randomizer, Kindgeneration, Elterngeneration, elternSize); /* * Der folgende Bereich sollte nicht direkt beschritten werden * Die Methoden sollten aufrufbar / wählbar sein */ // ### [NEW] ist ein wenig Kritisch, da diese Frage vor jedem Erteugen einer neuen Generation gestellt wird // ### das heißt wenn man auf einen Schlag 100 Generationen erzeugen will wird diese Schleife immer durch diese Frage unterbrochen // ### Frage Stellen, bevor ein neuen Durchlauf beginnt (siehe Frage nach Wiederholung) repeat2 = true; while (repeat2) { /* * Console.WriteLine("Welche Selektion soll ausgeführt werden?\r\n[n]: keine (Kinder als Elten übernehmen)\r\n[k]: Komma\r\n[p]: Plus\r\n[...]"); * var input = Console.ReadLine(); * if (input == "n") * {*/ repeat2 = false; //Lösche alle Eltern Elterngeneration.Clear(); //Kindgeneration ist neue Elterngeneration Elterngeneration.AddRange(Kindgeneration); //Jetzt kann die Kindgeneration gelöscht werden Kindgeneration.Clear(); /* * } * else if (input == "k") * { * repeat2 = false; * EvolutionAlgorithms.commaSelection(Kindgeneration, Wahlverfahren.determenistic); * //KommaSelektion(randomizer); * } * else if (input == "p") * { * repeat2 = false; * EvolutionAlgorithms.plusSelection(Elterngeneration,Kindgeneration, Wahlverfahren.determenistic); * //KommaSelektion(randomizer); * }*/ } //foreach (var tier in Elterngeneration) //{ // Console.WriteLine("Tier: {0} | Wert:\t{1}", tier.ToString(), tier.Wert.ToString("####0.#####")); //} if (counter != 0 && (countOfGenerations / counter) % 10 == 0) { Console.WriteLine("{0}% Verbleibend", countOfGenerations / counter); } counter++; if (counter >= countOfGenerations) { // letzte Sicherung der Elterngeneration in die History TierchenHistory.AddRange(Elterngeneration); //Eliminiere die Doppelten TierchenHistory = TierchenHistory.Distinct(new TierchenComparer()).OrderBy(tier => tier.Wert).Take(historySize).ToList(); counter = 0; Console.WriteLine("Soll das Beste aller erzeugten Individuen gezeigt werden? (y/n)"); var input = Console.ReadLine(); if (input == "y") { int countOfShownTierchen = 0; couldParsed = false; while (!couldParsed) { Console.WriteLine("Wie viele sollen gezeigt werden?"); string lenght = Console.ReadLine(); couldParsed = Int32.TryParse(lenght, out countOfShownTierchen); } foreach (var tier in TierchenHistory.OrderBy(tier => tier.Wert).Take(countOfShownTierchen).ToList()) { Console.WriteLine("Tier: {0}", tier.ToNicerString()); } } Console.WriteLine("Wiederholen? (y/n)"); input = Console.ReadLine(); if (input == "y") { repeat = true; } else { repeat = false; Console.WriteLine("Neustarten? (y/n)"); input = Console.ReadLine(); if (input == "y") { restart = true; } else { restart = false; } } } else { repeat = true; } } } }
public static bool NPointRecombination(Random randomizer, Tierchen mutter, Tierchen vater, out Tierchen kind1, out Tierchen kind2, int recombinationPoints = 1) { /* N-Punkt-Rekombination wählt zwei Tierchen sowie zufällig je n Allele ihres Gens. * Kinder setzen sich aus einem Teil der Mutter/Vater sowie einem Teil des Vaters zusammen. * Übergeben den Kindern zunächst den vollständigen Gencode und Entferne anschließend * an einer zufälligen Stelle den übergebliebenen Code, füge anschließend einen anderen Code * (des Vaters/Mutter) in das gleiche Tierchen ein. */ kind1 = null; kind2 = null; if (mutter.GenCode.Count() == vater.GenCode.Count() && mutter.GenCode.Count() > 0 && mutter.CompleteGenCode.Count() == vater.CompleteGenCode.Count() && mutter.CompleteGenCode.Count() > 0) { if (recombinationPoints <= mutter.CompleteGenCode.Count()) { bool chooseFirstFromMother = true; // Gib eine Folge von eindeutigen (unsortierten?) Allelen des jew. Tierchens aus // mehrere Allele in einem Tierchen sind möglich - müssen aber extra berücksichtigt werden var AllelSizeMutter = mutter.GenCode.Select(allel => allel.Size).Distinct(); var AllelSizeVater = mutter.GenCode.Select(allel => allel.Size).Distinct(); if (AllelSizeMutter.Count() == 1 && AllelSizeVater.Count() == 1) { var genCodeKind1 = mutter.CompleteGenCode; var genCodeKind2 = vater.CompleteGenCode; // erstelle Split-indizes var SplitIndizes = new List <int>(); for (int i = 0; i < recombinationPoints; i++) { SplitIndizes.Add(randomizer.Next(i == 0?0:SplitIndizes.LastOrDefault() + 1, genCodeKind1.Count() + 1 - (recombinationPoints - i))); } int GenCodeSize = genCodeKind1.Count(); SplitIndizes.Sort(); // für jeden Splitindex gencode zusammensetzen foreach (var splitIndex in SplitIndizes) { if (chooseFirstFromMother) { genCodeKind1.RemoveRange(splitIndex, GenCodeSize - splitIndex); genCodeKind1.AddRange(vater.CompleteGenCode.GetRange(splitIndex, GenCodeSize - splitIndex)); genCodeKind2.RemoveRange(splitIndex, GenCodeSize - splitIndex); genCodeKind2.AddRange(mutter.CompleteGenCode.GetRange(splitIndex, GenCodeSize - splitIndex)); } else { genCodeKind1.RemoveRange(splitIndex, GenCodeSize - splitIndex); genCodeKind1.AddRange(mutter.CompleteGenCode.GetRange(splitIndex, GenCodeSize - splitIndex)); genCodeKind2.RemoveRange(splitIndex, GenCodeSize - splitIndex); genCodeKind2.AddRange(vater.CompleteGenCode.GetRange(splitIndex, GenCodeSize - splitIndex)); } chooseFirstFromMother = !chooseFirstFromMother; } kind1 = new Tierchen(mutter.Problem, mutter.GenCode); kind1.CompleteGenCode = genCodeKind1; kind2 = new Tierchen(vater.Problem, vater.GenCode); kind2.CompleteGenCode = genCodeKind2; } } } return(false); }