#ifndef TRIP_NEAREST_NEIGHBOUR_HPP #define TRIP_NEAREST_NEIGHBOUR_HPP #include "util/dist_table_wrapper.hpp" #include "util/log.hpp" #include "util/typedefs.hpp" #include "osrm/json_container.hpp" #include #include #include #include #include namespace osrm { namespace engine { namespace trip { template std::vector NearestNeighbourTrip(const NodeIDIterator &start, const NodeIDIterator &end, const std::size_t number_of_locations, const util::DistTableWrapper &dist_table) { ////////////////////////////////////////////////////////////////////////////////////////////////// // START GREEDY NEAREST NEIGHBOUR HERE // 1. grab a random location and mark as starting point // 2. find the nearest unvisited neighbour, set it as the current location and mark as visited // 3. repeat 2 until there is no unvisited location // 4. return route back to starting point // 5. compute route // 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 component_size = std::distance(start, end); auto shortest_trip_distance = INVALID_EDGE_WEIGHT; // ALWAYS START AT ANOTHER STARTING POINT for (auto start_node = start; start_node != end; ++start_node) { NodeID curr_node = *start_node; 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; // 3. REPEAT FOR EVERY UNVISITED NODE EdgeWeight trip_dist = 0; for (std::size_t via_point = 1; via_point < component_size; ++via_point) { EdgeWeight min_dist = INVALID_EDGE_WEIGHT; NodeID min_id = SPECIAL_NODEID; // 2. FIND NEAREST NEIGHBOUR for (auto next = start; next != end; ++next) { const auto curr_dist = dist_table(curr_node, *next); BOOST_ASSERT_MSG(curr_dist != INVALID_EDGE_WEIGHT, "invalid distance found"); if (!visited[*next] && curr_dist < min_dist) { min_dist = curr_dist; min_id = *next; } } BOOST_ASSERT_MSG(min_id != SPECIAL_NODEID, "no next node found"); visited[min_id] = true; curr_route.push_back(min_id); trip_dist += min_dist; curr_node = min_id; } // check round trip with this starting point is shorter than the shortest round trip found // till now if (trip_dist < shortest_trip_distance) { shortest_trip_distance = trip_dist; route = std::move(curr_route); } } return route; } } } } #endif // TRIP_NEAREST_NEIGHBOUR_HPP