// selects the best element of the small and the big population together and sets global.solution to it's solution
        // then removes the best element
        public PopulationElement SelectBestElement(Boolean delete)
        {
            Base global = Base.GetInstance();
            PopulationElement bestElement = new PopulationElement();
            if (global.populationLarge.Count > 0)
            {
                bestElement = global.populationLarge[0];
            }

            Boolean bestFoundInSmall = false;
            int positionBestFound = 0;

            if(global.Verschnittoptimierung.radioButton_selMuePlusLambda.Checked || global.populationLarge.Count == 0)
            {
                bestElement = global.populationSmall[0];
                bestFoundInSmall = true;
                positionBestFound = 0;

                for (int i = 0; i < global.populationSmall.Count; i++)
                {
                    if (global.populationSmall[i].fitnessValue < bestElement.fitnessValue)
                    {
                        bestElement = global.populationSmall[i];
                        bestFoundInSmall = true;
                        positionBestFound = i;
                    }
                }
            }

            for(int i = 0; i < global.populationLarge.Count; i++)
            {
                if(global.populationLarge[i].fitnessValue < bestElement.fitnessValue)
                {
                    bestElement = global.populationLarge[i];
                    bestFoundInSmall = false;
                    positionBestFound = i;
                }
            }
            if(delete && bestFoundInSmall)
            {
                global.populationSmall.RemoveAt(positionBestFound);
            }
            if(delete && !bestFoundInSmall)
            {
                global.populationLarge.RemoveAt(positionBestFound);
            }
            return (bestElement);
        }
        public void BombingAlgorithm()
        {
            Base global = Base.GetInstance();
            ClassificationNumbers classificationNumbers = new ClassificationNumbers(global);

            if(global.runningProcess.firstStep)
            {
                global.changeCounter = 0;
            }

            // preparations
            global.runningProcess.state = 1;
            Tools tools = new Tools();

            // display running process display
            global.Verschnittoptimierung.processRunning_gear.Visible = true;
            global.Verschnittoptimierung.processRunning_label.Visible = true;

            // change "true" to an abort requirement, for example "best solution better than 95%"
            // best solution = global.solution (is set after each step/evolutionary step)
            int rim = 20;
            try
            {
                rim = Convert.ToInt32(global.Verschnittoptimierung.evAlg_numberMaxIterations.Value);
            }
            catch(Exception ex)
            {
                rim = 20;
            }

            while (rim > 0 && global.changeCounter < 10)
            {
                // creating a basic population
                if (global.runningProcess.firstStep)
                {
                    global.changeCounter = 0;
                    global.evolutionStep = 0;

                    tools.CleanFitnessChart();

                    global.populationSmall = new List<PopulationElement>();
                    List<int> greediesForRand = new List<int>();
                    if (!global.tournamentPopulation)
                    {
                        greediesForRand = tools.CloneList(global.chosenGreedies);
                    }
                    else
                    {
                        greediesForRand = GetTournamentGreedies(global.mue);
                    }

                    // set tournament methods too
                    if(global.tournamentGreediesOnly)
                    {
                        global.tournamentGreedyMethods = new List<int>();
                        int number = (global.mue > global.multForLambda) ? global.multForLambda : global.multForLambda;
                        global.tournamentGreedyMethods = GetTournamentGreedies(number);
                    }

                    for(int i = 0; i < global.mue; i++)
                    {
                        PopulationElement element = new PopulationElement();

                        Solution solution = tools.CloneSolution(global.emptySolution);

                        // select random greedy from the selectedGreedies and set its identifier, i.e. "1" for greedy1, in global
                        int selectedGreedyPosition = global.random.Next(0, greediesForRand.Count);
                        int selectedGreedy = greediesForRand[selectedGreedyPosition];
                        greediesForRand.RemoveAt(selectedGreedyPosition);
                        global.selectedGreedy = selectedGreedy;

                        // execute the greedy
                        Fill fill = new Fill();
                        element.solution = fill.Greedy(true, solution);
                        element.fitnessValue = tools.CalculateFitness(element.solution);
                        global.populationSmall.Add(element);
                    }
                    EndStepBombingAlgorithm();
                    global.runningProcess.firstStep = false;

                    if (global.runningProcess.stepType == 0)
                    {
                        global.runningProcess.state = 0;
                        break;
                    }
                }

                // creating a new population (lambda)
                for(int i = 0; i < global.populationSmall.Count; i ++)
                {
                    // clone the population element's solution
                    Solution newSolutionBase = tools.CloneSolution(global.populationSmall[i].solution);

                    // create a ranking of the boards of this solution
                    List<int> rankedBoards = CreateBoardRanking(newSolutionBase);

                    // remove rects according to the mutation rate
                    float mutationRate = global.mutationRate;
                    while(mutationRate >= 1)
                    {
                        // remove all rects from the worst board and add to collectionBoard
                            // while worst board isn't empty
                        while(newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList.Count > 0)
                        {
                            Rect rectToRemove = newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList[0];
                            newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList.RemoveAt(0);
                            newSolutionBase.BoardList[newSolutionBase.BoardList.Count - 1].RectList.Add(rectToRemove);
                        }
                        // remove board which was emptied from the ranked boards (so that the new last element is the weakest board again)
                        rankedBoards.RemoveAt(rankedBoards.Count - 1);
                        mutationRate -= 1;
                    }
                    if(mutationRate > 0)
                    {
                        // calculate how many have to be removed
                        int nrRectsOnBoard = newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList.Count;
                        int numbersToRemove = Convert.ToInt32(Math.Floor(nrRectsOnBoard * mutationRate));
                        // remove the rects left to remove (starting from the last added rect)
                        while(numbersToRemove > 0)
                        {
                            Rect rectToRemove = newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList[
                            newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList.Count - 1];
                            newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList.RemoveAt(
                                newSolutionBase.BoardList[rankedBoards[rankedBoards.Count - 1]].RectList.Count - 1);
                            newSolutionBase.BoardList[newSolutionBase.BoardList.Count - 1].RectList.Add(rectToRemove);
                            numbersToRemove--;
                        }
                    }

                    // fill with a random greedy from the selectedGreedies list
                    // and add to large population

                    for (int j = 0; j < global.multForLambda; j++)
                    {
                        Solution newSolution = tools.CloneSolution(newSolutionBase);

                        List<int> greediesForRand = new List<int>();

                        if (!global.tournamentGreediesOnly)
                        {
                            greediesForRand = tools.CloneList(global.chosenGreedies);
                        }
                        else
                        {
                            greediesForRand = tools.CloneList(global.tournamentGreedyMethods);
                        }

                        // select random greedy from the selectedGreedies and set its identifier, i.e. "1" for greedy1, in global
                        int selectedGreedyPosition = global.random.Next(0, greediesForRand.Count);
                        int selectedGreedy = greediesForRand[selectedGreedyPosition];
                        greediesForRand.RemoveAt(selectedGreedyPosition);
                        global.selectedGreedy = selectedGreedy;

                        // execute the greedy
                        PopulationElement element = new PopulationElement();
                        Fill fill = new Fill();
                        element.solution = fill.Greedy(true, newSolution);
                        element.fitnessValue = tools.CalculateFitness(element.solution);
                        global.populationLarge.Add(element);
                    }
                }
                // old (small) population still existing, new (large) population (lambda) created
                // -> end step if singleStep
                EndStepBombingAlgorithm();

                if(global.runningProcess.stepType == 0)
                {
                    global.runningProcess.state = 0;
                    rim--;
                    break;
                }

                rim--;

            }
            if (global.changeCounter == 10 || rim == 0)
            {
                global.runningProcess.existing = false;
                global.mue = 0;
                global.lambda = 0;
            }
        }