From 8429a1e792724c7ed50e04fe6b7a119c625013ba Mon Sep 17 00:00:00 2001 From: Huyen Chau Nguyen Date: Thu, 20 Aug 2015 15:32:28 +0200 Subject: [PATCH] add assertions --- plugins/round_trip.hpp | 37 ++++++++++++++++--- routing_algorithms/tsp_brute_force.hpp | 9 +++++ routing_algorithms/tsp_farthest_insertion.hpp | 24 ++++++++++-- routing_algorithms/tsp_nearest_neighbour.hpp | 6 ++- util/dist_table_wrapper.hpp | 7 +++- 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/plugins/round_trip.hpp b/plugins/round_trip.hpp index 460fe249d..5cbff46a7 100644 --- a/plugins/round_trip.hpp +++ b/plugins/round_trip.hpp @@ -120,9 +120,25 @@ template class RoundTripPlugin final : public BasePlugin // => in_range = [0, 5] SCC_Component(std::vector in_component, std::vector in_range) - : component(in_component), range(in_range) { - range.push_back(in_component.size()); - }; + : 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(), + "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; + }(), + "invalid component ranges"); + }; // constructor to use when whole graph is one single scc SCC_Component(std::vector in_component) @@ -190,11 +206,15 @@ template class RoundTripPlugin final : public BasePlugin 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); + 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); + + BOOST_ASSERT_MSG(min_route.shortest_path_length < INVALID_EDGE_WEIGHT, + "unroutable route"); } int HandleRequest(const RouteParameters &route_parameters, @@ -240,8 +260,11 @@ template class RoundTripPlugin final : public BasePlugin route_result.reserve(scc.GetNumberOfComponents()); TIMER_START(tsp); //run TSP computation for every SCC - for(auto k = 0; k < scc.GetNumberOfComponents(); ++k) { + 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"); + if (component_size > 1) { std::vector scc_route; NodeIDIterator start = std::begin(scc.component) + scc.range[k]; @@ -266,6 +289,7 @@ template class RoundTripPlugin final : public BasePlugin route_result.push_back(scc_route); } + // use this if output if debugging of route is needed: SimpleLogger().Write() << "Route #" << k << ": " << [&scc_route](){ @@ -276,13 +300,14 @@ template class RoundTripPlugin final : public BasePlugin return s; }(); } else { + // if component only consists of one node, add it to the result routes route_result.push_back({scc.component[scc.range[k]]}); } } // compute all round trip routes std::vector comp_route (route_result.size()); - for (auto r = 0; r < route_result.size(); ++r) { + for (std::size_t r = 0; r < route_result.size(); ++r) { ComputeRoute(phantom_node_vector, route_parameters, route_result[r], comp_route[r]); } @@ -293,7 +318,7 @@ template class RoundTripPlugin final : public BasePlugin // create a json object for every trip osrm::json::Array trip; - for (auto i = 0; i < route_result.size(); ++i) { + for (std::size_t i = 0; i < route_result.size(); ++i) { std::unique_ptr> descriptor; descriptor = osrm::make_unique>(facade); descriptor->SetConfig(route_parameters); diff --git a/routing_algorithms/tsp_brute_force.hpp b/routing_algorithms/tsp_brute_force.hpp index fb6849529..e02ac3252 100644 --- a/routing_algorithms/tsp_brute_force.hpp +++ b/routing_algorithms/tsp_brute_force.hpp @@ -52,6 +52,7 @@ namespace osrm namespace tsp { +// computes the distance of a given permutation EdgeWeight ReturnDistance(const DistTableWrapper & dist_table, const std::vector & location_order, const EdgeWeight min_route_dist, @@ -62,9 +63,13 @@ EdgeWeight ReturnDistance(const DistTableWrapper & dist_table, route_dist += dist_table(location_order[i], location_order[(i+1) % component_size]); ++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 BruteForceTSP(const NodeIDIterator start, const NodeIDIterator end, @@ -79,6 +84,10 @@ std::vector BruteForceTSP(const NodeIDIterator start, EdgeWeight min_route_dist = INVALID_EDGE_WEIGHT; // 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(*(std::min_element(std::begin(perm), std::end(perm))) >= 0, "invalid node id"); + do { const auto new_distance = ReturnDistance(dist_table, perm, min_route_dist, component_size); if (new_distance <= min_route_dist) { diff --git a/routing_algorithms/tsp_farthest_insertion.hpp b/routing_algorithms/tsp_farthest_insertion.hpp index 309471bef..9ffc44544 100644 --- a/routing_algorithms/tsp_farthest_insertion.hpp +++ b/routing_algorithms/tsp_farthest_insertion.hpp @@ -73,12 +73,21 @@ std::pair GetShortestRoundTrip(const NodeID 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);; + 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) { 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"); return std::make_pair(min_trip_distance, next_insert_point_candidate); } @@ -86,12 +95,15 @@ std::pair GetShortestRoundTrip(const NodeID new_loc, 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 & size_of_component, + 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"); + std::vector route; route.reserve(number_of_locations); @@ -104,7 +116,7 @@ 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 < size_of_component; ++j) { + for (std::size_t j = 2; j < component_size; ++j) { auto farthest_distance = 0; auto next_node = -1; @@ -116,6 +128,9 @@ std::vector FindRoute(const std::size_t & number_of_locations, if (!visited[*i]) { 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"); + // 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; @@ -125,6 +140,8 @@ std::vector FindRoute(const std::size_t & number_of_locations, } } + BOOST_ASSERT_MSG(next_node >= 0, "next node to visit is invalid"); + // mark as visited and insert node visited[next_node] = true; route.insert(next_insert_point, next_node); @@ -169,7 +186,8 @@ std::vector FarthestInsertionTSP(const NodeIDIterator & start, } } } - + BOOST_ASSERT_MSG(max_from < number_of_locations && max_from >= 0, "start node"); + BOOST_ASSERT_MSG(max_to < number_of_locations && max_to >= 0, "start node"); return FindRoute(number_of_locations, component_size, start, end, dist_table, max_from, max_to); } diff --git a/routing_algorithms/tsp_nearest_neighbour.hpp b/routing_algorithms/tsp_nearest_neighbour.hpp index 899eec60d..0f42b4514 100644 --- a/routing_algorithms/tsp_nearest_neighbour.hpp +++ b/routing_algorithms/tsp_nearest_neighbour.hpp @@ -84,7 +84,7 @@ std::vector NearestNeighbourTSP(const NodeIDIterator & start, // 3. REPEAT FOR EVERY UNVISITED NODE EdgeWeight trip_dist = 0; - for(auto 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; @@ -92,12 +92,16 @@ std::vector NearestNeighbourTSP(const NodeIDIterator & start, // 2. FIND NEAREST NEIGHBOUR for (auto next = start; next != end; ++next) { 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; diff --git a/util/dist_table_wrapper.hpp b/util/dist_table_wrapper.hpp index a626cfbc9..eda3878c7 100644 --- a/util/dist_table_wrapper.hpp +++ b/util/dist_table_wrapper.hpp @@ -43,7 +43,7 @@ public: DistTableWrapper(std::vector table, std::size_t 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_, "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 { @@ -57,8 +57,11 @@ public: 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"); + const auto index = from * number_of_nodes_ + to; - BOOST_ASSERT_MSG(index < table_size(), "index is out of bound"); + + BOOST_ASSERT_MSG(index < table_.size(), "index is out of bound"); + return table_[index]; }