have less redundant code for requests with one or multiple SCCs

This commit is contained in:
Huyen Chau Nguyen
2015-08-19 11:35:36 +02:00
parent 7587e97d46
commit 99cf3219d4
4 changed files with 175 additions and 289 deletions
+2 -25
View File
@@ -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
+125 -106
View File
@@ -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