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
This commit is contained in:
parent
e773a80b06
commit
74e00cf652
@ -40,19 +40,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../util/timing_util.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
template <typename GraphT> class TarjanSCC
|
||||
{
|
||||
@ -153,7 +146,8 @@ template <typename GraphT> 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 <typename GraphT> 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 <typename GraphT> class TarjanSCC
|
||||
}
|
||||
|
||||
unsigned get_component_id(const NodeID node) const { return components_index[node]; }
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* TARJAN_SCC_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 <osrm/json_container.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@ -53,28 +47,31 @@ namespace trip
|
||||
{
|
||||
|
||||
// computes the distance of a given permutation
|
||||
EdgeWeight ReturnDistance(const DistTableWrapper<EdgeWeight> & dist_table,
|
||||
const std::vector<NodeID> & location_order,
|
||||
const EdgeWeight & min_route_dist,
|
||||
const std::size_t & component_size) {
|
||||
EdgeWeight ReturnDistance(const DistTableWrapper<EdgeWeight> &dist_table,
|
||||
const std::vector<NodeID> &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 <typename NodeIDIterator>
|
||||
std::vector<NodeID> BruteForceTrip(const NodeIDIterator start,
|
||||
const NodeIDIterator end,
|
||||
const std::size_t number_of_locations,
|
||||
const DistTableWrapper<EdgeWeight> & dist_table) {
|
||||
const NodeIDIterator end,
|
||||
const std::size_t number_of_locations,
|
||||
const DistTableWrapper<EdgeWeight> &dist_table)
|
||||
{
|
||||
const auto component_size = std::distance(start, end);
|
||||
|
||||
std::vector<NodeID> perm(start, end);
|
||||
@ -85,20 +82,25 @@ std::vector<NodeID> 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
|
||||
} // end namespace trip
|
||||
} // end namespace osrm
|
||||
#endif // TRIP_BRUTE_FORCE_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 <osrm/json_container.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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<NodeID>::iterator;
|
||||
std::pair<EdgeWeight, NodeIDIter> GetShortestRoundTrip(const NodeID new_loc,
|
||||
const DistTableWrapper<EdgeWeight> & dist_table,
|
||||
const std::size_t number_of_locations,
|
||||
std::vector<NodeID> & route){
|
||||
using NodeIDIter = std::vector<NodeID>::iterator;
|
||||
std::pair<EdgeWeight, NodeIDIter>
|
||||
GetShortestRoundTrip(const NodeID new_loc,
|
||||
const DistTableWrapper<EdgeWeight> &dist_table,
|
||||
const std::size_t number_of_locations,
|
||||
std::vector<NodeID> &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 <typename NodeIDIterator>
|
||||
// given two initial start nodes, find a roundtrip route using the farthest insertion algorithm
|
||||
std::vector<NodeID> FindRoute(const std::size_t & number_of_locations,
|
||||
const std::size_t & component_size,
|
||||
const NodeIDIterator & start,
|
||||
const NodeIDIterator & end,
|
||||
const DistTableWrapper<EdgeWeight> & dist_table,
|
||||
const NodeID & start1,
|
||||
const NodeID & start2) {
|
||||
std::vector<NodeID> FindRoute(const std::size_t &number_of_locations,
|
||||
const std::size_t &component_size,
|
||||
const NodeIDIterator &start,
|
||||
const NodeIDIterator &end,
|
||||
const DistTableWrapper<EdgeWeight> &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<NodeID> 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<NodeID> FindRoute(const std::size_t & number_of_locations,
|
||||
}
|
||||
|
||||
template <typename NodeIDIterator>
|
||||
std::vector<NodeID> FarthestInsertionTrip(const NodeIDIterator & start,
|
||||
const NodeIDIterator & end,
|
||||
std::vector<NodeID> FarthestInsertionTrip(const NodeIDIterator &start,
|
||||
const NodeIDIterator &end,
|
||||
const std::size_t number_of_locations,
|
||||
const DistTableWrapper<EdgeWeight> & dist_table) {
|
||||
const DistTableWrapper<EdgeWeight> &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<NodeID> 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<NodeID> 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
|
@ -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 <vector>
|
||||
#include <limits>
|
||||
|
||||
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace trip
|
||||
{
|
||||
template <typename NodeIDIterator>
|
||||
std::vector<NodeID> NearestNeighbourTrip(const NodeIDIterator & start,
|
||||
const NodeIDIterator & end,
|
||||
std::vector<NodeID> NearestNeighbourTrip(const NodeIDIterator &start,
|
||||
const NodeIDIterator &end,
|
||||
const std::size_t number_of_locations,
|
||||
const DistTableWrapper<EdgeWeight> & dist_table) {
|
||||
const DistTableWrapper<EdgeWeight> &dist_table)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// START GREEDY NEAREST NEIGHBOUR HERE
|
||||
// 1. grab a random location and mark as starting point
|
||||
@ -70,7 +67,7 @@ std::vector<NodeID> 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<NodeID> 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<NodeID> 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
|
@ -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 <osrm/json_container.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
|
||||
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace trip
|
||||
{
|
||||
|
||||
void TabuSearchTrip(std::vector<unsigned> & location,
|
||||
const PhantomNodeArray & phantom_node_vector,
|
||||
const std::vector<EdgeWeight> & dist_table,
|
||||
InternalRouteResult & min_route,
|
||||
std::vector<int> & min_loc_permutation) {
|
||||
|
||||
|
||||
// todo: yet to be implemented
|
||||
void TabuSearchTrip(std::vector<unsigned> &location,
|
||||
const PhantomNodeArray &phantom_node_vector,
|
||||
const std::vector<EdgeWeight> &dist_table,
|
||||
InternalRouteResult &min_route,
|
||||
std::vector<int> &min_loc_permutation)
|
||||
{
|
||||
}
|
||||
|
||||
void TabuSearchTrip(const PhantomNodeArray & phantom_node_vector,
|
||||
const std::vector<EdgeWeight> & dist_table,
|
||||
InternalRouteResult & min_route,
|
||||
std::vector<int> & min_loc_permutation) {
|
||||
|
||||
|
||||
void TabuSearchTrip(const PhantomNodeArray &phantom_node_vector,
|
||||
const std::vector<EdgeWeight> &dist_table,
|
||||
InternalRouteResult &min_route,
|
||||
std::vector<int> &min_loc_permutation)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // TRIP_BRUTE_FORCE_HPP
|
@ -29,37 +29,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define MATRIX_GRAPH_WRAPPER_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
//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 <typename T> 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<T> table, const std::size_t number_of_nodes) : table_(table), number_of_nodes_(number_of_nodes) {};
|
||||
template <typename T> class MatrixGraphWrapper
|
||||
{
|
||||
public:
|
||||
MatrixGraphWrapper(std::vector<T> 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<T> GetAdjacentEdgeRange(const NodeID node) const
|
||||
{
|
||||
|
||||
std::vector<T> GetAdjacentEdgeRange(const NodeID node) const {
|
||||
std::vector<T> 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<T> table_;
|
||||
private:
|
||||
const std::vector<T> table_;
|
||||
const std::size_t number_of_nodes_;
|
||||
};
|
||||
|
||||
|
||||
#endif // MATRIX_GRAPH_WRAPPER_H
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
||||
|
271
plugins/trip.hpp
271
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 <osrm/json_container.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
@ -55,16 +52,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <iterator>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
|
||||
{
|
||||
private:
|
||||
@ -73,22 +65,25 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
|
||||
std::unique_ptr<SearchEngine<DataFacadeT>> 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<SearchEngine<DataFacadeT>>(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<std::size_t>(0, route_parameters.coordinates.size())) {
|
||||
for (const auto i : osrm::irange<std::size_t>(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 DataFacadeT> 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 DataFacadeT> 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 DataFacadeT> 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<NodeID> in_component,
|
||||
std::vector<size_t> in_range)
|
||||
: component(in_component),
|
||||
range(in_range) {
|
||||
SCC_Component(std::vector<NodeID> in_component, std::vector<size_t> 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<NodeID> 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<NodeID> component;
|
||||
// component range = in_range + [component.size()]
|
||||
std::vector<size_t> range;
|
||||
std::vector<std::size_t> 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<EdgeWeight> & result_table) {
|
||||
const DistTableWrapper<EdgeWeight> &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<NodeID> 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<MatrixGraphWrapper<EdgeWeight>>(result_table.GetTable(), number_of_locations);
|
||||
auto wrapper = std::make_shared<MatrixGraphWrapper<EdgeWeight>>(result_table.GetTable(),
|
||||
number_of_locations);
|
||||
auto scc = TarjanSCC<MatrixGraphWrapper<EdgeWeight>>(wrapper);
|
||||
scc.run();
|
||||
|
||||
std::vector<size_t> range_insertion;
|
||||
std::vector<size_t> 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<std::size_t> range_insertion;
|
||||
std::vector<std::size_t> range;
|
||||
range_insertion.reserve(number_of_components);
|
||||
range.reserve(number_of_components);
|
||||
|
||||
std::vector<NodeID> 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<NodeID> & permutation,
|
||||
osrm::json::Object & json_result){
|
||||
void SetLocPermutationOutput(const std::vector<NodeID> &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<NodeID> & trip,
|
||||
InternalRouteResult & min_route) {
|
||||
InternalRouteResult ComputeRoute(const PhantomNodeArray &phantom_node_vector,
|
||||
const RouteParameters &route_parameters,
|
||||
const std::vector<NodeID> &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<EdgeWeight>(*search_engine_ptr->distance_table(phantom_node_vector),
|
||||
number_of_locations);
|
||||
if (result_table.size() == 0){
|
||||
const auto result_table = DistTableWrapper<EdgeWeight>(
|
||||
*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<NodeID> 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<NodeID>::const_iterator;
|
||||
|
||||
std::vector<std::vector<NodeID>> 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<NodeID> 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<InternalRouteResult> 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<InternalRouteResult> 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<BaseDescriptor<DataFacadeT>> descriptor;
|
||||
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
|
||||
for (std::size_t i = 0; i < route_result.size(); ++i)
|
||||
{
|
||||
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
|
||||
descriptor->SetConfig(route_parameters);
|
||||
|
||||
osrm::json::Object scc_trip;
|
||||
@ -319,16 +343,15 @@ template <class DataFacadeT> 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
|
||||
|
@ -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 <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/mpl/list.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(trip)
|
||||
|
||||
// BOOST_AUTO_TEST_CASE(check_distance_computation)
|
||||
// {
|
||||
// BOOST_CHECK_EQUAL(true, true);
|
||||
// }
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
@ -31,30 +31,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
//This Wrapper provides an easier access to a distance table that is given as an linear vector
|
||||
|
||||
template <typename T> class DistTableWrapper {
|
||||
public:
|
||||
// This Wrapper provides an easier access to a distance table that is given as an linear vector
|
||||
|
||||
template <typename T> class DistTableWrapper
|
||||
{
|
||||
public:
|
||||
using Iterator = typename std::vector<T>::iterator;
|
||||
using ConstIterator = typename std::vector<T>::const_iterator;
|
||||
|
||||
DistTableWrapper(std::vector<T> 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<T> GetTable() const {
|
||||
return table_;
|
||||
}
|
||||
std::vector<T> GetTable() const { return table_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
std::vector<T> table_;
|
||||
const std::size_t number_of_nodes_;
|
||||
};
|
||||
|
||||
|
||||
#endif // DIST_TABLE_WRAPPER_H
|
||||
|
Loading…
Reference in New Issue
Block a user