Implemented T-Test and output of route options
This commit is contained in:
parent
5ebc4b392f
commit
61efd41194
@ -248,7 +248,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
||||
if(turnInstruction == TurnInstructions.UTurn)
|
||||
distance += uturnPenalty;
|
||||
if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
|
||||
distance += TurnInstructions.AccessRestrictionPenaly;
|
||||
distance += TurnInstructions.AccessRestrictionPenalty;
|
||||
turnInstruction |= TurnInstructions.AccessRestrictionFlag;
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,8 @@ struct SearchEngineData {
|
||||
static HeapPtr backwardHeap;
|
||||
static HeapPtr forwardHeap2;
|
||||
static HeapPtr backwardHeap2;
|
||||
static HeapPtr forwardHeap3;
|
||||
static HeapPtr backwardHeap3;
|
||||
|
||||
inline void InitializeOrClearFirstThreadLocalStorage() {
|
||||
if(!forwardHeap.get()) {
|
||||
@ -84,6 +86,20 @@ struct SearchEngineData {
|
||||
else
|
||||
backwardHeap2->Clear();
|
||||
}
|
||||
|
||||
inline void InitializeOrClearThirdThreadLocalStorage() {
|
||||
if(!forwardHeap3.get()) {
|
||||
forwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
||||
}
|
||||
else
|
||||
forwardHeap3->Clear();
|
||||
|
||||
if(!backwardHeap3.get()) {
|
||||
backwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
||||
}
|
||||
else
|
||||
backwardHeap3->Clear();
|
||||
}
|
||||
};
|
||||
|
||||
template<class EdgeData, class GraphT>
|
||||
@ -149,4 +165,7 @@ template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<Edge
|
||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap2;
|
||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap2;
|
||||
|
||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap3;
|
||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap3;
|
||||
|
||||
#endif /* SEARCHENGINE_H_ */
|
||||
|
@ -46,7 +46,7 @@ struct TurnInstructionsClass {
|
||||
const static short AccessRestrictionFlag = (1<<14);
|
||||
const static short InverseAccessRestrictionFlag = ~(1<<14);
|
||||
|
||||
const static int AccessRestrictionPenaly = 1 << 15; //unrelated to the bit set in the restriction flag
|
||||
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
|
||||
|
||||
// std::string TurnStrings[16];
|
||||
// std::string Ordinals[12];
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
BaseDescriptor() { }
|
||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() { }
|
||||
virtual void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) = 0;
|
||||
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) = 0;
|
||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
||||
};
|
||||
|
||||
|
@ -33,20 +33,20 @@ private:
|
||||
std::string tmp;
|
||||
public:
|
||||
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
||||
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
|
||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
|
||||
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content += "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||
"\">";
|
||||
reply.content += "<rte>";
|
||||
if(distance != UINT_MAX && rawRoute.computedRouted.size()) {
|
||||
if(rawRoute.lengthOfShortestPath != UINT_MAX && rawRoute.computedShortestPath.size()) {
|
||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||
|
||||
BOOST_FOREACH(_PathData pathData, rawRoute.computedRouted) {
|
||||
BOOST_FOREACH(_PathData pathData, rawRoute.computedShortestPath) {
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
|
||||
convertInternalLatLonToString(current.lat, tmp);
|
||||
|
@ -36,6 +36,7 @@ class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||
private:
|
||||
_DescriptorConfig config;
|
||||
DescriptionFactory descriptionFactory;
|
||||
DescriptionFactory alternateDescriptionFactory;
|
||||
_Coordinate current;
|
||||
unsigned numberOfEnteredRestrictedAreas;
|
||||
struct {
|
||||
@ -48,15 +49,15 @@ public:
|
||||
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
||||
|
||||
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, const unsigned durationOfTrip) {
|
||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
|
||||
WriteHeaderToOutput(reply.content);
|
||||
if(durationOfTrip != INT_MAX) {
|
||||
if(rawRoute.lengthOfShortestPath != INT_MAX) {
|
||||
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||
reply.content += "0,"
|
||||
"\"status_message\": \"Found route between points\",";
|
||||
|
||||
//Get all the coordinates for the computed route
|
||||
BOOST_FOREACH(_PathData & pathData, rawRoute.computedRouted) {
|
||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
descriptionFactory.AppendSegment(current, pathData );
|
||||
}
|
||||
@ -67,7 +68,7 @@ public:
|
||||
"\"status_message\": \"Cannot find route between points\",";
|
||||
}
|
||||
|
||||
descriptionFactory.Run(sEngine, config.z, durationOfTrip);
|
||||
descriptionFactory.Run(sEngine, config.z, rawRoute.lengthOfShortestPath);
|
||||
reply.content += "\"route_geometry\": ";
|
||||
if(config.geometry) {
|
||||
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
||||
@ -77,85 +78,9 @@ public:
|
||||
|
||||
reply.content += ","
|
||||
"\"route_instructions\": [";
|
||||
numberOfEnteredRestrictedAreas = 0;
|
||||
if(config.instructions) {
|
||||
//Segment information has following format:
|
||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
||||
unsigned prefixSumOfNecessarySegments = 0;
|
||||
roundAbout.leaveAtExit = 0;
|
||||
roundAbout.nameID = 0;
|
||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
||||
//Fetch data from Factory and generate a string from it.
|
||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
||||
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
|
||||
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
|
||||
roundAbout.nameID = segment.nameID;
|
||||
roundAbout.startIndex = prefixSumOfNecessarySegments;
|
||||
} else {
|
||||
if(0 != prefixSumOfNecessarySegments){
|
||||
reply.content += ",";
|
||||
}
|
||||
reply.content += "[\"";
|
||||
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
|
||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
reply.content += "-";
|
||||
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
roundAbout.leaveAtExit = 0;
|
||||
} else {
|
||||
intToString(currentInstruction, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
}
|
||||
reply.content += "\",\"";
|
||||
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
|
||||
reply.content += "\",";
|
||||
intToString(segment.length, tmpDist);
|
||||
reply.content += tmpDist;
|
||||
reply.content += ",";
|
||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
||||
reply.content += tmpLength;
|
||||
reply.content += ",";
|
||||
intToString(segment.duration, tmpDuration);
|
||||
reply.content += tmpDuration;
|
||||
reply.content += ",\"";
|
||||
intToString(segment.length, tmpLength);
|
||||
reply.content += tmpLength;
|
||||
reply.content += "m\",\"";
|
||||
reply.content += Azimuth::Get(segment.bearing);
|
||||
reply.content += "\",";
|
||||
intToString(round(segment.bearing), tmpBearing);
|
||||
reply.content += tmpBearing;
|
||||
reply.content += "]";
|
||||
}
|
||||
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
|
||||
++roundAbout.leaveAtExit;
|
||||
}
|
||||
if(segment.necessary)
|
||||
++prefixSumOfNecessarySegments;
|
||||
}
|
||||
if(durationOfTrip != INT_MAX) {
|
||||
reply.content += ",[\"";
|
||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
reply.content += "\",\"";
|
||||
reply.content += "\",";
|
||||
reply.content += "0";
|
||||
reply.content += ",";
|
||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
||||
reply.content += tmpLength;
|
||||
reply.content += ",";
|
||||
reply.content += "0";
|
||||
reply.content += ",\"";
|
||||
reply.content += "\",\"";
|
||||
reply.content += Azimuth::Get(0.0);
|
||||
reply.content += "\",";
|
||||
reply.content += "0.0";
|
||||
reply.content += "]";
|
||||
}
|
||||
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine);
|
||||
} else {
|
||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
||||
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
@ -163,11 +88,11 @@ public:
|
||||
}
|
||||
}
|
||||
reply.content += "],";
|
||||
// INFO("Entered " << numberOfEnteredRestrictedAreas << " restricted areas");
|
||||
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, durationOfTrip - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenaly));
|
||||
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
|
||||
|
||||
reply.content += "\"route_summary\": {"
|
||||
"\"total_distance\":";
|
||||
reply.content += "\"route_summary\":";
|
||||
reply.content += "{";
|
||||
reply.content += "\"total_distance\":";
|
||||
reply.content += descriptionFactory.summary.lengthString;
|
||||
reply.content += ","
|
||||
"\"total_time\":";
|
||||
@ -179,12 +104,54 @@ public:
|
||||
"\"end_point\":\"";
|
||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
|
||||
reply.content += "\"";
|
||||
reply.content += "},";
|
||||
reply.content += "}";
|
||||
reply.content +=",";
|
||||
|
||||
//only one alternative route is computed at this time, so this is hardcoded
|
||||
|
||||
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
|
||||
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||
//Get all the coordinates for the computed route
|
||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
alternateDescriptionFactory.AppendSegment(current, pathData );
|
||||
}
|
||||
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
||||
}
|
||||
alternateDescriptionFactory.Run(sEngine, config.z, rawRoute.lengthOfAlternativePath);
|
||||
|
||||
//give an array of alternative routes
|
||||
reply.content += "\"alternative_geometries\": [";
|
||||
if(config.geometry) {
|
||||
//Generate the linestrings for each alternative
|
||||
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content += "\"alternative_instructions\":[";
|
||||
if(config.instructions) {
|
||||
reply.content += "[";
|
||||
//Generate instructions for each alternative
|
||||
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine);
|
||||
reply.content += "]";
|
||||
}
|
||||
reply.content += "],";
|
||||
reply.content += "\"alternative_summaries\":[";
|
||||
//Generate route summary (length, duration) for each alternative
|
||||
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
|
||||
reply.content += "{";
|
||||
reply.content += "\"total_distance\":";
|
||||
reply.content += alternateDescriptionFactory.summary.lengthString;
|
||||
reply.content += ","
|
||||
"\"total_time\":";
|
||||
reply.content += alternateDescriptionFactory.summary.durationString;
|
||||
reply.content += "}";
|
||||
|
||||
reply.content += "],";
|
||||
|
||||
//list all viapoints so that the client may display it
|
||||
reply.content += "\"via_points\":[";
|
||||
std::string tmp;
|
||||
if(config.geometry && INT_MAX != durationOfTrip) {
|
||||
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
|
||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content += "[";
|
||||
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
|
||||
@ -231,5 +198,88 @@ public:
|
||||
"\"version\": 0.3,"
|
||||
"\"status\":";
|
||||
}
|
||||
|
||||
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngineT &sEngine) {
|
||||
//Segment information has following format:
|
||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
||||
unsigned prefixSumOfNecessarySegments = 0;
|
||||
roundAbout.leaveAtExit = 0;
|
||||
roundAbout.nameID = 0;
|
||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
||||
//Fetch data from Factory and generate a string from it.
|
||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
||||
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
||||
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
|
||||
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
|
||||
roundAbout.nameID = segment.nameID;
|
||||
roundAbout.startIndex = prefixSumOfNecessarySegments;
|
||||
} else {
|
||||
if(0 != prefixSumOfNecessarySegments){
|
||||
reply.content += ",";
|
||||
}
|
||||
reply.content += "[\"";
|
||||
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
|
||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
reply.content += "-";
|
||||
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
roundAbout.leaveAtExit = 0;
|
||||
} else {
|
||||
intToString(currentInstruction, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
}
|
||||
reply.content += "\",\"";
|
||||
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
|
||||
reply.content += "\",";
|
||||
intToString(segment.length, tmpDist);
|
||||
reply.content += tmpDist;
|
||||
reply.content += ",";
|
||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
||||
reply.content += tmpLength;
|
||||
reply.content += ",";
|
||||
intToString(segment.duration, tmpDuration);
|
||||
reply.content += tmpDuration;
|
||||
reply.content += ",\"";
|
||||
intToString(segment.length, tmpLength);
|
||||
reply.content += tmpLength;
|
||||
reply.content += "m\",\"";
|
||||
reply.content += Azimuth::Get(segment.bearing);
|
||||
reply.content += "\",";
|
||||
intToString(round(segment.bearing), tmpBearing);
|
||||
reply.content += tmpBearing;
|
||||
reply.content += "]";
|
||||
}
|
||||
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
|
||||
++roundAbout.leaveAtExit;
|
||||
}
|
||||
if(segment.necessary)
|
||||
++prefixSumOfNecessarySegments;
|
||||
}
|
||||
if(INT_MAX != lengthOfRoute) {
|
||||
reply.content += ",[\"";
|
||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
||||
reply.content += tmpInstruction;
|
||||
reply.content += "\",\"";
|
||||
reply.content += "\",";
|
||||
reply.content += "0";
|
||||
reply.content += ",";
|
||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
||||
reply.content += tmpLength;
|
||||
reply.content += ",";
|
||||
reply.content += "0";
|
||||
reply.content += ",\"";
|
||||
reply.content += "\",\"";
|
||||
reply.content += Azimuth::Get(0.0);
|
||||
reply.content += "\",";
|
||||
reply.content += "0.0";
|
||||
reply.content += "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
|
@ -22,10 +22,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#define RAWROUTEDATA_H_
|
||||
|
||||
struct RawRouteData {
|
||||
std::vector< _PathData > computedRouted;
|
||||
std::vector< _PathData > computedShortestPath;
|
||||
std::vector< _PathData > computedAlternativePath;
|
||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
||||
std::vector< _Coordinate > rawViaNodeCoordinates;
|
||||
unsigned checkSum;
|
||||
int lengthOfShortestPath;
|
||||
int lengthOfAlternativePath;
|
||||
};
|
||||
|
||||
#endif /* RAWROUTEDATA_H_ */
|
||||
|
@ -112,38 +112,39 @@ public:
|
||||
// INFO("Brute force lookup of coordinate " << i);
|
||||
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i]);
|
||||
}
|
||||
unsigned distance = 0;
|
||||
//unsigned distance = 0;
|
||||
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||
}
|
||||
distance = searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute.computedRouted);
|
||||
|
||||
std::vector<_PathData> alternative;
|
||||
if(1 == rawRoute.segmentEndCoordinates.size()) {
|
||||
INFO("Checking for alternative paths");
|
||||
int distance2 = searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], alternative);
|
||||
}
|
||||
std::cout << "latitude,longitude" << std::endl;
|
||||
for(unsigned i = 0; i < rawRoute.computedRouted.size(); ++i) {
|
||||
_Coordinate current;
|
||||
searchEngine->GetCoordinatesForNodeID(rawRoute.computedRouted[i].node, current);
|
||||
std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// INFO("Checking for alternative paths");
|
||||
searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
||||
|
||||
std::cout << "latitude,longitude" << std::endl;
|
||||
for(unsigned i = 0; i <alternative.size(); ++i) {
|
||||
_Coordinate current;
|
||||
searchEngine->GetCoordinatesForNodeID(alternative[i].node, current);
|
||||
std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl;
|
||||
} else {
|
||||
searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// std::cout << "latitude,longitude" << std::endl;
|
||||
// for(unsigned i = 0; i < rawRoute.computedShortestPath.size(); ++i) {
|
||||
// _Coordinate current;
|
||||
// searchEngine->GetCoordinatesForNodeID(rawRoute.computedShortestPath[i].node, current);
|
||||
// std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl;
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
//
|
||||
// std::cout << "latitude,longitude" << std::endl;
|
||||
// for(unsigned i = 0; i < rawRoute.computedAlternativePath.size(); ++i) {
|
||||
// _Coordinate current;
|
||||
// searchEngine->GetCoordinatesForNodeID(rawRoute.computedAlternativePath[i].node, current);
|
||||
// std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl;
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
|
||||
if(INT_MAX == distance ) {
|
||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
||||
DEBUG( "Error occurred, single path not found" );
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
@ -197,7 +198,7 @@ public:
|
||||
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
|
||||
desc->SetConfig(descriptorConfig);
|
||||
|
||||
desc->Run(reply, rawRoute, phantomNodes, *searchEngine, distance);
|
||||
desc->Run(reply, rawRoute, phantomNodes, *searchEngine);
|
||||
if("" != JSONParameter) {
|
||||
reply.content += ")\n";
|
||||
}
|
||||
|
@ -25,12 +25,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
|
||||
#include "BasicRoutingInterface.h"
|
||||
|
||||
const double VIAPATH_ALPHA = 0.25;
|
||||
const double VIAPATH_EPSILON = 0.25;
|
||||
const double VIAPATH_GAMMA = 0.80;
|
||||
|
||||
template<class QueryDataT>
|
||||
class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{
|
||||
typedef BasicRoutingInterface<QueryDataT> super;
|
||||
typedef std::pair<NodeID, int> PreselectedNode;
|
||||
typedef typename QueryDataT::HeapPtr HeapPtr;
|
||||
|
||||
struct RankedCandidateNode {
|
||||
RankedCandidateNode(NodeID n, int l, int s) : node(n), length(l), sharing(s) {}
|
||||
@ -47,18 +50,18 @@ public:
|
||||
|
||||
~AlternativeRouting() {}
|
||||
|
||||
int operator()(const PhantomNodes & phantomNodePair, std::vector<_PathData> & unpackedPath) {
|
||||
void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
|
||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||
return;
|
||||
}
|
||||
std::vector<NodeID> alternativePath;
|
||||
std::vector<NodeID> viaNodeCandidates;
|
||||
|
||||
int _lengthOfShortestPath = INT_MAX;
|
||||
|
||||
INFO("Checking for alternative between (" << phantomNodePair.startPhantom.location << ") and (" << phantomNodePair.targetPhantom.location << ")");
|
||||
|
||||
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap;
|
||||
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap;
|
||||
typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
|
||||
typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
|
||||
HeapPtr & forwardHeap = super::_queryData.forwardHeap;
|
||||
HeapPtr & backwardHeap = super::_queryData.backwardHeap;
|
||||
HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
|
||||
HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
|
||||
|
||||
//Initialize Queues
|
||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
||||
@ -87,17 +90,20 @@ public:
|
||||
}
|
||||
std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end());
|
||||
int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin();
|
||||
std::cout << "middle: " << middle << ", other: ";
|
||||
for(unsigned i = 0; i < size; ++i)
|
||||
if(middle != viaNodeCandidates[i])
|
||||
std::cout << viaNodeCandidates[i] << " ";
|
||||
std::cout << std::endl;
|
||||
// std::cout << "middle: " << middle << ", other: ";
|
||||
// for(unsigned i = 0; i < size; ++i)
|
||||
// if(middle != viaNodeCandidates[i])
|
||||
// std::cout << viaNodeCandidates[i] << " ";
|
||||
// std::cout << std::endl;
|
||||
viaNodeCandidates.resize(size);
|
||||
INFO("found " << viaNodeCandidates.size() << " nodes in search space intersection");
|
||||
// INFO("found " << viaNodeCandidates.size() << " nodes in search space intersection");
|
||||
//
|
||||
// INFO("upper bound: " << _upperBound);
|
||||
std::deque<NodeID> packedShortestPath;
|
||||
|
||||
INFO("upper bound: " << _upperBound);
|
||||
//TODO: save (packed) shortest path of shortest path and keep it for later use.
|
||||
//save (packed) shortest path of shortest path and keep it for later use.
|
||||
//we need it during the checks and dont want to recompute it always
|
||||
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath);
|
||||
|
||||
//ch-pruning of via nodes in both search spaces
|
||||
|
||||
@ -107,19 +113,19 @@ public:
|
||||
if(node == middle)
|
||||
continue;
|
||||
|
||||
// std::cout << "via path over " << node << std::endl;
|
||||
int sharing = approximateAmountOfSharing(middle, node, forwardHeap, backwardHeap);
|
||||
// std::cout << "via path over " << node << std::endl;
|
||||
int sharing = approximateAmountOfSharing(node, forwardHeap, backwardHeap, packedShortestPath);
|
||||
|
||||
int length1 = forwardHeap->GetKey(node);
|
||||
int length2 = backwardHeap->GetKey(node);
|
||||
// std::cout << " length: " << length1+length2 << std::endl;
|
||||
bool lengthPassed = (length1+length2 < _upperBound*1.25);
|
||||
// std::cout << " length passed: " << (lengthPassed ? "yes" : "no") << std::endl;
|
||||
// std::cout << " apx-sharing: " << sharing << std::endl;
|
||||
bool sharingPassed = (sharing <= _upperBound*0.8);
|
||||
// std::cout << " apx-sharing passed: " << ( sharingPassed ? "yes" : "no") << std::endl;
|
||||
bool stretchPassed = length1+length2 - sharing < 1.25*(_upperBound-sharing);
|
||||
// std::cout << " apx-stretch passed: " << ( stretchPassed ? "yes" : "no") << std::endl;
|
||||
// std::cout << " length: " << length1+length2 << std::endl;
|
||||
bool lengthPassed = (length1+length2 < _upperBound*(1+VIAPATH_EPSILON));
|
||||
// std::cout << " length passed: " << (lengthPassed ?osrm "yes" : "no") << std::endl;
|
||||
// std::cout << " apx-sharing: " << sharing << std::endl;
|
||||
bool sharingPassed = (sharing <= _upperBound*VIAPATH_GAMMA);
|
||||
// std::cout << " apx-sharing passed: " << ( sharingPassed ? "yes" : "no") << std::endl;
|
||||
bool stretchPassed = length1+length2 - sharing < (1.+VIAPATH_EPSILON)*(_upperBound-sharing);
|
||||
// std::cout << " apx-stretch passed: " << ( stretchPassed ? "yes" : "no") << std::endl;
|
||||
|
||||
if(lengthPassed && sharingPassed && stretchPassed)
|
||||
nodesThatPassPreselection.push_back(std::make_pair(node, length1+length2));
|
||||
@ -127,177 +133,153 @@ public:
|
||||
|
||||
std::vector<RankedCandidateNode > rankedCandidates;
|
||||
|
||||
INFO(nodesThatPassPreselection.size() << " out of " << viaNodeCandidates.size() << " passed preselection");
|
||||
// INFO(nodesThatPassPreselection.size() << " out of " << viaNodeCandidates.size() << " passed preselection");
|
||||
//prioritizing via nodes
|
||||
BOOST_FOREACH(const PreselectedNode node, nodesThatPassPreselection) {
|
||||
int lengthOfViaPath = 0;
|
||||
int sharingOfViaPath = 0;
|
||||
|
||||
computeLengthAndSharingOfViaPath(phantomNodePair, node, &lengthOfViaPath, &sharingOfViaPath, offset, middle);
|
||||
computeLengthAndSharingOfViaPath(phantomNodePair, node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath);
|
||||
rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath));
|
||||
}
|
||||
|
||||
std::sort(rankedCandidates.begin(), rankedCandidates.end());
|
||||
|
||||
NodeID selectedViaNode = UINT_MAX;
|
||||
int lengthOfViaPath = INT_MAX;
|
||||
|
||||
BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){
|
||||
//conduct T-Test
|
||||
if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, middle, _upperBound)) {
|
||||
if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, middle, _upperBound, &lengthOfViaPath)) {
|
||||
// select first admissable
|
||||
selectedViaNode = candidate.node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
|
||||
//Same (co-)routines necessary as for computing length and sharing
|
||||
if(selectedViaNode != UINT_MAX) {
|
||||
//Unpack shortest path and alternative, if they exist
|
||||
if(INT_MAX != _upperBound)
|
||||
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
|
||||
|
||||
retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, selectedViaNode, unpackedPath);
|
||||
}
|
||||
return 0;
|
||||
if(selectedViaNode != UINT_MAX)
|
||||
retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, selectedViaNode, rawRouteData.computedAlternativePath);
|
||||
|
||||
rawRouteData.lengthOfShortestPath = _upperBound;
|
||||
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void retrievePackedViaPath(typename QueryDataT::HeapPtr & _forwardHeap1, typename QueryDataT::HeapPtr & _backwardHeap1, typename QueryDataT::HeapPtr & _forwardHeap2, typename QueryDataT::HeapPtr & _backwardHeap2, const NodeID viaNode, std::vector<_PathData> & unpackedPath) {
|
||||
//unpack <s,..,v,..,t> by exploring search spaces from v
|
||||
inline void retrievePackedViaPath(HeapPtr & _forwardHeap1, HeapPtr & _backwardHeap1, HeapPtr & _forwardHeap2, HeapPtr & _backwardHeap2, const NodeID viaNode, std::vector<_PathData> & unpackedPath) {
|
||||
//unpack s,v
|
||||
std::deque<NodeID> packed_s_v_path, packed_v_t_path;
|
||||
std::cout << "1" << std::endl;
|
||||
// std::cout << "1" << std::endl;
|
||||
super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, viaNode, packed_s_v_path);
|
||||
std::cout << "2" << std::endl;
|
||||
// std::cout << "2" << std::endl;
|
||||
packed_s_v_path.resize(packed_s_v_path.size()-1);
|
||||
super::RetrievePackedPathFromHeap(_forwardHeap2, _backwardHeap1, viaNode, packed_v_t_path);
|
||||
std::cout << "3" << std::endl;
|
||||
// std::cout << "3" << std::endl;
|
||||
packed_s_v_path.insert(packed_s_v_path.end(),packed_v_t_path.begin(), packed_v_t_path.end() );
|
||||
std::cout << "4" << std::endl;
|
||||
// std::cout << "4" << std::endl;
|
||||
|
||||
for(unsigned i = 0; i < packed_s_v_path.size(); ++i)
|
||||
std::cout << packed_s_v_path[i] << " " << std::endl;
|
||||
std::cout << std::endl;
|
||||
// for(unsigned i = 0; i < packed_s_v_path.size(); ++i)
|
||||
// std::cout << packed_s_v_path[i] << " " << std::endl;
|
||||
// std::cout << std::endl;
|
||||
|
||||
super::UnpackPath(packed_s_v_path, unpackedPath);
|
||||
|
||||
}
|
||||
|
||||
inline void computeLengthAndSharingOfViaPath(const PhantomNodes & phantomNodePair, const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath, const int offset, const NodeID middleOfShortestPath) {
|
||||
inline void computeLengthAndSharingOfViaPath(const PhantomNodes & phantomNodePair, const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath, const int offset, const std::deque<NodeID> & packedShortestPath) {
|
||||
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
|
||||
//only half-searches have to be done at this stage
|
||||
std::cout << "deep check for via path " << node.first << std::endl;
|
||||
// std::cout << "deep check for via path " << node.first << std::endl;
|
||||
|
||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||
|
||||
typename QueryDataT::HeapPtr & existingForwardHeap = super::_queryData.forwardHeap;
|
||||
typename QueryDataT::HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap;
|
||||
|
||||
typename QueryDataT::HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
|
||||
typename QueryDataT::HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
|
||||
HeapPtr & existingForwardHeap = super::_queryData.forwardHeap;
|
||||
HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap;
|
||||
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
|
||||
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
|
||||
|
||||
NodeID s_v_middle = UINT_MAX;
|
||||
int upperBoundFor_s_v_Path = INT_MAX;//existingForwardHeap->GetKey(node.first);
|
||||
|
||||
//compute path <s,..,v> by reusing forward search from s
|
||||
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
|
||||
newBackwardHeap->Insert(node.first, 0, node.first);
|
||||
while(newBackwardHeap->Size() > 0){
|
||||
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
|
||||
while (newBackwardHeap->Size() > 0) {
|
||||
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
|
||||
}
|
||||
std::cout << " length of <s,..,v>: " << upperBoundFor_s_v_Path << " with middle node " << s_v_middle << std::endl;
|
||||
|
||||
// std::cout << " length of <s,..,v>: " << upperBoundFor_s_v_Path << " with middle node " << s_v_middle << std::endl;
|
||||
//compute path <v,..,t> by reusing backward search from t
|
||||
NodeID v_t_middle = UINT_MAX;
|
||||
int upperBoundFor_v_t_Path = INT_MAX;//existingBackwardHeap->GetKey(node.first);
|
||||
int upperBoundFor_v_t_Path = INT_MAX;
|
||||
newForwardHeap->Insert(node.first, 0, node.first);
|
||||
while(newForwardHeap->Size() > 0){
|
||||
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
|
||||
while (newForwardHeap->Size() > 0) {
|
||||
super::RoutingStep(newForwardHeap, existingBackwardHeap,
|
||||
&v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
|
||||
}
|
||||
std::cout << " length of <v,..,t>: " << upperBoundFor_v_t_Path << " with middle node " << v_t_middle << std::endl;
|
||||
// std::cout << " length of <v,..,t>: " << upperBoundFor_v_t_Path << " with middle node " << v_t_middle << std::endl;
|
||||
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
|
||||
// std::cout << " exact length of via path: " << *lengthOfViaPath << std::endl;
|
||||
|
||||
*lengthOfViaPath = upperBoundFor_s_v_Path+upperBoundFor_v_t_Path;
|
||||
std::cout << " exact length of via path: " << *lengthOfViaPath << std::endl;
|
||||
|
||||
std::deque<NodeID> packedShortestPath;
|
||||
std::deque<NodeID> packed_s_v_path;
|
||||
std::deque<NodeID> packed_v_t_path;
|
||||
std::deque < NodeID > packed_s_v_path;
|
||||
std::deque < NodeID > packed_v_t_path;
|
||||
//retrieve packed paths
|
||||
std::cout << " retrieving packed path for middle nodes " << middleOfShortestPath << "," << s_v_middle << "," << v_t_middle << " (shorstest, sv, vt)" << std::endl;
|
||||
super::RetrievePackedPathFromHeap(existingForwardHeap, existingBackwardHeap, middleOfShortestPath, packedShortestPath);
|
||||
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path);
|
||||
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle,packed_v_t_path);
|
||||
|
||||
std::cout << "packed sv: ";
|
||||
for(unsigned i = 0; i < packed_s_v_path.size(); ++i) {
|
||||
std::cout << packed_s_v_path[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
std::cout << "packed vt: ";
|
||||
for(unsigned i = 0; i < packed_v_t_path.size(); ++i) {
|
||||
std::cout << packed_v_t_path[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
std::cout << "packed shortest: ";
|
||||
for(unsigned i = 0; i < packedShortestPath.size(); ++i) {
|
||||
std::cout << packedShortestPath[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
|
||||
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle, packed_v_t_path);
|
||||
typedef std::pair<NodeID, NodeID> UnpackEdge;
|
||||
std::stack<UnpackEdge > unpackStack;
|
||||
|
||||
//TODO: partial unpacking, compute sharing
|
||||
std::stack<UnpackEdge> unpackStack;
|
||||
//partial unpacking, compute sharing
|
||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||
std::cout << "length of packed sv-path: " << packed_s_v_path.size() << ", length of packed shortest path: " << packedShortestPath.size() << std::endl;
|
||||
for(unsigned i = 0, lengthOfPackedPath = std::min(packed_s_v_path.size(), packedShortestPath.size() ) - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i ) {
|
||||
std::cout << " checking indices [" << i << "] and [" << (i+1) << "]" << std::endl;
|
||||
if(packed_s_v_path[i] == packedShortestPath[i] && packed_s_v_path[i+1] == packedShortestPath[i+1]) {
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i+1]);
|
||||
// std::cout << "length of packed sv-path: " << packed_s_v_path.size() << ", length of packed shortest path: " << packedShortestPath.size() << std::endl;
|
||||
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packedShortestPath.size()) - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
||||
// std::cout << " checking indices [" << i << "] and [" << (i + 1) << "]" << std::endl;
|
||||
if (packed_s_v_path[i] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) {
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
} else {
|
||||
if(packed_s_v_path[i] == packedShortestPath[i]) {
|
||||
unpackStack.push(std::make_pair(packed_s_v_path[i], packed_s_v_path[i+1]));
|
||||
unpackStack.push(std::make_pair(packedShortestPath[i], packedShortestPath[i+1]));
|
||||
if (packed_s_v_path[i] == packedShortestPath[i]) {
|
||||
unpackStack.push( std::make_pair(packed_s_v_path[i], packed_s_v_path[i + 1]));
|
||||
unpackStack.push( std::make_pair(packedShortestPath[i], packedShortestPath[i + 1]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
while(!unpackStack.empty()) {
|
||||
UnpackEdge shortestPathEdge = unpackStack.top(); unpackStack.pop();
|
||||
UnpackEdge viaPathEdge = unpackStack.top(); unpackStack.pop();
|
||||
std::cout << " unpacking edges (" << shortestPathEdge.first << "," << shortestPathEdge.second << ") and (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInShortestPath = super::_queryData.graph->FindEdgeInEitherDirection(shortestPathEdge.first, shortestPathEdge.second);
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
std::cout << " ids are " << edgeIDInShortestPath << " (shortest) and " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
|
||||
while (!unpackStack.empty()) {
|
||||
const UnpackEdge shortestPathEdge = unpackStack.top();
|
||||
unpackStack.pop();
|
||||
const UnpackEdge viaPathEdge = unpackStack.top();
|
||||
unpackStack.pop();
|
||||
// std::cout << " unpacking edges (" << shortestPathEdge.first << "," << shortestPathEdge.second << ") and (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInShortestPath = super::_queryData.graph->FindEdgeInEitherDirection( shortestPathEdge.first, shortestPathEdge.second);
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
// std::cout << " ids are " << edgeIDInShortestPath << " (shortest) and " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
bool IsShortestPathEdgeShortCut = super::_queryData.graph->GetEdgeData(edgeIDInShortestPath).shortcut;
|
||||
bool IsViaEdgeShortCut = super::_queryData.graph->GetEdgeData(edgeIDInViaPath).shortcut;
|
||||
|
||||
const NodeID middleOfShortestPath = !IsShortestPathEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInShortestPath).id;
|
||||
const NodeID middleOfViaPath = !IsViaEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInViaPath).id;
|
||||
const NodeID middleOfShortestPath = !IsShortestPathEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInShortestPath).id;
|
||||
const NodeID middleOfViaPath = !IsViaEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInViaPath ).id;
|
||||
|
||||
if(IsShortestPathEdgeShortCut || IsViaEdgeShortCut) {
|
||||
if(middleOfShortestPath != middleOfViaPath) { // unpack first segment
|
||||
if (IsShortestPathEdgeShortCut || IsViaEdgeShortCut) {
|
||||
if (middleOfShortestPath != middleOfViaPath) { // unpack first segment
|
||||
//put first segment of via edge on stack, else take the segment already available
|
||||
if(IsViaEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
else
|
||||
unpackStack.push(viaPathEdge);
|
||||
if (IsViaEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
else unpackStack.push(viaPathEdge);
|
||||
|
||||
//put first segment of shortest path edge on stack if not a shortcut, else take the segment already available
|
||||
if(IsShortestPathEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(shortestPathEdge.first, middleOfShortestPath));
|
||||
else
|
||||
unpackStack.push(shortestPathEdge);
|
||||
if (IsShortestPathEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(shortestPathEdge.first, middleOfShortestPath));
|
||||
else unpackStack.push(shortestPathEdge);
|
||||
|
||||
} else { // unpack second segment
|
||||
if(IsViaEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
else
|
||||
unpackStack.push(viaPathEdge);
|
||||
if (IsViaEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
else unpackStack.push(viaPathEdge);
|
||||
|
||||
//put first segment of shortest path edge on stack if not a shortcut, else take the segment already available
|
||||
if(IsShortestPathEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(middleOfShortestPath, shortestPathEdge.second ));
|
||||
else
|
||||
unpackStack.push(shortestPathEdge);
|
||||
//put first segment of shortest path edge on stack if not a shortcut, else take the segment already available
|
||||
if (IsShortestPathEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(middleOfShortestPath, shortestPathEdge.second));
|
||||
else unpackStack.push(shortestPathEdge);
|
||||
|
||||
//add length of first segment to amount of sharing
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
@ -305,252 +287,82 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "sharing of SV-Path: " << *sharingOfViaPath << std::endl;
|
||||
|
||||
// std::cout << "sharing of SV-Path: " << *sharingOfViaPath << std::endl;
|
||||
//Second, partially unpack v-->t in reverse until paths deviate and note lengths
|
||||
unsigned viaPathIndex = packed_v_t_path.size()-1;
|
||||
unsigned shortestPathIndex = packedShortestPath.size() -1;
|
||||
std::cout << "length of packed vt-path: " << packed_v_t_path.size() << ", length of packed shortest path: " << packedShortestPath.size() << std::endl;
|
||||
for( ; viaPathIndex>0 && shortestPathIndex>0; ) {
|
||||
// std::cout << " checking indices [" << shortestPathIndex << "] and [" << (shortestPathIndex-1) << "] (shortest) as well as [" << shortestPathIndex << "] and [" << (shortestPathIndex-1) << "]" << std::endl;
|
||||
if(packed_v_t_path[viaPathIndex-1] == packedShortestPath[shortestPathIndex-1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex]);
|
||||
// std::cout << "Id of edge (" << packed_v_t_path[viaPathIndex-1] << "," << packed_v_t_path[viaPathIndex] << ") : " << edgeID << std::endl;
|
||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
unsigned viaPathIndex = packed_v_t_path.size() - 1;
|
||||
unsigned shortestPathIndex = packedShortestPath.size() - 1;
|
||||
// std::cout << "length of packed vt-path: " << packed_v_t_path.size() << ", length of packed shortest path: " << packedShortestPath.size() << std::endl;
|
||||
for (; viaPathIndex > 0 && shortestPathIndex > 0;) {
|
||||
// std::cout << " checking indices [" << shortestPathIndex << "] and [" << (shortestPathIndex-1) << "] (shortest) as well as [" << shortestPathIndex << "] and [" << (shortestPathIndex-1) << "]" << std::endl;
|
||||
if (packed_v_t_path[viaPathIndex - 1] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
||||
// std::cout << "Id of edge (" << packed_v_t_path[viaPathIndex-1] << "," << packed_v_t_path[viaPathIndex] << ") : " << edgeID << std::endl;
|
||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData( edgeID).distance;
|
||||
} else {
|
||||
if(packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
|
||||
unpackStack.push(std::make_pair(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex]));
|
||||
unpackStack.push(std::make_pair(packedShortestPath[shortestPathIndex-1], packedShortestPath[shortestPathIndex]));
|
||||
if (packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
|
||||
unpackStack.push( std::make_pair( packed_v_t_path[viaPathIndex - 1] , packed_v_t_path[viaPathIndex] ));
|
||||
unpackStack.push( std::make_pair( packedShortestPath[shortestPathIndex - 1] , packedShortestPath[shortestPathIndex] ));
|
||||
}
|
||||
}
|
||||
--viaPathIndex; --shortestPathIndex;
|
||||
--viaPathIndex;
|
||||
--shortestPathIndex;
|
||||
}
|
||||
|
||||
while(!unpackStack.empty()) {
|
||||
UnpackEdge shortestPathEdge = unpackStack.top(); unpackStack.pop();
|
||||
UnpackEdge viaPathEdge = unpackStack.top(); unpackStack.pop();
|
||||
std::cout << " unpacking edges (" << shortestPathEdge.first << "," << shortestPathEdge.second << ") and (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInShortestPath = super::_queryData.graph->FindEdgeInEitherDirection(shortestPathEdge.first, shortestPathEdge.second);
|
||||
// std::cout << "!" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
std::cout << " ids are " << edgeIDInShortestPath << " (shortest) and " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
while (!unpackStack.empty()) {
|
||||
const UnpackEdge shortestPathEdge = unpackStack.top();
|
||||
unpackStack.pop();
|
||||
const UnpackEdge viaPathEdge = unpackStack.top();
|
||||
unpackStack.pop();
|
||||
// std::cout << " unpacking edges (" << shortestPathEdge.first << "," << shortestPathEdge.second << ") and (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInShortestPath = super::_queryData.graph->FindEdgeInEitherDirection(shortestPathEdge.first, shortestPathEdge.second);
|
||||
// std::cout << "!" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection( viaPathEdge.first, viaPathEdge.second);
|
||||
// std::cout << " ids are " << edgeIDInShortestPath << " (shortest) and " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
bool IsShortestPathEdgeShortCut = super::_queryData.graph->GetEdgeData(edgeIDInShortestPath).shortcut;
|
||||
bool IsViaEdgeShortCut = super::_queryData.graph->GetEdgeData(edgeIDInViaPath).shortcut;
|
||||
bool IsViaEdgeShortCut = super::_queryData.graph->GetEdgeData( edgeIDInViaPath).shortcut;
|
||||
|
||||
const NodeID middleOfShortestPath = !IsShortestPathEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInShortestPath).id;
|
||||
const NodeID middleOfViaPath = !IsViaEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInViaPath).id;
|
||||
const NodeID middleOfShortestPath = !IsShortestPathEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInShortestPath).id;
|
||||
const NodeID middleOfViaPath = !IsViaEdgeShortCut ? UINT_MAX : super::_queryData.graph->GetEdgeData(edgeIDInViaPath ).id;
|
||||
|
||||
std::cout << " shortest shrtcut: " << (IsShortestPathEdgeShortCut ? "yes": "no") << "(" <<middleOfShortestPath << ") , via shrtcut: "
|
||||
<< (IsViaEdgeShortCut ? "yes" : "no") << "(" << middleOfViaPath << ")" << std::endl;
|
||||
// std::cout << " shortest shrtcut: " << (IsShortestPathEdgeShortCut ? "yes" : "no") << "(" << middleOfShortestPath << ") , via shrtcut: " << (IsViaEdgeShortCut ? "yes" : "no") << "(" << middleOfViaPath << ")" << std::endl;
|
||||
|
||||
if(IsShortestPathEdgeShortCut || IsViaEdgeShortCut) {
|
||||
if(middleOfShortestPath == middleOfViaPath) { // unpack first segment
|
||||
if (IsShortestPathEdgeShortCut || IsViaEdgeShortCut) {
|
||||
if (middleOfShortestPath == middleOfViaPath) { // unpack first segment
|
||||
//put first segment of via edge on stack, else take the segment already available
|
||||
std::cout << " unpacking first segment" << std::endl;
|
||||
if(IsViaEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
else
|
||||
unpackStack.push(viaPathEdge);
|
||||
// std::cout << " unpacking first segment" << std::endl;
|
||||
if (IsViaEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
else unpackStack.push(viaPathEdge);
|
||||
|
||||
//put first segment of shortest path edge on stack if not a shortcut, else take the segment already available
|
||||
if(IsShortestPathEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(shortestPathEdge.first, middleOfShortestPath));
|
||||
else
|
||||
unpackStack.push(shortestPathEdge);
|
||||
if (IsShortestPathEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(shortestPathEdge.first, middleOfShortestPath));
|
||||
else unpackStack.push(shortestPathEdge);
|
||||
|
||||
//add length of first segment to amount of sharing
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeIDInViaPath).distance;
|
||||
|
||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData( edgeIDInViaPath).distance;
|
||||
} else { // unpack second segment
|
||||
std::cout << " unpacking second segment" << std::endl;
|
||||
if(IsViaEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
else
|
||||
unpackStack.push(viaPathEdge);
|
||||
// std::cout << " unpacking second segment" << std::endl;
|
||||
if (IsViaEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
else unpackStack.push(viaPathEdge);
|
||||
|
||||
//put first segment of shortest path edge on stack if not a shortcut, else take the segment already available
|
||||
if(IsShortestPathEdgeShortCut)
|
||||
unpackStack.push(std::make_pair(middleOfShortestPath, shortestPathEdge.second ));
|
||||
else
|
||||
unpackStack.push(shortestPathEdge);
|
||||
//put first segment of shortest path edge on stack if not a shortcut, else take the segment already available
|
||||
if (IsShortestPathEdgeShortCut)
|
||||
unpackStack.push( std::make_pair(middleOfShortestPath, shortestPathEdge.second));
|
||||
else unpackStack.push(shortestPathEdge);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "sharing of SVT-Path: " << *sharingOfViaPath << std::endl;
|
||||
|
||||
// std::cout << "sharing of SVT-Path: " << *sharingOfViaPath << std::endl;
|
||||
}
|
||||
|
||||
inline bool viaNodeCandidatePasses_T_Test(typename QueryDataT::HeapPtr & _forwardHeap1, typename QueryDataT::HeapPtr & _backwardHeap1, typename QueryDataT::HeapPtr & _forwardHeap2, typename QueryDataT::HeapPtr & _backwardHeap2, const RankedCandidateNode& candidate, const int offset, const NodeID middleOfShortestPath, const int lengthOfShortestPath) {
|
||||
bool hasPassed_T_Test = true;
|
||||
std::cout << "computing via path for T-Test " << candidate.node << std::endl;
|
||||
int lengthOfViaPath = 0;
|
||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||
|
||||
typename QueryDataT::HeapPtr & existingForwardHeap = super::_queryData.forwardHeap;
|
||||
typename QueryDataT::HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap;
|
||||
|
||||
typename QueryDataT::HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
|
||||
typename QueryDataT::HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
|
||||
|
||||
NodeID s_v_middle = UINT_MAX;
|
||||
int upperBoundFor_s_v_Path = INT_MAX;//existingForwardHeap->GetKey(node.first);
|
||||
|
||||
//compute path <s,..,v> by reusing forward search from s
|
||||
newBackwardHeap->Insert(candidate.node, 0, candidate.node);
|
||||
while(newBackwardHeap->Size() > 0){
|
||||
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
|
||||
}
|
||||
std::cout << " length of <s,..,v>: " << upperBoundFor_s_v_Path << " with middle node " << s_v_middle << std::endl;
|
||||
|
||||
//compute path <v,..,t> by reusing backward search from t
|
||||
NodeID v_t_middle = UINT_MAX;
|
||||
int upperBoundFor_v_t_Path = INT_MAX;//existingBackwardHeap->GetKey(node.first);
|
||||
newForwardHeap->Insert(candidate.node, 0, candidate.node);
|
||||
while(newForwardHeap->Size() > 0){
|
||||
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
|
||||
}
|
||||
std::cout << " length of <v,..,t>: " << upperBoundFor_v_t_Path << " with middle node " << v_t_middle << std::endl;
|
||||
|
||||
lengthOfViaPath = upperBoundFor_s_v_Path+upperBoundFor_v_t_Path;
|
||||
std::cout << " exact length of via path: " << lengthOfViaPath << std::endl;
|
||||
std::cout << " T-Test shall pass with length 0.25*" << (lengthOfShortestPath) << "=" << 0.25*(lengthOfShortestPath) << std::endl;
|
||||
|
||||
// std::deque<NodeID> packedShortestPath;
|
||||
std::deque<NodeID> packed_s_v_path;
|
||||
std::deque<NodeID> packed_v_t_path;
|
||||
//retrieve packed paths
|
||||
std::cout << " retrieving packed path for middle nodes " << middleOfShortestPath << "," << s_v_middle << "," << v_t_middle << " (shorstest, sv, vt)" << std::endl;
|
||||
// super::RetrievePackedPathFromHeap(existingForwardHeap, existingBackwardHeap, middleOfShortestPath, packedShortestPath);
|
||||
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path);
|
||||
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle,packed_v_t_path);
|
||||
|
||||
std::cout << "packed sv: ";
|
||||
for(unsigned i = 0; i < packed_s_v_path.size(); ++i) {
|
||||
std::cout << packed_s_v_path[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
std::cout << "packed vt: ";
|
||||
for(unsigned i = 0; i < packed_v_t_path.size(); ++i) {
|
||||
std::cout << packed_v_t_path[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// std::cout << "packed shortest: ";
|
||||
// for(unsigned i = 0; i < packedShortestPath.size(); ++i) {
|
||||
// std::cout << packedShortestPath[i] << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
|
||||
NodeID s_P = s_v_middle, t_P = v_t_middle;
|
||||
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
|
||||
int unpackedUntilDistance = 0;
|
||||
typedef std::pair<NodeID, NodeID> UnpackEdge;
|
||||
std::stack<UnpackEdge > unpackStack;
|
||||
|
||||
//partial unpacking until target of edge is the first endpoint of a non-shortcut edge farther away than threshold
|
||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||
std::cout << "unpacking sv-path until a node of non-shortcut edge is farther away than " << T_threshold << std::endl;
|
||||
for(unsigned i = packed_s_v_path.size()-1; (i > 0) && unpackStack.empty(); --i ) {
|
||||
std::cout << " checking indices [" << i << "] and [" << (i+1) << "]" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i-1], packed_s_v_path[i]);
|
||||
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
if(lengthOfCurrentEdge + unpackedUntilDistance > T_threshold) {
|
||||
unpackStack.push(std::make_pair(packed_s_v_path[i-1], packed_s_v_path[i]));
|
||||
} else {
|
||||
unpackedUntilDistance += lengthOfCurrentEdge;
|
||||
s_P = packed_s_v_path[i-1];
|
||||
}
|
||||
}
|
||||
while(!unpackStack.empty()) {
|
||||
UnpackEdge viaPathEdge = unpackStack.top(); unpackStack.pop();
|
||||
std::cout << " unpacking edge (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
std::cout << " id is " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
|
||||
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||
|
||||
if( IsViaEdgeShortCut) {
|
||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData(edgeIDOfFirstSegment).distance;
|
||||
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).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(unpackedUntilDistance+lengthOfSecondSegment > T_threshold ) {
|
||||
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
} else {
|
||||
unpackedUntilDistance+=lengthOfSecondSegment;
|
||||
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
}
|
||||
} else { // edge is not a shortcut, set the start node for T-Test to end of edge.
|
||||
unpackedUntilDistance += currentEdgeData.distance;
|
||||
s_P = viaPathEdge.second;
|
||||
}
|
||||
}
|
||||
std::cout << "threshold: " << T_threshold << ", unpackedDistance: " << unpackedUntilDistance << ", s_P: " << s_P << std::endl;
|
||||
int lengthOfPathT_Test_Path = unpackedUntilDistance;
|
||||
unpackedUntilDistance = 0;
|
||||
|
||||
//partial unpacking until target of edge is the first endpoint of a non-shortcut edge farther away than threshold
|
||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||
std::cout << "unpacking vt-path until a node of non-shortcut edge is farther away than " << T_threshold << std::endl;
|
||||
for(unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size()-1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i ) {
|
||||
std::cout << " checking indices [" << i << "] and [" << (i+1) << "]" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_v_t_path[i], packed_v_t_path[i+1]);
|
||||
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
if(lengthOfCurrentEdge + unpackedUntilDistance > T_threshold) {
|
||||
unpackStack.push(std::make_pair(packed_v_t_path[i], packed_v_t_path[i+1]));
|
||||
} else {
|
||||
unpackedUntilDistance += lengthOfCurrentEdge;
|
||||
t_P = packed_v_t_path[i+1];
|
||||
}
|
||||
}
|
||||
while(!unpackStack.empty()) {
|
||||
UnpackEdge viaPathEdge = unpackStack.top(); unpackStack.pop();
|
||||
std::cout << " unpacking edge (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
std::cout << " id is " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
|
||||
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||
|
||||
if( IsViaEdgeShortCut) {
|
||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData(edgeIDOfFirstSegment).distance;
|
||||
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).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(unpackedUntilDistance+lengthOfFirstSegment > T_threshold ) {
|
||||
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
} else {
|
||||
unpackedUntilDistance+=lengthOfFirstSegment;
|
||||
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
}
|
||||
} else { // edge is not a shortcut, set the start node for T-Test to end of edge.
|
||||
unpackedUntilDistance += currentEdgeData.distance;
|
||||
t_P = viaPathEdge.second;
|
||||
}
|
||||
}
|
||||
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
||||
std::cout << "check if path (" << s_P << "," << t_P << ") is not less than " << lengthOfPathT_Test_Path << ", while shortest path has length: " << lengthOfShortestPath << std::endl;
|
||||
//TODO: Run query and compare distances.
|
||||
|
||||
std::cout << "passed T-Test: " << (hasPassed_T_Test ? "yes" : "no") << std::endl;
|
||||
return hasPassed_T_Test;
|
||||
}
|
||||
|
||||
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfShortestPath, const NodeID middleNodeIDOfAlternativePath, typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap) {
|
||||
std::deque<NodeID> packedShortestPath;
|
||||
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::deque<NodeID> & packedShortestPath) {
|
||||
std::deque<NodeID> packedAlternativePath;
|
||||
|
||||
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfShortestPath, packedShortestPath);
|
||||
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
|
||||
|
||||
int sharing = 0;
|
||||
|
||||
int aindex = 0;
|
||||
//compute forward sharing
|
||||
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
||||
@ -568,11 +380,10 @@ private:
|
||||
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
--aindex; --bindex;
|
||||
}
|
||||
|
||||
return sharing;
|
||||
}
|
||||
|
||||
inline void AlternativeRoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector<NodeID>& searchSpaceIntersection) const {
|
||||
inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector<NodeID>& searchSpaceIntersection) const {
|
||||
const NodeID node = _forwardHeap->DeleteMin();
|
||||
|
||||
const int distance = _forwardHeap->GetKey(node);
|
||||
@ -582,7 +393,7 @@ private:
|
||||
const int newDistance = _backwardHeap->GetKey(node) + distance;
|
||||
if(newDistance < *_upperbound ){
|
||||
if(newDistance>=0 ) {
|
||||
INFO("upper bound decrease to: " << newDistance);
|
||||
// INFO("upper bound decrease to: " << newDistance);
|
||||
*middle = node;
|
||||
*_upperbound = newDistance;
|
||||
}
|
||||
@ -590,7 +401,7 @@ private:
|
||||
}
|
||||
|
||||
//0.8 implies an epsilon of 25%
|
||||
if((distance-edgeBasedOffset)*0.8 > *_upperbound){
|
||||
if((distance-edgeBasedOffset)*VIAPATH_GAMMA > *_upperbound){
|
||||
_forwardHeap->DeleteAll();
|
||||
return;
|
||||
}
|
||||
@ -625,7 +436,170 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
//conduct T-Test
|
||||
inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const NodeID middleOfShortestPath, const int lengthOfShortestPath, int * lengthOfViaPath) {
|
||||
// std::cout << "computing via path for T-Test " << candidate.node << std::endl;
|
||||
// int lengthOfViaPath = 0;
|
||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||
NodeID s_v_middle = UINT_MAX;
|
||||
int upperBoundFor_s_v_Path = INT_MAX;
|
||||
//compute path <s,..,v> by reusing forward search from s
|
||||
newBackwardHeap->Insert(candidate.node, 0, candidate.node);
|
||||
while (newBackwardHeap->Size() > 0) {
|
||||
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 0, false);
|
||||
}
|
||||
// std::cout << " length of <s,..,v>: " << upperBoundFor_s_v_Path << " with middle node " << s_v_middle << std::endl;
|
||||
//compute path <v,..,t> by reusing backward search from t
|
||||
NodeID v_t_middle = UINT_MAX;
|
||||
int upperBoundFor_v_t_Path = INT_MAX;
|
||||
newForwardHeap->Insert(candidate.node, 0, candidate.node);
|
||||
while (newForwardHeap->Size() > 0) {
|
||||
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 0, true);
|
||||
}
|
||||
// std::cout << " length of <v,..,t>: " << upperBoundFor_v_t_Path << " with middle node " << v_t_middle << std::endl;
|
||||
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
|
||||
// std::cout << " exact length of via path: " << lengthOfViaPath << std::endl;
|
||||
// std::cout << " T-Test shall pass with length 0.25*" << (lengthOfShortestPath) << "=" << 0.25 * (lengthOfShortestPath) << std::endl;
|
||||
std::deque < NodeID > packed_s_v_path;
|
||||
std::deque < NodeID > packed_v_t_path;
|
||||
//retrieve packed paths
|
||||
// std::cout << " retrieving packed path for middle nodes " << middleOfShortestPath << "," << s_v_middle << "," << v_t_middle << " (shorstest, sv, vt)" << std::endl;
|
||||
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path);
|
||||
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle, packed_v_t_path);
|
||||
// std::cout << "packed sv: ";
|
||||
// for (unsigned i = 0; i < packed_s_v_path.size(); ++i) {
|
||||
// std::cout << packed_s_v_path[i] << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
// std::cout << "packed vt: ";
|
||||
// for (unsigned i = 0; i < packed_v_t_path.size(); ++i) {
|
||||
// std::cout << packed_v_t_path[i] << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
// std::cout << "packed shortest: ";
|
||||
// for(unsigned i = 0; i < packedShortestPath.size(); ++i) {
|
||||
// std::cout << packedShortestPath[i] << " ";
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
NodeID s_P = s_v_middle, t_P = v_t_middle;
|
||||
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
|
||||
int unpackedUntilDistance = 0;
|
||||
typedef std::pair<NodeID, NodeID> UnpackEdge;
|
||||
std::stack<UnpackEdge> unpackStack;
|
||||
//partial unpacking until target of edge is the first endpoint of a non-shortcut edge farther away than threshold
|
||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||
// std::cout << "unpacking sv-path until a node of non-shortcut edge is farther away than " << T_threshold << std::endl;
|
||||
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
|
||||
// std::cout << " checking indices [" << i << "] and [" << (i + 1) << "]" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
||||
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
|
||||
} else {
|
||||
unpackedUntilDistance += lengthOfCurrentEdge;
|
||||
s_P = packed_s_v_path[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
while (!unpackStack.empty()) {
|
||||
const UnpackEdge viaPathEdge = unpackStack.top();
|
||||
unpackStack.pop();
|
||||
// std::cout << " unpacking edge (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
// std::cout << " id is " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
|
||||
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||
if (IsViaEdgeShortCut) {
|
||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData(edgeIDOfFirstSegment).distance;
|
||||
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).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 (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
|
||||
unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
} else {
|
||||
unpackedUntilDistance += lengthOfSecondSegment;
|
||||
unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
}
|
||||
} else {
|
||||
// edge is not a shortcut, set the start node for T-Test to end of edge.
|
||||
unpackedUntilDistance += currentEdgeData.distance;
|
||||
s_P = viaPathEdge.first;
|
||||
}
|
||||
}
|
||||
|
||||
// std::cout << "threshold: " << T_threshold << ", unpackedDistance: " << unpackedUntilDistance << ", s_P: " << s_P << std::endl;
|
||||
int lengthOfPathT_Test_Path = unpackedUntilDistance;
|
||||
unpackedUntilDistance = 0;
|
||||
//partial unpacking until target of edge is the first endpoint of a non-shortcut edge farther away than threshold
|
||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||
// std::cout << "unpacking vt-path until a node of non-shortcut edge is farther away than " << T_threshold << std::endl;
|
||||
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
||||
// std::cout << " checking indices [" << i << "] and [" << (i + 1) << "]" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
||||
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
|
||||
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
||||
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
|
||||
} else {
|
||||
unpackedUntilDistance += lengthOfCurrentEdge;
|
||||
t_P = packed_v_t_path[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
while (!unpackStack.empty()) {
|
||||
const UnpackEdge viaPathEdge = unpackStack.top();
|
||||
unpackStack.pop();
|
||||
// std::cout << " unpacking edge (" << viaPathEdge.first << "," << viaPathEdge.second << ")" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||
// std::cout << " id is " << edgeIDInViaPath << " (via)" << std::endl;
|
||||
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
|
||||
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||
if (IsViaEdgeShortCut) {
|
||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||
typename QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData( edgeIDOfFirstSegment).distance;
|
||||
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData( edgeIDOfSecondSegment).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 (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
|
||||
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||
} else {
|
||||
unpackedUntilDistance += lengthOfFirstSegment;
|
||||
unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second));
|
||||
}
|
||||
} else {
|
||||
// edge is not a shortcut, set the start node for T-Test to end of edge.
|
||||
unpackedUntilDistance += currentEdgeData.distance;
|
||||
t_P = viaPathEdge.second;
|
||||
}
|
||||
}
|
||||
|
||||
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
||||
// std::cout << "check if path (" << s_P << "," << t_P << ") is not less than " << lengthOfPathT_Test_Path << ", while shortest path has length: " << lengthOfShortestPath << std::endl;
|
||||
//Run query and compare distances.
|
||||
HeapPtr& forwardHeap = super::_queryData.forwardHeap3;
|
||||
HeapPtr& backwardHeap = super::_queryData.backwardHeap3;
|
||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
||||
int _upperBound = INT_MAX;
|
||||
NodeID middle = UINT_MAX;
|
||||
forwardHeap->Insert(s_P, 0, s_P);
|
||||
backwardHeap->Insert(t_P, 0, t_P);
|
||||
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
||||
while (forwardHeap->Size() + backwardHeap->Size() > 0) {
|
||||
if (forwardHeap->Size() > 0) {
|
||||
super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true);
|
||||
}
|
||||
if (backwardHeap->Size() > 0) {
|
||||
super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false);
|
||||
}
|
||||
}
|
||||
// std::cout << "lengthOfPathT_Test_Path: " << lengthOfPathT_Test_Path << ", _upperBound: " << _upperBound << std::endl;
|
||||
bool hasPassed_T_Test = (_upperBound == lengthOfPathT_Test_Path);
|
||||
// std::cout << "passed T-Test: " << (hasPassed_T_Test ? "yes" : "no") << std::endl;
|
||||
return hasPassed_T_Test;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* ALTERNATIVEROUTES_H_ */
|
||||
|
@ -26,6 +26,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
|
||||
#include "../Plugins/RawRouteData.h"
|
||||
|
||||
template<class QueryDataT>
|
||||
class BasicRoutingInterface {
|
||||
protected:
|
||||
|
@ -33,10 +33,12 @@ public:
|
||||
|
||||
~ShortestPathRouting() {}
|
||||
|
||||
int operator()(std::vector<PhantomNodes> & phantomNodesVector, std::vector<_PathData> & unpackedPath) {
|
||||
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) {
|
||||
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
|
||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX())
|
||||
return INT_MAX;
|
||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||
return;
|
||||
}
|
||||
}
|
||||
int distance1 = 0;
|
||||
int distance2 = 0;
|
||||
@ -115,7 +117,8 @@ public:
|
||||
|
||||
//No path found for both target nodes?
|
||||
if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) {
|
||||
return INT_MAX;
|
||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||
return;
|
||||
}
|
||||
if(UINT_MAX == middle1) {
|
||||
searchFrom1stStartNode = false;
|
||||
@ -215,30 +218,34 @@ public:
|
||||
// INFO("length path2: " << distance2);
|
||||
if(distance1 <= distance2){
|
||||
//remove consecutive duplicates
|
||||
std::cout << "unclean 1: ";
|
||||
for(unsigned i = 0; i < packedPath1.size(); ++i)
|
||||
std::cout << packedPath1[i] << " ";
|
||||
std::cout << std::endl;
|
||||
_RemoveConsecutiveDuplicatesFromContainer(packedPath1);
|
||||
// std::cout << "unclean 1: ";
|
||||
// for(unsigned i = 0; i < packedPath1.size(); ++i)
|
||||
// std::cout << packedPath1[i] << " ";
|
||||
// std::cout << std::endl;
|
||||
|
||||
// std::cout << "cleaned 1: ";
|
||||
// for(unsigned i = 0; i < packedPath1.size(); ++i)
|
||||
// std::cout << packedPath1[i] << " ";
|
||||
// std::cout << std::endl;
|
||||
super::UnpackPath(packedPath1, unpackedPath);
|
||||
// super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
||||
} else {
|
||||
std::cout << "unclean 2: ";
|
||||
for(unsigned i = 0; i < packedPath2.size(); ++i)
|
||||
std::cout << packedPath2[i] << " ";
|
||||
std::cout << std::endl;
|
||||
_RemoveConsecutiveDuplicatesFromContainer(packedPath2);
|
||||
std::swap(packedPath1, packedPath2);
|
||||
// std::cout << "unclean 2: ";
|
||||
// for(unsigned i = 0; i < packedPath2.size(); ++i)
|
||||
// std::cout << packedPath2[i] << " ";
|
||||
// std::cout << std::endl;
|
||||
// _RemoveConsecutiveDuplicatesFromContainer(packedPath2);
|
||||
// std::cout << "cleaned 2: ";
|
||||
// for(unsigned i = 0; i < packedPath2.size(); ++i)
|
||||
// std::cout << packedPath2[i] << " ";
|
||||
// std::cout << std::endl;
|
||||
super::UnpackPath(packedPath2, unpackedPath);
|
||||
// super::UnpackPath(packedPath2, unpackedPath);
|
||||
}
|
||||
_RemoveConsecutiveDuplicatesFromContainer(packedPath1);
|
||||
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
||||
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
|
||||
// INFO("Found via route with distance " << std::min(distance1, distance2));
|
||||
return std::min(distance1, distance2);
|
||||
return;
|
||||
}
|
||||
private:
|
||||
template<class ContainerT>
|
||||
|
Loading…
Reference in New Issue
Block a user