2012-06-15 12:47:27 -04:00
|
|
|
|
/*
|
|
|
|
|
open source routing machine
|
|
|
|
|
Copyright (C) Dennis Luxen, others 2010
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU AFFERO General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
or see http://www.gnu.org/licenses/agpl.txt.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef SHORTESTPATHROUTING_H_
|
|
|
|
|
#define SHORTESTPATHROUTING_H_
|
|
|
|
|
|
2013-09-21 16:18:27 -04:00
|
|
|
|
#include <boost/assert.hpp>
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
2013-09-21 16:18:27 -04:00
|
|
|
|
#include "BasicRoutingInterface.h"
|
2013-09-19 12:53:34 -04:00
|
|
|
|
#include "../DataStructures/SearchEngineData.h"
|
|
|
|
|
|
2013-09-20 05:09:07 -04:00
|
|
|
|
template<class DataFacadeT>
|
|
|
|
|
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
|
|
|
|
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
|
|
|
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
2013-09-19 12:53:34 -04:00
|
|
|
|
SearchEngineData & engine_working_data;
|
2013-09-21 16:10:41 -04:00
|
|
|
|
|
2012-06-15 12:47:27 -04:00
|
|
|
|
public:
|
2013-09-21 16:10:41 -04:00
|
|
|
|
ShortestPathRouting(
|
|
|
|
|
DataFacadeT * facade,
|
|
|
|
|
SearchEngineData & engine_working_data
|
|
|
|
|
) :
|
|
|
|
|
super(facade),
|
|
|
|
|
engine_working_data(engine_working_data)
|
|
|
|
|
{}
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
|
|
~ShortestPathRouting() {}
|
|
|
|
|
|
2013-09-21 16:10:41 -04:00
|
|
|
|
void operator()(
|
|
|
|
|
std::vector<PhantomNodes> & phantom_nodes_vector,
|
|
|
|
|
RawRouteData & raw_route_data
|
|
|
|
|
) const {
|
|
|
|
|
BOOST_FOREACH(
|
|
|
|
|
const PhantomNodes & phantom_node_pair,
|
|
|
|
|
phantom_nodes_vector
|
|
|
|
|
){
|
|
|
|
|
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
|
|
|
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
|
|
|
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
2012-06-19 11:26:34 -04:00
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
int distance1 = 0;
|
|
|
|
|
int distance2 = 0;
|
|
|
|
|
|
2013-09-21 16:10:41 -04:00
|
|
|
|
bool search_from_1st_node = true;
|
|
|
|
|
bool search_from_2nd_node = true;
|
2013-02-03 10:47:32 -05:00
|
|
|
|
NodeID middle1 = UINT_MAX;
|
|
|
|
|
NodeID middle2 = UINT_MAX;
|
2013-09-21 16:10:41 -04:00
|
|
|
|
std::vector<NodeID> packed_path1;
|
|
|
|
|
std::vector<NodeID> packed_path2;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
2013-09-20 12:30:47 -04:00
|
|
|
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
|
|
|
|
super::facade->GetNumberOfNodes()
|
|
|
|
|
);
|
|
|
|
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
|
|
|
|
super::facade->GetNumberOfNodes()
|
|
|
|
|
);
|
|
|
|
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
|
|
|
|
super::facade->GetNumberOfNodes()
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
2013-09-20 12:30:47 -04:00
|
|
|
|
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
|
|
|
|
|
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
|
|
|
|
|
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
|
|
|
|
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
|
|
//Get distance to next pair of target nodes.
|
2013-09-21 16:21:33 -04:00
|
|
|
|
BOOST_FOREACH(
|
|
|
|
|
const PhantomNodes & phantom_node_pair,
|
|
|
|
|
phantom_nodes_vector
|
|
|
|
|
){
|
2013-02-06 09:23:57 -05:00
|
|
|
|
forward_heap1.Clear(); forward_heap2.Clear();
|
|
|
|
|
reverse_heap1.Clear(); reverse_heap2.Clear();
|
2013-09-21 16:10:41 -04:00
|
|
|
|
int local_upper_bound1 = INT_MAX;
|
|
|
|
|
int local_upper_bound2 = INT_MAX;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
2013-02-06 09:23:57 -05:00
|
|
|
|
middle1 = UINT_MAX;
|
|
|
|
|
middle2 = UINT_MAX;
|
|
|
|
|
|
2012-06-15 12:47:27 -04:00
|
|
|
|
//insert new starting nodes into forward heap, adjusted by previous distances.
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if(search_from_1st_node) {
|
|
|
|
|
forward_heap1.Insert(
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
|
|
|
|
-phantom_node_pair.startPhantom.weight1,
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode
|
|
|
|
|
);
|
|
|
|
|
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantom_node_pair.startPhantom.weight1);
|
|
|
|
|
forward_heap2.Insert(
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
|
|
|
|
-phantom_node_pair.startPhantom.weight1,
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode
|
|
|
|
|
);
|
|
|
|
|
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantom_node_pair.startPhantom.weight1);
|
2013-06-26 09:32:03 -04:00
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
|
|
|
|
|
forward_heap1.Insert(
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
|
|
|
|
-phantom_node_pair.startPhantom.weight2,
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
|
|
|
|
);
|
|
|
|
|
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantom_node_pair.startPhantom.weight2);
|
|
|
|
|
forward_heap2.Insert(
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
|
|
|
|
-phantom_node_pair.startPhantom.weight2,
|
|
|
|
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
|
|
|
|
);
|
|
|
|
|
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantom_node_pair.startPhantom.weight2);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//insert new backward nodes into backward heap, unadjusted.
|
2013-09-21 16:10:41 -04:00
|
|
|
|
reverse_heap1.Insert(
|
|
|
|
|
phantom_node_pair.targetPhantom.edgeBasedNode,
|
|
|
|
|
phantom_node_pair.targetPhantom.weight1,
|
|
|
|
|
phantom_node_pair.targetPhantom.edgeBasedNode
|
|
|
|
|
);
|
|
|
|
|
// INFO("rv1: " << phantom_node_pair.targetPhantom.edgeBasedNode << ", w;" << phantom_node_pair.targetPhantom.weight1 );
|
|
|
|
|
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
|
|
|
|
reverse_heap2.Insert(
|
|
|
|
|
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
|
|
|
|
phantom_node_pair.targetPhantom.weight2,
|
|
|
|
|
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
|
|
|
|
);
|
|
|
|
|
// INFO("rv2: " << phantom_node_pair.targetPhantom.edgeBasedNode+1 << ", w;" << phantom_node_pair.targetPhantom.weight2 );
|
2013-06-26 09:32:03 -04:00
|
|
|
|
}
|
2013-09-24 04:58:24 -04:00
|
|
|
|
const int forward_offset = super::ComputeEdgeOffset(
|
2013-09-22 16:18:54 -04:00
|
|
|
|
phantom_node_pair.startPhantom
|
|
|
|
|
);
|
2013-09-24 04:58:24 -04:00
|
|
|
|
const int reverse_offset = super::ComputeEdgeOffset(
|
2013-09-22 16:18:54 -04:00
|
|
|
|
phantom_node_pair.targetPhantom
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
|
|
//run two-Target Dijkstra routing step.
|
2013-02-06 09:23:57 -05:00
|
|
|
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( !forward_heap1.Empty()){
|
|
|
|
|
super::RoutingStep(
|
|
|
|
|
forward_heap1,
|
|
|
|
|
reverse_heap1,
|
|
|
|
|
&middle1,
|
|
|
|
|
&local_upper_bound1,
|
|
|
|
|
forward_offset,
|
|
|
|
|
true
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( !reverse_heap1.Empty() ){
|
|
|
|
|
super::RoutingStep(
|
|
|
|
|
reverse_heap1,
|
|
|
|
|
forward_heap1,
|
|
|
|
|
&middle1,
|
|
|
|
|
&local_upper_bound1,
|
|
|
|
|
reverse_offset,
|
|
|
|
|
false
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( !reverse_heap2.Empty() ) {
|
2013-02-06 09:23:57 -05:00
|
|
|
|
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( !forward_heap2.Empty() ){
|
|
|
|
|
super::RoutingStep(
|
|
|
|
|
forward_heap2,
|
|
|
|
|
reverse_heap2,
|
|
|
|
|
&middle2,
|
|
|
|
|
&local_upper_bound2,
|
|
|
|
|
forward_offset,
|
|
|
|
|
true
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( !reverse_heap2.Empty() ){
|
|
|
|
|
super::RoutingStep(
|
|
|
|
|
reverse_heap2,
|
|
|
|
|
forward_heap2,
|
|
|
|
|
&middle2,
|
|
|
|
|
&local_upper_bound2,
|
|
|
|
|
reverse_offset,
|
|
|
|
|
false
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//No path found for both target nodes?
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if(
|
|
|
|
|
(INT_MAX == local_upper_bound1) &&
|
|
|
|
|
(INT_MAX == local_upper_bound2)
|
|
|
|
|
) {
|
|
|
|
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
|
|
|
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
2012-06-19 11:26:34 -04:00
|
|
|
|
return;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
if(UINT_MAX == middle1) {
|
2013-09-21 16:10:41 -04:00
|
|
|
|
search_from_1st_node = false;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
if(UINT_MAX == middle2) {
|
2013-09-21 16:10:41 -04:00
|
|
|
|
search_from_2nd_node = false;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Was at most one of the two paths not found?
|
2013-09-21 16:18:27 -04:00
|
|
|
|
BOOST_ASSERT_MSG(
|
|
|
|
|
(INT_MAX != distance1 || INT_MAX != distance2),
|
|
|
|
|
"no path found"
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
|
|
//Unpack paths if they exist
|
2013-09-21 16:10:41 -04:00
|
|
|
|
std::vector<NodeID> temporary_packed_path1;
|
|
|
|
|
std::vector<NodeID> temporary_packed_path2;
|
|
|
|
|
if(INT_MAX != local_upper_bound1) {
|
|
|
|
|
super::RetrievePackedPathFromHeap(
|
|
|
|
|
forward_heap1,
|
|
|
|
|
reverse_heap1,
|
|
|
|
|
middle1,
|
|
|
|
|
temporary_packed_path1
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if(INT_MAX != local_upper_bound2) {
|
|
|
|
|
super::RetrievePackedPathFromHeap(
|
|
|
|
|
forward_heap2,
|
|
|
|
|
reverse_heap2,
|
|
|
|
|
middle2,
|
|
|
|
|
temporary_packed_path2
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if one of the paths was not found, replace it with the other one.
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( temporary_packed_path1.empty() ) {
|
|
|
|
|
temporary_packed_path1.insert(
|
|
|
|
|
temporary_packed_path1.end(),
|
|
|
|
|
temporary_packed_path2.begin(),
|
|
|
|
|
temporary_packed_path2.end()
|
|
|
|
|
);
|
|
|
|
|
local_upper_bound1 = local_upper_bound2;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( temporary_packed_path2.empty() ) {
|
|
|
|
|
temporary_packed_path2.insert(
|
|
|
|
|
temporary_packed_path2.end(),
|
|
|
|
|
temporary_packed_path1.begin(),
|
|
|
|
|
temporary_packed_path1.end()
|
|
|
|
|
);
|
|
|
|
|
local_upper_bound2 = local_upper_bound1;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-21 16:18:27 -04:00
|
|
|
|
BOOST_ASSERT_MSG(
|
|
|
|
|
temporary_packed_path1.empty() &&
|
|
|
|
|
temporary_packed_path2.empty(),
|
|
|
|
|
"tempory packed paths not empty"
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
|
|
|
|
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( !packed_path1.empty() && !packed_path2.empty() ) {
|
2013-09-22 16:29:03 -04:00
|
|
|
|
if(
|
|
|
|
|
temporary_packed_path1.front() ==
|
|
|
|
|
temporary_packed_path2.front()
|
|
|
|
|
) {
|
2013-09-21 16:21:33 -04:00
|
|
|
|
//both new route segments start with the same node
|
|
|
|
|
//thus, one of the packedPath must go.
|
2013-09-21 16:18:27 -04:00
|
|
|
|
BOOST_ASSERT_MSG(
|
|
|
|
|
(packed_path1.size() == packed_path2.size() ) ||
|
|
|
|
|
(packed_path1.back() != packed_path2.back() ),
|
|
|
|
|
"packed paths must be different"
|
|
|
|
|
);
|
|
|
|
|
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if( packed_path1.back() == temporary_packed_path1.front()) {
|
|
|
|
|
packed_path2.clear();
|
|
|
|
|
packed_path2.insert(
|
|
|
|
|
packed_path2.end(),
|
|
|
|
|
packed_path1.begin(),
|
|
|
|
|
packed_path1.end()
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
distance2 = distance1;
|
|
|
|
|
} else {
|
2013-09-21 16:10:41 -04:00
|
|
|
|
packed_path1.clear();
|
|
|
|
|
packed_path1.insert(
|
|
|
|
|
packed_path1.end(),
|
|
|
|
|
packed_path2.begin(),
|
|
|
|
|
packed_path2.end()
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
distance1 = distance2;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//packed paths 1 and 2 may need to switch.
|
2013-09-21 16:21:33 -04:00
|
|
|
|
if( packed_path1.back() != temporary_packed_path1.front()) {
|
2013-09-21 16:10:41 -04:00
|
|
|
|
packed_path1.swap(packed_path2);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
std::swap(distance1, distance2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
packed_path1.insert(
|
|
|
|
|
packed_path1.end(),
|
|
|
|
|
temporary_packed_path1.begin(),
|
|
|
|
|
temporary_packed_path1.end()
|
|
|
|
|
);
|
|
|
|
|
packed_path2.insert(
|
|
|
|
|
packed_path2.end(),
|
|
|
|
|
temporary_packed_path2.begin(),
|
|
|
|
|
temporary_packed_path2.end()
|
|
|
|
|
);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
|
2013-09-21 16:10:41 -04:00
|
|
|
|
if(
|
|
|
|
|
(packed_path1.back() == packed_path2.back()) &&
|
|
|
|
|
phantom_node_pair.targetPhantom.isBidirected()
|
|
|
|
|
) {
|
2013-09-21 16:21:33 -04:00
|
|
|
|
const NodeID last_node_id = packed_path2.back();
|
2013-09-21 16:10:41 -04:00
|
|
|
|
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
|
|
|
|
|
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-21 16:10:41 -04:00
|
|
|
|
distance1 += local_upper_bound1;
|
|
|
|
|
distance2 += local_upper_bound2;
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-22 16:29:03 -04:00
|
|
|
|
if( distance1 > distance2 ) {
|
2013-09-21 16:10:41 -04:00
|
|
|
|
std::swap( packed_path1, packed_path2 );
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
2013-09-21 16:10:41 -04:00
|
|
|
|
remove_consecutive_duplicates_from_vector(packed_path1);
|
|
|
|
|
super::UnpackPath(packed_path1, raw_route_data.computedShortestPath);
|
|
|
|
|
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
|
2012-06-15 12:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif /* SHORTESTPATHROUTING_H_ */
|