First working implementation of Contractor flush at 75% of contracted
nodes
This commit is contained in:
parent
a5c5f4c02c
commit
964c0425bf
@ -20,17 +20,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#ifndef CONTRACTOR_H_INCLUDED
|
#ifndef CONTRACTOR_H_INCLUDED
|
||||||
#define CONTRACTOR_H_INCLUDED
|
#define CONTRACTOR_H_INCLUDED
|
||||||
#ifdef _GLIBCXX_PARALLEL
|
|
||||||
#include <parallel/algorithm>
|
|
||||||
#else
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#endif
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/BinaryHeap.h"
|
#include "../DataStructures/BinaryHeap.h"
|
||||||
#include "../Util/OpenMPReplacement.h"
|
#include "../Util/OpenMPReplacement.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@ -45,7 +43,7 @@ private:
|
|||||||
_EdgeBasedContractorEdgeData() :
|
_EdgeBasedContractorEdgeData() :
|
||||||
distance(0), originalEdges(0), via(0), nameID(0), turnInstruction(0), shortcut(0), forward(0), backward(0) {}
|
distance(0), originalEdges(0), via(0), nameID(0), turnInstruction(0), shortcut(0), forward(0), backward(0) {}
|
||||||
_EdgeBasedContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _via, unsigned _nameID, short _turnInstruction, bool _shortcut, bool _forward, bool _backward) :
|
_EdgeBasedContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _via, unsigned _nameID, short _turnInstruction, bool _shortcut, bool _forward, bool _backward) :
|
||||||
distance(_distance), originalEdges(_originalEdges), via(_via), nameID(_nameID), turnInstruction(_turnInstruction), shortcut(_shortcut), forward(_forward), backward(_backward) {}
|
distance(_distance), originalEdges(_originalEdges), via(_via), nameID(_nameID), turnInstruction(_turnInstruction), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
|
||||||
unsigned distance;
|
unsigned distance;
|
||||||
unsigned originalEdges;
|
unsigned originalEdges;
|
||||||
unsigned via;
|
unsigned via;
|
||||||
@ -54,6 +52,7 @@ private:
|
|||||||
bool shortcut:1;
|
bool shortcut:1;
|
||||||
bool forward:1;
|
bool forward:1;
|
||||||
bool backward:1;
|
bool backward:1;
|
||||||
|
bool originalViaNodeID:1;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
struct _HeapData {
|
struct _HeapData {
|
||||||
@ -122,12 +121,7 @@ public:
|
|||||||
}
|
}
|
||||||
//remove data from memory
|
//remove data from memory
|
||||||
std::vector< InputEdge >().swap( inputEdges );
|
std::vector< InputEdge >().swap( inputEdges );
|
||||||
|
|
||||||
#ifdef _GLIBCXX_PARALLEL
|
|
||||||
__gnu_parallel::sort( edges.begin(), edges.end() );
|
|
||||||
#else
|
|
||||||
sort( edges.begin(), edges.end() );
|
sort( edges.begin(), edges.end() );
|
||||||
#endif
|
|
||||||
NodeID edge = 0;
|
NodeID edge = 0;
|
||||||
for ( NodeID i = 0; i < edges.size(); ) {
|
for ( NodeID i = 0; i < edges.size(); ) {
|
||||||
const NodeID source = edges[i].source;
|
const NodeID source = edges[i].source;
|
||||||
@ -194,9 +188,17 @@ public:
|
|||||||
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
|
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
//Create temporary file
|
||||||
|
|
||||||
|
GetTemporaryFileName(temporaryEdgeStorageFilename);
|
||||||
|
INFO("75% Storage at " << temporaryEdgeStorageFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Contractor() { }
|
~Contractor() {
|
||||||
|
//Delete temporary file
|
||||||
|
// remove(temporaryEdgeStorageFilename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
const NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||||
@ -235,9 +237,8 @@ public:
|
|||||||
|
|
||||||
bool flushedContractor = false;
|
bool flushedContractor = false;
|
||||||
while ( numberOfContractedNodes < numberOfNodes ) {
|
while ( numberOfContractedNodes < numberOfNodes ) {
|
||||||
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.75) ) ){
|
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.5) ) ){
|
||||||
INFO("Flushing memory after " << numberOfContractedNodes << " nodes");
|
INFO("Flushing memory after " << numberOfContractedNodes << " nodes");
|
||||||
//TODO:
|
|
||||||
|
|
||||||
//Delete old heap data to free memory that we need for the coming operations
|
//Delete old heap data to free memory that we need for the coming operations
|
||||||
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) {
|
for ( unsigned threadNum = 0; threadNum < maxThreads; threadNum++ ) {
|
||||||
@ -249,15 +250,15 @@ public:
|
|||||||
//Create new priority array
|
//Create new priority array
|
||||||
std::vector<double> newNodePriority(remainingNodes.size());
|
std::vector<double> newNodePriority(remainingNodes.size());
|
||||||
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
|
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
|
||||||
std::vector<NodeID> oldNodeIDMap(remainingNodes.size());
|
oldNodeIDFromNewNodeIDMap.resize(remainingNodes.size());
|
||||||
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
|
//this map gives the new IDs from the old ones, necessary to remap targets from the remaining graph
|
||||||
std::vector<NodeID> newNodeIDMap(numberOfNodes, UINT_MAX);
|
std::vector<NodeID> newNodeIDFromOldNodeIDMap(numberOfNodes, UINT_MAX);
|
||||||
|
|
||||||
//build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
|
//build forward and backward renumbering map and remap ids in remainingNodes and Priorities.
|
||||||
for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
|
for(unsigned newNodeID = 0; newNodeID < remainingNodes.size(); ++newNodeID) {
|
||||||
//create renumbering maps in both directions
|
//create renumbering maps in both directions
|
||||||
oldNodeIDMap[newNodeID] = remainingNodes[newNodeID].first;
|
oldNodeIDFromNewNodeIDMap[newNodeID] = remainingNodes[newNodeID].first;
|
||||||
newNodeIDMap[remainingNodes[newNodeID].first] = newNodeID;
|
newNodeIDFromOldNodeIDMap[remainingNodes[newNodeID].first] = newNodeID;
|
||||||
newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].first];
|
newNodePriority[newNodeID] = nodePriority[remainingNodes[newNodeID].first];
|
||||||
remainingNodes[newNodeID].first = newNodeID;
|
remainingNodes[newNodeID].first = newNodeID;
|
||||||
}
|
}
|
||||||
@ -265,15 +266,46 @@ public:
|
|||||||
//create new _DynamicGraph, goes out of scope after the renumbering
|
//create new _DynamicGraph, goes out of scope after the renumbering
|
||||||
boost::shared_ptr<_DynamicGraph> _newGraph ( new _DynamicGraph(remainingNodes.size()) );
|
boost::shared_ptr<_DynamicGraph> _newGraph ( new _DynamicGraph(remainingNodes.size()) );
|
||||||
|
|
||||||
//walk over all remainingNodes
|
//Write dummy number of edges to temporary file
|
||||||
for(unsigned i = 0; i < remainingNodes.size(); ++i) {
|
std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
||||||
//TODO:Wenn Knoten kontrahiert: speichern seiner Kanten in vector mit
|
initialFilePosition = temporaryEdgeStorage.tellp();
|
||||||
//TODO:Wenn Knoten nicht kontrahiert: Einfügen der Kanten in neuen DynamicGraph und
|
unsigned numberOfTemporaryEdges = 0;
|
||||||
// dabei Source, Target umnummerieren und Priorität in neuem Prioritäten-Array speichern.
|
temporaryEdgeStorage.write((char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||||
|
|
||||||
|
//walk over all nodes
|
||||||
|
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
||||||
|
//INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes());
|
||||||
|
const NodeID start = i;
|
||||||
|
//UINT_MAX indicates that node is already contracted
|
||||||
|
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
|
||||||
|
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
|
||||||
|
const NodeID target = _graph->GetTarget(currentEdge);
|
||||||
|
if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
|
||||||
|
//Save edges of this node w/o renumbering.
|
||||||
|
temporaryEdgeStorage.write((char*)&start, sizeof(NodeID));
|
||||||
|
temporaryEdgeStorage.write((char*)&target, sizeof(NodeID));
|
||||||
|
temporaryEdgeStorage.write((char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||||
|
++numberOfTemporaryEdges;
|
||||||
|
}else {
|
||||||
|
//node is not yet contracted.
|
||||||
|
//add (renumbered) outgoing edges to new DynamicGraph.
|
||||||
|
data.originalViaNodeID = true;
|
||||||
|
if(newNodeIDFromOldNodeIDMap[start] == UINT_MAX)
|
||||||
|
ERR("Could not resolve start");
|
||||||
|
if(UINT_MAX == newNodeIDFromOldNodeIDMap[target])
|
||||||
|
ERR("Could not resolve target");
|
||||||
|
_newGraph->InsertEdge(newNodeIDFromOldNodeIDMap[start], newNodeIDFromOldNodeIDMap[target], data );
|
||||||
}
|
}
|
||||||
//
|
}
|
||||||
|
}
|
||||||
|
//Note the number of temporarily stored edges
|
||||||
|
temporaryEdgeStorage.seekp(initialFilePosition);
|
||||||
|
temporaryEdgeStorage.write((char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||||
|
temporaryEdgeStorage.close();
|
||||||
|
INFO("Flushed " << numberOfTemporaryEdges << " to disk");
|
||||||
|
|
||||||
//Delete map from old NodeIDs to new ones.
|
//Delete map from old NodeIDs to new ones.
|
||||||
std::vector<NodeID>().swap(newNodeIDMap);
|
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
||||||
|
|
||||||
//Replace old priorities array by new one
|
//Replace old priorities array by new one
|
||||||
nodePriority.swap(newNodePriority);
|
nodePriority.swap(newNodePriority);
|
||||||
@ -281,15 +313,14 @@ public:
|
|||||||
std::vector<double>().swap(newNodePriority);
|
std::vector<double>().swap(newNodePriority);
|
||||||
//Alten Graphen löschen und neuen Graphen speichern.
|
//Alten Graphen löschen und neuen Graphen speichern.
|
||||||
|
|
||||||
//ThreadData mit Heaps passender Größe reinitialisieren.
|
//reinitialize heaps and ThreadData objects with appropriate size
|
||||||
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
for ( unsigned threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
||||||
threadData.push_back( new _ThreadData( remainingNodes.size() ) );
|
threadData.push_back( new _ThreadData( _newGraph->GetNumberOfNodes() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Check if old Graph is removed
|
//old Graph is removed
|
||||||
_graph.swap(_newGraph);
|
_graph.swap(_newGraph);
|
||||||
|
|
||||||
// numberOfContractedNodes = 0;
|
|
||||||
flushedContractor = true;
|
flushedContractor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,9 +430,49 @@ public:
|
|||||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) {
|
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; edge++ ) {
|
||||||
const NodeID target = _graph->GetTarget( edge );
|
const NodeID target = _graph->GetTarget( edge );
|
||||||
const _EdgeBasedContractorEdgeData& data = _graph->GetEdgeData( edge );
|
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
||||||
Edge newEdge;
|
Edge newEdge;
|
||||||
newEdge.source = node;
|
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
||||||
|
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
||||||
|
|
||||||
|
if(UINT_MAX == newEdge.source)
|
||||||
|
ERR("Could not resolve start");
|
||||||
|
if(UINT_MAX == newEdge.target)
|
||||||
|
ERR("Could not resolve target");
|
||||||
|
|
||||||
|
assert(UINT_MAX != newEdge.source);
|
||||||
|
assert(UINT_MAX != newEdge.target);
|
||||||
|
newEdge.data.distance = data.distance;
|
||||||
|
newEdge.data.shortcut = data.shortcut;
|
||||||
|
if(!data.originalViaNodeID)
|
||||||
|
newEdge.data.via = oldNodeIDFromNewNodeIDMap[data.via];
|
||||||
|
else
|
||||||
|
newEdge.data.via = data.via;
|
||||||
|
|
||||||
|
if(newEdge.data.via == UINT_MAX)
|
||||||
|
ERR("could not resolve via node");
|
||||||
|
newEdge.data.nameID = data.nameID;
|
||||||
|
newEdge.data.turnInstruction = data.turnInstruction;
|
||||||
|
newEdge.data.forward = data.forward;
|
||||||
|
newEdge.data.backward = data.backward;
|
||||||
|
edges.push_back( newEdge );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::ifstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
||||||
|
//Also get the edges from temporary storage
|
||||||
|
unsigned numberOfTemporaryEdges = 0;
|
||||||
|
temporaryEdgeStorage.read((char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||||
|
INFO("loading " << numberOfTemporaryEdges << " back from disk");
|
||||||
|
//loads edges of graph before renumbering, no need for further numbering action.
|
||||||
|
NodeID start;
|
||||||
|
NodeID target;
|
||||||
|
_DynamicGraph::EdgeData data;
|
||||||
|
for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
|
||||||
|
temporaryEdgeStorage.read((char*)&start, sizeof(NodeID));
|
||||||
|
temporaryEdgeStorage.read((char*)&target, sizeof(NodeID));
|
||||||
|
temporaryEdgeStorage.read((char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||||
|
Edge newEdge;
|
||||||
|
newEdge.source = start;
|
||||||
newEdge.target = target;
|
newEdge.target = target;
|
||||||
newEdge.data.distance = data.distance;
|
newEdge.data.distance = data.distance;
|
||||||
newEdge.data.shortcut = data.shortcut;
|
newEdge.data.shortcut = data.shortcut;
|
||||||
@ -412,7 +483,7 @@ public:
|
|||||||
newEdge.data.backward = data.backward;
|
newEdge.data.backward = data.backward;
|
||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
}
|
}
|
||||||
}
|
temporaryEdgeStorage.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -664,6 +735,9 @@ private:
|
|||||||
|
|
||||||
boost::shared_ptr<_DynamicGraph> _graph;
|
boost::shared_ptr<_DynamicGraph> _graph;
|
||||||
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
||||||
|
std::string temporaryEdgeStorageFilename;
|
||||||
|
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
|
||||||
|
long initialFilePosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTRACTOR_H_INCLUDED
|
#endif // CONTRACTOR_H_INCLUDED
|
||||||
|
@ -21,6 +21,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef STRINGUTIL_H_
|
#ifndef STRINGUTIL_H_
|
||||||
#define STRINGUTIL_H_
|
#define STRINGUTIL_H_
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// precision: position after decimal point
|
// precision: position after decimal point
|
||||||
// length: maximum number of digits including comma and decimals
|
// length: maximum number of digits including comma and decimals
|
||||||
template< int length, int precision >
|
template< int length, int precision >
|
||||||
@ -143,4 +146,18 @@ inline std::string HTMLDeEntitize( std::string result) {
|
|||||||
inline bool StringStartsWith(std::string & input, std::string & prefix) {
|
inline bool StringStartsWith(std::string & input, std::string & prefix) {
|
||||||
return (input.find(prefix) == 0);
|
return (input.find(prefix) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function returns a 'random' filename in temporary directors.
|
||||||
|
* May not be platform independent.
|
||||||
|
*/
|
||||||
|
inline void GetTemporaryFileName(std::string & filename) {
|
||||||
|
char buffer[L_tmpnam];
|
||||||
|
char * retPointer = tmpnam (buffer);
|
||||||
|
if(0 == retPointer)
|
||||||
|
ERR("Could not create temporary file name");
|
||||||
|
filename = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* STRINGUTIL_H_ */
|
#endif /* STRINGUTIL_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user