Exemple #1
0
        private static float Swap2OptDistance(List <ExploreCell> tour, CellsDistancer distances, int i, int k)
        {
            float travel_distance = 0;

            for (int n = 0; n < i - 1; ++n)
            {
                travel_distance += distances.GetDistance(tour[n].GlobalId, tour[n + 1].GlobalId);
            }

            travel_distance += distances.GetDistance(tour[i - 1].GlobalId, tour[k].GlobalId);

            for (int n = k; n > i; --n)
            {
                travel_distance += distances.GetDistance(tour[n].GlobalId, tour[n - 1].GlobalId);
            }

            if (k + 1 < tour.Count)
            {
                travel_distance += distances.GetDistance(tour[i].GlobalId, tour[k + 1].GlobalId);

                for (int n = k + 1; n < tour.Count - 1; ++n)
                {
                    travel_distance += distances.GetDistance(tour[n].GlobalId, tour[n + 1].GlobalId);
                }
            }

            return(travel_distance);
        }
Exemple #2
0
        private static float GetTravelDistance(List <ExploreCell> tour, CellsDistancer distances)
        {
            float travel_distance = 0;

            if (tour.Count > 2)
            {
                for (int i = 0; i < tour.Count - 1; ++i)
                {
                    travel_distance += distances.GetDistance(tour[i].GlobalId, tour[i + 1].GlobalId);
                }
            }

            return(travel_distance);
        }
Exemple #3
0
        private static float Swap2OptDistance(List <ExploreCell> tour, CellsDistancer distances, int i, int k)
        {
            var tour_indices = tour.Select(x => x.GlobalId).ToList();

            tour_indices.Reverse(i, k - i + 1);

            float travel_distance = 0;

            if (tour_indices.Count > 2)
            {
                for (int n = 0; n < tour_indices.Count - 1; ++n)
                {
                    travel_distance += distances.GetDistance(tour_indices[n], tour_indices[n + 1]);
                }
            }

            return(travel_distance);
        }
Exemple #4
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);
            }
        }
Exemple #5
0
        public static void FindExplorePath2Opt(ExploreCell start_cell, List <ExploreCell> explore_cells, CellsDistancer distances, ref List <ExploreCell> path)
        {
            using (new Profiler($"2-Opt %t"))
            {
                path = path ?? new List <ExploreCell>();
                path.Clear();

                if (start_cell == null)
                {
                    return;
                }

                //List<int> cells_id_in_start_cell_network = distances.GetConnectedTo(start_cell.GlobalId);
                //List<ExploreCell> best_tour_old = explore_cells.FindAll(c => cells_id_in_start_cell_network.Contains(c.GlobalId));

                // reordering cell in breadth-first order seems to help with 2-opt backtracking
                var collect_cells_visitor = new CollectVisitor();
                Algorihms.VisitBreadth(start_cell, visitor: collect_cells_visitor);
                var best_tour = collect_cells_visitor.cells.Select(x => x as ExploreCell).Intersect(explore_cells).ToList();

                best_tour.RemoveAll(c => c.Explored || c.Neighbours.Count == 0);

                if (start_cell.Explored) // re-insert start cell if needed
                {
                    best_tour.Insert(0, start_cell);
                }

                if (best_tour.Count == 1)
                {
                    path.Add(best_tour[0]);
                    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;
                    }
                }

                Trace.WriteLine("[FindExplorePath 2-Opt] Final solution distance: " + GetTravelDistance(best_tour, distances));

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

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