// allows a uturn at the target_phantom // searches source forward/reverse -> target forward/reverse void SearchWithUTurn(QueryHeap &forward_heap, QueryHeap &reverse_heap, const bool search_from_forward_node, const bool search_from_reverse_node, const bool search_to_forward_node, const bool search_to_reverse_node, const PhantomNode &source_phantom, const PhantomNode &target_phantom, const int total_distance_to_forward, const int total_distance_to_reverse, int &new_total_distance, std::vector<NodeID> &leg_packed_path) const { forward_heap.Clear(); reverse_heap.Clear(); if (search_from_forward_node) { forward_heap.Insert(source_phantom.forward_node_id, total_distance_to_forward - source_phantom.GetForwardWeightPlusOffset(), source_phantom.forward_node_id); } if (search_from_reverse_node) { forward_heap.Insert(source_phantom.reverse_node_id, total_distance_to_reverse - source_phantom.GetReverseWeightPlusOffset(), source_phantom.reverse_node_id); } if (search_to_forward_node) { reverse_heap.Insert(target_phantom.forward_node_id, target_phantom.GetForwardWeightPlusOffset(), target_phantom.forward_node_id); } if (search_to_reverse_node) { reverse_heap.Insert(target_phantom.reverse_node_id, target_phantom.GetReverseWeightPlusOffset(), target_phantom.reverse_node_id); } BOOST_ASSERT(forward_heap.Size() > 0); BOOST_ASSERT(reverse_heap.Size() > 0); super::Search(forward_heap, reverse_heap, new_total_distance, leg_packed_path, forceLoop(FORWARD_DIRECTION, source_phantom, target_phantom), forceLoop(REVERSE_DIRECTION, source_phantom, target_phantom)); }
// conduct T-Test bool ViaNodeCandidatePassesTTest(QueryHeap &existing_forward_heap, QueryHeap &existing_reverse_heap, QueryHeap &new_forward_heap, QueryHeap &new_reverse_heap, const RankedCandidateNode &candidate, const int length_of_shortest_path, int *length_of_via_path, NodeID *s_v_middle, NodeID *v_t_middle, const EdgeWeight min_edge_offset) const { new_forward_heap.Clear(); new_reverse_heap.Clear(); std::vector<NodeID> packed_s_v_path; std::vector<NodeID> packed_v_t_path; *s_v_middle = SPECIAL_NODEID; int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT; // compute path <s,..,v> by reusing forward search from s new_reverse_heap.Insert(candidate.node, 0, candidate.node); while (new_reverse_heap.Size() > 0) { super::RoutingStep(new_reverse_heap, existing_forward_heap, s_v_middle, &upper_bound_s_v_path_length, min_edge_offset, false); } if (INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length) { return false; } // compute path <v,..,t> by reusing backward search from t *v_t_middle = SPECIAL_NODEID; int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT; new_forward_heap.Insert(candidate.node, 0, candidate.node); while (new_forward_heap.Size() > 0) { super::RoutingStep(new_forward_heap, existing_reverse_heap, v_t_middle, &upper_bound_of_v_t_path_length, min_edge_offset, true); } if (INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length) { return false; } *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; // retrieve packed paths super::RetrievePackedPathFromHeap(existing_forward_heap, new_reverse_heap, *s_v_middle, packed_s_v_path); super::RetrievePackedPathFromHeap(new_forward_heap, existing_reverse_heap, *v_t_middle, packed_v_t_path); NodeID s_P = *s_v_middle, t_P = *v_t_middle; if (SPECIAL_NODEID == s_P) { return false; } if (SPECIAL_NODEID == t_P) { return false; } const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path); int unpacked_until_distance = 0; std::stack<SearchSpaceEdge> unpack_stack; // Traverse path s-->v for (std::size_t i = packed_s_v_path.size() - 1; (i > 0) && unpack_stack.empty(); --i) { const EdgeID current_edge_id = facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]); const int length_of_current_edge = facade->GetEdgeData(current_edge_id).distance; if ((length_of_current_edge + unpacked_until_distance) >= T_threshold) { unpack_stack.emplace(packed_s_v_path[i - 1], packed_s_v_path[i]); } else { unpacked_until_distance += length_of_current_edge; s_P = packed_s_v_path[i - 1]; } } while (!unpack_stack.empty()) { const SearchSpaceEdge via_path_edge = unpack_stack.top(); unpack_stack.pop(); EdgeID edge_in_via_path_id = facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second); if (SPECIAL_EDGEID == edge_in_via_path_id) { return false; } const EdgeData ¤t_edge_data = facade->GetEdgeData(edge_in_via_path_id); const bool current_edge_is_shortcut = current_edge_data.shortcut; if (current_edge_is_shortcut) { const NodeID via_path_middle_node_id = current_edge_data.id; const EdgeID second_segment_edge_id = facade->FindEdgeInEitherDirection( via_path_middle_node_id, via_path_edge.second); const int second_segment_length = facade->GetEdgeData(second_segment_edge_id).distance; // attention: !unpacking in reverse! // Check if second segment is the one to go over treshold? if yes add second segment // to stack, else push first segment to stack and add distance of second one. if (unpacked_until_distance + second_segment_length >= T_threshold) { unpack_stack.emplace(via_path_middle_node_id, via_path_edge.second); } else { unpacked_until_distance += second_segment_length; unpack_stack.emplace(via_path_edge.first, via_path_middle_node_id); } } else { // edge is not a shortcut, set the start node for T-Test to end of edge. unpacked_until_distance += current_edge_data.distance; s_P = via_path_edge.first; } } int t_test_path_length = unpacked_until_distance; unpacked_until_distance = 0; // Traverse path s-->v BOOST_ASSERT(!packed_v_t_path.empty()); for (unsigned i = 0, packed_path_length = static_cast<unsigned>(packed_v_t_path.size() - 1); (i < packed_path_length) && unpack_stack.empty(); ++i) { const EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i + 1]); int length_of_current_edge = facade->GetEdgeData(edgeID).distance; if (length_of_current_edge + unpacked_until_distance >= T_threshold) { unpack_stack.emplace(packed_v_t_path[i], packed_v_t_path[i + 1]); } else { unpacked_until_distance += length_of_current_edge; t_P = packed_v_t_path[i + 1]; } } while (!unpack_stack.empty()) { const SearchSpaceEdge via_path_edge = unpack_stack.top(); unpack_stack.pop(); EdgeID edge_in_via_path_id = facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second); if (SPECIAL_EDGEID == edge_in_via_path_id) { return false; } const EdgeData ¤t_edge_data = facade->GetEdgeData(edge_in_via_path_id); const bool IsViaEdgeShortCut = current_edge_data.shortcut; if (IsViaEdgeShortCut) { const NodeID middleOfViaPath = current_edge_data.id; EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath); int lengthOfFirstSegment = facade->GetEdgeData(edgeIDOfFirstSegment).distance; // Check if first segment is the one to go over treshold? if yes first segment to // stack, else push second segment to stack and add distance of first one. if (unpacked_until_distance + lengthOfFirstSegment >= T_threshold) { unpack_stack.emplace(via_path_edge.first, middleOfViaPath); } else { unpacked_until_distance += lengthOfFirstSegment; unpack_stack.emplace(middleOfViaPath, via_path_edge.second); } } else { // edge is not a shortcut, set the start node for T-Test to end of edge. unpacked_until_distance += current_edge_data.distance; t_P = via_path_edge.second; } } t_test_path_length += unpacked_until_distance; // Run actual T-Test query and compare if distances equal. engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes()); QueryHeap &forward_heap3 = *engine_working_data.forward_heap_3; QueryHeap &reverse_heap3 = *engine_working_data.reverse_heap_3; int upper_bound = INVALID_EDGE_WEIGHT; NodeID middle = SPECIAL_NODEID; forward_heap3.Insert(s_P, 0, s_P); reverse_heap3.Insert(t_P, 0, t_P); // exploration from s and t until deletemin/(1+epsilon) > _lengt_oO_sShortest_path while ((forward_heap3.Size() + reverse_heap3.Size()) > 0) { if (!forward_heap3.Empty()) { super::RoutingStep(forward_heap3, reverse_heap3, &middle, &upper_bound, min_edge_offset, true); } if (!reverse_heap3.Empty()) { super::RoutingStep(reverse_heap3, forward_heap3, &middle, &upper_bound, min_edge_offset, false); } } return (upper_bound <= t_test_path_length); }