refactor and improve the round trip computation of multiple SCCs

Problem:
- old solution was slow
- depending on the result of TarjanSCC, new distance tables and new phantom node vectors were created to run tsp on it

Solution:
- dont create new distance tables and phantom node vectors
- pass an additional vector with the information which locations are in the same component and ignore all others

fix bug for scc split computation
This commit is contained in:
Chau Nguyen
2015-07-05 00:15:55 +02:00
committed by Huyen Chau Nguyen
parent 84c12793e8
commit b15f8f68e4
10 changed files with 634 additions and 287 deletions
+71 -92
View File
@@ -31,11 +31,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "plugin_base.hpp"
#include "../algorithms/object_encoder.hpp"
#include "../algorithms/tiny_components.hpp"
#include "../routing_algorithms/tsp_nearest_neighbour.hpp"
#include "../routing_algorithms/tsp_farthest_insertion.hpp"
#include "../routing_algorithms/tsp_brute_force.hpp"
#include "../data_structures/query_edge.hpp"
#include "../data_structures/search_engine.hpp"
#include "../data_structures/matrix_graph_wrapper.hpp"
#include "../descriptors/descriptor_base.hpp"
#include "../descriptors/json_descriptor.hpp"
#include "../util/json_renderer.hpp"
@@ -95,97 +97,41 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
}
}
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector, std::vector<EdgeWeight> & result_table) {
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector,
std::vector<EdgeWeight> & result_table,
std::vector<std::vector<unsigned>> & components) {
// Run TarjanSCC
auto number_of_locations = phantom_node_vector.size();
const auto maxint = std::numeric_limits<int>::max();
auto wrapper = std::make_shared<MatrixGraphWrapper<EdgeWeight>>(result_table, number_of_locations);
auto empty_restriction = RestrictionMap(std::vector<TurnRestriction>());
auto empty_vector = std::vector<bool>();
auto scc = TarjanSCC<MatrixGraphWrapper<EdgeWeight>>(wrapper, empty_restriction, empty_vector);
scc.run();
//////////////////////////////////// DELETE UNACCESSIBLE LOCATIONS /////////////////////////////////////////
if (*std::max_element(result_table.begin(), result_table.end()) == maxint) {
const int half = number_of_locations / 2;
std::vector<int> to_delete;
for (int j = 0; j < scc.get_number_of_components(); ++j){
components.push_back(std::vector<unsigned>());
}
for (int i = number_of_locations - 1; i >= 0; --i) {
// if the location is unaccessible by most of the other locations, remember the location
if (std::count(result_table.begin() + i * number_of_locations, result_table.begin() + (i+1) * number_of_locations, maxint) > half) {
to_delete.push_back(i);
}
}
//delete all unaccessible locations
for (int k = 0; k < to_delete.size(); ++k) {
// delete its row
result_table.erase(result_table.begin() + to_delete[k] * number_of_locations, result_table.begin() + (to_delete[k]+1) * number_of_locations);
--number_of_locations;
// delete its column
for (int j = 0; j < number_of_locations; ++j) {
result_table.erase(result_table.begin() + j * number_of_locations + to_delete[k]);
}
// delete its PhantomNode
phantom_node_vector.erase(phantom_node_vector.begin() + to_delete[k]);
}
for (int i = 0; i < number_of_locations; ++i) {
components[scc.get_component_id(i)].push_back(i);
}
}
void SetJSONOutput (const RouteParameters &route_parameters,
int tsp_time,
InternalRouteResult & min_route,
std::vector<int> & min_loc_permutation,
osrm::json::Object & json_result){
void SetLocPermutationOutput(const std::vector<int> & loc_permutation, osrm::json::Object & json_result){
osrm::json::Array json_loc_permutation;
json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
json_loc_permutation.values.insert(json_loc_permutation.values.end(), loc_permutation.begin(), loc_permutation.end());
json_result.values["loc_permutation"] = json_loc_permutation;
json_result.values["distance"] = min_route.shortest_path_length;
json_result.values["runtime"] = tsp_time;
}
void SetDistanceOutput(const int distance, osrm::json::Object & json_result) {
json_result.values["distance"] = distance;
}
void SetRuntimeOutput(const float runtime, osrm::json::Object & json_result) {
json_result.values["runtime"] = runtime;
}
// if (route_parameters.tsp_algo.compare("NN"))
// //######################### NEAREST NEIGHBOUR ###############################//
// TIMER_START(tsp);
// osrm::tsp::NearestNeighbour(route_parameters, phantom_node_vector, *result_table, min_route, min_loc_permutation);
// search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
// TIMER_STOP(tsp);
// SimpleLogger().Write() << "Distance " << min_route.shortest_path_length;
// SimpleLogger().Write() << "Time " << TIMER_MSEC(tsp) + TIMER_MSEC(tsp_pre);
// osrm::json::Array json_loc_permutation;
// json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
// json_result.values["loc_permutation"] = json_loc_permutation;
// json_result.values["distance"] = min_route.shortest_path_length;
// json_result.values["runtime"] = TIMER_MSEC(tsp);
// else if (route_parameters.tsp_algo.compare("BF")
// //########################### BRUTE FORCE ####################################//
// if (route_parameters.coordinates.size() < 12) {
// TIMER_START(tsp);
// osrm::tsp::BruteForce(route_parameters, phantom_node_vector, *result_table, min_route, min_loc_permutation);
// search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
// TIMER_STOP(tsp);
// SimpleLogger().Write() << "Distance " << min_route.shortest_path_length;
// SimpleLogger().Write() << "Time " << TIMER_MSEC(tsp);
// osrm::json::Array json_loc_permutation;
// json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
// json_result.values["loc_permutation"] = json_loc_permutation;
// json_result.values["distance"] = min_route.shortest_path_length;
// json_result.values["runtime"] = TIMER_MSEC(tsp);
// } else {
// json_result.values["distance"] = -1;
// json_result.values["runtime"] = -1;
// }
// else
// //######################## FARTHEST INSERTION ###############################//
// TIMER_START(tsp);
// osrm::tsp::FarthestInsertion(route_parameters, phantom_node_vector, *result_table, min_route, min_loc_permutation);
// search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
// TIMER_STOP(tsp);
// SimpleLogger().Write() << "Distance " << min_route.shortest_path_length;
// SimpleLogger().Write() << "Time " << TIMER_MSEC(tsp);
// osrm::json::Array json_loc_permutation;
// json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
// json_result.values["loc_permutation"] = json_loc_permutation;
// json_result.values["distance"] = min_route.shortest_path_length;
// json_result.values["runtime"] = TIMER_MSEC(tsp);
void SetGeometry(const RouteParameters &route_parameters, const InternalRouteResult & min_route, osrm::json::Object & json_result) {
// return geometry result to json
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
@@ -212,20 +158,53 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
return 400;
}
SplitUnaccessibleLocations(phantom_node_vector, *result_table);
auto number_of_locations = phantom_node_vector.size();
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(number_of_locations, -1);
//######################## FARTHEST INSERTION ###############################//
TIMER_START(tsp);
osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
const auto maxint = std::numeric_limits<int>::max();
if (*std::max_element(result_table->begin(), result_table->end()) == maxint) {
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
descriptor->SetConfig(route_parameters);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
std::vector<std::vector<unsigned>> components;
TIMER_START(tsp);
SplitUnaccessibleLocations(phantom_node_vector, *result_table, components);
auto number_of_locations = phantom_node_vector.size();
std::vector<int> min_loc_permutation(number_of_locations, -1);
auto min_dist = 0;
for(auto k = 0; k < components.size(); ++k) {
if (components[k].size() > 1) {
InternalRouteResult min_route;
osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
min_dist += min_route.shortest_path_length;
descriptor->Run(min_route, json_result);
}
}
TIMER_STOP(tsp);
SetJSONOutput(route_parameters, TIMER_MSEC(tsp), min_route, min_loc_permutation, json_result);
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetDistanceOutput(min_dist, json_result);
SetLocPermutationOutput(min_loc_permutation, json_result);
} else {
auto number_of_locations = phantom_node_vector.size();
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(number_of_locations, -1);
//######################## FARTHEST INSERTION ###############################//
TIMER_START(tsp);
osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
// //######################### NEAREST NEIGHBOUR ###############################//
// TIMER_START(tsp);
// osrm::tsp::NearestNeighbourTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
// search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
// TIMER_STOP(tsp);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
SetLocPermutationOutput(min_loc_permutation, json_result);
SetDistanceOutput(min_route.shortest_path_length, json_result);
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetGeometry(route_parameters, min_route, json_result);
}
+71 -58
View File
@@ -96,47 +96,41 @@ template <class DataFacadeT> class RoundTripPluginBF final : public BasePlugin
}
}
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector, std::vector<EdgeWeight> & result_table) {
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector,
std::vector<EdgeWeight> & result_table,
std::vector<std::vector<unsigned>> & components) {
// Run TarjanSCC
auto number_of_locations = phantom_node_vector.size();
const auto maxint = std::numeric_limits<int>::max();
auto wrapper = std::make_shared<MatrixGraphWrapper<EdgeWeight>>(result_table, number_of_locations);
auto empty_restriction = RestrictionMap(std::vector<TurnRestriction>());
auto empty_vector = std::vector<bool>();
auto scc = TarjanSCC<MatrixGraphWrapper<EdgeWeight>>(wrapper, empty_restriction, empty_vector);
scc.run();
//////////////////////////////////// DELETE UNACCESSIBLE LOCATIONS /////////////////////////////////////////
if (*std::max_element(result_table.begin(), result_table.end()) == maxint) {
const int half = number_of_locations / 2;
std::vector<int> to_delete;
for (int j = 0; j < scc.get_number_of_components(); ++j){
components.push_back(std::vector<unsigned>());
}
for (int i = number_of_locations - 1; i >= 0; --i) {
// if the location is unaccessible by most of the other locations, remember the location
if (std::count(result_table.begin() + i * number_of_locations, result_table.begin() + (i+1) * number_of_locations, maxint) > half) {
to_delete.push_back(i);
}
}
//delete all unaccessible locations
for (int k = 0; k < to_delete.size(); ++k) {
// delete its row
result_table.erase(result_table.begin() + to_delete[k] * number_of_locations, result_table.begin() + (to_delete[k]+1) * number_of_locations);
--number_of_locations;
// delete its column
for (int j = 0; j < number_of_locations; ++j) {
result_table.erase(result_table.begin() + j * number_of_locations + to_delete[k]);
}
// delete its PhantomNode
phantom_node_vector.erase(phantom_node_vector.begin() + to_delete[k]);
}
for (int i = 0; i < number_of_locations; ++i) {
components[scc.get_component_id(i)].push_back(i);
}
}
void SetJSONOutput (const RouteParameters &route_parameters,
int tsp_time,
InternalRouteResult & min_route,
std::vector<int> & min_loc_permutation,
osrm::json::Object & json_result){
void SetLocPermutationOutput(const std::vector<int> & loc_permutation, osrm::json::Object & json_result){
osrm::json::Array json_loc_permutation;
json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
json_loc_permutation.values.insert(json_loc_permutation.values.end(), loc_permutation.begin(), loc_permutation.end());
json_result.values["loc_permutation"] = json_loc_permutation;
json_result.values["distance"] = min_route.shortest_path_length;
json_result.values["runtime"] = tsp_time;
}
void SetDistanceOutput(const int distance, osrm::json::Object & json_result) {
json_result.values["distance"] = distance;
}
void SetRuntimeOutput(const float runtime, osrm::json::Object & json_result) {
json_result.values["runtime"] = runtime;
}
void SetGeometry(const RouteParameters &route_parameters, const InternalRouteResult & min_route, osrm::json::Object & json_result) {
// return geometry result to json
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
@@ -145,6 +139,7 @@ template <class DataFacadeT> class RoundTripPluginBF final : public BasePlugin
descriptor->Run(min_route, json_result);
}
int HandleRequest(const RouteParameters &route_parameters,
osrm::json::Object &json_result) override final
{
@@ -163,39 +158,57 @@ template <class DataFacadeT> class RoundTripPluginBF final : public BasePlugin
return 400;
}
SplitUnaccessibleLocations(phantom_node_vector, *result_table);
if (route_parameters.coordinates.size() < 14) {
const auto maxint = std::numeric_limits<int>::max();
if (*std::max_element(result_table->begin(), result_table->end()) == maxint) {
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
descriptor->SetConfig(route_parameters);
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(phantom_node_vector.size(), -1);
//########################### BRUTE FORCE ####################################//
if (route_parameters.coordinates.size() < 11) {
std::vector<std::vector<unsigned>> components;
TIMER_START(tsp);
osrm::tsp::BruteForceTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
SplitUnaccessibleLocations(phantom_node_vector, *result_table, components);
std::vector<int> min_loc_permutation(phantom_node_vector.size(), -1);
auto min_dist = 0;
for(auto k = 0; k < components.size(); ++k) {
if (components[k].size() > 1) {
InternalRouteResult min_route;
//run nearest neighbour
osrm::tsp::BruteForceTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation);
//compute route
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
//return geometry
min_dist += min_route.shortest_path_length;
descriptor->Run(min_route, json_result);
}
}
TIMER_STOP(tsp);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetDistanceOutput(min_dist, json_result);
SetLocPermutationOutput(min_loc_permutation, json_result);
} else {
auto number_of_locations = phantom_node_vector.size();
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(number_of_locations, -1);
//########################### BRUTE FORCE ####################################//
TIMER_START(tsp);
osrm::tsp::BruteForceTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
osrm::json::Array json_loc_permutation;
json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
json_result.values["loc_permutation"] = json_loc_permutation;
json_result.values["distance"] = min_route.shortest_path_length;
SimpleLogger().Write() << "BF GEOM DISTANCE " << min_route.shortest_path_length;
json_result.values["runtime"] = TIMER_MSEC(tsp);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
SetLocPermutationOutput(min_loc_permutation, json_result);
SetDistanceOutput(min_route.shortest_path_length, json_result);
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetGeometry(route_parameters, min_route, json_result);
}
} else {
json_result.values["distance"] = -1;
json_result.values["runtime"] = -1;
SetRuntimeOutput(-1, json_result);
SetDistanceOutput(-1, json_result);
}
// return geometry result to json
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
descriptor->SetConfig(route_parameters);
descriptor->Run(min_route, json_result);
return 200;
}
+65 -42
View File
@@ -95,47 +95,41 @@ template <class DataFacadeT> class RoundTripPluginFI final : public BasePlugin
}
}
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector, std::vector<EdgeWeight> & result_table) {
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector,
std::vector<EdgeWeight> & result_table,
std::vector<std::vector<unsigned>> & components) {
// Run TarjanSCC
auto number_of_locations = phantom_node_vector.size();
const auto maxint = std::numeric_limits<int>::max();
auto wrapper = std::make_shared<MatrixGraphWrapper<EdgeWeight>>(result_table, number_of_locations);
auto empty_restriction = RestrictionMap(std::vector<TurnRestriction>());
auto empty_vector = std::vector<bool>();
auto scc = TarjanSCC<MatrixGraphWrapper<EdgeWeight>>(wrapper, empty_restriction, empty_vector);
scc.run();
//////////////////////////////////// DELETE UNACCESSIBLE LOCATIONS /////////////////////////////////////////
if (*std::max_element(result_table.begin(), result_table.end()) == maxint) {
const int half = number_of_locations / 2;
std::vector<int> to_delete;
for (int j = 0; j < scc.get_number_of_components(); ++j){
components.push_back(std::vector<unsigned>());
}
for (int i = number_of_locations - 1; i >= 0; --i) {
// if the location is unaccessible by most of the other locations, remember the location
if (std::count(result_table.begin() + i * number_of_locations, result_table.begin() + (i+1) * number_of_locations, maxint) > half) {
to_delete.push_back(i);
}
}
//delete all unaccessible locations
for (int k = 0; k < to_delete.size(); ++k) {
// delete its row
result_table.erase(result_table.begin() + to_delete[k] * number_of_locations, result_table.begin() + (to_delete[k]+1) * number_of_locations);
--number_of_locations;
// delete its column
for (int j = 0; j < number_of_locations; ++j) {
result_table.erase(result_table.begin() + j * number_of_locations + to_delete[k]);
}
// delete its PhantomNode
phantom_node_vector.erase(phantom_node_vector.begin() + to_delete[k]);
}
for (int i = 0; i < number_of_locations; ++i) {
components[scc.get_component_id(i)].push_back(i);
}
}
void SetJSONOutput (const RouteParameters &route_parameters,
int tsp_time,
InternalRouteResult & min_route,
std::vector<int> & min_loc_permutation,
osrm::json::Object & json_result){
void SetLocPermutationOutput(const std::vector<int> & loc_permutation, osrm::json::Object & json_result){
osrm::json::Array json_loc_permutation;
json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
json_loc_permutation.values.insert(json_loc_permutation.values.end(), loc_permutation.begin(), loc_permutation.end());
json_result.values["loc_permutation"] = json_loc_permutation;
json_result.values["distance"] = min_route.shortest_path_length;
json_result.values["runtime"] = tsp_time;
}
void SetDistanceOutput(const int distance, osrm::json::Object & json_result) {
json_result.values["distance"] = distance;
}
void SetRuntimeOutput(const float runtime, osrm::json::Object & json_result) {
json_result.values["runtime"] = runtime;
}
void SetGeometry(const RouteParameters &route_parameters, const InternalRouteResult & min_route, osrm::json::Object & json_result) {
// return geometry result to json
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
@@ -162,19 +156,48 @@ template <class DataFacadeT> class RoundTripPluginFI final : public BasePlugin
return 400;
}
SplitUnaccessibleLocations(phantom_node_vector, *result_table);
const auto maxint = std::numeric_limits<int>::max();
if (*std::max_element(result_table->begin(), result_table->end()) == maxint) {
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
descriptor->SetConfig(route_parameters);
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(phantom_node_vector.size(), -1);
//######################## FARTHEST INSERTION ###############################//
TIMER_START(tsp);
osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
std::vector<std::vector<unsigned>> components;
TIMER_START(tsp);
SplitUnaccessibleLocations(phantom_node_vector, *result_table, components);
auto number_of_locations = phantom_node_vector.size();
std::vector<int> min_loc_permutation(number_of_locations, -1);
auto min_dist = 0;
for(auto k = 0; k < components.size(); ++k) {
if (components[k].size() > 1) {
InternalRouteResult min_route;
osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
min_dist += min_route.shortest_path_length;
descriptor->Run(min_route, json_result);
}
}
TIMER_STOP(tsp);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetDistanceOutput(min_dist, json_result);
SetLocPermutationOutput(min_loc_permutation, json_result);
} else {
auto number_of_locations = phantom_node_vector.size();
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(number_of_locations, -1);
//######################## FARTHEST INSERTION ###############################//
TIMER_START(tsp);
osrm::tsp::FarthestInsertionTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
SetJSONOutput(route_parameters, TIMER_MSEC(tsp), min_route, min_loc_permutation, json_result);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
SetLocPermutationOutput(min_loc_permutation, json_result);
SetDistanceOutput(min_route.shortest_path_length, json_result);
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetGeometry(route_parameters, min_route, json_result);
}
return 200;
}
+68 -42
View File
@@ -96,47 +96,41 @@ template <class DataFacadeT> class RoundTripPluginNN final : public BasePlugin
}
}
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector, std::vector<EdgeWeight> & result_table) {
void SplitUnaccessibleLocations(PhantomNodeArray & phantom_node_vector,
std::vector<EdgeWeight> & result_table,
std::vector<std::vector<unsigned>> & components) {
// Run TarjanSCC
auto number_of_locations = phantom_node_vector.size();
const auto maxint = std::numeric_limits<int>::max();
auto wrapper = std::make_shared<MatrixGraphWrapper<EdgeWeight>>(result_table, number_of_locations);
auto empty_restriction = RestrictionMap(std::vector<TurnRestriction>());
auto empty_vector = std::vector<bool>();
auto scc = TarjanSCC<MatrixGraphWrapper<EdgeWeight>>(wrapper, empty_restriction, empty_vector);
scc.run();
//////////////////////////////////// DELETE UNACCESSIBLE LOCATIONS /////////////////////////////////////////
if (*std::max_element(result_table.begin(), result_table.end()) == maxint) {
const int half = number_of_locations / 2;
std::vector<int> to_delete;
for (int j = 0; j < scc.get_number_of_components(); ++j){
components.push_back(std::vector<unsigned>());
}
for (int i = number_of_locations - 1; i >= 0; --i) {
// if the location is unaccessible by most of the other locations, remember the location
if (std::count(result_table.begin() + i * number_of_locations, result_table.begin() + (i+1) * number_of_locations, maxint) > half) {
to_delete.push_back(i);
}
}
//delete all unaccessible locations
for (int k = 0; k < to_delete.size(); ++k) {
// delete its row
result_table.erase(result_table.begin() + to_delete[k] * number_of_locations, result_table.begin() + (to_delete[k]+1) * number_of_locations);
--number_of_locations;
// delete its column
for (int j = 0; j < number_of_locations; ++j) {
result_table.erase(result_table.begin() + j * number_of_locations + to_delete[k]);
}
// delete its PhantomNode
phantom_node_vector.erase(phantom_node_vector.begin() + to_delete[k]);
}
for (int i = 0; i < number_of_locations; ++i) {
components[scc.get_component_id(i)].push_back(i);
}
}
void SetJSONOutput (const RouteParameters &route_parameters,
int tsp_time,
InternalRouteResult & min_route,
std::vector<int> & min_loc_permutation,
osrm::json::Object & json_result){
void SetLocPermutationOutput(const std::vector<int> & loc_permutation, osrm::json::Object & json_result){
osrm::json::Array json_loc_permutation;
json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
json_loc_permutation.values.insert(json_loc_permutation.values.end(), loc_permutation.begin(), loc_permutation.end());
json_result.values["loc_permutation"] = json_loc_permutation;
json_result.values["distance"] = min_route.shortest_path_length;
json_result.values["runtime"] = tsp_time;
}
void SetDistanceOutput(const int distance, osrm::json::Object & json_result) {
json_result.values["distance"] = distance;
}
void SetRuntimeOutput(const float runtime, osrm::json::Object & json_result) {
json_result.values["runtime"] = runtime;
}
void SetGeometry(const RouteParameters &route_parameters, const InternalRouteResult & min_route, osrm::json::Object & json_result) {
// return geometry result to json
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
@@ -163,19 +157,51 @@ template <class DataFacadeT> class RoundTripPluginNN final : public BasePlugin
return 400;
}
SplitUnaccessibleLocations(phantom_node_vector, *result_table);
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(phantom_node_vector.size(), -1);
//######################### NEAREST NEIGHBOUR ###############################//
TIMER_START(tsp);
osrm::tsp::NearestNeighbourTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
const auto maxint = std::numeric_limits<int>::max();
if (*std::max_element(result_table->begin(), result_table->end()) == maxint) {
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
descriptor->SetConfig(route_parameters);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
std::vector<std::vector<unsigned>> components;
TIMER_START(tsp);
SplitUnaccessibleLocations(phantom_node_vector, *result_table, components);
SetJSONOutput(route_parameters, TIMER_MSEC(tsp), min_route, min_loc_permutation, json_result);
std::vector<int> min_loc_permutation(phantom_node_vector.size(), -1);
auto min_dist = 0;
for(auto k = 0; k < components.size(); ++k) {
if (components[k].size() > 1) {
InternalRouteResult min_route;
//run nearest neighbour
osrm::tsp::NearestNeighbourTSP(components[k], phantom_node_vector, *result_table, min_route, min_loc_permutation);
//compute route
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
//return geometry
min_dist += min_route.shortest_path_length;
descriptor->Run(min_route, json_result);
}
}
TIMER_STOP(tsp);
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetDistanceOutput(min_dist, json_result);
SetLocPermutationOutput(min_loc_permutation, json_result);
} else {
auto number_of_locations = phantom_node_vector.size();
InternalRouteResult min_route;
std::vector<int> min_loc_permutation(number_of_locations, -1);
//######################### NEAREST NEIGHBOUR ###############################//
TIMER_START(tsp);
osrm::tsp::NearestNeighbourTSP(phantom_node_vector, *result_table, min_route, min_loc_permutation);
search_engine_ptr->shortest_path(min_route.segment_end_coordinates, route_parameters.uturns, min_route);
TIMER_STOP(tsp);
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
SetLocPermutationOutput(min_loc_permutation, json_result);
SetDistanceOutput(min_route.shortest_path_length, json_result);
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
SetGeometry(route_parameters, min_route, json_result);
}
return 200;
}