fix bugs and add comments
rename subroute to via_point merge is_lonely_island and is_connected to make code easier to understand
This commit is contained in:
		
							parent
							
								
									00146ae87c
								
							
						
					
					
						commit
						108f87678a
					
				| @ -98,11 +98,9 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin | ||||
|                                                             phantom_node_vector[i], 1); | ||||
|             if (phantom_node_vector[i].size() > 1) | ||||
|             { | ||||
|                 phantom_node_vector[i].pop_back(); | ||||
|                 phantom_node_vector[i].erase(phantom_node_vector[i].begin()); | ||||
|             } | ||||
| 
 | ||||
|             BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes())); | ||||
|             // SimpleLogger().Write() << "In loop 1";
 | ||||
|         } | ||||
| 
 | ||||
|         // compute the distance table of all phantom nodes
 | ||||
| @ -114,9 +112,6 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin | ||||
|             return 400; | ||||
|         } | ||||
| 
 | ||||
|         // SimpleLogger().Write() << "Distance Table Computed";
 | ||||
| 
 | ||||
| 
 | ||||
|         //////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|         // START GREEDY NEAREST NEIGHBOUR HERE
 | ||||
|         // 1. grab a random location and mark as starting point
 | ||||
| @ -124,87 +119,123 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin | ||||
|         // 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
 | ||||
|         // 6. DONE!
 | ||||
|         //////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
|         const auto number_of_locations = phantom_node_vector.size(); | ||||
|         InternalRouteResult raw_route; | ||||
|         // 1. START WITH LOCATION 0 AS START POINT
 | ||||
|         int curr_node = 0;    | ||||
|         std::vector<int> loc_permutation(number_of_locations, -1); | ||||
|         loc_permutation[0] = 0; | ||||
|         std::vector<bool> visited(number_of_locations, false); | ||||
|         visited[0] = true; | ||||
|         // min_route is the shortest route found
 | ||||
|         InternalRouteResult min_route; | ||||
|         min_route.shortest_path_length = std::numeric_limits<int>::max(); | ||||
|         // min_loc_permutation stores the order of visited locations of the shortest route
 | ||||
|         std::vector<int> min_loc_permutation; | ||||
| 
 | ||||
|         // SimpleLogger().Write() << "Added an initial via";
 | ||||
|         // SimpleLogger().Write() << "Started from location 0";
 | ||||
|         // SimpleLogger().Write() << "Number of locs: " << number_of_locations;
 | ||||
|         // is_lonely_island[i] indicates whether node i is a node that cannot be reached from other nodes
 | ||||
|         //  1 means that node i is a lonely island
 | ||||
|         //  0 means that it is not known for node i
 | ||||
|         // -1 means that node i is not a lonely island but a reachable, connected node
 | ||||
|         std::vector<int> is_lonely_island(number_of_locations, 0); | ||||
|         int count_unreachables; | ||||
| 
 | ||||
|         PhantomNodes subroute; | ||||
|         // 3. REPEAT FOR EVERY UNVISITED NODE
 | ||||
|         for(int stopover = 1; stopover < number_of_locations; ++stopover) | ||||
|         // ALWAYS START AT ANOTHER STARTING POINT
 | ||||
|         for(int start_node = 0; start_node < number_of_locations; ++start_node) | ||||
|         { | ||||
|             auto row_begin_iterator = result_table->begin() + (curr_node * number_of_locations); | ||||
|             auto row_end_iterator = result_table->begin() + ((curr_node + 1) * number_of_locations); | ||||
|             int min_dist = std::numeric_limits<int>::max(); | ||||
|             int min_id = -1; | ||||
| 
 | ||||
|             // 2. FIND NEAREST NEIGHBOUR
 | ||||
|             for (auto it = row_begin_iterator; it != row_end_iterator; ++it) { | ||||
|                 auto index = std::distance(row_begin_iterator, it);  | ||||
|                  | ||||
|                 if (!visited[index] && *it < min_dist) | ||||
|                 { | ||||
|                     min_dist = *it; | ||||
|                     min_id = index; | ||||
|          | ||||
|             if (is_lonely_island[start_node] >= 0) | ||||
|             { | ||||
|                 // if node is a lonely island it is an unsuitable node to start from and shall be skipped
 | ||||
|                 if (is_lonely_island[start_node]) | ||||
|                     continue; | ||||
|                 count_unreachables = 0; | ||||
|                 auto start_dist_begin = result_table->begin() + (start_node * number_of_locations); | ||||
|                 auto start_dist_end = result_table->begin() + ((start_node + 1) * number_of_locations); | ||||
|                 for (auto it2 = start_dist_begin; it2 != start_dist_end; ++it2) { | ||||
|                     if (*it2 == 0 || *it2 == std::numeric_limits<int>::max()) { | ||||
|                         ++count_unreachables; | ||||
|                     } | ||||
|                 } | ||||
|                 if (count_unreachables >= number_of_locations) { | ||||
|                     is_lonely_island[start_node] = 1; | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 // SimpleLogger().Write() << "In loop 2";
 | ||||
|             } | ||||
|             // SimpleLogger().Write() << "After loop 2";
 | ||||
| 
 | ||||
|             int curr_node = start_node;    | ||||
|             is_lonely_island[curr_node] = -1; | ||||
|             InternalRouteResult raw_route; | ||||
|             //TODO: Should we always use the same vector or does it not matter at all because of loop scope?
 | ||||
|             std::vector<int> loc_permutation(number_of_locations, -1); | ||||
|             loc_permutation[start_node] = 0; | ||||
|             // visited[i] indicates whether node i was already visited by the salesman
 | ||||
|             std::vector<bool> visited(number_of_locations, false); | ||||
|             visited[start_node] = true; | ||||
| 
 | ||||
|             PhantomNodes viapoint; | ||||
|             // 3. REPEAT FOR EVERY UNVISITED NODE
 | ||||
|             for(int via_point = 1; via_point < number_of_locations; ++via_point) | ||||
|             { | ||||
|                 int min_dist = std::numeric_limits<int>::max(); | ||||
|                 int min_id = -1; | ||||
| 
 | ||||
|                 // 2. FIND NEAREST NEIGHBOUR
 | ||||
|                 auto row_begin_iterator = result_table->begin() + (curr_node * number_of_locations); | ||||
|                 auto row_end_iterator = result_table->begin() + ((curr_node + 1) * number_of_locations); | ||||
|                 for (auto it = row_begin_iterator; it != row_end_iterator; ++it) { | ||||
|                     auto index = std::distance(row_begin_iterator, it);  | ||||
|                     if (is_lonely_island[index] < 1 && !visited[index] && *it < min_dist) | ||||
|                     { | ||||
|                         min_dist = *it; | ||||
|                         min_id = index; | ||||
|                     } | ||||
|                 } | ||||
|                 // in case there was no unvisited and reachable node found, it means that all remaining (unvisited) nodes must be lonely islands
 | ||||
|                 if (min_id == -1) | ||||
|                 { | ||||
|                     for(int loc = 0; loc < visited.size(); ++loc) { | ||||
|                         if (!visited[loc]) { | ||||
|                             is_lonely_island[loc] = 1; | ||||
|                         } | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|                 // set the nearest unvisited location as the next via_point
 | ||||
|                 else | ||||
|                 { | ||||
|                     is_lonely_island[min_id] = -1; | ||||
|                     loc_permutation[min_id] = via_point; | ||||
|                     visited[min_id] = true; | ||||
|                     viapoint = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]}; | ||||
|                     raw_route.segment_end_coordinates.emplace_back(viapoint); | ||||
|                     curr_node = min_id; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // 4. ROUTE BACK TO STARTING POINT
 | ||||
|             viapoint = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[start_node][0]}; | ||||
|             raw_route.segment_end_coordinates.emplace_back(viapoint); | ||||
| 
 | ||||
|             // 5. COMPUTE ROUTE
 | ||||
|             search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, route_parameters.uturns, raw_route); | ||||
|             // SimpleLogger().Write() << "Route starting at " << start_node << " with length " << raw_route.shortest_path_length;
 | ||||
|              | ||||
|             // SimpleLogger().Write() << "visited size is " << visited.size();
 | ||||
| 
 | ||||
|             if (min_id == -1) | ||||
|             { | ||||
|                 SimpleLogger().Write() << "ALARM: NO ROUTE!"; | ||||
|                 break; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 loc_permutation[min_id] = stopover; | ||||
|                 visited[min_id] = true; | ||||
|                 subroute = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]}; | ||||
|                 raw_route.segment_end_coordinates.emplace_back(subroute); | ||||
|                  | ||||
|                 // SimpleLogger().Write() << "Found location " << curr_node;   
 | ||||
|                 // SimpleLogger().Write() << "Added a looped via" << curr_node << " " << min_id;
 | ||||
|                  | ||||
|                 curr_node = min_id; | ||||
| 
 | ||||
|                 // SimpleLogger().Write() << "In loop 3";
 | ||||
|             // check round trip with this starting point is shorter than the shortest round trip found till now
 | ||||
|             if (raw_route.shortest_path_length < min_route.shortest_path_length) { | ||||
|                 min_route = raw_route; | ||||
|                 min_loc_permutation = loc_permutation; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // 4. ROUTE BACK TO STARTING POINT
 | ||||
|         // SimpleLogger().Write() << "Added a final via";
 | ||||
|         subroute = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[0][0]}; | ||||
|         raw_route.segment_end_coordinates.emplace_back(subroute); | ||||
| 
 | ||||
|         // 5. COMPUTE ROUTE
 | ||||
|         search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, | ||||
|                                              route_parameters.uturns, raw_route); | ||||
|         SimpleLogger().Write() << "Shortest route " << min_route.shortest_path_length; | ||||
| 
 | ||||
|         // return result to json
 | ||||
|         std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor; | ||||
|         descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade); | ||||
|          | ||||
|         descriptor->SetConfig(route_parameters); | ||||
|         descriptor->Run(raw_route, json_result); | ||||
|         descriptor->Run(min_route, json_result); | ||||
| 
 | ||||
|         osrm::json::Array json_loc_permutation; | ||||
|         json_loc_permutation.values.insert(json_loc_permutation.values.end(), loc_permutation.begin(), loc_permutation.end()); | ||||
|         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; | ||||
| 
 | ||||
|         return 200; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user