have less redundant code for requests with one or multiple SCCs
This commit is contained in:
parent
7587e97d46
commit
99cf3219d4
@ -197,112 +197,66 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
|
||||
const constexpr std::size_t BF_MAX_FEASABLE = 10;
|
||||
auto number_of_locations = phantom_node_vector.size();
|
||||
BOOST_ASSERT_MSG(result_table->size() > 0, "Distance Table is empty.");
|
||||
std::vector<std::vector<NodeID>> components;
|
||||
|
||||
//check if locations are in different strongly connected components (SCC)
|
||||
const auto maxint = INVALID_EDGE_WEIGHT;
|
||||
if (*std::max_element(std::begin(*result_table), std::end(*result_table)) == maxint) {
|
||||
|
||||
//TODO DELETE
|
||||
// JSON output related objects
|
||||
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
||||
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
|
||||
descriptor->SetConfig(route_parameters);
|
||||
|
||||
TIMER_START(tsp);
|
||||
// Compute all SCC
|
||||
std::vector<std::vector<NodeID>> components;
|
||||
SplitUnaccessibleLocations(number_of_locations, *result_table, components);
|
||||
// std::vector<std::vector<NodeID>> res_route (components.size()-1);
|
||||
std::vector<std::vector<NodeID>> res_route;
|
||||
} else {
|
||||
// fill a vector with node ids
|
||||
std::vector<NodeID> location_ids(number_of_locations);
|
||||
std::iota(location_ids.begin(), location_ids.end(), 0);
|
||||
components.push_back(location_ids);
|
||||
|
||||
}
|
||||
|
||||
//run TSP computation for every SCC
|
||||
for(auto k = 0; k < components.size(); ++k) {
|
||||
if (components[k].size() > 1) {
|
||||
std::vector<NodeID> scc_route;
|
||||
std::vector<std::vector<NodeID>> res_route;
|
||||
TIMER_START(tsp);
|
||||
//run TSP computation for every SCC
|
||||
for(auto k = 0; k < components.size(); ++k) {
|
||||
if (components[k].size() > 1) {
|
||||
std::vector<NodeID> scc_route;
|
||||
|
||||
// Compute the TSP with the given algorithm
|
||||
if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < BF_MAX_FEASABLE) {
|
||||
SimpleLogger().Write() << "Running brute force on multiple SCC";
|
||||
scc_route = osrm::tsp::BruteForceTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
} else if (route_parameters.tsp_algo == "NN") {
|
||||
SimpleLogger().Write() << "Running nearest neighbour on multiple SCC";
|
||||
scc_route = osrm::tsp::NearestNeighbourTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
} else if (route_parameters.tsp_algo == "FI") {
|
||||
SimpleLogger().Write() << "Running farthest insertion on multiple SCC";
|
||||
scc_route = osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
} else{
|
||||
SimpleLogger().Write() << "Running farthest insertion on multiple SCC";
|
||||
scc_route = osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
}
|
||||
// Compute the TSP with the given algorithm
|
||||
if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < BF_MAX_FEASABLE) {
|
||||
SimpleLogger().Write() << "Running brute force";
|
||||
scc_route = osrm::tsp::BruteForceTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
} else if (route_parameters.tsp_algo == "NN") {
|
||||
SimpleLogger().Write() << "Running nearest neighbour";
|
||||
scc_route = osrm::tsp::NearestNeighbourTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
} else if (route_parameters.tsp_algo == "FI") {
|
||||
SimpleLogger().Write() << "Running farthest insertion";
|
||||
scc_route = osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
} else{
|
||||
SimpleLogger().Write() << "Running farthest insertion";
|
||||
scc_route = osrm::tsp::FarthestInsertionTSP(components[k], number_of_locations, *result_table);
|
||||
res_route.push_back(scc_route);
|
||||
}
|
||||
}
|
||||
std::vector<InternalRouteResult> route;
|
||||
ComputeRoute(phantom_node_vector, route_parameters, res_route, route);
|
||||
TIMER_STOP(tsp);
|
||||
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
|
||||
SimpleLogger().Write() << "Computed roundtrip in " << TIMER_MSEC(tsp) << "ms";
|
||||
// SimpleLogger().Write() << "Route is";
|
||||
// for (auto x : res_route) {
|
||||
// for (auto y : x)
|
||||
// std::cout << y << " ";
|
||||
// }
|
||||
// SimpleLogger().Write() << "";
|
||||
|
||||
auto dist = 0;
|
||||
for (auto curr_route : route) {
|
||||
dist += curr_route.shortest_path_length;
|
||||
SetGeometry(route_parameters, curr_route, json_result);
|
||||
}
|
||||
SetDistanceOutput(dist, json_result);
|
||||
} else { //run TSP computation for all locations
|
||||
std::vector<NodeID> res_route;
|
||||
|
||||
// Compute the TSP with the given algorithm
|
||||
TIMER_START(tsp);
|
||||
// TODO patrick nach userfreundlichkeit fragen, BF vs bf usw
|
||||
if (route_parameters.tsp_algo == "BF" && route_parameters.coordinates.size() < BF_MAX_FEASABLE) {
|
||||
SimpleLogger().Write() << "Running brute force";
|
||||
res_route = osrm::tsp::BruteForceTSP(number_of_locations, *result_table);
|
||||
} else if (route_parameters.tsp_algo == "NN") {
|
||||
SimpleLogger().Write() << "Running nearest neighbour";
|
||||
res_route = osrm::tsp::NearestNeighbourTSP(number_of_locations, *result_table);
|
||||
} else if (route_parameters.tsp_algo == "FI") {
|
||||
SimpleLogger().Write() << "Running farthest insertion";
|
||||
res_route = osrm::tsp::FarthestInsertionTSP(number_of_locations, *result_table);
|
||||
} else {
|
||||
SimpleLogger().Write() << "Running farthest insertion";
|
||||
res_route = osrm::tsp::FarthestInsertionTSP(number_of_locations, *result_table);
|
||||
}
|
||||
// TODO asserts numer of result blablabla size
|
||||
// TODO std::is_permutation
|
||||
// TODO boost range
|
||||
|
||||
|
||||
|
||||
InternalRouteResult min_route;
|
||||
ComputeRoute(phantom_node_vector, route_parameters, res_route, min_route);
|
||||
TIMER_STOP(tsp);
|
||||
|
||||
// SimpleLogger().Write() << "Route is";
|
||||
// for (auto x : res_route) {
|
||||
// std::cout << x << " ";
|
||||
// }
|
||||
// SimpleLogger().Write() << "";
|
||||
|
||||
//TODO TIMER im LOGGER
|
||||
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
|
||||
SimpleLogger().Write() << "Computed roundtrip in " << TIMER_MSEC(tsp) << "ms";
|
||||
SetLocPermutationOutput(res_route, json_result);
|
||||
//TODO MEHR ASSERTIONS! :O
|
||||
SetDistanceOutput(min_route.shortest_path_length, json_result);
|
||||
SetGeometry(route_parameters, min_route, json_result);
|
||||
BOOST_ASSERT(min_route.segment_end_coordinates.size() == route_parameters.coordinates.size());
|
||||
}
|
||||
std::vector<InternalRouteResult> route;
|
||||
ComputeRoute(phantom_node_vector, route_parameters, res_route, route);
|
||||
TIMER_STOP(tsp);
|
||||
SetRuntimeOutput(TIMER_MSEC(tsp), json_result);
|
||||
SimpleLogger().Write() << "Computed roundtrip in " << TIMER_MSEC(tsp) << "ms";
|
||||
// SimpleLogger().Write() << "Route is";
|
||||
// for (auto x : res_route) {
|
||||
// for (auto y : x)
|
||||
// std::cout << y << " ";
|
||||
// }
|
||||
// SimpleLogger().Write() << "";
|
||||
|
||||
auto dist = 0;
|
||||
for (auto curr_route : route) {
|
||||
dist += curr_route.shortest_path_length;
|
||||
SetGeometry(route_parameters, curr_route, json_result);
|
||||
}
|
||||
SetDistanceOutput(dist, json_result);
|
||||
|
||||
|
||||
|
||||
|
@ -89,29 +89,6 @@ std::vector<NodeID> BruteForceTSP(std::vector<NodeID> & component,
|
||||
return route;
|
||||
}
|
||||
|
||||
std::vector<NodeID> BruteForceTSP(const std::size_t number_of_locations,
|
||||
const std::vector<EdgeWeight> & dist_table) {
|
||||
std::vector<NodeID> route;
|
||||
route.reserve(number_of_locations);
|
||||
|
||||
// fill a vector with node ids
|
||||
std::vector<NodeID> location_ids(number_of_locations);
|
||||
std::iota(location_ids.begin(), location_ids.end(), 0);
|
||||
|
||||
EdgeWeight min_route_dist = INVALID_EDGE_WEIGHT;
|
||||
// check length of all possible permutation of the location ids
|
||||
do {
|
||||
const auto new_distance = ReturnDistance(dist_table, location_ids, min_route_dist, number_of_locations);
|
||||
|
||||
if (new_distance <= min_route_dist) {
|
||||
min_route_dist = new_distance;
|
||||
route = location_ids;
|
||||
}
|
||||
} while(std::next_permutation(location_ids.begin(), location_ids.end()));
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} //end namespace osrm
|
||||
} //end namespace tsp
|
||||
#endif // TSP_BRUTE_FORCE_HPP
|
@ -49,12 +49,16 @@ namespace osrm
|
||||
namespace tsp
|
||||
{
|
||||
|
||||
void GetShortestRoundTrip(const int current_loc,
|
||||
const std::vector<EdgeWeight> & dist_table,
|
||||
const int number_of_locations,
|
||||
std::vector<NodeID> & route,
|
||||
int & min_trip_distance,
|
||||
std::vector<NodeID>::iterator & next_insert_point_candidate){
|
||||
using NodeIterator = typename std::vector<NodeID>::iterator;
|
||||
|
||||
std::pair<EdgeWeight, NodeIterator> GetShortestRoundTrip(const int current_loc,
|
||||
const std::vector<EdgeWeight> & dist_table,
|
||||
const int number_of_locations,
|
||||
std::vector<NodeID> & route){
|
||||
|
||||
auto min_trip_distance = INVALID_EDGE_WEIGHT;
|
||||
NodeIterator 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 = route.begin(); from_node != std::prev(route.end()); ++from_node) {
|
||||
@ -81,6 +85,55 @@ void GetShortestRoundTrip(const int current_loc,
|
||||
min_trip_distance = trip_dist;
|
||||
next_insert_point_candidate = to_node;
|
||||
}
|
||||
|
||||
return std::make_pair(min_trip_distance, next_insert_point_candidate);
|
||||
}
|
||||
|
||||
// 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 & size_of_component,
|
||||
const std::vector<NodeID> & locations,
|
||||
const std::vector<EdgeWeight> & dist_table,
|
||||
const NodeID & start1,
|
||||
const NodeID & start2) {
|
||||
std::vector<NodeID> route;
|
||||
route.reserve(number_of_locations);
|
||||
|
||||
// tracks which nodes have been already visited
|
||||
std::vector<bool> visited(number_of_locations, false);
|
||||
|
||||
visited[start1] = true;
|
||||
visited[start2] = true;
|
||||
route.push_back(start1);
|
||||
route.push_back(start2);
|
||||
|
||||
// add all other nodes missing (two nodes are already in the initial start trip)
|
||||
for (int j = 2; j < size_of_component; ++j) {
|
||||
|
||||
auto farthest_distance = 0;
|
||||
auto next_node = -1;
|
||||
NodeIterator next_insert_point;
|
||||
|
||||
// find unvisited loc i that is the farthest away from all other visited locs
|
||||
for (auto i : locations) {
|
||||
// find the shortest distance from i to all visited nodes
|
||||
if (!visited[i]) {
|
||||
auto insert_candidate = GetShortestRoundTrip(i, dist_table, number_of_locations, route);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark as visited and insert node
|
||||
visited[next_node] = true;
|
||||
route.insert(next_insert_point, next_node);
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
// osrm::tsp::FarthestInsertionTSP(components[k], phantom_node_vector, *result_table, scc_route);
|
||||
@ -96,126 +149,92 @@ std::vector<NodeID> FarthestInsertionTSP(const std::vector<NodeID> & locations,
|
||||
// 5. DONE!
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<NodeID> route;
|
||||
route.reserve(number_of_locations);
|
||||
|
||||
const int size_of_component = locations.size();
|
||||
// tracks which nodes have been already visited
|
||||
std::vector<bool> visited(number_of_locations, false);
|
||||
|
||||
auto max_dist = 0;
|
||||
auto max_from = -1;
|
||||
auto max_to = -1;
|
||||
|
||||
//TODO
|
||||
for (auto x : locations) {
|
||||
for (auto y : locations) {
|
||||
auto xy_dist = *(dist_table.begin() + x * number_of_locations + y);
|
||||
if (xy_dist > max_dist) {
|
||||
max_dist = xy_dist;
|
||||
max_from = x;
|
||||
max_to = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (size_of_component == 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(dist_table.begin(), std::max_element(dist_table.begin(), dist_table.end()));
|
||||
max_from = index / number_of_locations;
|
||||
max_to = index % number_of_locations;
|
||||
|
||||
visited[max_from] = true;
|
||||
visited[max_to] = true;
|
||||
route.push_back(max_from);
|
||||
route.push_back(max_to);
|
||||
// SimpleLogger().Write() << size_of_component;
|
||||
// add all other nodes missing (two nodes are already in the initial start trip)
|
||||
for (int j = 2; j < size_of_component; ++j) {
|
||||
// SimpleLogger().Write() << j << "/" << size_of_component;
|
||||
auto farthest_distance = 0;
|
||||
auto next_node = -1;
|
||||
std::vector<NodeID>::iterator next_insert_point;
|
||||
|
||||
// find unvisited loc i that is the farthest away from all other visited locs
|
||||
for (auto i : locations) {
|
||||
// find the shortest distance from i to all visited nodes
|
||||
if (!visited[i]) {
|
||||
auto min_trip_distance = INVALID_EDGE_WEIGHT;
|
||||
std::vector<NodeID>::iterator next_insert_point_candidate;
|
||||
|
||||
GetShortestRoundTrip(i, dist_table, number_of_locations, route, min_trip_distance, next_insert_point_candidate);
|
||||
|
||||
// add the location to the current trip such that it results in the shortest total tour
|
||||
// SimpleLogger().Write() << "min_trip_distance " << min_trip_distance;
|
||||
if (min_trip_distance >= farthest_distance) {
|
||||
farthest_distance = min_trip_distance;
|
||||
next_node = i;
|
||||
next_insert_point = next_insert_point_candidate;
|
||||
} else {
|
||||
auto max_dist = 0;
|
||||
for (auto x : locations) {
|
||||
for (auto y : locations) {
|
||||
auto xy_dist = *(dist_table.begin() + x * number_of_locations + y);
|
||||
if (xy_dist > max_dist) {
|
||||
max_dist = xy_dist;
|
||||
max_from = x;
|
||||
max_to = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "next node " << next_node;
|
||||
// mark as visited and insert node
|
||||
visited[next_node] = true;
|
||||
route.insert(next_insert_point, next_node);
|
||||
}
|
||||
return route;
|
||||
|
||||
return FindRoute(number_of_locations, size_of_component, locations, dist_table, max_from, max_to);
|
||||
}
|
||||
|
||||
std::vector<NodeID> FarthestInsertionTSP(const std::size_t number_of_locations,
|
||||
const std::vector<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
|
||||
// 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!
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// std::vector<NodeID> FarthestInsertionTSP(const std::size_t number_of_locations,
|
||||
// const std::vector<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
|
||||
// // 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!
|
||||
// //////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<NodeID> route;
|
||||
route.reserve(number_of_locations);
|
||||
// std::vector<NodeID> route;
|
||||
// route.reserve(number_of_locations);
|
||||
|
||||
// tracks which nodes have been already visited
|
||||
std::vector<bool> visited(number_of_locations, false);
|
||||
// // tracks which nodes have been already visited
|
||||
// std::vector<bool> visited(number_of_locations, false);
|
||||
|
||||
// find the pair of location with the biggest distance and make the pair the initial start trip
|
||||
const auto index = std::distance(dist_table.begin(), std::max_element(dist_table.begin(), dist_table.end()));
|
||||
const int max_from = index / number_of_locations;
|
||||
const int max_to = index % number_of_locations;
|
||||
visited[max_from] = true;
|
||||
visited[max_to] = true;
|
||||
route.push_back(max_from);
|
||||
route.push_back(max_to);
|
||||
// // find the pair of location with the biggest distance and make the pair the initial start trip
|
||||
// const auto index = std::distance(dist_table.begin(), std::max_element(dist_table.begin(), dist_table.end()));
|
||||
// const int max_from = index / number_of_locations;
|
||||
// const int max_to = index % number_of_locations;
|
||||
// visited[max_from] = true;
|
||||
// visited[max_to] = true;
|
||||
// route.push_back(max_from);
|
||||
// route.push_back(max_to);
|
||||
|
||||
// add all other nodes missing (two nodes are already in the initial start trip)
|
||||
for (int j = 2; j < number_of_locations; ++j) {
|
||||
auto farthest_distance = 0;
|
||||
auto next_node = -1;
|
||||
//todo move out of loop and overwrite
|
||||
std::vector<NodeID>::iterator next_insert_point;
|
||||
// // add all other nodes missing (two nodes are already in the initial start trip)
|
||||
// for (int j = 2; j < number_of_locations; ++j) {
|
||||
// auto farthest_distance = 0;
|
||||
// auto next_node = -1;
|
||||
// //todo move out of loop and overwrite
|
||||
// NodeIterator next_insert_point;
|
||||
|
||||
// find unvisited loc i that is the farthest away from all other visited locs
|
||||
for (int i = 0; i < number_of_locations; ++i) {
|
||||
if (!visited[i]) {
|
||||
auto min_trip_distance = INVALID_EDGE_WEIGHT;
|
||||
std::vector<NodeID>::iterator next_insert_point_candidate;
|
||||
// // find unvisited loc i that is the farthest away from all other visited locs
|
||||
// for (int i = 0; i < number_of_locations; ++i) {
|
||||
// if (!visited[i]) {
|
||||
// auto min_trip_distance = INVALID_EDGE_WEIGHT;
|
||||
// NodeIterator next_insert_point_candidate;
|
||||
|
||||
GetShortestRoundTrip(i, dist_table, number_of_locations, route, min_trip_distance, next_insert_point_candidate);
|
||||
// GetShortestRoundTrip(i, dist_table, number_of_locations, route, min_trip_distance, next_insert_point_candidate);
|
||||
|
||||
// add the location to the current trip such that it results in the shortest total tour
|
||||
if (min_trip_distance >= farthest_distance) {
|
||||
farthest_distance = min_trip_distance;
|
||||
next_node = i;
|
||||
next_insert_point = next_insert_point_candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
// // add the location to the current trip such that it results in the shortest total tour
|
||||
// if (min_trip_distance >= farthest_distance) {
|
||||
// farthest_distance = min_trip_distance;
|
||||
// next_node = i;
|
||||
// next_insert_point = next_insert_point_candidate;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// mark as visited and insert node
|
||||
visited[next_node] = true;
|
||||
route.insert(next_insert_point, next_node);
|
||||
}
|
||||
return route;
|
||||
}
|
||||
// // mark as visited and insert node
|
||||
// visited[next_node] = true;
|
||||
// route.insert(next_insert_point, next_node);
|
||||
// }
|
||||
// return route;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} //end namespace osrm
|
||||
} //end namespace tsp
|
||||
|
||||
#endif // TSP_FARTHEST_INSERTION_HPP
|
@ -110,70 +110,6 @@ std::vector<NodeID> NearestNeighbourTSP(const std::vector<NodeID> & locations,
|
||||
return route;
|
||||
}
|
||||
|
||||
std::vector<NodeID> NearestNeighbourTSP(const std::size_t number_of_locations,
|
||||
const std::vector<EdgeWeight> & dist_table) {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// START GREEDY NEAREST NEIGHBOUR HERE
|
||||
// 1. grab a random location and mark as starting point
|
||||
// 2. find the nearest unvisited neighbour, set it as the current location and mark as visited
|
||||
// 3. repeat 2 until there is no unvisited location
|
||||
// 4. return route back to starting point
|
||||
// 5. compute route
|
||||
// 6. repeat 1-5 with different starting points and choose iteration with shortest trip
|
||||
// 7. DONE!
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<NodeID> route;
|
||||
route.reserve(number_of_locations);
|
||||
|
||||
int shortest_trip_distance = INVALID_EDGE_WEIGHT;
|
||||
|
||||
// ALWAYS START AT ANOTHER STARTING POINT
|
||||
for(int start_node = 0; start_node < number_of_locations; ++start_node)
|
||||
{
|
||||
int curr_node = start_node;
|
||||
|
||||
std::vector<NodeID> curr_route;
|
||||
curr_route.reserve(number_of_locations);
|
||||
curr_route.push_back(start_node);
|
||||
|
||||
// visited[i] indicates whether node i was already visited by the salesman
|
||||
std::vector<bool> visited(number_of_locations, false);
|
||||
visited[start_node] = true;
|
||||
|
||||
// 3. REPEAT FOR EVERY UNVISITED NODE
|
||||
int trip_dist = 0;
|
||||
for(int via_point = 1; via_point < number_of_locations; ++via_point)
|
||||
{
|
||||
int min_dist = INVALID_EDGE_WEIGHT;
|
||||
int min_id = -1;
|
||||
|
||||
// 2. FIND NEAREST NEIGHBOUR
|
||||
auto row_begin_iterator = dist_table.begin() + (curr_node * number_of_locations);
|
||||
auto row_end_iterator = dist_table.begin() + ((curr_node + 1) * number_of_locations);
|
||||
for (auto it = row_begin_iterator; it != row_end_iterator; ++it) {
|
||||
const auto index = std::distance(row_begin_iterator, it);
|
||||
if (!visited[index] && *it < min_dist)
|
||||
{
|
||||
min_dist = *it;
|
||||
min_id = index;
|
||||
}
|
||||
}
|
||||
visited[min_id] = true;
|
||||
curr_route.push_back(min_id);
|
||||
trip_dist += min_dist;
|
||||
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) {
|
||||
shortest_trip_distance = trip_dist;
|
||||
route = curr_route;
|
||||
}
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif // TSP_NEAREST_NEIGHBOUR_HPP
|
Loading…
Reference in New Issue
Block a user