1 #ifndef SRC_ALGORITHMS_DIJKSTRA_SHORTEST_PATHS_H_
2 #define SRC_ALGORITHMS_DIJKSTRA_SHORTEST_PATHS_H_
5 #include "../utils/thread_utils.h"
6 #include "../sketch/node_sketch.h"
7 #include "../sketch/graph_sketch.h"
18 struct PrunningAlgoStatistics {
19 PrunningAlgoStatistics() : num_visited_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;
27 num_visited_nodes = 0;
29 num_relaxed_edges = 0;
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;
41 struct compareNodeDistanceAndId {
44 if (n1.GetDistance() < n2.GetDistance()) {
47 if (n1.GetDistance() > n2.GetDistance()) {
50 if (n1.GetNId() < n2.GetNId()) {
53 if (n1.GetNId() > n2.GetNId()) {
60 struct DijkstraParams {
61 std::set< NodeIdDistanceData, compareNodeDistanceAndId > heap;
62 std::vector<graph::EdgeWeight> min_distance;
68 class DefaultDijkstraCallBacks {
70 inline void Started(
int source_node_id,
graph::Graph<T>* graph) {
return; }
72 inline void NodePopedFromHeap(
int poped_node_id,
76 inline bool ShouldPrune(
int visited_node_id,
77 graph::EdgeWeight distance_from_source_to_visited_node)
80 inline bool ShouldStop() {
return false; }
82 inline void RelaxedPath(
int node_id) { }
86 class CollectorNodesUpToTRank {
88 void InitCollectorNodesUpToTRank(
int T) {
93 algo_statistics_.Clear();
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);
100 ++algo_statistics_.num_visited_nodes;
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_;
108 inline bool ShouldStop() {
return algo_statistics_.num_visited_nodes >= T_; }
110 inline void RelaxedPath(
int node_id) { }
112 const std::vector<NodeIdDistanceData>& get_nodes_found() {
116 PrunningAlgoStatistics algo_statistics_;
117 std::vector<NodeIdDistanceData> nodes_found_;
122 class CollectorNodesUpToUpperBoundRankRank {
124 void InitCollectorNodesUpToUpperBoundRankRank(
int T) {
128 nodes_found_.clear();
129 algo_statistics_.Clear();
130 nodes_under_T.clear();
131 current_distance = -1;
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;
140 nodes_found_.back().push_back(heap_value);
141 ++algo_statistics_.num_visited_nodes;
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();
150 return num_nodes_ranked >= T_;
153 inline bool ShouldStop() {
return false; }
155 inline void RelaxedPath(
int node_id) { }
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_) {
165 nodes_under_T.insert(nodes_under_T.end(), nodes_found_[i].begin(), nodes_found_[i].end());
167 LOG_M(DEBUG4,
"returnin vector of size= " << nodes_under_T.size());
168 return nodes_under_T;
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;
176 graph::EdgeWeight current_distance;
180 class DijkstraRankCallBack {
183 dijkstra_rank_.clear();
185 dijkstra_rank_[source_node_id] = 0;
186 algo_statistics_.Clear();
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;
194 inline bool ShouldPrune(
int visited_node_id, graph::EdgeWeight distance_from_source_to_visited_node) {
return false; }
196 inline bool ShouldStop() {
return false; }
198 inline void RelaxedPath(
int node_id) { }
200 const std::vector<int>& get_dijkstra_rank() {
201 return dijkstra_rank_;
205 PrunningAlgoStatistics algo_statistics_;
206 std::vector<int> dijkstra_rank_;
210 class SketchDijkstraCallBacks {
212 void InitSketchDijkstraCallBacks(
GraphSketch* graph_sketch) {
213 graph_sketch_ = graph_sketch;
214 is_multi_threaded_ =
false;
215 should_calculate_dijkstra_rank_ =
false;
218 algo_statistics_.Clear();
221 void set_multi_threaded_params(
bool multi_threaded_run, thread::ModuloLock * lock) {
222 is_multi_threaded_ = multi_threaded_run;
226 void set_should_calculate_dijkstra_rank(
bool should_calc) {
227 should_calculate_dijkstra_rank_ = should_calc;
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();
237 dijkstra_rank_[source_node_id_] = 0;
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;
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;
252 if (graph_sketch_->ShouldPrune(distance_from_source_to_visited_node, visited_node_id)) {
253 ++algo_statistics_.num_pruned_nodes;
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);
262 NodeDistanceIdRandomIdData sourceNodeDetails(distance_from_source_to_visited_node, source_node_id_, source_node_random_id_);
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);
269 added_node_to_ads = visited_noted_sketch->Add(sourceNodeDetails);
272 if (added_node_to_ads ==
false && visited_node_id != source_node_id_) {
273 ++algo_statistics_.num_pruned_nodes;
280 inline bool ShouldStop() {
281 if (stop_after_ != -1 && algo_statistics_.num_visited_nodes > stop_after_) {
287 inline void RelaxedPath(
int node_id) {
288 ++algo_statistics_.num_relaxed_edges;
291 inline int get_num_pruned_nodes() {
292 return algo_statistics_.num_pruned_nodes;
296 bool is_multi_threaded_;
297 bool should_calculate_dijkstra_rank_;
298 thread::ModuloLock * sketch_lock_;
300 PrunningAlgoStatistics algo_statistics_;
304 std::vector<int> dijkstra_rank_;
308 template <
class T,
class CallBacks>
309 static void PrunedDijkstra(
typename T::TNode source,
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);
322 param->min_distance[source.GetId()] = 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()) {
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);
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;
345 if (call_backs->ShouldPrune(visited_node_id, distance_from_source_to_visited_node)) {
346 LOG_M(DEBUG4,
"Prunned node=" << 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() <<
358 " Is Node? " << graph->IsNode(visited_node_id));
360 if (param->poped[id_of_neighbor_of_visited_node] ==
true) {
365 graph::EdgeWeight distance_through_u = distance_from_source_to_visited_node + (*nodeWeights)[i].get_edge_weight();
366 if ((param->touched[id_of_neighbor_of_visited_node] ==
false) ||
367 (distance_through_u < param->min_distance[id_of_neighbor_of_visited_node])) {
369 if (param->touched[id_of_neighbor_of_visited_node] ==
false) {
370 LOG_M(DEBUG1,
"Node " << id_of_neighbor_of_visited_node <<
" Untouced ");
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);
378 call_backs->RelaxedPath(id_of_neighbor_of_visited_node);
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);
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);
390 param->touched[id_of_neighbor_of_visited_node] =
true;
391 param->min_distance[id_of_neighbor_of_visited_node] = distance_through_u;
401 #endif // SRC_ALGORITHMS_DIJKSTRA_SHORTEST_PATHS_H_
Single node sketch.
Definition: node_sketch.h:204
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