public override async Task Solve()

in Source/Extensions/TSP Resources/GeneticTspAlgorithm.cs [61:337]


        public override async Task<TspResult> Solve(DistanceMatrix matrix, TspOptimizationType tspOptimization)
        {
            return await Task<TspResult>.Run<TspResult>(() =>
            {
                int population = matrix.Origins.Count;

                double[] weight = new double[population];

                var minTour = new int[population];

                int[,] chromosome = new int[population, population];

                double minWeight = double.MaxValue;

                for (int p = 0; p < population; p++)
                {
                    bool[] used = new bool[population];
                    int[] currentOrder = new int[population];

                    for (int n = 0; n < population; n++)
                    {
                        used[n] = false;
                    }

                    for (int n = 0; n < population; n++)
                    {
                        int i;

                        do
                        {
                            i = random.Next(population);
                        }
                        while (used[i]);

                        used[i] = true;
                        currentOrder[n] = i;
                    }

                    for (int n = 0; n < population; n++)
                    {
                        chromosome[p, n] = currentOrder[n];
                    }

                    if (tspOptimization == TspOptimizationType.TravelTime)
                    {
                        weight[p] = matrix.GetEdgeTime(currentOrder, true);
                    }
                    else
                    {
                        weight[p] = matrix.GetEdgeDistance(currentOrder, true);
                    }

                    if (weight[p] < minWeight)
                    {
                        minWeight = weight[p];

                        for (int n = 0; n < population; n++)
                        {
                            minTour[n] = chromosome[p, n];
                        }
                    }
                }

                for (int g = 0; g < Generations; g++)
                {
                    if (random.NextDouble() < MutationRate)
                    {
                        int i, j, parent1, parent2;
                        int[] p1 = new int[population];
                        int[] p2 = new int[population];
                        int[] o1 = new int[population];
                        int[] o2 = new int[population];

                        i = random.Next(population);
                        j = random.Next(population);

                        if (weight[i] < weight[j])
                        {
                            parent1 = i;
                        }
                        else
                        {
                            parent1 = j;
                        }

                        i = random.Next(population);
                        j = random.Next(population);

                        if (weight[i] < weight[j])
                        {
                            parent2 = i;
                        }
                        else
                        {
                            parent2 = j;
                        }

                        for (i = 0; i < population; i++)
                        {
                            p1[i] = chromosome[parent1, i];
                            p2[i] = chromosome[parent2, i];
                        }

                        int cp1 = -1, cp2 = -1;

                        do
                        {
                            cp1 = random.Next(population);
                            cp2 = random.Next(population);
                        } while (cp1 == cp2 || cp1 > cp2);

                        Crossover(cp1, cp2, p1, p2, o1, o2, population, random);

                        double o1Fitness; 

                        if (tspOptimization == TspOptimizationType.TravelTime)
                        {
                            o1Fitness = matrix.GetEdgeTime(o1, true);
                        }
                        else
                        {
                            o1Fitness = matrix.GetEdgeDistance(o1, true);
                        }

                        if (o1Fitness < weight[parent1])
                        {
                            for (i = 0; i < population; i++)
                            {
                                chromosome[parent1, i] = o1[i];
                            }
                        }

                        double o2Fitness;

                        if (tspOptimization == TspOptimizationType.TravelTime)
                        {
                            o2Fitness = matrix.GetEdgeTime(o2, true);
                        }
                        else
                        {
                            o2Fitness = matrix.GetEdgeDistance(o2, true);
                        }

                        if (o2Fitness < weight[parent2])
                        {
                            for (i = 0; i < population; i++)
                            {
                                chromosome[parent2, i] = o2[i];
                            }
                        }

                        for (int p = 0; p < population; p++)
                        {
                            if (weight[p] < minWeight)
                            {
                                minWeight = weight[p];

                                for (int n = 0; n < population; n++)
                                {
                                    minTour[n] = chromosome[p, n];
                                }
                            }
                        }
                    }
                    else
                    {
                        int i, j, p;
                        int[] child = new int[population];

                        i = random.Next(population);
                        j = random.Next(population);

                        if (weight[i] < weight[j])
                        {
                            p = i;
                        }
                        else
                        {
                            p = j;
                        }

                        double childWeight;

                        for (int n = 0; n < population; n++)
                        {
                            child[n] = chromosome[p, n];
                        }

                        do
                        {
                            i = random.Next(population);
                            j = random.Next(population);
                        }
                        while (i == j);

                        int t = child[i];

                        child[i] = child[j];
                        child[j] = t;
                        
                        if (tspOptimization == TspOptimizationType.TravelTime)
                        {
                            childWeight = matrix.GetEdgeTime(child, true);
                        }
                        else
                        {
                            childWeight = matrix.GetEdgeDistance(child, true);
                        }
                        
                        int maxIndex = int.MaxValue;
                        double maxD = double.MinValue;

                        for (int q = 0; q < population; q++)
                        {
                            if (weight[q] >= maxD)
                            {
                                maxIndex = q;
                                maxD = weight[q];
                            }
                        }

                        int[] index = new int[population];
                        int count = 0;

                        for (int q = 0; q < population; q++)
                        {
                            if (weight[q] == maxD)
                            {
                                index[count++] = q;
                            }
                        }

                        maxIndex = index[random.Next(count)];

                        if (childWeight < weight[maxIndex])
                        {
                            weight[maxIndex] = childWeight;

                            for (int n = 0; n < population; n++)
                            {
                                chromosome[maxIndex, n] = child[n];
                            }

                            if (childWeight < minWeight)
                            {
                                minWeight = childWeight;

                                for (int n = 0; n < population; n++)
                                {
                                    minTour[n] = child[n];
                                }
                            }
                        }
                    }
                }

                //Ensure first point is the starting point. Indicies form a cycle, so just need to shift.
                if (minTour[0] != 0)
                {
                    var minTourList = minTour.ToList();
                    var startIdx = minTourList.IndexOf(0);

                    var order = new List<int>();
                    order.AddRange(minTourList.GetRange(startIdx, minTourList.Count - startIdx));
                    order.AddRange(minTourList.GetRange(0, startIdx));

                    minTour = order.ToArray();
                }

                return new TspResult()
                {
                    DistanceMatrix = matrix,
                    OptimizedWeight = minWeight,
                    OptimizedWaypoints = GetOptimizedWaypoints(matrix.Origins, minTour)
                };
            }).ConfigureAwait(false);
        }