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 void generateNewGenerations(BackgroundWorker bgworker, MutationType mutationType, int mutationRateStart, int mutationRateEnd, int historySize, int countOfGenerations, int countOfChilds, int pointOfRecombination, SelectionsStrategie selectionsStrategie, Wahlverfahren wahlverfahren) { bool repeat = true; /* * 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) { BesteFitness.Add(Elterngeneration.OrderBy(tier => tier.Wert).Select(tier => tier.Wert).FirstOrDefault()); DurchschnittsFitness.Add(Elterngeneration.Sum(tier => tier.Wert) / Elterngeneration.Count()); 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(); BesterDerHistoryFitness.Add(TierchenHistory.Select(tier => tier.Wert).FirstOrDefault()); Kindgeneration = new List <Tierchen>(); int countOfMutations = EvolutionAlgorithms.CalculateMutations(mutationType, mutationRateStart, mutationRateEnd, countOfChilds, countOfGenerations, counter); int countOfRecombinations = countOfChilds - countOfMutations; //Rufe Ein-Punkt-Rekombination auf Kindgeneration = EvolutionAlgorithms.NPunktRekombination(randomizer, countOfRecombinations, pointOfRecombination, Kindgeneration, Elterngeneration); Kindgeneration = EvolutionAlgorithms.mutiereKinder(randomizer, Kindgeneration, Elterngeneration, countOfChilds); /* * 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(); switch (selectionsStrategie) { case SelectionsStrategie.keine: //repeat2 = false; //Lösche alle Eltern Elterngeneration.Clear(); //Kindgeneration ist neue Elterngeneration Elterngeneration.AddRange(Kindgeneration); //Jetzt kann die Kindgeneration gelöscht werden Kindgeneration.Clear(); break; case SelectionsStrategie.comma: //repeat2 = false; var tmpList1 = EvolutionAlgorithms.commaSelection(randomizer, Kindgeneration, Wahlverfahren.determenistic); Elterngeneration.Clear(); //Kindgeneration ist neue Elterngeneration Elterngeneration.AddRange(tmpList1); //Jetzt kann die Kindgeneration gelöscht werden Kindgeneration.Clear(); //KommaSelektion(randomizer); break; case SelectionsStrategie.plus: //repeat2 = false; var tmpList2 = EvolutionAlgorithms.plusSelection(randomizer, Elterngeneration, Kindgeneration, Wahlverfahren.determenistic); //Lösche alle Eltern Elterngeneration.Clear(); //Kindgeneration ist neue Elterngeneration Elterngeneration.AddRange(tmpList2); //Jetzt kann die Kindgeneration gelöscht werden Kindgeneration.Clear(); //KommaSelektion(randomizer); break; } //} /* * foreach (var tier in Elterngeneration) * { * Console.WriteLine("Tier: {0} | Wert:\t{1}", tier.ToString(), tier.Wert.ToString("####0.#####")); * } */ counter++; bgworker.ReportProgress((counter * 100 / countOfGenerations), counter); if (counter >= countOfGenerations) { BesteFitness.Add(Elterngeneration.OrderBy(tier => tier.Wert).Select(tier => tier.Wert).FirstOrDefault()); DurchschnittsFitness.Add(Elterngeneration.Sum(tier => tier.Wert) / Elterngeneration.Count()); // 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; return; } else { repeat = true; } } }