diff --git a/plugins/round_trip.hpp b/plugins/round_trip.hpp index 03840824a..0670af3d4 100644 --- a/plugins/round_trip.hpp +++ b/plugins/round_trip.hpp @@ -47,6 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../util/simple_logger.hpp" #include +#include #include #include @@ -55,6 +56,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include + +#include template class RoundTripPlugin final : public BasePlugin { @@ -102,10 +106,10 @@ template class RoundTripPlugin final : public BasePlugin std::vector> & components) { // Run TarjanSCC - auto number_of_locations = phantom_node_vector.size(); + 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()); - auto empty_vector = std::vector(); + std::vector empty_vector; auto scc = TarjanSCC>(wrapper, empty_restriction, empty_vector); scc.run(); @@ -118,7 +122,8 @@ template class RoundTripPlugin final : public BasePlugin } } - void SetLocPermutationOutput(const std::vector & loc_permutation, osrm::json::Object & json_result){ + template + void SetLocPermutationOutput(const std::vector & loc_permutation, osrm::json::Object & json_result){ osrm::json::Array json_loc_permutation; json_loc_permutation.values.insert(json_loc_permutation.values.end(), loc_permutation.begin(), loc_permutation.end()); json_result.values["loc_permutation"] = json_loc_permutation; @@ -140,6 +145,36 @@ template class RoundTripPlugin final : public BasePlugin descriptor->Run(min_route, json_result); } + void ComputeRoute(const PhantomNodeArray & phantom_node_vector, + const RouteParameters & route_parameters, + std::vector & trip, + InternalRouteResult & min_route) { + // given he final trip, compute total distance and return the route and location permutation + PhantomNodes viapoint; + for (auto it = trip.begin(); it != std::prev(trip.end()); ++it) { + auto from_node = *it; + auto to_node = *std::next(it); + viapoint = PhantomNodes{phantom_node_vector[from_node][0], phantom_node_vector[to_node][0]}; + min_route.segment_end_coordinates.emplace_back(viapoint); + } + // check dist between last and first location too + viapoint = PhantomNodes{phantom_node_vector[*std::prev(trip.end())][0], phantom_node_vector[trip.front()][0]}; + min_route.segment_end_coordinates.emplace_back(viapoint); + search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route); + } + + void ComputeRoute(const PhantomNodeArray & phantom_node_vector, + const RouteParameters & route_parameters, + std::vector> & trip, + std::vector & route) { + for (const auto & curr_trip : trip) { + InternalRouteResult curr_route; + ComputeRoute(phantom_node_vector, route_parameters, curr_trip, curr_route); + route.push_back(curr_route); + search_engine_ptr->shortest_path(route.back().segment_end_coordinates, route_parameters.uturns, route.back()); + } + } + int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) override final { @@ -158,67 +193,117 @@ template class RoundTripPlugin final : public BasePlugin return 400; } + + BOOST_ASSERT_MSG(result_table->size() > 0, "Distance Table is empty."); //check if locations are in different strongly connected components (SCC) - const auto maxint = std::numeric_limits::max(); - if (*std::max_element(result_table->begin(), result_table->end()) == maxint) { - //run TSP computation for every SCC + const auto maxint = std::numeric_limits::max(); + if (*std::max_element(std::begin(*result_table), std::end(*result_table)) == maxint) { + + //TODO DELETE + // JSON output related objects std::unique_ptr> descriptor; descriptor = osrm::make_unique>(facade); descriptor->SetConfig(route_parameters); - std::vector> components; TIMER_START(tsp); + // Compute all SCC + std::vector> components; SplitUnaccessibleLocations(phantom_node_vector, *result_table, components); - auto number_of_locations = phantom_node_vector.size(); - std::vector min_loc_permutation(number_of_locations, -1); + // std::vector> res_route (components.size()-1); + std::vector> res_route; + const constexpr std::size_t BF_MAX_FEASABLE = 14; - auto min_dist = 0; + + //run TSP computation for every SCC 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 - InternalRouteResult min_route; - if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < 14) { - osrm::tsp::BruteForceTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation); + if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < BF_MAX_FEASABLE) { + SimpleLogger().Write() << "Running SCC BF"; + osrm::tsp::BruteForceTSP(components[k], phantom_node_vector, *result_table, scc_route); + res_route.push_back(scc_route); } else if (route_parameters.tsp_algo == "NN") { - osrm::tsp::NearestNeighbourTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation); + SimpleLogger().Write() << "Running SCC NN"; + osrm::tsp::NearestNeighbourTSP(components[k], phantom_node_vector, *result_table, scc_route); + res_route.push_back(scc_route); } else if (route_parameters.tsp_algo == "FI") { - osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation); + SimpleLogger().Write() << "Running SCC FI"; + osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, scc_route); + res_route.push_back(scc_route); } else{ - osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation); + SimpleLogger().Write() << "Running SCC FI"; + osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, scc_route); + res_route.push_back(scc_route); } - search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route); - min_dist += min_route.shortest_path_length; - descriptor->Run(min_route, json_result); } } - + SimpleLogger().Write() << "DONE"; + std::vector route; + ComputeRoute(phantom_node_vector, route_parameters, res_route, route); TIMER_STOP(tsp); SetRuntimeOutput(TIMER_MSEC(tsp), json_result); - SetDistanceOutput(min_dist, json_result); - SetLocPermutationOutput(min_loc_permutation, json_result); + + // SimpleLogger().Write() << "Route is"; + // for (auto x : res_route) { + // for (auto y : x) + // std::cout << y << " "; + // } + // SimpleLogger().Write() << ""; + + auto dist = 0; + for (auto curr_route : route) { + dist += curr_route.shortest_path_length; + SetGeometry(route_parameters, curr_route, json_result); + } + SetDistanceOutput(dist, json_result); } else { //run TSP computation for all locations auto number_of_locations = phantom_node_vector.size(); - InternalRouteResult min_route; - std::vector min_loc_permutation(number_of_locations, -1); + std::vector res_route; + res_route.reserve(number_of_locations); // Compute the TSP with the given algorithm TIMER_START(tsp); - if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < 14) { - osrm::tsp::BruteForceTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation); + // 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"; + res_route = osrm::tsp::BruteForceTSP(phantom_node_vector, *result_table, res_route); } else if (route_parameters.tsp_algo == "NN") { - osrm::tsp::NearestNeighbourTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation); + SimpleLogger().Write() << "Running NN"; + osrm::tsp::NearestNeighbourTSP(phantom_node_vector, *result_table, res_route); } else if (route_parameters.tsp_algo == "FI") { - osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation); + SimpleLogger().Write() << "Running FI"; + osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, res_route); } else { - osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation); + SimpleLogger().Write() << "Running FI"; + osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, res_route); + // osrm::tsp::NearestNeighbourTSP(phantom_node_vector, *result_table, res_route); } - search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route); + // TODO asserts numer of result blablabla size + // TODO std::is_permutation + // TODO boost range + SimpleLogger().Write() << "DONE"; + + + InternalRouteResult min_route; + ComputeRoute(phantom_node_vector, route_parameters, res_route, min_route); TIMER_STOP(tsp); - BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size()); - SetLocPermutationOutput(min_loc_permutation, json_result); - SetDistanceOutput(min_route.shortest_path_length, json_result); + + // SimpleLogger().Write() << "Route is"; + // for (auto x : res_route) { + // std::cout << x << " "; + // } + // SimpleLogger().Write() << ""; + + //TODO TIMER im LOGGER SetRuntimeOutput(TIMER_MSEC(tsp), json_result); + SetLocPermutationOutput(res_route, json_result); + //TODO MEHR ASSERTIONS! :O + SetDistanceOutput(min_route.shortest_path_length, json_result); SetGeometry(route_parameters, min_route, json_result); + BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size()); } diff --git a/routing_algorithms/tsp_brute_force.hpp b/routing_algorithms/tsp_brute_force.hpp index eac32aa15..bb83aa888 100644 --- a/routing_algorithms/tsp_brute_force.hpp +++ b/routing_algorithms/tsp_brute_force.hpp @@ -52,87 +52,57 @@ namespace tsp { template -int ReturnDistance(const std::vector & dist_table, const std::vector & location_order, const int min_route_dist, const int number_of_locations, const int component_size) { - int i = 0; +int ReturnDistance(const std::vector & dist_table, + const std::vector & location_order, + const int min_route_dist, + const int number_of_locations) { int route_dist = 0; - - // compute length and stop if length is longer than route already found - while (i < component_size - 1 && route_dist < min_route_dist) { - //get distance from location i to location i+1 + int i = 0; + while (i < location_order.size() - 1 && route_dist < min_route_dist) { route_dist += *(dist_table.begin() + (location_order[i] * number_of_locations) + location_order[i+1]); ++i; } //get distance from last location to first location - route_dist += *(dist_table.begin() + (location_order[component_size-1] * number_of_locations) + location_order[0]); - - if (route_dist < min_route_dist) { - return route_dist; - } - else { - return -1; - } + route_dist += *(dist_table.begin() + (location_order[location_order.size()-1] * number_of_locations) + location_order[0]); + return route_dist; } -void BruteForceTSP(std::vector & location, +void BruteForceTSP(std::vector & component, const PhantomNodeArray & phantom_node_vector, const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { + std::vector & route) { - const int component_size = location.size(); - int min_route_dist = std::numeric_limits::max(); + const unsigned component_size = component.size(); + unsigned min_route_dist = std::numeric_limits::max(); - std::vector min_location; - - // check length of all possible permutation of the location ids + // check length of all possible permutation of the component ids do { - // int new_distance = ReturnDistance(dist_table, location, min_route_dist, number_of_location, component_size); - int new_distance = 4; - if (new_distance != -1) { + const auto new_distance = ReturnDistance(dist_table, component, min_route_dist, component_size); + if (new_distance < min_route_dist) { min_route_dist = new_distance; - min_location = location; + route = component; } - } while(std::next_permutation(location.begin(), location.end())); - - PhantomNodes viapoint; - for (int i = 0; i < component_size - 1; ++i) { - viapoint = PhantomNodes{phantom_node_vector[min_location[i]][0], phantom_node_vector[min_location[i + 1]][0]}; - min_route.segment_end_coordinates.emplace_back(viapoint); - min_loc_permutation[min_location[i]] = i; - } - min_loc_permutation[min_location[component_size - 1]] = component_size - 1; - viapoint = PhantomNodes{phantom_node_vector[min_location[component_size - 1]][0], phantom_node_vector[min_location[0]][0]}; - min_route.segment_end_coordinates.emplace_back(viapoint); + } while(std::next_permutation(component.begin(), component.end())); } void BruteForceTSP(const PhantomNodeArray & phantom_node_vector, const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { - + std::vector & route) { const auto number_of_locations = phantom_node_vector.size(); // 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); - int min_route_dist = std::numeric_limits::max(); - + unsigned min_route_dist = std::numeric_limits::max(); // check length of all possible permutation of the location ids do { - int new_distance = ReturnDistance(dist_table, location_ids, min_route_dist, number_of_locations, number_of_locations); - if (new_distance != -1) { + const auto new_distance = ReturnDistance(dist_table, location_ids, min_route_dist, number_of_locations); + + if (new_distance < min_route_dist) { min_route_dist = new_distance; - //TODO: this gets copied right? fix this - min_loc_permutation = location_ids; + route = location_ids; } } while(std::next_permutation(location_ids.begin(), location_ids.end())); - PhantomNodes viapoint; - for (int i = 0; i < number_of_locations - 1; ++i) { - viapoint = PhantomNodes{phantom_node_vector[min_loc_permutation[i]][0], phantom_node_vector[min_loc_permutation[i + 1]][0]}; - min_route.segment_end_coordinates.emplace_back(viapoint); - } - viapoint = PhantomNodes{phantom_node_vector[min_loc_permutation[number_of_locations - 1]][0], phantom_node_vector[min_loc_permutation[0]][0]}; - min_route.segment_end_coordinates.emplace_back(viapoint); } } diff --git a/routing_algorithms/tsp_farthest_insertion.hpp b/routing_algorithms/tsp_farthest_insertion.hpp index cb3353d9e..94755306f 100644 --- a/routing_algorithms/tsp_farthest_insertion.hpp +++ b/routing_algorithms/tsp_farthest_insertion.hpp @@ -49,66 +49,45 @@ namespace osrm namespace tsp { -void GetLongestRoundTrip(const int current_loc, - std::list & current_trip, +void GetShortestRoundTrip(const int current_loc, const std::vector & dist_table, const int number_of_locations, - int & longest_min_tour, - std::list::iterator & following_loc){ + std::vector & current_trip, + int & min_trip_distance, + 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) { - auto to_node = std::next(from_node); + const auto to_node = std::next(from_node); - 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); - auto trip_dist = dist_from + dist_to - *(dist_table.begin() + (*from_node * number_of_locations) + *to_node); + const auto dist_from = *(dist_table.begin() + (*from_node * number_of_locations) + current_loc); + const auto dist_to = *(dist_table.begin() + (current_loc * number_of_locations) + *to_node); + const auto trip_dist = dist_from + dist_to - *(dist_table.begin() + (*from_node * number_of_locations) + *to_node); - // from all possible insertions to the current trip, choose the longest of all minimal insertions - if (trip_dist < longest_min_tour) { - longest_min_tour = trip_dist; - following_loc = to_node; + // from all possible insertions to the current trip, choose the shortest of all insertions + if (trip_dist < min_trip_distance) { + min_trip_distance = trip_dist; + next_insert_point_candidate = to_node; } } - { // check insertion between last and first location too - auto from_node = std::prev(current_trip.end()); - auto to_node = current_trip.begin(); + // check insertion between last and first location too + auto from_node = std::prev(current_trip.end()); + auto to_node = current_trip.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); - auto trip_dist = dist_from + dist_to - *(dist_table.begin() + (*from_node * number_of_locations) + *to_node); - if (trip_dist < longest_min_tour) { - longest_min_tour = trip_dist; - following_loc = to_node; - } + 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); + auto trip_dist = dist_from + dist_to - *(dist_table.begin() + (*from_node * number_of_locations) + *to_node); + if (trip_dist < min_trip_distance) { + min_trip_distance = trip_dist; + next_insert_point_candidate = to_node; } } -void ComputeRouteAndPermutation(const PhantomNodeArray & phantom_node_vector, - std::list & current_trip, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { - // given he final trip, compute total distance and return the route and location permutation - PhantomNodes viapoint; - int perm = 0; - for (auto it = current_trip.begin(); it != std::prev(current_trip.end()); ++it) { - auto from_node = *it; - auto to_node = *std::next(it); - viapoint = PhantomNodes{phantom_node_vector[from_node][0], phantom_node_vector[to_node][0]}; - min_route.segment_end_coordinates.emplace_back(viapoint); - min_loc_permutation[from_node] = perm; - ++perm; - } - // check dist between last and first location too - viapoint = PhantomNodes{phantom_node_vector[*std::prev(current_trip.end())][0], phantom_node_vector[current_trip.front()][0]}; - min_route.segment_end_coordinates.emplace_back(viapoint); - min_loc_permutation[*std::prev(current_trip.end())] = perm; -} - +// 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, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { + std::vector & current_trip) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START FARTHEST INSERTION HERE // 1. start at a random round trip of 2 locations @@ -119,63 +98,65 @@ void FarthestInsertionTSP(const std::vector & locations, ////////////////////////////////////////////////////////////////////////////////////////////////// const int number_of_locations = phantom_node_vector.size(); const int size_of_component = locations.size(); - // list of the trip that will be found incrementally - std::list current_trip; // tracks which nodes have been already visited std::vector visited(number_of_locations, false); auto max_dist = 0; - auto index = -1; + auto max_from = -1; + auto max_to = -1; + + //TODO for (auto x : locations) { for (auto y : locations) { - if (*(dist_table.begin() + x * number_of_locations + y) > max_dist) { - max_dist = *(dist_table.begin() + x * number_of_locations + y); - index = x * number_of_locations + y; + auto xy_dist = *(dist_table.begin() + x * number_of_locations + y); + if (xy_dist > max_dist) { + max_dist = xy_dist; + max_from = x; + max_to = y; } } } - const int max_from = index / number_of_locations; - 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); - + // 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) { - auto shortest_max_tour = -1; - int next_node = -1; - std::list::iterator min_max_insert; + // SimpleLogger().Write() << j << "/" << size_of_component; + auto farthest_distance = 0; + auto next_node = -1; + 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]) { - // longest_min_tour is the distance of the longest of all insertions with the minimal distance - auto longest_min_tour = std::numeric_limits::max(); - // following_loc is the location that comes after the location that is to be inserted - std::list::iterator following_loc; - GetLongestRoundTrip(i, current_trip, dist_table, number_of_locations, longest_min_tour, following_loc); + auto min_trip_distance = std::numeric_limits::max(); + std::vector::iterator next_insert_point_candidate; + + GetShortestRoundTrip(i, dist_table, number_of_locations, current_trip, min_trip_distance, next_insert_point_candidate); // add the location to the current trip such that it results in the shortest total tour - if (longest_min_tour > shortest_max_tour) { - shortest_max_tour = longest_min_tour; + // SimpleLogger().Write() << "min_trip_distance " << min_trip_distance; + if (min_trip_distance >= farthest_distance) { + farthest_distance = min_trip_distance; next_node = i; - min_max_insert = following_loc; + next_insert_point = next_insert_point_candidate; } } } + // SimpleLogger().Write() << "next node " << next_node; // mark as visited and insert node visited[next_node] = true; - current_trip.insert(min_max_insert, next_node); + current_trip.insert(next_insert_point, next_node); } - ComputeRouteAndPermutation(phantom_node_vector, current_trip, min_route, min_loc_permutation); } void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { + std::vector & current_trip) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START FARTHEST INSERTION HERE // 1. start at a random round trip of 2 locations @@ -186,12 +167,9 @@ void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, ////////////////////////////////////////////////////////////////////////////////////////////////// const auto number_of_locations = phantom_node_vector.size(); - // list of the trip that will be found incrementally - std::list current_trip; // tracks which nodes have been already visited std::vector visited(number_of_locations, false); - // find the pair of location with the biggest distance and make the pair the initial start trip const auto index = std::distance(dist_table.begin(), std::max_element(dist_table.begin(), dist_table.end())); const int max_from = index / number_of_locations; @@ -203,34 +181,32 @@ void FarthestInsertionTSP(const PhantomNodeArray & phantom_node_vector, // add all other nodes missing (two nodes are already in the initial start trip) for (int j = 2; j < number_of_locations; ++j) { - auto shortest_max_tour = -1; - int next_node = -1; - std::list::iterator min_max_insert; + auto farthest_distance = 0; + auto next_node = -1; + //todo move out of loop and overwrite + 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]) { - // longest_min_tour is the distance of the longest of all insertions with the minimal distance - auto longest_min_tour = std::numeric_limits::max(); - // following_loc is the location that comes after the location that is to be inserted - std::list::iterator following_loc; + auto min_trip_distance = std::numeric_limits::max(); + std::vector::iterator next_insert_point_candidate; - GetLongestRoundTrip(i, current_trip, dist_table, number_of_locations, longest_min_tour, following_loc); + GetShortestRoundTrip(i, dist_table, number_of_locations, current_trip, min_trip_distance, next_insert_point_candidate); // add the location to the current trip such that it results in the shortest total tour - if (longest_min_tour > shortest_max_tour) { - shortest_max_tour = longest_min_tour; + if (min_trip_distance >= farthest_distance) { + farthest_distance = min_trip_distance; next_node = i; - min_max_insert = following_loc; + next_insert_point = next_insert_point_candidate; } } } + // mark as visited and insert node visited[next_node] = true; - current_trip.insert(min_max_insert, next_node); + current_trip.insert(next_insert_point, next_node); } - - ComputeRouteAndPermutation(phantom_node_vector, current_trip, min_route, min_loc_permutation); } diff --git a/routing_algorithms/tsp_nearest_neighbour.hpp b/routing_algorithms/tsp_nearest_neighbour.hpp index 6a5d05994..8c182f779 100644 --- a/routing_algorithms/tsp_nearest_neighbour.hpp +++ b/routing_algorithms/tsp_nearest_neighbour.hpp @@ -51,8 +51,7 @@ namespace tsp void NearestNeighbourTSP(const std::vector & locations, const PhantomNodeArray & phantom_node_vector, const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { + std::vector & route) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START GREEDY NEAREST NEIGHBOUR HERE // 1. grab a random location and mark as starting point @@ -65,25 +64,25 @@ void NearestNeighbourTSP(const std::vector & locations, ////////////////////////////////////////////////////////////////////////////////////////////////// const auto number_of_locations = phantom_node_vector.size(); - const int size_of_component = locations.size(); - min_route.shortest_path_length = std::numeric_limits::max(); + const int component_size = locations.size(); + int shortest_trip_distance = std::numeric_limits::max(); // ALWAYS START AT ANOTHER STARTING POINT for(auto start_node : locations) { int curr_node = start_node; - InternalRouteResult raw_route; - //TODO: Should we always use the same vector or does it not matter at all because of loop scope? - std::vector loc_permutation(number_of_locations, -1); - loc_permutation[start_node] = 0; + + std::vector curr_route; + curr_route.reserve(component_size); + curr_route.push_back(start_node); + // visited[i] indicates whether node i was already visited by the salesman std::vector visited(number_of_locations, false); visited[start_node] = true; - PhantomNodes viapoint; // 3. REPEAT FOR EVERY UNVISITED NODE int trip_dist = 0; - for(int via_point = 1; via_point < size_of_component; ++via_point) + for(int via_point = 1; via_point < component_size; ++via_point) { int min_dist = std::numeric_limits::max(); int min_id = -1; @@ -96,84 +95,23 @@ void NearestNeighbourTSP(const std::vector & locations, min_id = next; } } - loc_permutation[min_id] = via_point; visited[min_id] = true; - viapoint = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]}; - raw_route.segment_end_coordinates.emplace_back(viapoint); + curr_route.push_back(min_id); trip_dist += min_dist; curr_node = min_id; } - // 4. ROUTE BACK TO STARTING POINT - viapoint = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[start_node][0]}; - raw_route.segment_end_coordinates.emplace_back(viapoint); - // check round trip with this starting point is shorter than the shortest round trip found till now - if (trip_dist < min_route.shortest_path_length) { - min_route = raw_route; - min_route.shortest_path_length = trip_dist; - //TODO: this gets copied right? fix this - min_loc_permutation = loc_permutation; + if (trip_dist < shortest_trip_distance) { + shortest_trip_distance = trip_dist; + route = curr_route; } } - - // // ALWAYS START AT ANOTHER STARTING POINT - // for(auto start_node : locations) { - // SimpleLogger().Write() << "STARTING AT " << start_node; - // int curr_node = start_node; - // InternalRouteResult raw_route; - // //TODO: Should we always use the same vector or does it not matter at all because of loop scope? - // std::vector loc_permutation(number_of_locations, -1); - - // // visited[i] indicates whether node i was already visited by the salesman - // std::vector visited(number_of_locations, false); - // visited[start_node] = true; - // loc_permutation[start_node] = 0; - - // PhantomNodes viapoint; - // // 3. REPEAT FOR EVERY UNVISITED NODE - // int trip_dist = 0; - // for(int via_point = 1; via_point < size_of_component; ++via_point) - // { - // int min_dist = std::numeric_limits::max(); - // int min_id = -1; - - // // 2. FIND NEAREST NEIGHBOUR - // for (auto next : locations) { - // if(!visited[next] && - // *(dist_table.begin() + curr_node * number_of_locations + next) < min_dist) { - // min_dist = *(dist_table.begin() + curr_node * number_of_locations + next); - // min_id = next; - // } - // } - - // loc_permutation[min_id] = via_point; - // visited[min_id] = true; - // SimpleLogger().Write() << "MOVING TO " << min_id; - // viapoint = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]}; - // raw_route.segment_end_coordinates.emplace_back(viapoint); - // trip_dist += min_dist; - // curr_node = min_id; - // } - - // // 4. ROUTE BACK TO STARTING POINT - // viapoint = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[start_node][0]}; - // raw_route.segment_end_coordinates.emplace_back(viapoint); - - // // check round trip with this starting point is shorter than the shortest round trip found till now - // if (trip_dist < min_route.shortest_path_length) { - // min_route = raw_route; - // min_route.shortest_path_length = trip_dist; - // //TODO: this gets copied right? fix this - // min_loc_permutation = loc_permutation; - // } - // } } void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { + std::vector & route) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START GREEDY NEAREST NEIGHBOUR HERE // 1. grab a random location and mark as starting point @@ -186,21 +124,21 @@ void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, ////////////////////////////////////////////////////////////////////////////////////////////////// const auto number_of_locations = phantom_node_vector.size(); - min_route.shortest_path_length = std::numeric_limits::max(); + int shortest_trip_distance = std::numeric_limits::max(); // ALWAYS START AT ANOTHER STARTING POINT for(int start_node = 0; start_node < number_of_locations; ++start_node) { int curr_node = start_node; - InternalRouteResult raw_route; - //TODO: Should we always use the same vector or does it not matter at all because of loop scope? - std::vector loc_permutation(number_of_locations, -1); - loc_permutation[start_node] = 0; + + std::vector curr_route; + curr_route.reserve(number_of_locations); + curr_route.push_back(start_node); + // visited[i] indicates whether node i was already visited by the salesman std::vector visited(number_of_locations, false); visited[start_node] = true; - PhantomNodes viapoint; // 3. REPEAT FOR EVERY UNVISITED NODE int trip_dist = 0; for(int via_point = 1; via_point < number_of_locations; ++via_point) @@ -212,31 +150,23 @@ void NearestNeighbourTSP(const PhantomNodeArray & phantom_node_vector, auto row_begin_iterator = dist_table.begin() + (curr_node * number_of_locations); auto row_end_iterator = dist_table.begin() + ((curr_node + 1) * number_of_locations); for (auto it = row_begin_iterator; it != row_end_iterator; ++it) { - auto index = std::distance(row_begin_iterator, it); + const auto index = std::distance(row_begin_iterator, it); if (!visited[index] && *it < min_dist) { min_dist = *it; min_id = index; } } - loc_permutation[min_id] = via_point; visited[min_id] = true; - viapoint = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]}; - raw_route.segment_end_coordinates.emplace_back(viapoint); + curr_route.push_back(min_id); trip_dist += min_dist; curr_node = min_id; } - // 4. ROUTE BACK TO STARTING POINT - viapoint = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[start_node][0]}; - raw_route.segment_end_coordinates.emplace_back(viapoint); - // check round trip with this starting point is shorter than the shortest round trip found till now - if (trip_dist < min_route.shortest_path_length) { - min_route = raw_route; - min_route.shortest_path_length = trip_dist; - //TODO: this gets copied right? fix this - min_loc_permutation = loc_permutation; + if (trip_dist < shortest_trip_distance) { + shortest_trip_distance = trip_dist; + route = curr_route; } } } diff --git a/routing_algorithms/tsp_tabu_search.hpp b/routing_algorithms/tsp_tabu_search.hpp new file mode 100644 index 000000000..4db7dc470 --- /dev/null +++ b/routing_algorithms/tsp_tabu_search.hpp @@ -0,0 +1,73 @@ +/* + +Copyright (c) 2015, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TSP_BRUTE_FORCE_HPP +#define TSP_BRUTE_FORCE_HPP + + +#include "../data_structures/search_engine.hpp" +#include "../util/string_util.hpp" + +#include + +#include + +#include +#include +#include +#include +#include +#include "../util/simple_logger.hpp" + + + + +namespace osrm +{ +namespace tsp +{ + +void TabuSearchTSP(std::vector & location, + const PhantomNodeArray & phantom_node_vector, + const std::vector & dist_table, + InternalRouteResult & min_route, + std::vector & min_loc_permutation) { + + +} + +void TabuSearchTSP(const PhantomNodeArray & phantom_node_vector, + const std::vector & dist_table, + InternalRouteResult & min_route, + std::vector & min_loc_permutation) { + + +} + +} +} +#endif // TSP_BRUTE_FORCE_HPP \ No newline at end of file