mirror of https://gitee.com/bigwinds/arangodb
253 lines
8.4 KiB
C++
253 lines
8.4 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief vocbase traversals
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2014-2015 ArangoDB GmbH, Cologne, Germany
|
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Michael Hackstein
|
|
/// @author Copyright 2014-2015, ArangoDB GmbH, Cologne, Germany
|
|
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef ARANGODB_TRAVERSAL_H
|
|
#define ARANGODB_TRAVERSAL_H 1
|
|
|
|
#include "Basics/Common.h"
|
|
|
|
namespace triagens {
|
|
namespace basics {
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- class Traverser
|
|
// -----------------------------------------------------------------------------
|
|
|
|
class Traverser {
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- data structures
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- path
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
public:
|
|
|
|
typedef std::string VertexId;
|
|
typedef std::string EdgeId;
|
|
typedef double EdgeWeight;
|
|
|
|
// Convention vertices.size() -1 === edges.size()
|
|
// path is vertices[0] , edges[0], vertices[1] etc.
|
|
struct Path {
|
|
std::vector<VertexId> vertices;
|
|
std::vector<EdgeId> edges;
|
|
EdgeWeight weight;
|
|
|
|
Path (
|
|
std::vector<VertexId> vertices,
|
|
std::vector<EdgeId> edges,
|
|
EdgeWeight weight
|
|
) : vertices(vertices),
|
|
edges(edges),
|
|
weight(weight) {
|
|
};
|
|
};
|
|
|
|
struct Neighbor {
|
|
VertexId neighbor;
|
|
EdgeId edge;
|
|
EdgeWeight weight;
|
|
|
|
Neighbor (
|
|
VertexId neighbor,
|
|
EdgeId edge,
|
|
EdgeWeight weight
|
|
) : neighbor(neighbor),
|
|
edge(edge),
|
|
weight(weight) {
|
|
};
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief edge direction
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
typedef enum {FORWARD, BACKWARD} Direction;
|
|
|
|
typedef std::function<void(VertexId source, std::vector<Neighbor>& result)>
|
|
ExpanderFunction;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief create the Traverser
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Traverser (
|
|
ExpanderFunction const& forwardExpander,
|
|
ExpanderFunction const& backwardExpander
|
|
) : highscore(1e50),
|
|
bingo(false),
|
|
intermediate(""),
|
|
forwardExpander(forwardExpander),
|
|
backwardExpander(backwardExpander) {
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @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.
|
|
/// nullptr indicates there is no path.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Caller has to free the result
|
|
// nullptr indicates there is no path
|
|
Path* ShortestPath (
|
|
VertexId const& start,
|
|
VertexId const& target
|
|
);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- private methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief Function to compute all neighbors of a given vertex
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
private:
|
|
|
|
std::atomic<EdgeWeight> highscore;
|
|
std::atomic<bool> bingo;
|
|
std::mutex resultMutex;
|
|
VertexId intermediate;
|
|
|
|
struct LookupInfo {
|
|
EdgeWeight weight;
|
|
bool done;
|
|
EdgeId edge;
|
|
VertexId predecessor;
|
|
|
|
LookupInfo (
|
|
EdgeWeight weight,
|
|
EdgeId edge,
|
|
VertexId predecessor
|
|
) : weight(weight),
|
|
done(false),
|
|
edge(edge),
|
|
predecessor(predecessor) {
|
|
};
|
|
};
|
|
|
|
struct QueueInfo {
|
|
EdgeWeight weight;
|
|
VertexId vertex;
|
|
|
|
QueueInfo (
|
|
VertexId vertex,
|
|
EdgeWeight weight
|
|
) : weight(weight),
|
|
vertex(vertex) {
|
|
};
|
|
|
|
friend bool operator< (QueueInfo const& a, QueueInfo const& b) {
|
|
if (a.weight == b.weight) {
|
|
return a.vertex < b.vertex;
|
|
}
|
|
return a.weight < b.weight;
|
|
};
|
|
|
|
};
|
|
|
|
// 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) {
|
|
};
|
|
};
|
|
|
|
|
|
ExpanderFunction const& forwardExpander;
|
|
ExpanderFunction const& 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;
|
|
|
|
|
|
void insertNeighbor ( ThreadInfo& info,
|
|
VertexId neighbor,
|
|
VertexId predecessor,
|
|
EdgeId edge,
|
|
EdgeWeight weight
|
|
);
|
|
|
|
void lookupPeer ( ThreadInfo& info,
|
|
VertexId& neighbor,
|
|
EdgeWeight& weight
|
|
);
|
|
void searchFromVertex ( ThreadInfo myInfo,
|
|
ThreadInfo peerInfo,
|
|
VertexId start,
|
|
ExpanderFunction expander
|
|
);
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- END-OF-FILE
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
|
// End:
|