All Distance Sketch  0.1
All distance sketch based algorithms
dijkstra_shortest_paths.h
Go to the documentation of this file.
1 #ifndef SRC_ALGORITHMS_DIJKSTRA_SHORTEST_PATHS_H_
2 #define SRC_ALGORITHMS_DIJKSTRA_SHORTEST_PATHS_H_
3 
4 #include "../common.h"
5 #include "../utils/thread_utils.h"
6 #include "../sketch/node_sketch.h"
7 #include "../sketch/graph_sketch.h"
8 
13 namespace all_distance_sketch {
14 
18 struct PrunningAlgoStatistics {
19  PrunningAlgoStatistics() : num_visited_nodes(0),
20  num_pruned_nodes(0),
21  num_relaxed_edges(0) {}
22  unsigned int num_visited_nodes;
23  unsigned int num_pruned_nodes;
24  unsigned int num_relaxed_edges;
25 
26  void Clear() {
27  num_visited_nodes = 0;
28  num_pruned_nodes = 0;
29  num_relaxed_edges = 0;
30  }
31 
32  friend std::ostream& operator<<(std::ostream& os,
33  const PrunningAlgoStatistics& algo_statistics) {
34  os << " num Nodes Visited=" << algo_statistics.num_visited_nodes <<
35  " num Pruned Nodes=" << algo_statistics.num_pruned_nodes <<
36  " num Relaxed Edges=" << algo_statistics.num_relaxed_edges;
37  return os;
38  }
39 };
40 
41 struct compareNodeDistanceAndId {
42  inline bool operator()(const NodeIdDistanceData& n1,
43  const NodeIdDistanceData& n2) const {
44  if (n1.GetDistance() < n2.GetDistance()) {
45  return true;
46  }
47  if (n1.GetDistance() > n2.GetDistance()) {
48  return false;
49  }
50  if (n1.GetNId() < n2.GetNId()) {
51  return true;
52  }
53  if (n1.GetNId() > n2.GetNId()) {
54  return false;
55  }
56  return false;
57  }
58 };
59 
60 struct DijkstraParams {
61  std::set< NodeIdDistanceData, compareNodeDistanceAndId > heap;
62  std::vector<graph::EdgeWeight> min_distance;
63  TBitSet poped;
64  TBitSet touched;
65 };
66 
67 template<class T>
68 class DefaultDijkstraCallBacks {
69  public:
70  inline void Started(int source_node_id, graph::Graph<T>* graph) { return; }
71 
72  inline void NodePopedFromHeap(int poped_node_id,
73  const NodeIdDistanceData& heap_value)
74  { return; }
75 
76  inline bool ShouldPrune(int visited_node_id,
77  graph::EdgeWeight distance_from_source_to_visited_node)
78  { return false; }
79 
80  inline bool ShouldStop() { return false; }
81 
82  inline void RelaxedPath(int node_id) { }
83 };
84 
85 template<class Z>
86 class CollectorNodesUpToTRank {
87  public:
88  void InitCollectorNodesUpToTRank(int T) {
89  T_ = T;
90  }
91  inline void Started(int source_node_id, graph::Graph<Z>* graph) {
92  nodes_found_.clear();
93  algo_statistics_.Clear();
94  }
95 
96  inline void NodePopedFromHeap(int poped_node_id, const NodeIdDistanceData& heap_value) {
97  if (algo_statistics_.num_visited_nodes <= T_) {
98  nodes_found_.push_back(heap_value);
99  }
100  ++algo_statistics_.num_visited_nodes;
101  }
102 
103  inline bool ShouldPrune(int visited_node_id,
104  graph::EdgeWeight distance_from_source_to_visited_node) {
105  return algo_statistics_.num_visited_nodes >= T_;
106  }
107 
108  inline bool ShouldStop() { return algo_statistics_.num_visited_nodes >= T_; }
109 
110  inline void RelaxedPath(int node_id) { }
111 
112  const std::vector<NodeIdDistanceData>& get_nodes_found() {
113  return nodes_found_;
114  }
115  private:
116  PrunningAlgoStatistics algo_statistics_;
117  std::vector<NodeIdDistanceData> nodes_found_;
118  int T_;
119 };
120 
121 template<class Z>
122 class CollectorNodesUpToUpperBoundRankRank {
123  public:
124  void InitCollectorNodesUpToUpperBoundRankRank(int T) {
125  T_ = T;
126  }
127  inline void Started(int source_node_id, graph::Graph<Z>* graph) {
128  nodes_found_.clear();
129  algo_statistics_.Clear();
130  nodes_under_T.clear();
131  current_distance = -1;
132  }
133 
134  inline void NodePopedFromHeap(int poped_node_id, const NodeIdDistanceData& heap_value) {
135  graph::EdgeWeight distance = heap_value.GetDistance();
136  if (current_distance != distance) {
137  nodes_found_.resize(nodes_found_.size() + 1);
138  current_distance = distance;
139  }
140  nodes_found_.back().push_back(heap_value);
141  ++algo_statistics_.num_visited_nodes;
142  }
143 
144  inline bool ShouldPrune(int visited_node_id,
145  graph::EdgeWeight distance_from_source_to_visited_node) {
146  int num_nodes_ranked = 0;
147  for (int i=0; i < nodes_found_.size(); i++) {
148  num_nodes_ranked += nodes_found_[i].size();
149  }
150  return num_nodes_ranked >= T_;
151  }
152 
153  inline bool ShouldStop() { return false; }
154 
155  inline void RelaxedPath(int node_id) { }
156 
157  const std::vector<NodeIdDistanceData>& get_nodes_found() {
158  int num_nodes_collected = 0;
159  int vector_size = nodes_found_.size();
160  for (int i=0; i < vector_size; i++) {
161  num_nodes_collected += nodes_found_[i].size();
162  if (num_nodes_collected >= T_) {
163  break;
164  }
165  nodes_under_T.insert(nodes_under_T.end(), nodes_found_[i].begin(), nodes_found_[i].end());
166  }
167  LOG_M(DEBUG4, "returnin vector of size= " << nodes_under_T.size());
168  return nodes_under_T;
169  }
170  private:
171  PrunningAlgoStatistics algo_statistics_;
172  std::vector< std::vector<NodeIdDistanceData> > nodes_found_;
173  std::vector<NodeIdDistanceData> nodes_under_T;
174  std::vector<graph::EdgeWeight> rank_buckets;
175  int T_;
176  graph::EdgeWeight current_distance;
177 };
178 
179 template<class T>
180 class DijkstraRankCallBack {
181  public:
182  inline void Started(int source_node_id, graph::Graph<T>* graph) {
183  dijkstra_rank_.clear();
184  dijkstra_rank_.resize(graph->GetMxNId(), constants::UNREACHABLE);
185  dijkstra_rank_[source_node_id] = 0;
186  algo_statistics_.Clear();
187  }
188 
189  inline void NodePopedFromHeap(int poped_node_id, const NodeIdDistanceData& heap_value) {
190  dijkstra_rank_[poped_node_id] = algo_statistics_.num_visited_nodes;
191  ++algo_statistics_.num_visited_nodes;
192  }
193 
194  inline bool ShouldPrune(int visited_node_id, graph::EdgeWeight distance_from_source_to_visited_node) { return false; }
195 
196  inline bool ShouldStop() { return false; }
197 
198  inline void RelaxedPath(int node_id) { }
199 
200  const std::vector<int>& get_dijkstra_rank() {
201  return dijkstra_rank_;
202  }
203 
204  private:
205  PrunningAlgoStatistics algo_statistics_;
206  std::vector<int> dijkstra_rank_;
207 };
208 
209 template<class T>
210 class SketchDijkstraCallBacks {
211  public:
212  void InitSketchDijkstraCallBacks(GraphSketch* graph_sketch) {
213  graph_sketch_ = graph_sketch;
214  is_multi_threaded_ = false;
215  should_calculate_dijkstra_rank_ = false;
216  sketch_lock_ = NULL;
217  stop_after_ = -1;
218  algo_statistics_.Clear();
219  }
220 
221  void set_multi_threaded_params(bool multi_threaded_run, thread::ModuloLock * lock) {
222  is_multi_threaded_ = multi_threaded_run;
223  sketch_lock_ = lock;
224  }
225 
226  void set_should_calculate_dijkstra_rank(bool should_calc) {
227  should_calculate_dijkstra_rank_ = should_calc;
228  }
229 
230  inline void Started(int source_node_id, graph::Graph<T>* graph) {
231  algo_statistics_.Clear();
232  source_node_id_ = source_node_id;
233  source_node_random_id_ = graph_sketch_->GetNodeRandomId(source_node_id_);
234  if (should_calculate_dijkstra_rank_) {
235  dijkstra_rank_.clear();
236  dijkstra_rank_.resize(graph->GetMxNId(), constants::UNREACHABLE);
237  dijkstra_rank_[source_node_id_] = 0;
238  }
239  }
240 
241  inline void NodePopedFromHeap(int poped_node_id, const NodeIdDistanceData& heap_value) {
242  ++algo_statistics_.num_visited_nodes;
243  if (should_calculate_dijkstra_rank_) {
244  dijkstra_rank_[poped_node_id] = algo_statistics_.num_visited_nodes;
245  }
246  }
247 
248  inline bool ShouldPrune(int visited_node_id, graph::EdgeWeight distance_from_source_to_visited_node) {
249  bool should_prune = false;
250  bool added_node_to_ads = true;
251  NodeSketch * visited_noted_sketch = NULL;
252  if (graph_sketch_->ShouldPrune(distance_from_source_to_visited_node, visited_node_id)) {
253  ++algo_statistics_.num_pruned_nodes;
254  return true;
255  }
256 
257  // Get Node NodeSketch
258  NodeDistanceIdRandomIdData visitingNode(distance_from_source_to_visited_node,
259  visited_node_id, graph_sketch_->GetNodeRandomId(visited_node_id));
260  visited_noted_sketch = graph_sketch_->GetNodeSketch(visitingNode);
261  // Distance from source to visiting node
262  NodeDistanceIdRandomIdData sourceNodeDetails(distance_from_source_to_visited_node, source_node_id_, source_node_random_id_);
263  // Update the visiting node NodeSketch with the source Node
264  if (is_multi_threaded_) {
265  sketch_lock_->Lock(visited_node_id);
266  added_node_to_ads = visited_noted_sketch->AddToCandidates(sourceNodeDetails);
267  sketch_lock_->UnLock(visited_node_id);
268  } else {
269  added_node_to_ads = visited_noted_sketch->Add(sourceNodeDetails);
270  }
271 
272  if (added_node_to_ads == false && visited_node_id != source_node_id_) {
273  ++algo_statistics_.num_pruned_nodes;
274  return true;
275  }
276 
277  return should_prune;
278  }
279 
280  inline bool ShouldStop() {
281  if (stop_after_ != -1 && algo_statistics_.num_visited_nodes > stop_after_) {
282  return true;
283  }
284  return false;
285  }
286 
287  inline void RelaxedPath(int node_id) {
288  ++algo_statistics_.num_relaxed_edges;
289  }
290 
291  inline int get_num_pruned_nodes() {
292  return algo_statistics_.num_pruned_nodes;
293  }
294 private:
295  GraphSketch * graph_sketch_;
296  bool is_multi_threaded_;
297  bool should_calculate_dijkstra_rank_;
298  thread::ModuloLock * sketch_lock_;
299  int stop_after_;
300  PrunningAlgoStatistics algo_statistics_;
301 
302  int source_node_id_;
303  RandomId source_node_random_id_;
304  std::vector<int> dijkstra_rank_;
305 };
306 
307 
308 template <class T, class CallBacks>
309 static void PrunedDijkstra(typename T::TNode source,
310  graph::Graph<T> *graph,
311  CallBacks* call_backs,
312  DijkstraParams * param) {
313  int max_node_id = graph->GetMxNId();
314  int source_node_id = source.GetId();
315  param->poped.clear();
316  param->poped.resize(max_node_id, false);
317  param->touched.clear();
318  param->touched.resize(max_node_id, false);
319  call_backs->Started(source_node_id, graph);
320 
321  param->min_distance.resize(max_node_id, constants::UNREACHABLE);
322  param->min_distance[source.GetId()] = 0;
323  param->heap.clear();
324  param->heap.insert(NodeIdDistanceData(source_node_id, 0));
325  param->touched[source_node_id] = true;
326  LOG_M(DEBUG4, "Starting Dijkstra from node=" << source_node_id << " Max node Id " << max_node_id);
327  double last_distance = 0;
328  while (!param->heap.empty()) {
329  NodeIdDistanceData top_node = *(param->heap.begin());
330  graph::EdgeWeight distance_from_source_to_visited_node = top_node.GetDistance();
331  int visited_node_id = top_node.GetNId();
332  call_backs->NodePopedFromHeap(visited_node_id, top_node);
333  if (call_backs->ShouldStop()) {
334  LOG_M(DEBUG4, " Stopped on node=" << visited_node_id);
335  return;
336  }
337  assert(last_distance <= distance_from_source_to_visited_node);
338  last_distance = distance_from_source_to_visited_node;
339  _unused(last_distance);
340  param->min_distance[visited_node_id] = distance_from_source_to_visited_node;
341  param->heap.erase(param->heap.begin());
342  param->poped[visited_node_id] = true;
343  // Insert the source node to the top NodeSketch
344 
345  if (call_backs->ShouldPrune(visited_node_id, distance_from_source_to_visited_node)) {
346  LOG_M(DEBUG4, "Prunned node=" << visited_node_id);
347  continue;
348  }
349  // Visit each edge exiting visited_node_id
350  typename T::TNodeI neighbors = graph->GetNI(visited_node_id);
351  graph::TEdgesWeights * nodeWeights = graph->GetNodeWeights(visited_node_id);
352  for (int i = 0 ; i < neighbors.GetOutDeg(); i++) {
353  int id_of_neighbor_of_visited_node = neighbors.GetOutNId(i);
354  LOG_M(DEBUG4, " Node u= " << visited_node_id <<
355  " neighbor= " << id_of_neighbor_of_visited_node <<
356  " Out deg= " << neighbors.GetOutDeg() <<
357  " Index " << i <<
358  " Is Node? " << graph->IsNode(visited_node_id));
359 
360  if (param->poped[id_of_neighbor_of_visited_node] == true) {
361  continue;
362  }
363 
364  // std::pair<bool, graph::EdgeWeight> edge_u_v = graph->GetEdgeWeight(visited_node_id, id_of_neighbor_of_visited_node);
365  graph::EdgeWeight distance_through_u = distance_from_source_to_visited_node + (*nodeWeights)[i].get_edge_weight(); // + edge_u_v.second;
366  if ((param->touched[id_of_neighbor_of_visited_node] == false) ||
367  (distance_through_u < param->min_distance[id_of_neighbor_of_visited_node])) {
368 
369  if (param->touched[id_of_neighbor_of_visited_node] == false) {
370  LOG_M(DEBUG1, "Node " << id_of_neighbor_of_visited_node << " Untouced ");
371  } else {
372  LOG_M(DEBUG1, "Node " << visited_node_id <<
373  " neighbor=" << id_of_neighbor_of_visited_node <<
374  " Distance before relax=" << param->min_distance[id_of_neighbor_of_visited_node] <<
375  " distance through visited_node_id=" << distance_through_u);
376  }
377 
378  call_backs->RelaxedPath(id_of_neighbor_of_visited_node);
379  // UNREACHABLE only if this is our first time
380  if ( param->touched[id_of_neighbor_of_visited_node] == false ) {
381  param->heap.insert(NodeIdDistanceData(id_of_neighbor_of_visited_node, distance_through_u));
382  LOG_M(DEBUG1, "Inserting node " << id_of_neighbor_of_visited_node << " to heap with distance " << distance_through_u);
383  } else {
384  param->heap.erase(NodeIdDistanceData(id_of_neighbor_of_visited_node, param->min_distance[id_of_neighbor_of_visited_node]));
385  param->heap.insert(NodeIdDistanceData(id_of_neighbor_of_visited_node, distance_through_u));
386  LOG_M(DEBUG5, "Decreasing distance of node " << id_of_neighbor_of_visited_node <<
387  " from " << param->min_distance[id_of_neighbor_of_visited_node] <<
388  " to " << distance_through_u);
389  }
390  param->touched[id_of_neighbor_of_visited_node] = true;
391  param->min_distance[id_of_neighbor_of_visited_node] = distance_through_u;
392  }
393  }
394  }
395 }
396 
400 } // namespace all_distance_sketch
401 #endif // SRC_ALGORITHMS_DIJKSTRA_SHORTEST_PATHS_H_
Single node sketch.
Definition: node_sketch.h:204
Definition: common.h:53
Graph data structure Thin wrapper over SNAP graph.
Definition: graph.h:107
RandomId GetNodeRandomId(const int &node_id)
returns specific node random id
Definition: graph_sketch.h:371
const float UNREACHABLE
Definition: common.h:62
Data structure for the graph sketch.
Definition: graph_sketch.h:17
double RandomId
Type for random ids.
Definition: node_sketch.h:14
Container class to store node id and distance.
Definition: node_sketch.h:26