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::basics;
|
||||||
using namespace triagens::arango;
|
using namespace triagens::arango;
|
||||||
|
|
||||||
std::mutex m;
|
|
||||||
|
|
||||||
class SimpleEdgeExpander {
|
class SimpleEdgeExpander {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -100,13 +98,8 @@ class SimpleEdgeExpander {
|
||||||
return edgeIdPrefix.append(key);
|
return edgeIdPrefix.append(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
void operator() ( Traverser::VertexId source,
|
void operator() (Traverser::VertexId source,
|
||||||
Traverser::Direction dir,
|
vector<Traverser::Step>& result) {
|
||||||
vector<Traverser::Neighbor>& result
|
|
||||||
) {
|
|
||||||
//std::lock_guard<std::mutex> guard(m);
|
|
||||||
|
|
||||||
// cout << "Hallole: " << id << endl;
|
|
||||||
std::vector<TRI_doc_mptr_copy_t> edges;
|
std::vector<TRI_doc_mptr_copy_t> edges;
|
||||||
// Process Vertex Id!
|
// Process Vertex Id!
|
||||||
size_t split;
|
size_t split;
|
||||||
|
@ -133,19 +126,19 @@ class SimpleEdgeExpander {
|
||||||
// cout << edges.size() << endl;
|
// 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 from;
|
||||||
Traverser::VertexId to;
|
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) {
|
if (usesDist) {
|
||||||
for (size_t j = 0; j < edges.size(); ++j) {
|
for (size_t j = 0; j < edges.size(); ++j) {
|
||||||
from = extractFromId(edges[j]);
|
from = extractFromId(edges[j]);
|
||||||
to = extractFromId(edges[j]);
|
to = extractToId(edges[j]);
|
||||||
if (from != source) {
|
if (from != source) {
|
||||||
candidates.find(from);
|
candidates.find(from);
|
||||||
if (cand == candidates.end()) {
|
if (cand == candidates.end()) {
|
||||||
// Add weight
|
// Add weight
|
||||||
candidates.emplace(from, Traverser::Neighbor(from, edges[j]._id, 1));
|
candidates.emplace(from, Traverser::Step(to, from, 1, extractEdgeId(edges[j])));
|
||||||
} else {
|
} else {
|
||||||
// Compare weight
|
// Compare weight
|
||||||
}
|
}
|
||||||
|
@ -153,7 +146,7 @@ class SimpleEdgeExpander {
|
||||||
candidates.find(to);
|
candidates.find(to);
|
||||||
if (cand == candidates.end()) {
|
if (cand == candidates.end()) {
|
||||||
// Add weight
|
// Add weight
|
||||||
candidates.emplace(to, Traverser::Neighbor(to, edges[j]._id, 1));
|
candidates.emplace(to, Traverser::Step(from, to, 1, extractEdgeId(edges[j])));
|
||||||
} else {
|
} else {
|
||||||
// Compare weight
|
// Compare weight
|
||||||
}
|
}
|
||||||
|
@ -166,12 +159,12 @@ class SimpleEdgeExpander {
|
||||||
if (from != source) {
|
if (from != source) {
|
||||||
candidates.find(from);
|
candidates.find(from);
|
||||||
if (cand == candidates.end()) {
|
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) {
|
} else if (to != source) {
|
||||||
candidates.find(to);
|
candidates.find(to);
|
||||||
if (cand == candidates.end()) {
|
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");
|
SimpleEdgeExpander backwardExpander(TRI_EDGE_IN, ecol, edgeCollectionName, &resolver2, "B");
|
||||||
|
|
||||||
Traverser traverser(forwardExpander, backwardExpander);
|
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) {
|
if (path.get() == nullptr) {
|
||||||
res = trx.finish(res);
|
res = trx.finish(res);
|
||||||
v8::EscapableHandleScope scope(isolate);
|
v8::EscapableHandleScope scope(isolate);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
///
|
///
|
||||||
/// @author Michael Hackstein
|
/// @author Michael Hackstein
|
||||||
|
/// @author Max Neunhoeffer
|
||||||
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
||||||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -58,59 +59,73 @@ class Searcher : public Thread {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void insertNeighbor (Traverser::ThreadInfo& info,
|
void insertNeighbor (Traverser::VertexId& neighbor,
|
||||||
Traverser::VertexId& neighbor,
|
|
||||||
Traverser::VertexId& predecessor,
|
Traverser::VertexId& predecessor,
|
||||||
Traverser::EdgeId& edge,
|
Traverser::EdgeId& edge,
|
||||||
Traverser::EdgeWeight weight) {
|
Traverser::EdgeWeight weight) {
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(info.mutex);
|
std::lock_guard<std::mutex> guard(_myInfo._mutex);
|
||||||
auto it = info.lookup.find(neighbor);
|
Traverser::Step* s = _myInfo._pq.lookup(neighbor);
|
||||||
|
|
||||||
// Not found, so insert it:
|
// Not found, so insert it:
|
||||||
if (it == info.lookup.end()) {
|
if (s == nullptr) {
|
||||||
info.lookup.emplace(
|
_myInfo._pq.insert(neighbor,
|
||||||
neighbor,
|
Traverser::Step(neighbor, predecessor,
|
||||||
Traverser::LookupInfo(weight, edge, predecessor)
|
weight, edge));
|
||||||
);
|
|
||||||
info.queue.insert(
|
|
||||||
Traverser::QueueInfo(neighbor, weight)
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (it->second.done) {
|
if (s->_done) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (it->second.weight > weight) {
|
if (s->_weight > weight) {
|
||||||
Traverser::QueueInfo q(neighbor, it->second.weight);
|
_myInfo._pq.lowerWeight(neighbor, weight);
|
||||||
info.queue.erase(q);
|
|
||||||
q.weight = weight;
|
|
||||||
info.queue.insert(q);
|
|
||||||
it->second.weight = 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,
|
void lookupPeer (Traverser::VertexId& vertex,
|
||||||
Traverser::VertexId& neighbor,
|
|
||||||
Traverser::EdgeWeight weight) {
|
Traverser::EdgeWeight weight) {
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(info.mutex);
|
std::lock_guard<std::mutex> guard(_peerInfo._mutex);
|
||||||
auto it = info.lookup.find(neighbor);
|
Traverser::Step* s = _peerInfo._pq.lookup(vertex);
|
||||||
if (it == info.lookup.end()) {
|
if (s == nullptr) {
|
||||||
|
// Not found, nothing more to do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Traverser::EdgeWeight total = it->second.weight + weight;
|
Traverser::EdgeWeight total = s->_weight + weight;
|
||||||
if (total < _traverser->highscore) {
|
|
||||||
_traverser->highscore = total;
|
// 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);
|
// Now the highscore is set!
|
||||||
_traverser->intermediate = neighbor;
|
|
||||||
_traverser->bingo = true;
|
// 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 () {
|
virtual void run () {
|
||||||
|
|
||||||
auto nextVertexIt = _myInfo.queue.begin();
|
Traverser::VertexId v;
|
||||||
std::vector<Traverser::Neighbor> neighbors;
|
Traverser::Step s;
|
||||||
|
bool b = _myInfo._pq.popMinimal(v, s, true);
|
||||||
|
|
||||||
|
std::vector<Traverser::Step> neighbors;
|
||||||
|
|
||||||
// Iterate while no bingo found and
|
// Iterate while no bingo found and
|
||||||
// there still is a vertex on the stack.
|
// there still is a vertex on the stack.
|
||||||
while (!_traverser->bingo && nextVertexIt != _myInfo.queue.end()) {
|
while (!_traverser->_bingo && b) {
|
||||||
auto nextVertex = *nextVertexIt;
|
|
||||||
_myInfo.queue.erase(nextVertexIt);
|
|
||||||
neighbors.clear();
|
neighbors.clear();
|
||||||
_expander(nextVertex.vertex, neighbors);
|
_expander(v, neighbors);
|
||||||
for (auto& neighbor : neighbors) {
|
for (auto& neighbor : neighbors) {
|
||||||
insertNeighbor(_myInfo, neighbor.neighbor, nextVertex.vertex,
|
insertNeighbor(neighbor._vertex, v, neighbor._edge,
|
||||||
neighbor.edge, nextVertex.weight + neighbor.weight);
|
s._weight + neighbor._weight);
|
||||||
}
|
}
|
||||||
lookupPeer(_peerInfo, nextVertex.vertex, nextVertex.weight);
|
lookupPeer(v, s._weight);
|
||||||
_myInfo.mutex.lock();
|
|
||||||
// Can move nextVertexLookup up?
|
|
||||||
auto nextVertexLookup = _myInfo.lookup.find(nextVertex.vertex);
|
|
||||||
|
|
||||||
TRI_ASSERT(nextVertexLookup != _myInfo.lookup.end());
|
std::lock_guard<std::mutex> guard(_myInfo._mutex);
|
||||||
|
Traverser::Step* s2 = _myInfo._pq.lookup(v);
|
||||||
nextVertexLookup->second.done = true;
|
s2->_done = true;
|
||||||
_myInfo.mutex.unlock();
|
b = _myInfo._pq.popMinimal(v, s, true);
|
||||||
nextVertexIt = _myInfo.queue.begin();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -155,62 +167,60 @@ class Searcher : public Thread {
|
||||||
/// @brief return the shortest path between the start and target vertex.
|
/// @brief return the shortest path between the start and target vertex.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Traverser::Path* Traverser::ShortestPath (VertexId const& start,
|
Traverser::Path* Traverser::shortestPath (VertexId const& start,
|
||||||
VertexId const& target) {
|
VertexId const& target) {
|
||||||
|
|
||||||
|
// For the result:
|
||||||
std::deque<VertexId> r_vertices;
|
std::deque<VertexId> r_vertices;
|
||||||
std::deque<VertexId> r_edges;
|
std::deque<VertexId> r_edges;
|
||||||
highscore = 1e50;
|
_highscoreSet = false;
|
||||||
bingo = false;
|
_highscore = 0;
|
||||||
|
_bingo = false;
|
||||||
|
|
||||||
// Forward with initialization:
|
// Forward with initialization:
|
||||||
_forwardLookup.clear();
|
string empty;
|
||||||
_forwardLookup.emplace(start, LookupInfo(0, "", ""));
|
ThreadInfo forward;
|
||||||
_forwardQueue.clear();
|
forward._pq.insert(start, Step(start, empty, 0, empty));
|
||||||
_forwardQueue.insert(QueueInfo(start, 0));
|
|
||||||
ThreadInfo forwardInfo(_forwardLookup, _forwardQueue, _forwardMutex);
|
|
||||||
|
|
||||||
_backwardLookup.clear();
|
// backward with initialization:
|
||||||
_backwardLookup.emplace(target, LookupInfo(0, "", ""));
|
ThreadInfo backward;
|
||||||
_backwardQueue.clear();
|
backward._pq.insert(target, Step(target, empty, 0, empty));
|
||||||
_backwardQueue.insert(QueueInfo(target, 0));
|
|
||||||
ThreadInfo backwardInfo(_backwardLookup, _backwardQueue, _backwardMutex);
|
|
||||||
|
|
||||||
Searcher forwardSearcher(this, forwardInfo, backwardInfo, start,
|
// Now the searcher threads:
|
||||||
_forwardExpander, "X");
|
Searcher forwardSearcher(this, forward, backward, start,
|
||||||
Searcher backwardSearcher(this, backwardInfo, forwardInfo, target,
|
_forwardExpander, "Forward");
|
||||||
_backwardExpander, "Y");
|
Searcher backwardSearcher(this, backward, forward, target,
|
||||||
|
_backwardExpander, "Backward");
|
||||||
forwardSearcher.start();
|
forwardSearcher.start();
|
||||||
backwardSearcher.start();
|
backwardSearcher.start();
|
||||||
forwardSearcher.join();
|
forwardSearcher.join();
|
||||||
backwardSearcher.join();
|
backwardSearcher.join();
|
||||||
|
|
||||||
if (!bingo || intermediate == "") {
|
if (!_bingo || _intermediate == "") {
|
||||||
return nullptr;
|
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.
|
// FORWARD Go path back from intermediate -> start.
|
||||||
// Insert all vertices and edges at front of vector
|
// Insert all vertices and edges at front of vector
|
||||||
// Do NOT! insert the intermediate vertex
|
// Do NOT! insert the intermediate vertex
|
||||||
TRI_ASSERT(pathLookup != _forwardLookup.end());
|
while (s->_predecessor != "") {
|
||||||
r_vertices.push_back(intermediate);
|
r_edges.push_front(s->_edge);
|
||||||
while (pathLookup->second.predecessor != "") {
|
r_vertices.push_front(s->_predecessor);
|
||||||
r_edges.push_front(pathLookup->second.edge);
|
s = forward._pq.lookup(s->_predecessor);
|
||||||
r_vertices.push_front(pathLookup->second.predecessor);
|
|
||||||
pathLookup = _forwardLookup.find(pathLookup->second.predecessor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BACKWARD Go path back from intermediate -> target.
|
// BACKWARD Go path back from intermediate -> target.
|
||||||
// Insert all vertices and edges at back of vector
|
// Insert all vertices and edges at back of vector
|
||||||
// Also insert the intermediate vertex
|
// Also insert the intermediate vertex
|
||||||
pathLookup = _backwardLookup.find(intermediate);
|
s = backward._pq.lookup(_intermediate);
|
||||||
TRI_ASSERT(pathLookup != _backwardLookup.end());
|
while (s->_predecessor != "") {
|
||||||
while (pathLookup->second.predecessor != "") {
|
r_edges.push_back(s->_edge);
|
||||||
r_edges.push_back(pathLookup->second.edge);
|
r_vertices.push_back(s->_predecessor);
|
||||||
r_vertices.push_back(pathLookup->second.predecessor);
|
s = backward._pq.lookup(s->_predecessor);
|
||||||
pathLookup = _backwardLookup.find(pathLookup->second.predecessor);
|
|
||||||
}
|
}
|
||||||
Path* res = new Path(r_vertices, r_edges, highscore);
|
return new Path(r_vertices, r_edges, _highscore);
|
||||||
return res;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
class Searcher;
|
|
||||||
|
|
||||||
namespace triagens {
|
namespace triagens {
|
||||||
namespace basics {
|
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);
|
auto it = _lookup.find(k);
|
||||||
if (it == _lookup.end()) {
|
if (it == _lookup.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (it->second >= 0) { // still in the queue
|
if (it->second >= 0) { // still in the queue
|
||||||
return const_cast<Value const*>
|
return &(_heap[static_cast<size_t>(it->second) - _popped]);
|
||||||
(&(_heap[static_cast<size_t>(it->second) - _popped]));
|
|
||||||
}
|
}
|
||||||
else { // already in the history
|
else { // already in the history
|
||||||
return const_cast<Value const*>
|
return &(_history[static_cast<size_t>(-it->second) - 1]);
|
||||||
(&(_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()) {
|
if (_heap.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return const_cast<Value const*>(&(_heap[0]));
|
return &(_heap[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief popMinimal, returns true if something was returned and false
|
/// @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 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) {
|
bool popMinimal (Key& k, Value& v, bool keepForLookup = false) {
|
||||||
|
@ -358,15 +362,6 @@ namespace triagens {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void removeFromHeap (bool keepForLookup) {
|
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());
|
auto it = _lookup.find(_heap[0].getKey());
|
||||||
TRI_ASSERT(it != _lookup.end());
|
TRI_ASSERT(it != _lookup.end());
|
||||||
if (keepForLookup) {
|
if (keepForLookup) {
|
||||||
|
@ -377,6 +372,14 @@ namespace triagens {
|
||||||
else {
|
else {
|
||||||
_lookup.erase(it);
|
_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[0] = _heap.back();
|
||||||
_heap.pop_back();
|
_heap.pop_back();
|
||||||
it = _lookup.find(_heap[0].getKey());
|
it = _lookup.find(_heap[0].getKey());
|
||||||
|
@ -438,23 +441,29 @@ namespace triagens {
|
||||||
|
|
||||||
class Traverser {
|
class Traverser {
|
||||||
|
|
||||||
friend class ::Searcher;
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- data structures
|
// --SECTION-- data structures
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- path
|
// --SECTION-- types
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief types for vertices, edges and weights
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef std::string VertexId;
|
typedef std::string VertexId;
|
||||||
typedef std::string EdgeId;
|
typedef std::string EdgeId;
|
||||||
typedef double EdgeWeight;
|
typedef double EdgeWeight;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Path, type for the result
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Convention vertices.size() -1 === edges.size()
|
// Convention vertices.size() -1 === edges.size()
|
||||||
// path is vertices[0] , edges[0], vertices[1] etc.
|
// path is vertices[0] , edges[0], vertices[1] etc.
|
||||||
struct Path {
|
struct Path {
|
||||||
|
@ -462,29 +471,43 @@ namespace triagens {
|
||||||
std::deque<EdgeId> edges;
|
std::deque<EdgeId> edges;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
|
|
||||||
Path (
|
Path (std::deque<VertexId> vertices, std::deque<EdgeId> edges,
|
||||||
std::deque<VertexId> vertices,
|
EdgeWeight weight)
|
||||||
std::deque<EdgeId> edges,
|
: vertices(vertices), edges(edges), weight(weight) {
|
||||||
EdgeWeight weight
|
|
||||||
) : vertices(vertices),
|
|
||||||
edges(edges),
|
|
||||||
weight(weight) {
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Neighbor {
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
VertexId neighbor;
|
/// @brief Step, one position with a predecessor and the edge
|
||||||
EdgeId edge;
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
EdgeWeight weight;
|
|
||||||
|
|
||||||
Neighbor (
|
struct Step {
|
||||||
VertexId neighbor,
|
VertexId _vertex;
|
||||||
EdgeId edge,
|
VertexId _predecessor;
|
||||||
EdgeWeight weight
|
EdgeWeight _weight;
|
||||||
) : neighbor(neighbor),
|
EdgeId _edge;
|
||||||
edge(edge),
|
bool _done;
|
||||||
weight(weight) {
|
|
||||||
};
|
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 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;
|
ExpanderFunction;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -504,12 +531,12 @@ namespace triagens {
|
||||||
/// @brief create the Traverser
|
/// @brief create the Traverser
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Traverser (
|
Traverser (ExpanderFunction forwardExpander,
|
||||||
ExpanderFunction forwardExpander,
|
ExpanderFunction backwardExpander)
|
||||||
ExpanderFunction backwardExpander
|
: _highscoreSet(false),
|
||||||
) : highscore(1e50),
|
_highscore(0),
|
||||||
bingo(false),
|
_bingo(false),
|
||||||
intermediate(""),
|
_intermediate(""),
|
||||||
_forwardExpander(forwardExpander),
|
_forwardExpander(forwardExpander),
|
||||||
_backwardExpander(backwardExpander) {
|
_backwardExpander(backwardExpander) {
|
||||||
};
|
};
|
||||||
|
@ -517,16 +544,14 @@ namespace triagens {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief destructor
|
/// @brief destructor
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
~Traverser () {
|
~Traverser () {
|
||||||
// TODO: Implement!!
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- public methods
|
// --SECTION-- public methods
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Find the shortest path between start and target.
|
/// @brief Find the shortest path between start and target.
|
||||||
/// Only edges having the given direction are followed.
|
/// Only edges having the given direction are followed.
|
||||||
|
@ -535,91 +560,59 @@ namespace triagens {
|
||||||
|
|
||||||
// Caller has to free the result
|
// Caller has to free the result
|
||||||
// nullptr indicates there is no path
|
// nullptr indicates there is no path
|
||||||
Path* ShortestPath (
|
Path* shortestPath (
|
||||||
VertexId const& start,
|
VertexId const& start,
|
||||||
VertexId const& target
|
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;
|
/// @brief lowest total weight for a complete path found
|
||||||
std::mutex resultMutex;
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
VertexId intermediate;
|
|
||||||
|
|
||||||
struct LookupInfo {
|
EdgeWeight _highscore;
|
||||||
EdgeWeight weight;
|
|
||||||
bool done;
|
|
||||||
EdgeId edge;
|
|
||||||
VertexId predecessor;
|
|
||||||
|
|
||||||
LookupInfo (
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
EdgeWeight weight,
|
/// @brief _bingo, flag that indicates termination
|
||||||
EdgeId edge,
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
VertexId predecessor
|
|
||||||
) : weight(weight),
|
|
||||||
done(false),
|
|
||||||
edge(edge),
|
|
||||||
predecessor(predecessor) {
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QueueInfo {
|
std::atomic<bool> _bingo;
|
||||||
EdgeWeight weight;
|
|
||||||
VertexId vertex;
|
|
||||||
|
|
||||||
QueueInfo (
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
VertexId vertex,
|
/// @brief _resultMutex, this is used to protect access to the result data
|
||||||
EdgeWeight weight
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
) : weight(weight),
|
|
||||||
vertex(vertex) {
|
|
||||||
};
|
|
||||||
|
|
||||||
friend bool operator< (QueueInfo const& a, QueueInfo const& b) {
|
std::mutex _resultMutex;
|
||||||
if (a.weight == b.weight) {
|
|
||||||
return a.vertex < b.vertex;
|
|
||||||
}
|
|
||||||
return a.weight < b.weight;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @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 {
|
struct ThreadInfo {
|
||||||
std::unordered_map<VertexId, LookupInfo>& lookup;
|
PQueue _pq;
|
||||||
std::set<QueueInfo, std::less<QueueInfo>>& queue;
|
std::mutex _mutex;
|
||||||
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) {
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ExpanderFunction _forwardExpander;
|
ExpanderFunction _forwardExpander;
|
||||||
ExpanderFunction _backwardExpander;
|
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