From 74e00cf652afc69b9fd5f40c3ff64a7353550714 Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Fri, 28 Aug 2015 20:18:15 +0200 Subject: [PATCH] fix some small issues: remove empty unit test remove compiler directives move trip related files from routing_algorithms to algorithms run clang-format on files fix all std::size_t related issues improve code by adding std::move()s clean up includes fixing several code stye and improvement issues add several small code improvements return single scc in SplitUnaccessibleLocations() when theres only one change ComputeRoute() to return an InternalRouteResult by value improve some code style issues --- algorithms/tarjan_scc.hpp | 13 +- .../trip_brute_force.hpp | 58 ++-- .../trip_farthest_insertion.hpp | 117 ++++---- .../trip_nearest_neighbour.hpp | 36 +-- .../trip_tabu_search.hpp | 35 +-- data_structures/matrix_graph_wrapper.hpp | 39 +-- data_structures/route_parameters.cpp | 1 - library/osrm_impl.hpp | 4 - plugins/trip.hpp | 271 ++++++++++-------- unit_tests/routing_algorithms/tsp.cpp | 45 --- util/dist_table_wrapper.hpp | 54 ++-- 11 files changed, 319 insertions(+), 354 deletions(-) rename {routing_algorithms => algorithms}/trip_brute_force.hpp (70%) rename {routing_algorithms => algorithms}/trip_farthest_insertion.hpp (70%) rename {routing_algorithms => algorithms}/trip_nearest_neighbour.hpp (84%) rename {routing_algorithms => algorithms}/trip_tabu_search.hpp (73%) delete mode 100644 unit_tests/routing_algorithms/tsp.cpp diff --git a/algorithms/tarjan_scc.hpp b/algorithms/tarjan_scc.hpp index 6f5bc1563..f3fab7fd5 100644 --- a/algorithms/tarjan_scc.hpp +++ b/algorithms/tarjan_scc.hpp @@ -40,19 +40,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../util/timing_util.hpp" #include - #include - -#include - #include #include #include -#include -#include #include -#include template class TarjanSCC { @@ -153,7 +146,8 @@ template class TarjanSCC else { processing_node_before_recursion[v] = true; - tarjan_node_list[u].low_link = std::min(tarjan_node_list[u].low_link, tarjan_node_list[v].low_link); + tarjan_node_list[u].low_link = + std::min(tarjan_node_list[u].low_link, tarjan_node_list[v].low_link); // after recursion, lets do cycle checking // Check if we found a cycle. This is the bottom part of the recursion if (tarjan_node_list[v].low_link == tarjan_node_list[v].index) @@ -193,7 +187,6 @@ template class TarjanSCC }); } - std::size_t get_number_of_components() const { return component_size_vector.size(); } std::size_t get_size_one_count() const { return size_one_counter; } @@ -204,8 +197,6 @@ template class TarjanSCC } unsigned get_component_id(const NodeID node) const { return components_index[node]; } - - }; #endif /* TARJAN_SCC_HPP */ diff --git a/routing_algorithms/trip_brute_force.hpp b/algorithms/trip_brute_force.hpp similarity index 70% rename from routing_algorithms/trip_brute_force.hpp rename to algorithms/trip_brute_force.hpp index 0bd1c725c..5c8eb03fa 100644 --- a/routing_algorithms/trip_brute_force.hpp +++ b/algorithms/trip_brute_force.hpp @@ -25,27 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Trip_BRUTE_FORCE_HPP -#define Trip_BRUTE_FORCE_HPP - +#ifndef TRIP_BRUTE_FORCE_HPP +#define TRIP_BRUTE_FORCE_HPP #include "../data_structures/search_engine.hpp" -#include "../util/string_util.hpp" #include "../util/dist_table_wrapper.hpp" +#include "../util/simple_logger.hpp" #include #include - #include #include +#include #include #include -#include -#include "../util/simple_logger.hpp" - - - namespace osrm { @@ -53,28 +47,31 @@ namespace trip { // computes the distance of a given permutation -EdgeWeight ReturnDistance(const DistTableWrapper & dist_table, - const std::vector & location_order, - const EdgeWeight & min_route_dist, - const std::size_t & component_size) { +EdgeWeight ReturnDistance(const DistTableWrapper &dist_table, + const std::vector &location_order, + const EdgeWeight min_route_dist, + const std::size_t component_size) +{ EdgeWeight route_dist = 0; std::size_t i = 0; - while (i < location_order.size() && (route_dist < min_route_dist)) { - route_dist += dist_table(location_order[i], location_order[(i+1) % component_size]); + while (i < location_order.size() && (route_dist < min_route_dist)) + { + route_dist += dist_table(location_order[i], location_order[(i + 1) % component_size]); + BOOST_ASSERT_MSG(dist_table(location_order[i], location_order[(i + 1) % component_size]) + != INVALID_EDGE_WEIGHT, "invalid route found"); ++i; } - BOOST_ASSERT_MSG(route_dist != INVALID_EDGE_WEIGHT, "invalid route found"); - return route_dist; } // computes the route by computing all permutations and selecting the shortest template std::vector BruteForceTrip(const NodeIDIterator start, - const NodeIDIterator end, - const std::size_t number_of_locations, - const DistTableWrapper & dist_table) { + const NodeIDIterator end, + const std::size_t number_of_locations, + const DistTableWrapper &dist_table) +{ const auto component_size = std::distance(start, end); std::vector perm(start, end); @@ -85,20 +82,25 @@ std::vector BruteForceTrip(const NodeIDIterator start, // check length of all possible permutation of the component ids - BOOST_ASSERT_MSG(*(std::max_element(std::begin(perm), std::end(perm))) < number_of_locations, "invalid node id"); + BOOST_ASSERT_MSG(perm.size() > 0, + "no permutation given"); + BOOST_ASSERT_MSG(*(std::max_element(std::begin(perm), std::end(perm))) < number_of_locations, + "invalid node id"); BOOST_ASSERT_MSG(*(std::min_element(std::begin(perm), std::end(perm))) >= 0, "invalid node id"); - do { + do + { const auto new_distance = ReturnDistance(dist_table, perm, min_route_dist, component_size); - if (new_distance <= min_route_dist) { + if (new_distance <= min_route_dist) + { min_route_dist = new_distance; route = perm; } - } while(std::next_permutation(std::begin(perm), std::end(perm))); + } while (std::next_permutation(std::begin(perm), std::end(perm))); return route; } -} //end namespace trip -} //end namespace osrm -#endif // Trip_BRUTE_FORCE_HPP \ No newline at end of file +} // end namespace trip +} // end namespace osrm +#endif // TRIP_BRUTE_FORCE_HPP \ No newline at end of file diff --git a/routing_algorithms/trip_farthest_insertion.hpp b/algorithms/trip_farthest_insertion.hpp similarity index 70% rename from routing_algorithms/trip_farthest_insertion.hpp rename to algorithms/trip_farthest_insertion.hpp index 2368192fb..8f5c59ebb 100644 --- a/routing_algorithms/trip_farthest_insertion.hpp +++ b/algorithms/trip_farthest_insertion.hpp @@ -28,22 +28,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TRIP_FARTHEST_INSERTION_HPP #define TRIP_FARTHEST_INSERTION_HPP - #include "../data_structures/search_engine.hpp" -#include "../util/string_util.hpp" #include "../util/dist_table_wrapper.hpp" #include #include - #include #include #include #include -#include - namespace osrm { namespace trip @@ -51,55 +46,59 @@ namespace trip // given a route and a new location, find the best place of insertion and // check the distance of roundtrip when the new location is additionally visited -using NodeIDIter = typename std::vector::iterator; -std::pair GetShortestRoundTrip(const NodeID new_loc, - const DistTableWrapper & dist_table, - const std::size_t number_of_locations, - std::vector & route){ +using NodeIDIter = std::vector::iterator; +std::pair +GetShortestRoundTrip(const NodeID new_loc, + const DistTableWrapper &dist_table, + const std::size_t number_of_locations, + std::vector &route) +{ auto min_trip_distance = INVALID_EDGE_WEIGHT; NodeIDIter 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 route - for (auto from_node = std::begin(route); from_node != std::end(route); ++from_node) { + const auto start = std::begin(route); + const auto end = std::end(route); + for (auto from_node = start; from_node != end; ++from_node) + { auto to_node = std::next(from_node); - if (to_node == std::end(route)) { - to_node = std::begin(route); + if (to_node == end) + { + to_node = start; } const auto dist_from = dist_table(*from_node, new_loc); const auto dist_to = dist_table(new_loc, *to_node); - const auto trip_dist = dist_from + dist_to - dist_table(*from_node, *to_node);; + const auto trip_dist = dist_from + dist_to - dist_table(*from_node, *to_node); - BOOST_ASSERT_MSG(dist_from != INVALID_EDGE_WEIGHT, - "distance has invalid edge weight"); - BOOST_ASSERT_MSG(dist_to != INVALID_EDGE_WEIGHT, - "distance has invalid edge weight"); - BOOST_ASSERT_MSG(trip_dist >= 0, - "previous trip was not minimal. something's wrong"); + BOOST_ASSERT_MSG(dist_from != INVALID_EDGE_WEIGHT, "distance has invalid edge weight"); + BOOST_ASSERT_MSG(dist_to != INVALID_EDGE_WEIGHT, "distance has invalid edge weight"); + BOOST_ASSERT_MSG(trip_dist >= 0, "previous trip was not minimal. something's wrong"); // from all possible insertions to the current trip, choose the shortest of all insertions - if (trip_dist < min_trip_distance) { + if (trip_dist < min_trip_distance) + { min_trip_distance = trip_dist; next_insert_point_candidate = to_node; } } - BOOST_ASSERT_MSG(min_trip_distance != INVALID_EDGE_WEIGHT, - "trip has invalid edge weight"); + BOOST_ASSERT_MSG(min_trip_distance != INVALID_EDGE_WEIGHT, "trip has invalid edge weight"); return std::make_pair(min_trip_distance, next_insert_point_candidate); } template // given two initial start nodes, find a roundtrip route using the farthest insertion algorithm -std::vector FindRoute(const std::size_t & number_of_locations, - const std::size_t & component_size, - const NodeIDIterator & start, - const NodeIDIterator & end, - const DistTableWrapper & dist_table, - const NodeID & start1, - const NodeID & start2) { +std::vector FindRoute(const std::size_t &number_of_locations, + const std::size_t &component_size, + const NodeIDIterator &start, + const NodeIDIterator &end, + const DistTableWrapper &dist_table, + const NodeID &start1, + const NodeID &start2) +{ BOOST_ASSERT_MSG(number_of_locations >= component_size, "component size bigger than total number of locations"); @@ -115,23 +114,29 @@ std::vector FindRoute(const std::size_t & number_of_locations, route.push_back(start2); // add all other nodes missing (two nodes are already in the initial start trip) - for (std::size_t j = 2; j < component_size; ++j) { + for (std::size_t j = 2; j < component_size; ++j) + { auto farthest_distance = 0; auto next_node = -1; NodeIDIter next_insert_point; // find unvisited loc i that is the farthest away from all other visited locs - for (auto i = start; i != end; ++i) { + for (auto i = start; i != end; ++i) + { // find the shortest distance from i to all visited nodes - if (!visited[*i]) { - auto insert_candidate = GetShortestRoundTrip(*i, dist_table, number_of_locations, route); + if (!visited[*i]) + { + const auto insert_candidate = + GetShortestRoundTrip(*i, dist_table, number_of_locations, route); BOOST_ASSERT_MSG(insert_candidate.first != INVALID_EDGE_WEIGHT, - "shortest round trip is invalid"); + "shortest round trip is invalid"); - // add the location to the current trip such that it results in the shortest total tour - if (insert_candidate.first >= farthest_distance) { + // add the location to the current trip such that it results in the shortest total + // tour + if (insert_candidate.first >= farthest_distance) + { farthest_distance = insert_candidate.first; next_node = *i; next_insert_point = insert_candidate.second; @@ -149,14 +154,16 @@ std::vector FindRoute(const std::size_t & number_of_locations, } template -std::vector FarthestInsertionTrip(const NodeIDIterator & start, - const NodeIDIterator & end, +std::vector FarthestInsertionTrip(const NodeIDIterator &start, + const NodeIDIterator &end, const std::size_t number_of_locations, - const DistTableWrapper & dist_table) { + const DistTableWrapper &dist_table) +{ ////////////////////////////////////////////////////////////////////////////////////////////////// // START FARTHEST INSERTION HERE // 1. start at a random round trip of 2 locations - // 2. find the location that is the farthest away from the visited locations and whose insertion will make the round trip the longest + // 2. find the location that is the farthest away from the visited locations and whose insertion + // will make the round trip the longest // 3. add the found location to the current round trip such that round trip is the shortest // 4. repeat 2-3 until all locations are visited // 5. DONE! @@ -166,18 +173,25 @@ std::vector FarthestInsertionTrip(const NodeIDIterator & start, auto max_from = -1; auto max_to = -1; - if (component_size == number_of_locations) { - // find the pair of location with the biggest distance and make the pair the initial start trip - const auto index = std::distance(std::begin(dist_table), std::max_element(std::begin(dist_table), std::end(dist_table))); + if (component_size == number_of_locations) + { + // find the pair of location with the biggest distance and make the pair the initial start + // trip + const auto index = std::distance( + std::begin(dist_table), std::max_element(std::begin(dist_table), std::end(dist_table))); max_from = index / number_of_locations; max_to = index % number_of_locations; - - } else { + } + else + { auto max_dist = 0; - for (auto x = start; x != end; ++x) { - for (auto y = start; y != end; ++y) { + for (auto x = start; x != end; ++x) + { + for (auto y = start; y != end; ++y) + { const auto xy_dist = dist_table(*x, *y); - if (xy_dist > max_dist) { + if (xy_dist > max_dist) + { max_dist = xy_dist; max_from = *x; max_to = *y; @@ -190,8 +204,7 @@ std::vector FarthestInsertionTrip(const NodeIDIterator & start, return FindRoute(number_of_locations, component_size, start, end, dist_table, max_from, max_to); } - -} //end namespace trip -} //end namespace osrm +} // end namespace trip +} // end namespace osrm #endif // TRIP_FARTHEST_INSERTION_HPP \ No newline at end of file diff --git a/routing_algorithms/trip_nearest_neighbour.hpp b/algorithms/trip_nearest_neighbour.hpp similarity index 84% rename from routing_algorithms/trip_nearest_neighbour.hpp rename to algorithms/trip_nearest_neighbour.hpp index 510e87436..0ae179284 100644 --- a/routing_algorithms/trip_nearest_neighbour.hpp +++ b/algorithms/trip_nearest_neighbour.hpp @@ -28,9 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TRIP_NEAREST_NEIGHBOUR_HPP #define TRIP_NEAREST_NEIGHBOUR_HPP - #include "../data_structures/search_engine.hpp" -#include "../util/string_util.hpp" #include "../util/simple_logger.hpp" #include "../util/dist_table_wrapper.hpp" @@ -42,17 +40,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - - namespace osrm { namespace trip { template -std::vector NearestNeighbourTrip(const NodeIDIterator & start, - const NodeIDIterator & end, +std::vector NearestNeighbourTrip(const NodeIDIterator &start, + const NodeIDIterator &end, const std::size_t number_of_locations, - const DistTableWrapper & dist_table) { + const DistTableWrapper &dist_table) +{ ////////////////////////////////////////////////////////////////////////////////////////////////// // START GREEDY NEAREST NEIGHBOUR HERE // 1. grab a random location and mark as starting point @@ -70,7 +67,7 @@ std::vector NearestNeighbourTrip(const NodeIDIterator & start, auto shortest_trip_distance = INVALID_EDGE_WEIGHT; // ALWAYS START AT ANOTHER STARTING POINT - for(auto start_node = start; start_node != end; ++start_node) + for (auto start_node = start; start_node != end; ++start_node) { NodeID curr_node = *start_node; @@ -84,17 +81,18 @@ std::vector NearestNeighbourTrip(const NodeIDIterator & start, // 3. REPEAT FOR EVERY UNVISITED NODE EdgeWeight trip_dist = 0; - for(std::size_t via_point = 1; via_point < component_size; ++via_point) + 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) { - auto curr_dist = dist_table(curr_node, *next); + 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) { + if (!visited[*next] && curr_dist < min_dist) + { min_dist = curr_dist; min_id = *next; } @@ -108,15 +106,17 @@ std::vector NearestNeighbourTrip(const NodeIDIterator & start, 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) { + // 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 = curr_route; + route = std::move(curr_route); } } return route; } -} //end namespace trip -} //end namespace osrm +} // end namespace trip +} // end namespace osrm #endif // TRIP_NEAREST_NEIGHBOUR_HPP \ No newline at end of file diff --git a/routing_algorithms/trip_tabu_search.hpp b/algorithms/trip_tabu_search.hpp similarity index 73% rename from routing_algorithms/trip_tabu_search.hpp rename to algorithms/trip_tabu_search.hpp index 02e063a0e..32f50fc59 100644 --- a/routing_algorithms/trip_tabu_search.hpp +++ b/algorithms/trip_tabu_search.hpp @@ -28,46 +28,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TRIP_BRUTE_FORCE_HPP #define TRIP_BRUTE_FORCE_HPP - #include "../data_structures/search_engine.hpp" -#include "../util/string_util.hpp" +#include "../util/simple_logger.hpp" #include #include - #include #include #include #include -#include -#include "../util/simple_logger.hpp" - - - namespace osrm { namespace trip { -void TabuSearchTrip(std::vector & location, - const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { - - +// todo: yet to be implemented +void TabuSearchTrip(std::vector &location, + const PhantomNodeArray &phantom_node_vector, + const std::vector &dist_table, + InternalRouteResult &min_route, + std::vector &min_loc_permutation) +{ } -void TabuSearchTrip(const PhantomNodeArray & phantom_node_vector, - const std::vector & dist_table, - InternalRouteResult & min_route, - std::vector & min_loc_permutation) { - - +void TabuSearchTrip(const PhantomNodeArray &phantom_node_vector, + const std::vector &dist_table, + InternalRouteResult &min_route, + std::vector &min_loc_permutation) +{ } - } } #endif // TRIP_BRUTE_FORCE_HPP \ No newline at end of file diff --git a/data_structures/matrix_graph_wrapper.hpp b/data_structures/matrix_graph_wrapper.hpp index 95b0e4c86..f8b3e65bb 100644 --- a/data_structures/matrix_graph_wrapper.hpp +++ b/data_structures/matrix_graph_wrapper.hpp @@ -29,37 +29,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define MATRIX_GRAPH_WRAPPER_H #include +#include +#include -//This Wrapper provides all methods that are needed for TarjanSCC, when the graph is given in a -//matrix representation (e.g. as output from a distance table call) +#include "../typedefs.h" -template class MatrixGraphWrapper { -public: +// This Wrapper provides all methods that are needed for TarjanSCC, when the graph is given in a +// matrix representation (e.g. as output from a distance table call) - MatrixGraphWrapper(std::vector table, const std::size_t number_of_nodes) : table_(table), number_of_nodes_(number_of_nodes) {}; +template class MatrixGraphWrapper +{ + public: + MatrixGraphWrapper(std::vector table, const std::size_t number_of_nodes) + : table_(std::move(table)), number_of_nodes_(number_of_nodes){}; - std::size_t GetNumberOfNodes() const { - return number_of_nodes_; - } + std::size_t GetNumberOfNodes() const { return number_of_nodes_; } + + std::vector GetAdjacentEdgeRange(const NodeID node) const + { - std::vector GetAdjacentEdgeRange(const NodeID node) const { std::vector edges; - for (auto i = 0; i < number_of_nodes_; ++i) { - if (*(std::begin(table_) + node * number_of_nodes_ + i) != INVALID_EDGE_WEIGHT) { + // find all valid adjacent edges and move to vector `edges` + for (std::size_t i = 0; i < number_of_nodes_; ++i) + { + if (*(std::begin(table_) + node * number_of_nodes_ + i) != INVALID_EDGE_WEIGHT) + { edges.push_back(i); } } return edges; } - EdgeWeight GetTarget(const EdgeWeight edge) const { - return edge; - } + EdgeWeight GetTarget(const EdgeWeight edge) const { return edge; } -private: - std::vector table_; + private: + const std::vector table_; const std::size_t number_of_nodes_; }; - #endif // MATRIX_GRAPH_WRAPPER_H diff --git a/data_structures/route_parameters.cpp b/data_structures/route_parameters.cpp index 52e900ec6..86b955358 100644 --- a/data_structures/route_parameters.cpp +++ b/data_structures/route_parameters.cpp @@ -122,7 +122,6 @@ void RouteParameters::setLanguage(const std::string &language_string) language = language_string; } - void RouteParameters::setGeometryFlag(const bool flag) { geometry = flag; } void RouteParameters::setCompressionFlag(const bool flag) { compression = flag; } diff --git a/library/osrm_impl.hpp b/library/osrm_impl.hpp index 6984c5ff2..a736c042f 100644 --- a/library/osrm_impl.hpp +++ b/library/osrm_impl.hpp @@ -28,10 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OSRM_IMPL_HPP #define OSRM_IMPL_HPP -// #if __cplusplus > 199711L -// #define register // Deprecated in C++11. -// #endif // #if __cplusplus > 199711L - class BasePlugin; struct RouteParameters; diff --git a/plugins/trip.hpp b/plugins/trip.hpp index 1ae6bc57a..860f03645 100644 --- a/plugins/trip.hpp +++ b/plugins/trip.hpp @@ -32,22 +32,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../algorithms/object_encoder.hpp" #include "../algorithms/tarjan_scc.hpp" -#include "../routing_algorithms/trip_nearest_neighbour.hpp" -#include "../routing_algorithms/trip_farthest_insertion.hpp" -#include "../routing_algorithms/trip_brute_force.hpp" -#include "../data_structures/query_edge.hpp" +#include "../algorithms/trip_nearest_neighbour.hpp" +#include "../algorithms/trip_farthest_insertion.hpp" +#include "../algorithms/trip_brute_force.hpp" #include "../data_structures/search_engine.hpp" -#include "../data_structures/matrix_graph_wrapper.hpp" -#include "../data_structures/restriction.hpp" -#include "../data_structures/restriction_map.hpp" -#include "../descriptors/descriptor_base.hpp" -#include "../descriptors/json_descriptor.hpp" -#include "../util/json_renderer.hpp" +#include "../data_structures/matrix_graph_wrapper.hpp" // wrapper to use tarjan + // scc on dist table +#include "../descriptors/descriptor_base.hpp" // to make json output +#include "../descriptors/json_descriptor.hpp" // to make json output #include "../util/make_unique.hpp" -#include "../util/string_util.hpp" -#include "../util/timing_util.hpp" -#include "../util/simple_logger.hpp" -#include "../util/dist_table_wrapper.hpp" +#include "../util/timing_util.hpp" // to time runtime +#include "../util/simple_logger.hpp" // for logging output +#include "../util/dist_table_wrapper.hpp" // to access the dist + // table more easily #include #include @@ -55,16 +52,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include #include #include #include -#include -#include #include -#include - template class RoundTripPlugin final : public BasePlugin { private: @@ -73,22 +65,25 @@ template class RoundTripPlugin final : public BasePlugin std::unique_ptr> search_engine_ptr; public: - explicit RoundTripPlugin(DataFacadeT *facade) - : descriptor_string("trip"), facade(facade) + explicit RoundTripPlugin(DataFacadeT *facade) : descriptor_string("trip"), facade(facade) { search_engine_ptr = osrm::make_unique>(facade); } const std::string GetDescriptor() const override final { return descriptor_string; } - void GetPhantomNodes(const RouteParameters &route_parameters, PhantomNodeArray & phantom_node_vector) { + void GetPhantomNodes(const RouteParameters &route_parameters, + PhantomNodeArray &phantom_node_vector) + { const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); // find phantom nodes for all input coords - for (const auto i : osrm::irange(0, route_parameters.coordinates.size())) { + for (const auto i : osrm::irange(0, route_parameters.coordinates.size())) + { // if client hints are helpful, encode hints if (checksum_OK && i < route_parameters.hints.size() && - !route_parameters.hints[i].empty()) { + !route_parameters.hints[i].empty()) + { PhantomNode current_phantom_node; ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node); if (current_phantom_node.is_valid(facade->GetNumberOfNodes())) @@ -99,7 +94,8 @@ template class RoundTripPlugin final : public BasePlugin } facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], phantom_node_vector[i], 1); - if (phantom_node_vector[i].size() > 1) { + if (phantom_node_vector[i].size() > 1) + { phantom_node_vector[i].erase(std::begin(phantom_node_vector[i])); } BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes())); @@ -110,7 +106,8 @@ template class RoundTripPlugin final : public BasePlugin // to access all graphs with component ID i, get the iterators by: // auto start = std::begin(scc_component.component) + scc_component.range[i]; // auto end = std::begin(scc_component.component) + scc_component.range[i+1]; - struct SCC_Component{ + struct SCC_Component + { // in_component: all NodeIDs sorted by component ID // in_range: index where a new component starts // @@ -118,198 +115,225 @@ template class RoundTripPlugin final : public BasePlugin // NodeID 3, 6, 7, 8 are in component 1 // => in_component = [0, 1, 2, 4, 5, 3, 6, 7, 8] // => in_range = [0, 5] - SCC_Component(std::vector in_component, - std::vector in_range) - : component(in_component), - range(in_range) { + SCC_Component(std::vector in_component, std::vector in_range) + : component(in_component), range(in_range) + { range.push_back(in_component.size()); + BOOST_ASSERT_MSG(in_component.size() >= in_range.size(), "scc component and its ranges do not match"); - BOOST_ASSERT_MSG(*std::max_element(in_range.begin(), in_range.end()) < in_component.size(), + BOOST_ASSERT_MSG(in_component.size() > 0, + "there's no scc component"); + BOOST_ASSERT_MSG(*std::max_element(in_range.begin(), in_range.end()) <= + in_component.size(), "scc component ranges are out of bound"); BOOST_ASSERT_MSG(*std::min_element(in_range.begin(), in_range.end()) >= 0, "invalid scc component range"); - BOOST_ASSERT_MSG([&in_range](){ - for (std::size_t r = 0; r < in_range.size() - 1; ++r) { - if (in_range[r] > in_range[r+1]) { - return false; - } - } - return true; - }(), + BOOST_ASSERT_MSG(std::is_sorted(std::begin(in_range), std::end(in_range)), "invalid component ranges"); - }; + }; // constructor to use when whole graph is one single scc SCC_Component(std::vector in_component) - : component(in_component), range({0, in_component.size()}) { - }; + : component(in_component), range({0, in_component.size()}){}; - std::size_t GetNumberOfComponents() const{ + std::size_t GetNumberOfComponents() const { + BOOST_ASSERT_MSG(range.size() > 0, + "there's no range"); return range.size() - 1; } const std::vector component; - // component range = in_range + [component.size()] - std::vector range; + std::vector range; }; // takes the number of locations and its distance matrix, // identifies and splits the graph in its strongly connected components (scc) // and returns an SCC_Component SCC_Component SplitUnaccessibleLocations(const std::size_t number_of_locations, - const DistTableWrapper & result_table) { + const DistTableWrapper &result_table) + { + + if (std::find(std::begin(result_table), std::end(result_table), INVALID_EDGE_WEIGHT) == std::end(result_table)) + { + // whole graph is one scc + std::vector location_ids(number_of_locations); + std::iota(std::begin(location_ids), std::end(location_ids), 0); + return SCC_Component(std::move(location_ids)); + } + // Run TarjanSCC - auto wrapper = std::make_shared>(result_table.GetTable(), number_of_locations); + auto wrapper = std::make_shared>(result_table.GetTable(), + number_of_locations); auto scc = TarjanSCC>(wrapper); scc.run(); - std::vector range_insertion; - std::vector range; - range_insertion.reserve(scc.get_number_of_components()); - range.reserve(scc.get_number_of_components()); + const auto number_of_components = scc.get_number_of_components(); + + std::vector range_insertion; + std::vector range; + range_insertion.reserve(number_of_components); + range.reserve(number_of_components); std::vector components(number_of_locations, 0); - auto prefix = 0; - for (size_t j = 0; j < scc.get_number_of_components(); ++j){ + std::size_t prefix = 0; + for (std::size_t j = 0; j < number_of_components; ++j) + { range_insertion.push_back(prefix); range.push_back(prefix); prefix += scc.get_component_size(j); } - for (size_t i = 0; i < number_of_locations; ++i) { + for (std::size_t i = 0; i < number_of_locations; ++i) + { components[range_insertion[scc.get_component_id(i)]] = i; ++range_insertion[scc.get_component_id(i)]; } - return SCC_Component(components, range); + return SCC_Component(std::move(components), std::move(range)); } - void SetLocPermutationOutput(const std::vector & permutation, - osrm::json::Object & json_result){ + void SetLocPermutationOutput(const std::vector &permutation, + osrm::json::Object &json_result) + { osrm::json::Array json_permutation; - json_permutation.values.insert(std::end(json_permutation.values), - std::begin(permutation), + json_permutation.values.insert(std::end(json_permutation.values), std::begin(permutation), std::end(permutation)); json_result.values["permutation"] = json_permutation; } - void ComputeRoute(const PhantomNodeArray & phantom_node_vector, - const RouteParameters & route_parameters, - const std::vector & trip, - InternalRouteResult & min_route) { + InternalRouteResult ComputeRoute(const PhantomNodeArray &phantom_node_vector, + const RouteParameters &route_parameters, + const 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 = std::begin(trip); it != std::end(trip); ++it) { + const auto start = std::begin(trip); + const auto end = std::end(trip); + for (auto it = start; it != end; ++it) + { const auto from_node = *it; // if from_node is the last node, compute the route from the last to the first location - const auto to_node = std::next(it) != std::end(trip) ? *std::next(it) : *std::begin(trip); + const auto to_node = + std::next(it) != end ? *std::next(it) : *start; - viapoint = PhantomNodes{phantom_node_vector[from_node][0], phantom_node_vector[to_node][0]}; + viapoint = + PhantomNodes{phantom_node_vector[from_node][0], phantom_node_vector[to_node][0]}; min_route.segment_end_coordinates.emplace_back(viapoint); } - search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route); + search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, + min_route); - BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, - "unroutable route"); + BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, "unroutable route"); + return min_route; } int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) override final { // check if all inputs are coordinates - if (!check_all_coordinates(route_parameters.coordinates)) { + if (!check_all_coordinates(route_parameters.coordinates)) + { return 400; } // get phantom nodes PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size()); GetPhantomNodes(route_parameters, phantom_node_vector); - auto number_of_locations = phantom_node_vector.size(); + const auto number_of_locations = phantom_node_vector.size(); // compute the distance table of all phantom nodes - const auto result_table = DistTableWrapper(*search_engine_ptr->distance_table(phantom_node_vector), - number_of_locations); - if (result_table.size() == 0){ + const auto result_table = DistTableWrapper( + *search_engine_ptr->distance_table(phantom_node_vector), number_of_locations); + + if (result_table.size() == 0) + { return 400; } const constexpr std::size_t BF_MAX_FEASABLE = 10; - BOOST_ASSERT_MSG(result_table.size() > 0, "Distance Table is empty."); + BOOST_ASSERT_MSG(result_table.size() == number_of_locations * number_of_locations, + "Distance Table has wrong size."); // get scc components - SCC_Component scc = [&](){ - if (*std::max_element(result_table.begin(), result_table.end()) == INVALID_EDGE_WEIGHT) { - // compute all scc with tarjan - return SplitUnaccessibleLocations(number_of_locations, result_table); - } else { - // whole graph is one scc - std::vector location_ids(number_of_locations); - std::iota(std::begin(location_ids), std::end(location_ids), 0); - return SCC_Component(location_ids); - } - }(); - + SCC_Component scc = SplitUnaccessibleLocations(number_of_locations, result_table); using NodeIDIterator = typename std::vector::const_iterator; std::vector> route_result; route_result.reserve(scc.GetNumberOfComponents()); - TIMER_START(trip); - //run Trip computation for every SCC - for (std::size_t k = 0; k < scc.GetNumberOfComponents(); ++k) { - const auto component_size = scc.range[k+1] - scc.range[k]; + TIMER_START(TRIP_TIMER); + // run Trip computation for every SCC + for (std::size_t k = 0; k < scc.GetNumberOfComponents(); ++k) + { + const auto component_size = scc.range[k + 1] - scc.range[k]; - BOOST_ASSERT_MSG(component_size >= 0,"invalid component size"); + BOOST_ASSERT_MSG(component_size >= 0, "invalid component size"); - if (component_size > 1) { + if (component_size > 1) + { std::vector scc_route; NodeIDIterator start = std::begin(scc.component) + scc.range[k]; - NodeIDIterator end = std::begin(scc.component) + scc.range[k+1]; + NodeIDIterator end = std::begin(scc.component) + scc.range[k + 1]; - if (component_size < BF_MAX_FEASABLE) { - scc_route = osrm::trip::BruteForceTrip(start, end, number_of_locations, result_table); - route_result.push_back(scc_route); - } else { - scc_route = osrm::trip::FarthestInsertionTrip(start, end, number_of_locations, result_table); - route_result.push_back(scc_route); + if (component_size < BF_MAX_FEASABLE) + { + scc_route = + osrm::trip::BruteForceTrip(start, + end, + number_of_locations, + result_table); + } + else + { + scc_route = osrm::trip::FarthestInsertionTrip(start, + end, + number_of_locations, + result_table); } - // use this if output if debugging of route is needed: - SimpleLogger().Write() << "Route #" - << k << ": " - << [&scc_route](){ - std::string s = ""; - for (auto x : scc_route) { - s += std::to_string(x) + " "; - } - return s; - }(); - } else { + // use this output if debugging of route is needed: + // SimpleLogger().Write() << "Route #" << k << ": " << [&scc_route]() + // { + // std::string s = ""; + // for (auto x : scc_route) + // { + // s += std::to_string(x) + " "; + // } + // return s; + // }(); + + route_result.push_back(std::move(scc_route)); + } + else + { // if component only consists of one node, add it to the result routes - route_result.push_back({scc.component[scc.range[k]]}); + route_result.emplace_back(scc.component[scc.range[k]]); } } // compute all round trip routes - std::vector comp_route (route_result.size()); - for (std::size_t r = 0; r < route_result.size(); ++r) { - ComputeRoute(phantom_node_vector, route_parameters, route_result[r], comp_route[r]); + std::vector comp_route; + comp_route.reserve(route_result.size()); + for (std::size_t r = 0; r < route_result.size(); ++r) + { + comp_route.push_back(ComputeRoute(phantom_node_vector, route_parameters, route_result[r])); } - TIMER_STOP(trip); + TIMER_STOP(TRIP_TIMER); + + SimpleLogger().Write() << "Trip calculation took: " << TIMER_MSEC(TRIP_TIMER) / 1000. << "s"; // prepare JSON output - - // create a json object for every trip osrm::json::Array trip; - for (std::size_t i = 0; i < route_result.size(); ++i) { - std::unique_ptr> descriptor; - descriptor = osrm::make_unique>(facade); + for (std::size_t i = 0; i < route_result.size(); ++i) + { + std::unique_ptr> descriptor = osrm::make_unique>(facade); descriptor->SetConfig(route_parameters); osrm::json::Object scc_trip; @@ -319,16 +343,15 @@ template class RoundTripPlugin final : public BasePlugin // set viaroute output descriptor->Run(comp_route[i], scc_trip); - trip.values.push_back(scc_trip); + trip.values.push_back(std::move(scc_trip)); } - json_result.values["trips"] = trip; + json_result.values["trips"] = std::move(trip); return 200; } - }; #endif // TRIP_HPP diff --git a/unit_tests/routing_algorithms/tsp.cpp b/unit_tests/routing_algorithms/tsp.cpp deleted file mode 100644 index fde22295c..000000000 --- a/unit_tests/routing_algorithms/tsp.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - -Copyright (c) 2014, 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. - -*/ - -#include "../../routing_algorithms/trip_brute_force.hpp" - -#include -#include -#include - -#include - -#include - -BOOST_AUTO_TEST_SUITE(trip) - -// BOOST_AUTO_TEST_CASE(check_distance_computation) -// { -// BOOST_CHECK_EQUAL(true, true); -// } - -BOOST_AUTO_TEST_SUITE_END() diff --git a/util/dist_table_wrapper.hpp b/util/dist_table_wrapper.hpp index eda3878c7..15550fafe 100644 --- a/util/dist_table_wrapper.hpp +++ b/util/dist_table_wrapper.hpp @@ -31,30 +31,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include -//This Wrapper provides an easier access to a distance table that is given as an linear vector - -template class DistTableWrapper { -public: +// This Wrapper provides an easier access to a distance table that is given as an linear vector +template class DistTableWrapper +{ + public: using Iterator = typename std::vector::iterator; using ConstIterator = typename std::vector::const_iterator; DistTableWrapper(std::vector table, std::size_t number_of_nodes) - : table_(std::move(table)), number_of_nodes_(number_of_nodes) { + : table_(std::move(table)), number_of_nodes_(number_of_nodes) + { BOOST_ASSERT_MSG(table.size() == 0, "table is empty"); - BOOST_ASSERT_MSG(number_of_nodes_ * number_of_nodes_ <= table_.size(), "number_of_nodes_ is invalid"); + BOOST_ASSERT_MSG(number_of_nodes_ * number_of_nodes_ <= table_.size(), + "number_of_nodes_ is invalid"); }; - std::size_t GetNumberOfNodes() const { - return number_of_nodes_; - } + std::size_t GetNumberOfNodes() const { return number_of_nodes_; } - std::size_t size() const { - return table_.size(); - } + std::size_t size() const { return table_.size(); } - EdgeWeight operator() (NodeID from, NodeID to) const { + EdgeWeight operator()(NodeID from, NodeID to) const + { BOOST_ASSERT_MSG(from < number_of_nodes_, "from ID is out of bound"); BOOST_ASSERT_MSG(to < number_of_nodes_, "to ID is out of bound"); @@ -62,37 +62,27 @@ public: BOOST_ASSERT_MSG(index < table_.size(), "index is out of bound"); - return table_[index]; + return table_[index]; } - ConstIterator begin() const{ - return std::begin(table_); - } + ConstIterator begin() const { return std::begin(table_); } - Iterator begin() { - return std::begin(table_); - } + Iterator begin() { return std::begin(table_); } - ConstIterator end() const{ - return std::end(table_); - } + ConstIterator end() const { return std::end(table_); } - Iterator end() { - return std::end(table_); - } + Iterator end() { return std::end(table_); } - NodeID GetIndexOfMaxValue() const { + NodeID GetIndexOfMaxValue() const + { return std::distance(table_.begin(), std::max_element(table_.begin(), table_.end())); } - std::vector GetTable() const { - return table_; - } + std::vector GetTable() const { return table_; } -private: + private: std::vector table_; const std::size_t number_of_nodes_; }; - #endif // DIST_TABLE_WRAPPER_H