From 7587e97d46f8f31e8de09a88f298be4baa571909 Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Wed, 19 Aug 2015 10:25:32 +0200 Subject: [PATCH] use typedefs from typedefs.h return roundtrip result as a return parameter and not as an input parameter --- plugins/round_trip.hpp | 39 ++++++------ routing_algorithms/tsp_brute_force.hpp | 41 +++++++----- routing_algorithms/tsp_farthest_insertion.hpp | 63 ++++++++++--------- routing_algorithms/tsp_nearest_neighbour.hpp | 33 +++++----- 4 files changed, 94 insertions(+), 82 deletions(-) diff --git a/plugins/round_trip.hpp b/plugins/round_trip.hpp index a1a955f9f..14f5b4bfa 100644 --- a/plugins/round_trip.hpp +++ b/plugins/round_trip.hpp @@ -103,12 +103,11 @@ template class RoundTripPlugin final : public BasePlugin } } - void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector, + void SplitUnaccessibleLocations(const std::size_t number_of_locations, std::vector & result_table, std::vector> & components) { // Run TarjanSCC - const auto number_of_locations = phantom_node_vector.size(); auto wrapper = std::make_shared>(result_table, number_of_locations); // auto empty_restriction = RestrictionMap(std::vector()); // std::vector empty_vector; @@ -212,7 +211,7 @@ template class RoundTripPlugin final : public BasePlugin TIMER_START(tsp); // Compute all SCC std::vector> components; - SplitUnaccessibleLocations(phantom_node_vector, *result_table, components); + SplitUnaccessibleLocations(number_of_locations, *result_table, components); // std::vector> res_route (components.size()-1); std::vector> res_route; @@ -221,24 +220,23 @@ template class RoundTripPlugin final : public BasePlugin for(auto k = 0; k < components.size(); ++k) { if (components[k].size() > 1) { std::vector scc_route; - scc_route.reserve(components[k].size()); // Compute the TSP with the given algorithm if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < BF_MAX_FEASABLE) { - SimpleLogger().Write() << "Running SCC BF"; - osrm::tsp::BruteForceTSP(components[k], number_of_locations, *result_table, scc_route); + SimpleLogger().Write() << "Running brute force on multiple SCC"; + scc_route = osrm::tsp::BruteForceTSP(components[k], number_of_locations, *result_table); res_route.push_back(scc_route); } else if (route_parameters.tsp_algo == "NN") { - SimpleLogger().Write() << "Running SCC NN"; - osrm::tsp::NearestNeighbourTSP(components[k], number_of_locations, *result_table, scc_route); + SimpleLogger().Write() << "Running nearest neighbour on multiple SCC"; + scc_route = osrm::tsp::NearestNeighbourTSP(components[k], number_of_locations, *result_table); res_route.push_back(scc_route); } else if (route_parameters.tsp_algo == "FI") { - SimpleLogger().Write() << "Running SCC FI"; - osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table, scc_route); + SimpleLogger().Write() << "Running farthest insertion on multiple SCC"; + scc_route = osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table); res_route.push_back(scc_route); } else{ - SimpleLogger().Write() << "Running SCC FI"; - osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table, scc_route); + SimpleLogger().Write() << "Running farthest insertion on multiple SCC"; + scc_route = osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table); res_route.push_back(scc_route); } } @@ -263,23 +261,22 @@ template class RoundTripPlugin final : public BasePlugin SetDistanceOutput(dist, json_result); } else { //run TSP computation for all locations std::vector res_route; - res_route.reserve(number_of_locations); // Compute the TSP with the given algorithm TIMER_START(tsp); // TODO patrick nach userfreundlichkeit fragen, BF vs bf usw if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < BF_MAX_FEASABLE) { - SimpleLogger().Write() << "Running BF"; - osrm::tsp::BruteForceTSP(number_of_locations, *result_table, res_route); + SimpleLogger().Write() << "Running brute force"; + res_route = osrm::tsp::BruteForceTSP(number_of_locations, *result_table); } else if (route_parameters.tsp_algo == "NN") { - SimpleLogger().Write() << "Running NN"; - osrm::tsp::NearestNeighbourTSP(number_of_locations, *result_table, res_route); + SimpleLogger().Write() << "Running nearest neighbour"; + res_route = osrm::tsp::NearestNeighbourTSP(number_of_locations, *result_table); } else if (route_parameters.tsp_algo == "FI") { - SimpleLogger().Write() << "Running FI"; - osrm::tsp::FarthestInsertionTSP(number_of_locations, *result_table, res_route); + SimpleLogger().Write() << "Running farthest insertion"; + res_route = osrm::tsp::FarthestInsertionTSP(number_of_locations, *result_table); } else { - SimpleLogger().Write() << "Running FI"; - osrm::tsp::FarthestInsertionTSP(number_of_locations, *result_table, res_route); + SimpleLogger().Write() << "Running farthest insertion"; + res_route = osrm::tsp::FarthestInsertionTSP(number_of_locations, *result_table); } // TODO asserts numer of result blablabla size // TODO std::is_permutation diff --git a/routing_algorithms/tsp_brute_force.hpp b/routing_algorithms/tsp_brute_force.hpp index bb83aa888..2665d68f2 100644 --- a/routing_algorithms/tsp_brute_force.hpp +++ b/routing_algorithms/tsp_brute_force.hpp @@ -54,11 +54,11 @@ namespace tsp template int ReturnDistance(const std::vector & dist_table, const std::vector & location_order, - const int min_route_dist, + const EdgeWeight min_route_dist, const int number_of_locations) { int route_dist = 0; int i = 0; - while (i < location_order.size() - 1 && route_dist < min_route_dist) { + while (i < location_order.size() - 1) { route_dist += *(dist_table.begin() + (location_order[i] * number_of_locations) + location_order[i+1]); ++i; } @@ -67,42 +67,49 @@ int ReturnDistance(const std::vector & dist_table, return route_dist; } -void BruteForceTSP(std::vector & component, - const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - std::vector & route) { +std::vector BruteForceTSP(std::vector & component, + const std::size_t number_of_locations, + const std::vector & dist_table) { - const unsigned component_size = component.size(); - unsigned min_route_dist = std::numeric_limits::max(); + std::vector route; + route.reserve(number_of_locations); + + + EdgeWeight min_route_dist = INVALID_EDGE_WEIGHT; // check length of all possible permutation of the component ids do { - const auto new_distance = ReturnDistance(dist_table, component, min_route_dist, component_size); - if (new_distance < min_route_dist) { + const auto new_distance = ReturnDistance(dist_table, component, min_route_dist, number_of_locations); + if (new_distance <= min_route_dist) { min_route_dist = new_distance; route = component; } } while(std::next_permutation(component.begin(), component.end())); + + return route; } -void BruteForceTSP(const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - std::vector & route) { - const auto number_of_locations = phantom_node_vector.size(); +std::vector BruteForceTSP(const std::size_t number_of_locations, + const std::vector & dist_table) { + std::vector route; + route.reserve(number_of_locations); + // fill a vector with node ids - std::vector location_ids(number_of_locations); + std::vector location_ids(number_of_locations); std::iota(location_ids.begin(), location_ids.end(), 0); - unsigned min_route_dist = std::numeric_limits::max(); + EdgeWeight min_route_dist = INVALID_EDGE_WEIGHT; // check length of all possible permutation of the location ids do { const auto new_distance = ReturnDistance(dist_table, location_ids, min_route_dist, number_of_locations); - if (new_distance < min_route_dist) { + if (new_distance <= min_route_dist) { min_route_dist = new_distance; route = location_ids; } } while(std::next_permutation(location_ids.begin(), location_ids.end())); + + return route; } } diff --git a/routing_algorithms/tsp_farthest_insertion.hpp b/routing_algorithms/tsp_farthest_insertion.hpp index 94755306f..5f53447e7 100644 --- a/routing_algorithms/tsp_farthest_insertion.hpp +++ b/routing_algorithms/tsp_farthest_insertion.hpp @@ -52,12 +52,12 @@ namespace tsp void GetShortestRoundTrip(const int current_loc, const std::vector & dist_table, const int number_of_locations, - std::vector & current_trip, + std::vector & route, int & min_trip_distance, - std::vector::iterator & next_insert_point_candidate){ + std::vector::iterator & next_insert_point_candidate){ // for all nodes in the current trip find the best insertion resulting in the shortest path - // assert min 2 nodes in current_trip - for (auto from_node = current_trip.begin(); from_node != std::prev(current_trip.end()); ++from_node) { + // assert min 2 nodes in route + for (auto from_node = route.begin(); from_node != std::prev(route.end()); ++from_node) { const auto to_node = std::next(from_node); const auto dist_from = *(dist_table.begin() + (*from_node * number_of_locations) + current_loc); @@ -71,8 +71,8 @@ void GetShortestRoundTrip(const int current_loc, } } // check insertion between last and first location too - auto from_node = std::prev(current_trip.end()); - auto to_node = current_trip.begin(); + auto from_node = std::prev(route.end()); + auto to_node = route.begin(); auto dist_from = *(dist_table.begin() + (*from_node * number_of_locations) + current_loc); auto dist_to = *(dist_table.begin() + (current_loc * number_of_locations) + *to_node); @@ -84,10 +84,9 @@ void GetShortestRoundTrip(const int current_loc, } // osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, scc_route); -void FarthestInsertionTSP(const std::vector & locations, - const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - std::vector & current_trip) { +std::vector FarthestInsertionTSP(const std::vector & locations, + const std::size_t number_of_locations, + const std::vector & dist_table) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START FARTHEST INSERTION HERE // 1. start at a random round trip of 2 locations @@ -96,7 +95,10 @@ void FarthestInsertionTSP(const std::vector & locations, // 4. repeat 2-3 until all locations are visited // 5. DONE! ////////////////////////////////////////////////////////////////////////////////////////////////// - const int number_of_locations = phantom_node_vector.size(); + + std::vector route; + route.reserve(number_of_locations); + const int size_of_component = locations.size(); // tracks which nodes have been already visited std::vector visited(number_of_locations, false); @@ -119,24 +121,24 @@ void FarthestInsertionTSP(const std::vector & locations, visited[max_from] = true; visited[max_to] = true; - current_trip.push_back(max_from); - current_trip.push_back(max_to); + route.push_back(max_from); + route.push_back(max_to); // SimpleLogger().Write() << size_of_component; // add all other nodes missing (two nodes are already in the initial start trip) for (int j = 2; j < size_of_component; ++j) { // SimpleLogger().Write() << j << "/" << size_of_component; auto farthest_distance = 0; auto next_node = -1; - std::vector::iterator next_insert_point; + std::vector::iterator next_insert_point; // find unvisited loc i that is the farthest away from all other visited locs for (auto i : locations) { // find the shortest distance from i to all visited nodes if (!visited[i]) { - auto min_trip_distance = std::numeric_limits::max(); - std::vector::iterator next_insert_point_candidate; + auto min_trip_distance = INVALID_EDGE_WEIGHT; + std::vector::iterator next_insert_point_candidate; - GetShortestRoundTrip(i, dist_table, number_of_locations, current_trip, min_trip_distance, next_insert_point_candidate); + GetShortestRoundTrip(i, dist_table, number_of_locations, route, min_trip_distance, next_insert_point_candidate); // add the location to the current trip such that it results in the shortest total tour // SimpleLogger().Write() << "min_trip_distance " << min_trip_distance; @@ -150,13 +152,13 @@ void FarthestInsertionTSP(const std::vector & locations, // SimpleLogger().Write() << "next node " << next_node; // mark as visited and insert node visited[next_node] = true; - current_trip.insert(next_insert_point, next_node); + route.insert(next_insert_point, next_node); } + return route; } -void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - std::vector & current_trip) { +std::vector FarthestInsertionTSP(const std::size_t number_of_locations, + const std::vector & dist_table) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START FARTHEST INSERTION HERE // 1. start at a random round trip of 2 locations @@ -166,7 +168,9 @@ void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, // 5. DONE! ////////////////////////////////////////////////////////////////////////////////////////////////// - const auto number_of_locations = phantom_node_vector.size(); + std::vector route; + route.reserve(number_of_locations); + // tracks which nodes have been already visited std::vector visited(number_of_locations, false); @@ -176,23 +180,23 @@ void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, const int max_to = index % number_of_locations; visited[max_from] = true; visited[max_to] = true; - current_trip.push_back(max_from); - current_trip.push_back(max_to); + route.push_back(max_from); + route.push_back(max_to); // add all other nodes missing (two nodes are already in the initial start trip) for (int j = 2; j < number_of_locations; ++j) { auto farthest_distance = 0; auto next_node = -1; //todo move out of loop and overwrite - std::vector::iterator next_insert_point; + std::vector::iterator next_insert_point; // find unvisited loc i that is the farthest away from all other visited locs for (int i = 0; i < number_of_locations; ++i) { if (!visited[i]) { - auto min_trip_distance = std::numeric_limits::max(); - std::vector::iterator next_insert_point_candidate; + auto min_trip_distance = INVALID_EDGE_WEIGHT; + std::vector::iterator next_insert_point_candidate; - GetShortestRoundTrip(i, dist_table, number_of_locations, current_trip, min_trip_distance, next_insert_point_candidate); + GetShortestRoundTrip(i, dist_table, number_of_locations, route, min_trip_distance, next_insert_point_candidate); // add the location to the current trip such that it results in the shortest total tour if (min_trip_distance >= farthest_distance) { @@ -205,8 +209,9 @@ void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, // mark as visited and insert node visited[next_node] = true; - current_trip.insert(next_insert_point, next_node); + route.insert(next_insert_point, next_node); } + return route; } diff --git a/routing_algorithms/tsp_nearest_neighbour.hpp b/routing_algorithms/tsp_nearest_neighbour.hpp index 8c182f779..e7820c506 100644 --- a/routing_algorithms/tsp_nearest_neighbour.hpp +++ b/routing_algorithms/tsp_nearest_neighbour.hpp @@ -48,10 +48,9 @@ namespace osrm namespace tsp { -void NearestNeighbourTSP(const std::vector & locations, - const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - std::vector & route) { +std::vector NearestNeighbourTSP(const std::vector & locations, + const std::size_t number_of_locations, + const std::vector & dist_table) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START GREEDY NEAREST NEIGHBOUR HERE // 1. grab a random location and mark as starting point @@ -62,17 +61,18 @@ void NearestNeighbourTSP(const std::vector & locations, // 6. repeat 1-5 with different starting points and choose iteration with shortest trip // 7. DONE! ////////////////////////////////////////////////////////////////////////////////////////////////// + std::vector route; + route.reserve(number_of_locations); - const auto number_of_locations = phantom_node_vector.size(); const int component_size = locations.size(); - int shortest_trip_distance = std::numeric_limits::max(); + int shortest_trip_distance = INVALID_EDGE_WEIGHT; // ALWAYS START AT ANOTHER STARTING POINT for(auto start_node : locations) { int curr_node = start_node; - std::vector curr_route; + std::vector curr_route; curr_route.reserve(component_size); curr_route.push_back(start_node); @@ -84,7 +84,7 @@ void NearestNeighbourTSP(const std::vector & locations, int trip_dist = 0; for(int via_point = 1; via_point < component_size; ++via_point) { - int min_dist = std::numeric_limits::max(); + int min_dist = INVALID_EDGE_WEIGHT; int min_id = -1; // 2. FIND NEAREST NEIGHBOUR @@ -107,11 +107,11 @@ void NearestNeighbourTSP(const std::vector & locations, route = curr_route; } } + return route; } -void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - std::vector & route) { +std::vector NearestNeighbourTSP(const std::size_t number_of_locations, + const std::vector & dist_table) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START GREEDY NEAREST NEIGHBOUR HERE // 1. grab a random location and mark as starting point @@ -123,15 +123,17 @@ void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, // 7. DONE! ////////////////////////////////////////////////////////////////////////////////////////////////// - const auto number_of_locations = phantom_node_vector.size(); - int shortest_trip_distance = std::numeric_limits::max(); + std::vector route; + route.reserve(number_of_locations); + + int shortest_trip_distance = INVALID_EDGE_WEIGHT; // ALWAYS START AT ANOTHER STARTING POINT for(int start_node = 0; start_node < number_of_locations; ++start_node) { int curr_node = start_node; - std::vector curr_route; + std::vector curr_route; curr_route.reserve(number_of_locations); curr_route.push_back(start_node); @@ -143,7 +145,7 @@ void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, int trip_dist = 0; for(int via_point = 1; via_point < number_of_locations; ++via_point) { - int min_dist = std::numeric_limits::max(); + int min_dist = INVALID_EDGE_WEIGHT; int min_id = -1; // 2. FIND NEAREST NEIGHBOUR @@ -169,6 +171,7 @@ void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, route = curr_route; } } + return route; } }