mirror of https://gitee.com/bigwinds/arangodb
Use new PriorityQueue, compiles, does not work.
This commit is contained in:
parent
3fc8243432
commit
e508a1697d
|
@ -45,8 +45,6 @@ using namespace std;
|
|||
using namespace triagens::basics;
|
||||
using namespace triagens::arango;
|
||||
|
||||
std::mutex m;
|
||||
|
||||
class SimpleEdgeExpander {
|
||||
|
||||
private:
|
||||
|
@ -100,13 +98,8 @@ class SimpleEdgeExpander {
|
|||
return edgeIdPrefix.append(key);
|
||||
};
|
||||
|
||||
void operator() ( Traverser::VertexId source,
|
||||
Traverser::Direction dir,
|
||||
vector<Traverser::Neighbor>& result
|
||||
) {
|
||||
//std::lock_guard<std::mutex> guard(m);
|
||||
|
||||
// cout << "Hallole: " << id << endl;
|
||||
void operator() (Traverser::VertexId source,
|
||||
vector<Traverser::Step>& result) {
|
||||
std::vector<TRI_doc_mptr_copy_t> edges;
|
||||
// Process Vertex Id!
|
||||
size_t split;
|
||||
|
@ -133,19 +126,19 @@ class SimpleEdgeExpander {
|
|||
// cout << edges.size() << endl;
|
||||
}
|
||||
|
||||
std::unordered_map<Traverser::VertexId, Traverser::Neighbor> candidates;
|
||||
std::unordered_map<Traverser::VertexId, Traverser::Step> candidates;
|
||||
Traverser::VertexId from;
|
||||
Traverser::VertexId to;
|
||||
std::unordered_map<Traverser::VertexId, Traverser::Neighbor>::const_iterator cand;
|
||||
std::unordered_map<Traverser::VertexId, Traverser::Step>::const_iterator cand;
|
||||
if (usesDist) {
|
||||
for (size_t j = 0; j < edges.size(); ++j) {
|
||||
from = extractFromId(edges[j]);
|
||||
to = extractFromId(edges[j]);
|
||||
to = extractToId(edges[j]);
|
||||
if (from != source) {
|
||||
candidates.find(from);
|
||||
if (cand == candidates.end()) {
|
||||
// Add weight
|
||||
candidates.emplace(from, Traverser::Neighbor(from, edges[j]._id, 1));
|
||||
candidates.emplace(from, Traverser::Step(to, from, 1, extractEdgeId(edges[j])));
|
||||
} else {
|
||||
// Compare weight
|
||||
}
|
||||
|
@ -153,7 +146,7 @@ class SimpleEdgeExpander {
|
|||
candidates.find(to);
|
||||
if (cand == candidates.end()) {
|
||||
// Add weight
|
||||
candidates.emplace(to, Traverser::Neighbor(to, edges[j]._id, 1));
|
||||
candidates.emplace(to, Traverser::Step(from, to, 1, extractEdgeId(edges[j])));
|
||||
} else {
|
||||
// Compare weight
|
||||
}
|
||||
|
@ -166,12 +159,12 @@ class SimpleEdgeExpander {
|
|||
if (from != source) {
|
||||
candidates.find(from);
|
||||
if (cand == candidates.end()) {
|
||||
candidates.emplace(from, Traverser::Neighbor(from, edges[j]._id, 1));
|
||||
candidates.emplace(from, Traverser::Step(to, from, 1, extractEdgeId(edges[j])));
|
||||
}
|
||||
} else if (to != source) {
|
||||
candidates.find(to);
|
||||
if (cand == candidates.end()) {
|
||||
candidates.emplace(to, Traverser::Neighbor(to, edges[j]._id, 1));
|
||||
candidates.emplace(to, Traverser::Step(from, to, 1, extractEdgeId(edges[j])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +322,7 @@ void TRI_RunDijkstraSearch (const v8::FunctionCallbackInfo<v8::Value>& args) {
|
|||
SimpleEdgeExpander backwardExpander(TRI_EDGE_IN, ecol, edgeCollectionName, &resolver2, "B");
|
||||
|
||||
Traverser traverser(forwardExpander, backwardExpander);
|
||||
unique_ptr<Traverser::Path> path(traverser.ShortestPath(startVertex, targetVertex));
|
||||
unique_ptr<Traverser::Path> path(traverser.shortestPath(startVertex, targetVertex));
|
||||
if (path.get() == nullptr) {
|
||||
res = trx.finish(res);
|
||||
v8::EscapableHandleScope scope(isolate);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Michael Hackstein
|
||||
/// @author Max Neunhoeffer
|
||||
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -58,59 +59,73 @@ class Searcher : public Thread {
|
|||
|
||||
private:
|
||||
|
||||
void insertNeighbor (Traverser::ThreadInfo& info,
|
||||
Traverser::VertexId& neighbor,
|
||||
void insertNeighbor (Traverser::VertexId& neighbor,
|
||||
Traverser::VertexId& predecessor,
|
||||
Traverser::EdgeId& edge,
|
||||
Traverser::EdgeWeight weight) {
|
||||
|
||||
std::lock_guard<std::mutex> guard(info.mutex);
|
||||
auto it = info.lookup.find(neighbor);
|
||||
std::lock_guard<std::mutex> guard(_myInfo._mutex);
|
||||
Traverser::Step* s = _myInfo._pq.lookup(neighbor);
|
||||
|
||||
// Not found, so insert it:
|
||||
if (it == info.lookup.end()) {
|
||||
info.lookup.emplace(
|
||||
neighbor,
|
||||
Traverser::LookupInfo(weight, edge, predecessor)
|
||||
);
|
||||
info.queue.insert(
|
||||
Traverser::QueueInfo(neighbor, weight)
|
||||
);
|
||||
if (s == nullptr) {
|
||||
_myInfo._pq.insert(neighbor,
|
||||
Traverser::Step(neighbor, predecessor,
|
||||
weight, edge));
|
||||
return;
|
||||
}
|
||||
if (it->second.done) {
|
||||
if (s->_done) {
|
||||
return;
|
||||
}
|
||||
if (it->second.weight > weight) {
|
||||
Traverser::QueueInfo q(neighbor, it->second.weight);
|
||||
info.queue.erase(q);
|
||||
q.weight = weight;
|
||||
info.queue.insert(q);
|
||||
it->second.weight = weight;
|
||||
if (s->_weight > weight) {
|
||||
_myInfo._pq.lowerWeight(neighbor, weight);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Lookup a neighbor in the list of our peer.
|
||||
/// @brief Lookup our current vertex in the data of our peer.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void lookupPeer (Traverser::ThreadInfo& info,
|
||||
Traverser::VertexId& neighbor,
|
||||
void lookupPeer (Traverser::VertexId& vertex,
|
||||
Traverser::EdgeWeight weight) {
|
||||
|
||||
std::lock_guard<std::mutex> guard(info.mutex);
|
||||
auto it = info.lookup.find(neighbor);
|
||||
if (it == info.lookup.end()) {
|
||||
std::lock_guard<std::mutex> guard(_peerInfo._mutex);
|
||||
Traverser::Step* s = _peerInfo._pq.lookup(vertex);
|
||||
if (s == nullptr) {
|
||||
// Not found, nothing more to do
|
||||
return;
|
||||
}
|
||||
Traverser::EdgeWeight total = it->second.weight + weight;
|
||||
if (total < _traverser->highscore) {
|
||||
_traverser->highscore = total;
|
||||
Traverser::EdgeWeight total = s->_weight + weight;
|
||||
|
||||
// Update the highscore:
|
||||
std::lock_guard<std::mutex> guard2(_traverser->_resultMutex);
|
||||
if (!_traverser->_highscoreSet || total < _traverser->_highscore) {
|
||||
_traverser->_highscoreSet = true;
|
||||
_traverser->_highscore = total;
|
||||
}
|
||||
if (it->second.done && total <= _traverser->highscore) {
|
||||
std::lock_guard<std::mutex> guard(_traverser->resultMutex);
|
||||
_traverser->intermediate = neighbor;
|
||||
_traverser->bingo = true;
|
||||
|
||||
// Now the highscore is set!
|
||||
|
||||
// Did we find a solution together with the other thread?
|
||||
if (s->_done) {
|
||||
if (total <= _traverser->_highscore) {
|
||||
_traverser->_intermediate = vertex;
|
||||
_traverser->_bingo = true;
|
||||
}
|
||||
// We found a way, but somebody else found a better way, so
|
||||
// this is not the shortest path
|
||||
return;
|
||||
}
|
||||
|
||||
// Did we find a solution on our own? This is for the single thread
|
||||
// case and for the case that the other thread is too slow to even
|
||||
// finish its own start vertex!
|
||||
if (s->_weight == 0) {
|
||||
// We have found the target, we have finished all vertices with
|
||||
// a smaller weight than this one (and did not succeed), so this
|
||||
// must be a best solution:
|
||||
_traverser->_intermediate = vertex;
|
||||
_traverser->_bingo = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,30 +138,27 @@ class Searcher : public Thread {
|
|||
|
||||
virtual void run () {
|
||||
|
||||
auto nextVertexIt = _myInfo.queue.begin();
|
||||
std::vector<Traverser::Neighbor> neighbors;
|
||||
Traverser::VertexId v;
|
||||
Traverser::Step s;
|
||||
bool b = _myInfo._pq.popMinimal(v, s, true);
|
||||
|
||||
std::vector<Traverser::Step> neighbors;
|
||||
|
||||
// Iterate while no bingo found and
|
||||
// there still is a vertex on the stack.
|
||||
while (!_traverser->bingo && nextVertexIt != _myInfo.queue.end()) {
|
||||
auto nextVertex = *nextVertexIt;
|
||||
_myInfo.queue.erase(nextVertexIt);
|
||||
while (!_traverser->_bingo && b) {
|
||||
neighbors.clear();
|
||||
_expander(nextVertex.vertex, neighbors);
|
||||
_expander(v, neighbors);
|
||||
for (auto& neighbor : neighbors) {
|
||||
insertNeighbor(_myInfo, neighbor.neighbor, nextVertex.vertex,
|
||||
neighbor.edge, nextVertex.weight + neighbor.weight);
|
||||
insertNeighbor(neighbor._vertex, v, neighbor._edge,
|
||||
s._weight + neighbor._weight);
|
||||
}
|
||||
lookupPeer(_peerInfo, nextVertex.vertex, nextVertex.weight);
|
||||
_myInfo.mutex.lock();
|
||||
// Can move nextVertexLookup up?
|
||||
auto nextVertexLookup = _myInfo.lookup.find(nextVertex.vertex);
|
||||
lookupPeer(v, s._weight);
|
||||
|
||||
TRI_ASSERT(nextVertexLookup != _myInfo.lookup.end());
|
||||
|
||||
nextVertexLookup->second.done = true;
|
||||
_myInfo.mutex.unlock();
|
||||
nextVertexIt = _myInfo.queue.begin();
|
||||
std::lock_guard<std::mutex> guard(_myInfo._mutex);
|
||||
Traverser::Step* s2 = _myInfo._pq.lookup(v);
|
||||
s2->_done = true;
|
||||
b = _myInfo._pq.popMinimal(v, s, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -155,62 +167,60 @@ class Searcher : public Thread {
|
|||
/// @brief return the shortest path between the start and target vertex.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Traverser::Path* Traverser::ShortestPath (VertexId const& start,
|
||||
VertexId const& target) {
|
||||
Traverser::Path* Traverser::shortestPath (VertexId const& start,
|
||||
VertexId const& target) {
|
||||
|
||||
// For the result:
|
||||
std::deque<VertexId> r_vertices;
|
||||
std::deque<VertexId> r_edges;
|
||||
highscore = 1e50;
|
||||
bingo = false;
|
||||
_highscoreSet = false;
|
||||
_highscore = 0;
|
||||
_bingo = false;
|
||||
|
||||
// Forward with initialization:
|
||||
_forwardLookup.clear();
|
||||
_forwardLookup.emplace(start, LookupInfo(0, "", ""));
|
||||
_forwardQueue.clear();
|
||||
_forwardQueue.insert(QueueInfo(start, 0));
|
||||
ThreadInfo forwardInfo(_forwardLookup, _forwardQueue, _forwardMutex);
|
||||
string empty;
|
||||
ThreadInfo forward;
|
||||
forward._pq.insert(start, Step(start, empty, 0, empty));
|
||||
|
||||
_backwardLookup.clear();
|
||||
_backwardLookup.emplace(target, LookupInfo(0, "", ""));
|
||||
_backwardQueue.clear();
|
||||
_backwardQueue.insert(QueueInfo(target, 0));
|
||||
ThreadInfo backwardInfo(_backwardLookup, _backwardQueue, _backwardMutex);
|
||||
// backward with initialization:
|
||||
ThreadInfo backward;
|
||||
backward._pq.insert(target, Step(target, empty, 0, empty));
|
||||
|
||||
Searcher forwardSearcher(this, forwardInfo, backwardInfo, start,
|
||||
_forwardExpander, "X");
|
||||
Searcher backwardSearcher(this, backwardInfo, forwardInfo, target,
|
||||
_backwardExpander, "Y");
|
||||
// Now the searcher threads:
|
||||
Searcher forwardSearcher(this, forward, backward, start,
|
||||
_forwardExpander, "Forward");
|
||||
Searcher backwardSearcher(this, backward, forward, target,
|
||||
_backwardExpander, "Backward");
|
||||
forwardSearcher.start();
|
||||
backwardSearcher.start();
|
||||
forwardSearcher.join();
|
||||
backwardSearcher.join();
|
||||
|
||||
if (!bingo || intermediate == "") {
|
||||
if (!_bingo || _intermediate == "") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pathLookup = _forwardLookup.find(intermediate);
|
||||
Step* s = forward._pq.lookup(_intermediate);
|
||||
r_vertices.push_back(_intermediate);
|
||||
|
||||
// FORWARD Go path back from intermediate -> start.
|
||||
// Insert all vertices and edges at front of vector
|
||||
// Do NOT! insert the intermediate vertex
|
||||
TRI_ASSERT(pathLookup != _forwardLookup.end());
|
||||
r_vertices.push_back(intermediate);
|
||||
while (pathLookup->second.predecessor != "") {
|
||||
r_edges.push_front(pathLookup->second.edge);
|
||||
r_vertices.push_front(pathLookup->second.predecessor);
|
||||
pathLookup = _forwardLookup.find(pathLookup->second.predecessor);
|
||||
while (s->_predecessor != "") {
|
||||
r_edges.push_front(s->_edge);
|
||||
r_vertices.push_front(s->_predecessor);
|
||||
s = forward._pq.lookup(s->_predecessor);
|
||||
}
|
||||
|
||||
// BACKWARD Go path back from intermediate -> target.
|
||||
// Insert all vertices and edges at back of vector
|
||||
// Also insert the intermediate vertex
|
||||
pathLookup = _backwardLookup.find(intermediate);
|
||||
TRI_ASSERT(pathLookup != _backwardLookup.end());
|
||||
while (pathLookup->second.predecessor != "") {
|
||||
r_edges.push_back(pathLookup->second.edge);
|
||||
r_vertices.push_back(pathLookup->second.predecessor);
|
||||
pathLookup = _backwardLookup.find(pathLookup->second.predecessor);
|
||||
s = backward._pq.lookup(_intermediate);
|
||||
while (s->_predecessor != "") {
|
||||
r_edges.push_back(s->_edge);
|
||||
r_vertices.push_back(s->_predecessor);
|
||||
s = backward._pq.lookup(s->_predecessor);
|
||||
}
|
||||
Path* res = new Path(r_vertices, r_edges, highscore);
|
||||
return res;
|
||||
return new Path(r_vertices, r_edges, _highscore);
|
||||
};
|
||||
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
|
||||
#include <mutex>
|
||||
|
||||
class Searcher;
|
||||
|
||||
namespace triagens {
|
||||
namespace basics {
|
||||
|
||||
|
@ -158,21 +156,22 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookup
|
||||
/// @brief lookup, note that the resulting pointer is only valid until the
|
||||
/// the next modification of the data structure happens (insert or lowerWeight
|
||||
/// or popMinimal). The weight in the Value type must not be modified other
|
||||
/// than via lowerWeight, otherwise the queue order could be violated.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Value const* lookup (Key const& k) {
|
||||
Value* lookup (Key const& k) {
|
||||
auto it = _lookup.find(k);
|
||||
if (it == _lookup.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (it->second >= 0) { // still in the queue
|
||||
return const_cast<Value const*>
|
||||
(&(_heap[static_cast<size_t>(it->second) - _popped]));
|
||||
return &(_heap[static_cast<size_t>(it->second) - _popped]);
|
||||
}
|
||||
else { // already in the history
|
||||
return const_cast<Value const*>
|
||||
(&(_history[static_cast<size_t>(-it->second) - 1]));
|
||||
return &(_history[static_cast<size_t>(-it->second) - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,19 +200,24 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getMinimal
|
||||
/// @brief getMinimal, note that the resulting pointer is only valid until the
|
||||
/// the next modification of the data structure happens (insert or lowerWeight
|
||||
/// or popMinimal). The weight in the Value type must not be modified other
|
||||
/// than via lowerWeight, otherwise the queue order could be violated.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Value const* getMinimal() {
|
||||
Value* getMinimal() {
|
||||
if (_heap.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<Value const*>(&(_heap[0]));
|
||||
return &(_heap[0]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief popMinimal, returns true if something was returned and false
|
||||
/// if the structure is empty. Key and Value are stored in k and v.
|
||||
/// If keepForLookup is true then the Value is kept for lookup in the
|
||||
/// hash table but removed from the priority queue.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool popMinimal (Key& k, Value& v, bool keepForLookup = false) {
|
||||
|
@ -358,15 +362,6 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void removeFromHeap (bool keepForLookup) {
|
||||
if (_heap.size() == 1) {
|
||||
_heap.clear();
|
||||
_popped = 0;
|
||||
_lookup.clear();
|
||||
_isHeap = false;
|
||||
_maxWeight = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = _lookup.find(_heap[0].getKey());
|
||||
TRI_ASSERT(it != _lookup.end());
|
||||
if (keepForLookup) {
|
||||
|
@ -377,6 +372,14 @@ namespace triagens {
|
|||
else {
|
||||
_lookup.erase(it);
|
||||
}
|
||||
if (_heap.size() == 1) {
|
||||
_heap.clear();
|
||||
_popped = 0;
|
||||
_isHeap = false;
|
||||
_maxWeight = 0;
|
||||
return;
|
||||
}
|
||||
// Move one in front:
|
||||
_heap[0] = _heap.back();
|
||||
_heap.pop_back();
|
||||
it = _lookup.find(_heap[0].getKey());
|
||||
|
@ -438,23 +441,29 @@ namespace triagens {
|
|||
|
||||
class Traverser {
|
||||
|
||||
friend class ::Searcher;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- data structures
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- path
|
||||
// --SECTION-- types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief types for vertices, edges and weights
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::string VertexId;
|
||||
typedef std::string EdgeId;
|
||||
typedef double EdgeWeight;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Path, type for the result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Convention vertices.size() -1 === edges.size()
|
||||
// path is vertices[0] , edges[0], vertices[1] etc.
|
||||
struct Path {
|
||||
|
@ -462,29 +471,43 @@ namespace triagens {
|
|||
std::deque<EdgeId> edges;
|
||||
EdgeWeight weight;
|
||||
|
||||
Path (
|
||||
std::deque<VertexId> vertices,
|
||||
std::deque<EdgeId> edges,
|
||||
EdgeWeight weight
|
||||
) : vertices(vertices),
|
||||
edges(edges),
|
||||
weight(weight) {
|
||||
Path (std::deque<VertexId> vertices, std::deque<EdgeId> edges,
|
||||
EdgeWeight weight)
|
||||
: vertices(vertices), edges(edges), weight(weight) {
|
||||
};
|
||||
};
|
||||
|
||||
struct Neighbor {
|
||||
VertexId neighbor;
|
||||
EdgeId edge;
|
||||
EdgeWeight weight;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Step, one position with a predecessor and the edge
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Neighbor (
|
||||
VertexId neighbor,
|
||||
EdgeId edge,
|
||||
EdgeWeight weight
|
||||
) : neighbor(neighbor),
|
||||
edge(edge),
|
||||
weight(weight) {
|
||||
};
|
||||
struct Step {
|
||||
VertexId _vertex;
|
||||
VertexId _predecessor;
|
||||
EdgeWeight _weight;
|
||||
EdgeId _edge;
|
||||
bool _done;
|
||||
|
||||
Step () : _done(false) {
|
||||
}
|
||||
|
||||
Step (VertexId const& vert, VertexId const& pred,
|
||||
EdgeWeight weig, EdgeId const& edge)
|
||||
: _vertex(vert), _predecessor(pred), _weight(weig), _edge(edge),
|
||||
_done(false) {
|
||||
}
|
||||
|
||||
EdgeWeight weight () const {
|
||||
return _weight;
|
||||
}
|
||||
|
||||
void setWeight (EdgeWeight w) {
|
||||
_weight = w;
|
||||
}
|
||||
|
||||
VertexId const& getKey () const {
|
||||
return _vertex;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -493,7 +516,11 @@ namespace triagens {
|
|||
|
||||
typedef enum {FORWARD, BACKWARD} Direction;
|
||||
|
||||
typedef std::function<void(VertexId source, std::vector<Neighbor>& result)>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief callback to find neighbours
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::function<void(VertexId V, std::vector<Step>& result)>
|
||||
ExpanderFunction;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -504,12 +531,12 @@ namespace triagens {
|
|||
/// @brief create the Traverser
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Traverser (
|
||||
ExpanderFunction forwardExpander,
|
||||
ExpanderFunction backwardExpander
|
||||
) : highscore(1e50),
|
||||
bingo(false),
|
||||
intermediate(""),
|
||||
Traverser (ExpanderFunction forwardExpander,
|
||||
ExpanderFunction backwardExpander)
|
||||
: _highscoreSet(false),
|
||||
_highscore(0),
|
||||
_bingo(false),
|
||||
_intermediate(""),
|
||||
_forwardExpander(forwardExpander),
|
||||
_backwardExpander(backwardExpander) {
|
||||
};
|
||||
|
@ -517,16 +544,14 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~Traverser () {
|
||||
// TODO: Implement!!
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Find the shortest path between start and target.
|
||||
/// Only edges having the given direction are followed.
|
||||
|
@ -535,91 +560,59 @@ namespace triagens {
|
|||
|
||||
// Caller has to free the result
|
||||
// nullptr indicates there is no path
|
||||
Path* ShortestPath (
|
||||
Path* shortestPath (
|
||||
VertexId const& start,
|
||||
VertexId const& target
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// --SECTION-- public data
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Function to compute all neighbors of a given vertex
|
||||
/// @brief lowest total weight for a complete path found
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
bool _highscoreSet;
|
||||
|
||||
std::atomic<EdgeWeight> highscore;
|
||||
std::atomic<bool> bingo;
|
||||
std::mutex resultMutex;
|
||||
VertexId intermediate;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lowest total weight for a complete path found
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct LookupInfo {
|
||||
EdgeWeight weight;
|
||||
bool done;
|
||||
EdgeId edge;
|
||||
VertexId predecessor;
|
||||
EdgeWeight _highscore;
|
||||
|
||||
LookupInfo (
|
||||
EdgeWeight weight,
|
||||
EdgeId edge,
|
||||
VertexId predecessor
|
||||
) : weight(weight),
|
||||
done(false),
|
||||
edge(edge),
|
||||
predecessor(predecessor) {
|
||||
};
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _bingo, flag that indicates termination
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct QueueInfo {
|
||||
EdgeWeight weight;
|
||||
VertexId vertex;
|
||||
std::atomic<bool> _bingo;
|
||||
|
||||
QueueInfo (
|
||||
VertexId vertex,
|
||||
EdgeWeight weight
|
||||
) : weight(weight),
|
||||
vertex(vertex) {
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _resultMutex, this is used to protect access to the result data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
friend bool operator< (QueueInfo const& a, QueueInfo const& b) {
|
||||
if (a.weight == b.weight) {
|
||||
return a.vertex < b.vertex;
|
||||
}
|
||||
return a.weight < b.weight;
|
||||
};
|
||||
std::mutex _resultMutex;
|
||||
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief _intermediate, one vertex on the shortest path found
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VertexId _intermediate;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private data
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
typedef triagens::basics::PriorityQueue<VertexId, Step, EdgeWeight>
|
||||
PQueue;
|
||||
|
||||
// TODO: Destructor?!
|
||||
struct ThreadInfo {
|
||||
std::unordered_map<VertexId, LookupInfo>& lookup;
|
||||
std::set<QueueInfo, std::less<QueueInfo>>& queue;
|
||||
std::mutex& mutex;
|
||||
|
||||
ThreadInfo (
|
||||
std::unordered_map<VertexId, LookupInfo>& lookup,
|
||||
std::set<QueueInfo, std::less<QueueInfo>>& queue,
|
||||
std::mutex& mutex
|
||||
) : lookup(lookup),
|
||||
queue(queue),
|
||||
mutex(mutex) {
|
||||
};
|
||||
PQueue _pq;
|
||||
std::mutex _mutex;
|
||||
};
|
||||
|
||||
|
||||
ExpanderFunction _forwardExpander;
|
||||
ExpanderFunction _backwardExpander;
|
||||
|
||||
// ShortestPath will create these variables
|
||||
std::unordered_map<VertexId, LookupInfo> _forwardLookup;
|
||||
std::set<QueueInfo, std::less<QueueInfo>> _forwardQueue;
|
||||
std::mutex _forwardMutex;
|
||||
|
||||
std::unordered_map<VertexId, LookupInfo> _backwardLookup;
|
||||
std::set<QueueInfo, std::less<QueueInfo>> _backwardQueue;
|
||||
std::mutex _backwardMutex;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue