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;
                }
            }
        }