Beispiel #1
0
        public static void FindExplorePath2Opt(ExploreCell start_cell, List <ExploreCell> explore_cells, CellsDistancer distances, ref List <Vec3> path)
        {
            path.Clear();

            if (start_cell == null)
            {
                return;
            }

            List <int> cells_id_in_start_cell_network = distances.GetConnectedTo(start_cell.GlobalId);

            List <ExploreCell> best_tour = explore_cells.FindAll(c => cells_id_in_start_cell_network.Contains(c.GlobalId));

            best_tour.RemoveAll(c => c.Explored || c.Neighbours.Count == 0);
            if (start_cell.Explored)
            {
                best_tour.Insert(0, start_cell);
            }

            if (best_tour.Count == 1)
            {
                path.Add(best_tour[0].Position);
                return;
            }

            float best_dist = GetTravelDistance(best_tour, distances);


            if (best_tour.Count < 90)
            {
                // based on http://en.wikipedia.org/wiki/2-opt

                while (true)
                {
                    bool better_found = false;

                    for (int i = 1; i < best_tour.Count - 1; ++i)
                    {
                        for (int k = i + 1; k < best_tour.Count; ++k)
                        {
                            float new_dist = Swap2OptDistance(best_tour, distances, i, k);

                            if (new_dist < best_dist)
                            {
                                Swap2Opt(ref best_tour, i, k);
                                best_dist = new_dist;

                                better_found = true;
                                break;
                            }
                        }

                        if (better_found)
                        {
                            break;
                        }
                    }

                    if (!better_found)
                    {
                        break;
                    }
                }
            }
            else // greedy
            {
                // based on http://on-demand.gputechconf.com/gtc/2014/presentations/S4534-high-speed-2-opt-tsp-solver.pdf

                while (true)
                {
                    float min_change = 0;

                    int min_i = -1;
                    int min_j = -1;

                    for (int i = 0; i < best_tour.Count - 2; ++i)
                    {
                        for (int j = i + 2; j < best_tour.Count - 1; ++j)
                        {
                            int city_a = best_tour[i].GlobalId;
                            int city_b = best_tour[i + 1].GlobalId;
                            int city_c = best_tour[j].GlobalId;
                            int city_d = best_tour[j + 1].GlobalId;

                            float change = (distances.GetDistance(city_a, city_c) + distances.GetDistance(city_b, city_d)) -
                                           (distances.GetDistance(city_a, city_b) + distances.GetDistance(city_c, city_d));

                            if (change < min_change)
                            {
                                min_change = change;
                                min_i      = i + 1;
                                min_j      = j;
                            }
                        }
                    }

                    if (min_change >= 0)
                    {
                        break;
                    }

                    // apply min_i/min_j move
                    ExploreCell t = best_tour[min_i];
                    best_tour[min_i] = best_tour[min_j];
                    best_tour[min_j] = t;
                }
            }

            //Navmesh.Log("[FindExplorePath 2-Opt] Final solution distance: " + GetTravelDistance(tour, distances));

            foreach (ExploreCell cell in best_tour)
            {
                path.Add(cell.Position);
            }

            if (start_cell.Explored)
            {
                path.RemoveAt(0);
            }
        }
Beispiel #2
0
        public static void FindExplorePath(ExploreCell start_cell, List <ExploreCell> explore_cells, CellsDistancer distances, ref List <Vec3> path)
        {
            //based on http://www.theprojectspot.com/tutorial-post/simulated-annealing-algorithm-for-beginners/6

            path.Clear();

            if (start_cell == null)
            {
                return;
            }

            List <int> cells_id_in_start_cell_network = distances.GetConnectedTo(start_cell.GlobalId);

            List <ExploreCell> best_solution = explore_cells.FindAll(c => cells_id_in_start_cell_network.Contains(c.Id));

            best_solution.RemoveAll(c => (c.Explored || c.Neighbours.Count == 0) && c.GlobalId != start_cell.GlobalId);
            best_solution.Remove(start_cell);
            best_solution.Insert(0, start_cell);

            if (best_solution.Count == 1)
            {
                path.Add(best_solution[0].Position);
                return;
            }

            float best_energy = GetTravelDistance(best_solution, distances);

            List <ExploreCell> current_solution = best_solution;
            float current_energy = best_energy;

            Random rng = new Random();

            double temp            = 10000;
            double alpha           = 0.999;
            double epsilon         = 0.0001;
            int    temp_iterations = 2;

            // Loop until system has cooled
            while (temp > epsilon)
            {
                for (int iter = 0; iter < temp_iterations; ++iter)
                {
                    // Create new neighbour tour
                    List <ExploreCell> new_solution = new List <ExploreCell>(current_solution);

                    // Get a random positions in the tour
                    int tour_pos_1 = rng.Next(1, new_solution.Count);
                    int tour_pos_2 = rng.Next(1, new_solution.Count);

                    // Swap them
                    ExploreCell t = new_solution[tour_pos_1];
                    new_solution[tour_pos_1] = new_solution[tour_pos_2];
                    new_solution[tour_pos_2] = t;

                    // Get energy of solutions
                    float new_energy = GetTravelDistance(new_solution, distances);

                    // Decide if we should accept the neighbour
                    if (AcceptanceProbability(current_energy, new_energy, temp) >= rng.NextDouble())
                    {
                        current_solution = new_solution;
                        current_energy   = new_energy;
                    }

                    // Keep track of the best solution found
                    if (current_energy < best_energy)
                    {
                        best_solution = current_solution;
                        best_energy   = current_energy;
                    }
                }

                // Cool system
                temp *= alpha;
            }

            //Navmesh.Log("[FindExplorePath] Final solution distance: " + best_energy);

            foreach (ExploreCell cell in best_solution)
            {
                path.Add(cell.Position);
            }

            if (start_cell.Explored)
            {
                path.RemoveAt(0);
            }
        }