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