private void OptimizeRoutes() { var itn = 0; var mask = (byte)rng.Next(); CreateGeneration(); while (true) { progress(itn + 1); // 1. Objective function calculation Generations.ForEach(element => { element.ObjectiveFunctionValue = CalculateObjectiveFunction(element.Elements); reporting.NextPopulation(element); }); // Report this reporting.NextIteration(); // 2. Check stop condition if (itn + 1 >= IterationCount) { goto finish; } // 3. Selection var selected = Generations .Select((element, index) => new { element, groupId = rng.Next(0, (int)Math.Floor(Generations.Count * 0.3d)) }) .GroupBy(x => x.groupId) .Select(x => x.Aggregate((i1, i2) => i1.element.ObjectiveFunctionValue > i2.element.ObjectiveFunctionValue ? i1 : i2)) .Select(x => x.element) .ToList(); // 4. Pairing var pairs = new List <Population[]>(); while (pairs.Count < Generations.Count / 2) { var idx1 = rng.Next(0, selected.Count); var idx2 = rng.Next(0, selected.Count); while (idx1 != idx2) { idx2 = rng.Next(0, selected.Count); } var first = selected[idx1]; var second = selected[idx2]; pairs.Add(new Population[] { first, second }); } // 5. Crossing var newGeneration = new List <Population>(); foreach (var pair in pairs) { var first = pair[0].Elements; var second = pair[1].Elements; var newFirst = new Population(); var newSecond = new Population(); for (int i = 0; i < first.Count(); i++) { var firstElement = first[i]; var secondElement = second[i]; var newFirstElement = new PopulationElement() { Plane = firstElement.Plane, }; var newSecondElement = new PopulationElement() { Plane = secondElement.Plane, }; byte cnt = 1; for (int j = 0; j < firstElement.Route.Count(); j++) { var newFirstRouteItem = (mask & cnt) > 1 ? firstElement.Route[j] : secondElement.Route[j]; var newSecondRouteItem = (mask & cnt) == 0 ? firstElement.Route[j] : secondElement.Route[j]; newFirstElement.Route.Add(newFirstRouteItem); newSecondElement.Route.Add(newSecondRouteItem); cnt <<= 1; } newFirst.Elements.Add(newFirstElement); newSecond.Elements.Add(newSecondElement); } newGeneration.Add(newFirst); newGeneration.Add(newSecond); } // 6. Mutation newGeneration.SelectMany(x => x.Elements).ForEach(x => { if (RngMutation()) { var swap1 = rng.Next(0, x.Route.Count()); var swap2 = swap1; while (swap1 == swap2) { swap2 = rng.Next(0, x.Route.Count()); } x.Route.Swap(swap1, swap2); } }); // 7. Replace population if (newGeneration.Count == 0) { newGeneration.AddRange(selected); } Generations = newGeneration; if (Generations.Count == 1) { goto finish; } else if (Generations.Count == 0) { throw new Exception("Generations count has reached 0"); } itn++; } finish: var final = Generations.OrderByDescending(x => x.ObjectiveFunctionValue).FirstOrDefault(); CalculateObjectiveFunction(final.Elements); reporting.FinalSolution(final); reporting.NextPopulation(final); }