Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
bid_dijkstra.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file bid_dijkstra.cpp
1 /* This software is distributed under the GNU Lesser General Public License */
2 //==========================================================================
3 //
4 // bid_dijkstra.cpp
5 //
6 //==========================================================================
7 //$Id: bid_dijkstra.cpp,v 1.2 2004/05/06 11:58:19 chris Exp $
8 
9 #include <GTL/bid_dijkstra.h>
10 #include <GTL/bin_heap.h>
11 
12 #include <cstdlib>
13 #include <iostream>
14 #include <cassert>
15 
16 #ifdef __GTL_MSVCC
17 # ifdef _DEBUG
18 # ifndef SEARCH_MEMORY_LEAKS_ENABLED
19 # error SEARCH NOT ENABLED
20 # endif
21 # define new DEBUG_NEW
22 # undef THIS_FILE
23 static char THIS_FILE[] = __FILE__;
24 # endif // _DEBUG
25 #endif // __GTL_MSVCC
26 
28 
33 class less_dist : public binary_function<node, node, bool>
34 {
35 public:
41  {
42  this->dist = dist;
43  this->mark = mark;
44  }
45 
50  bool operator()(const node n1, const node n2) const
51  {
52  if (((*mark)[n1] == bid_dijkstra::black) &&
53  ((*mark)[n2] == bid_dijkstra::black))
54  {
55  return false;
56  }
57  else if ((*mark)[n1] == bid_dijkstra::black)
58  {
59  return false;
60  }
61  else if ((*mark)[n2] == bid_dijkstra::black)
62  {
63  return true;
64  }
65  return (*dist)[n1] < (*dist)[n2];
66  }
67 private:
73 
79 };
80 
81 
83 {
85 }
86 
87 
89 {
90 }
91 
92 
93 void bid_dijkstra::source_target(const node& s, const node& t)
94 {
95  this->s = s;
96  this->t = t;
97 }
98 
99 
101 {
102  this->weight = weight;
103  weights_set = true;
104 }
105 
106 
108 {
109  path_set = set;
110 }
111 
112 
114 {
115  if ((s == node()) || (t == node()) || (!weights_set))
116  {
117  return GTL_ERROR;
118  }
119 
120  bool source_found = false;
121  bool target_found = false;
122  graph::node_iterator node_it;
123  graph::node_iterator nodes_end = G.nodes_end();
124  for (node_it = G.nodes_begin(); node_it != nodes_end; ++node_it)
125  {
126  if (*node_it == s)
127  {
128  source_found = true;
129  if (target_found)
130  {
131  break;
132  }
133  }
134  if (*node_it == t)
135  {
136  target_found = true;
137  if (source_found)
138  {
139  break;
140  }
141  }
142  }
143  if ((!source_found) || (!target_found))
144  {
145  return(GTL_ERROR);
146  }
147 
148  graph::edge_iterator edge_it;
149  graph::edge_iterator edges_end = G.edges_end();
150  for(edge_it = G.edges_begin(); edge_it != edges_end; ++edge_it)
151  {
152  if (weight[*edge_it] < 0.0)
153  {
154  return false;
155  }
156  }
157 
158  return GTL_OK;
159 }
160 
161 
163 {
164  init(G);
165 
166  double max_dist = 1;
167  graph::edge_iterator edge_it;
168  graph::edge_iterator edges_end = G.edges_end();
169  for(edge_it = G.edges_begin(); edge_it != edges_end; ++edge_it)
170  {
171  max_dist += weight[*edge_it];
172  }
173 
174  less_dist source_prd(&source_dist, &source_mark);
175  less_dist target_prd(&target_dist, &target_mark);
176  bin_heap<node, less_dist> source_heap(source_prd,
177  G.number_of_nodes());
178  bin_heap<node, less_dist> target_heap(target_prd,
179  G.number_of_nodes());
180 
181  source_mark[s] = grey;
182  source_dist[s] = 0.0;
183  source_heap.push(s);
184  target_mark[t] = grey;
185  target_dist[t] = 0.0;
186  target_heap.push(t);
187  while ((!source_heap.is_empty()) || (!target_heap.is_empty()))
188  {
189  if (source_dist[source_heap.top()] <=
190  target_dist[target_heap.top()])
191  {
192 
193  // debug:
194  // source_heap.print_data_container();
195 
196  node cur_node = source_heap.top();
197  source_heap.pop();
198 
199  // debug:
200  // source_heap.print_data_container();
201 
202  source_mark[cur_node] = white;
203 
204  if ((target_mark[cur_node] == white) &&
205  (max_dist == source_dist[cur_node] +
206  target_dist[cur_node]))
207  {
208  fill_node_edge_lists(cur_node);
209  break;
210  }
211 
212  node::adj_edges_iterator adj_edge_it;
213  node::adj_edges_iterator adj_edges_end =
214  cur_node.adj_edges_end();
215  for (adj_edge_it = cur_node.adj_edges_begin();
216  adj_edge_it != adj_edges_end;
217  ++adj_edge_it)
218  {
219  node op_node = (*adj_edge_it).opposite(cur_node);
220  if (source_mark[op_node] == black)
221  {
222  source_mark[op_node] = grey;
223  source_dist[op_node] = source_dist[cur_node] +
224  weight[*adj_edge_it];
225  source_heap.push(op_node);
226 
227  // debug:
228  // source_heap.print_data_container();
229 
230  if (path_set)
231  {
232  pred[op_node] = *adj_edge_it;
233  }
234 
235  if ((target_mark[op_node] == grey) ||
236  (target_mark[op_node] == white))
237  {
238  if (max_dist > source_dist[op_node] +
239  target_dist[op_node])
240  {
241  max_dist = source_dist[op_node] +
242  target_dist[op_node];
243  }
244  }
245  }
246  else if (source_mark[op_node] == grey)
247  {
248  if (source_dist[op_node] > source_dist[cur_node] +
249  weight[*adj_edge_it])
250  {
251  source_dist[op_node] = source_dist[cur_node] +
252  weight[*adj_edge_it];
253  source_heap.changeKey(op_node);
254 
255  // debug:
256  // source_heap.print_data_container();
257 
258  if (path_set)
259  {
260  pred[op_node] = *adj_edge_it;
261  }
262 
263  if ((target_mark[op_node] == grey) ||
264  (target_mark[op_node] == white))
265  {
266  if (max_dist > source_dist[op_node] +
267  target_dist[op_node])
268  {
269  max_dist = source_dist[op_node] +
270  target_dist[op_node];
271  }
272  }
273  }
274  }
275  else // (source_mark[op_node] == white)
276  {
277  // nothing to do: shortest distance to op_node is
278  // already computed
279  }
280  }
281  }
282  else // (source_dist[source_heap.top()] >
283  // target_dist[target_heap.top()])
284  {
285 
286  // debug:
287  // target_heap.print_data_container();
288 
289  node cur_node = target_heap.top();
290  target_heap.pop();
291 
292  // debug:
293  // target_heap.print_data_container();
294 
295  target_mark[cur_node] = white;
296 
297  if ((source_mark[cur_node] == white) &&
298  (max_dist == source_dist[cur_node] +
299  target_dist[cur_node]))
300  {
301  fill_node_edge_lists(cur_node);
302  break;
303  }
304 
305  if (G.is_directed())
306  {
307  node::in_edges_iterator in_edge_it;
308  node::in_edges_iterator in_edges_end =
309  cur_node.in_edges_end();
310  for (in_edge_it = cur_node.in_edges_begin();
311  in_edge_it != in_edges_end;
312  ++in_edge_it)
313  {
314  node op_node = (*in_edge_it).opposite(cur_node);
315  if (target_mark[op_node] == black)
316  {
317  target_mark[op_node] = grey;
318  target_dist[op_node] = target_dist[cur_node] +
319  weight[*in_edge_it];
320  target_heap.push(op_node);
321 
322  // debug:
323  // target_heap.print_data_container();
324 
325  if (path_set)
326  {
327  succ[op_node] = *in_edge_it;
328  }
329 
330  if ((source_mark[op_node] == grey) ||
331  (source_mark[op_node] == white))
332  {
333  if (max_dist > source_dist[op_node] +
334  target_dist[op_node])
335  {
336  max_dist = source_dist[op_node] +
337  target_dist[op_node];
338  }
339  }
340  }
341  else if (target_mark[op_node] == grey)
342  {
343  if (target_dist[op_node] > target_dist[cur_node] +
344  weight[*in_edge_it])
345  {
346  target_dist[op_node] = target_dist[cur_node] +
347  weight[*in_edge_it];
348  target_heap.changeKey(op_node);
349 
350  // debug:
351  // target_heap.print_data_container();
352 
353  if (path_set)
354  {
355  succ[op_node] = *in_edge_it;
356  }
357 
358  if ((source_mark[op_node] == grey) ||
359  (source_mark[op_node] == white))
360  {
361  if (max_dist > source_dist[op_node] +
362  target_dist[op_node])
363  {
364  max_dist = source_dist[op_node] +
365  target_dist[op_node];
366  }
367  }
368  }
369  }
370  else // (target_mark[op_node] == white)
371  {
372  // nothing to do: shortest distance to op_node is
373  // already computed
374  }
375  }
376  }
377  else // (G.is_undirected())
378  {
379  node::adj_edges_iterator adj_edge_it;
380  node::adj_edges_iterator adj_edges_end =
381  cur_node.adj_edges_end();
382  for (adj_edge_it = cur_node.adj_edges_begin();
383  adj_edge_it != adj_edges_end;
384  ++adj_edge_it)
385  {
386  node op_node = (*adj_edge_it).opposite(cur_node);
387  if (target_mark[op_node] == black)
388  {
389  target_mark[op_node] = grey;
390  target_dist[op_node] = target_dist[cur_node] +
391  weight[*adj_edge_it];
392  target_heap.push(op_node);
393 
394  // debug:
395  // target_heap.print_data_container();
396 
397  if (path_set)
398  {
399  succ[op_node] = *adj_edge_it;
400  }
401 
402  if ((source_mark[op_node] == grey) ||
403  (source_mark[op_node] == white))
404  {
405  if (max_dist > source_dist[op_node] +
406  target_dist[op_node])
407  {
408  max_dist = source_dist[op_node] +
409  target_dist[op_node];
410  }
411  }
412  }
413  else if (target_mark[op_node] == grey)
414  {
415  if (target_dist[op_node] > target_dist[cur_node] +
416  weight[*adj_edge_it])
417  {
418  target_dist[op_node] = target_dist[cur_node] +
419  weight[*adj_edge_it];
420  target_heap.changeKey(op_node);
421 
422  // debug:
423  // target_heap.print_data_container();
424 
425  if (path_set)
426  {
427  succ[op_node] = *adj_edge_it;
428  }
429 
430  if ((source_mark[op_node] == grey) ||
431  (source_mark[op_node] == white))
432  {
433  if (max_dist > source_dist[op_node] +
434  target_dist[op_node])
435  {
436  max_dist = source_dist[op_node] +
437  target_dist[op_node];
438  }
439  }
440  }
441  }
442  else // (target_mark[op_node] == white)
443  {
444  // nothing to do: shortest distance to op_node is
445  // already computed
446  }
447  }
448  }
449  }
450  }
451 
452  return GTL_OK;
453 }
454 
455 
457 {
458  return s;
459 }
460 
461 
463 {
464  return t;
465 }
466 
467 
469 {
470  return path_set;
471 }
472 
473 
475 {
476  return reached_t;
477 }
478 
479 
481 {
482  return dist;
483 }
484 
485 
488 {
489  assert(path_set);
490  return shortest_path_node_list.begin();
491 }
492 
493 
496 {
497  assert(path_set);
498  return shortest_path_node_list.end();
499 }
500 
501 
504 {
505  assert(path_set);
506  return shortest_path_edge_list.begin();
507 }
508 
509 
512 {
513  assert(path_set);
514  return shortest_path_edge_list.end();
515 }
516 
517 
519 {
520  reset_algorithm();
521 }
522 
523 
525 {
526  s = node();
527  t = node();
528  weights_set = false;
529  path_set = false;
530  dist = -1.0;
531  reached_t = false;
532 }
533 
534 
536 {
537  source_dist.init(G, -1.0);
538  source_mark.init(G, black);
539  target_dist.init(G, -1.0);
540  target_mark.init(G, black);
541 
542  if (path_set)
543  {
544  pred.init(G, edge());
545  succ.init(G, edge());
546  shortest_path_node_list.clear();
547  shortest_path_edge_list.clear();
548  }
549 }
550 
551 
553 {
554  reached_t = true;
555  if (t == s)
556  {
557  return;
558  }
560  if (path_set)
561  {
562  node cur_node;
563  edge cur_edge;
564 
565  cur_node = n;
566  cur_edge = pred[cur_node];
567  while (cur_edge != edge())
568  {
569  shortest_path_edge_list.push_front(cur_edge);
570  cur_node = cur_edge.opposite(cur_node);
571  cur_edge = pred[cur_node];
572  shortest_path_node_list.push_front(cur_node);
573  }
574  shortest_path_node_list.push_back(n);
575  cur_node = n;
576  cur_edge = succ[cur_node];
577  while (cur_edge != edge())
578  {
579  shortest_path_edge_list.push_back(cur_edge);
580  cur_node = cur_edge.opposite(cur_node);
581  cur_edge = succ[cur_node];
582  shortest_path_node_list.push_back(cur_node);
583  }
584  }
585 }
586 
588 
589 //--------------------------------------------------------------------------
590 // end of file
591 //--------------------------------------------------------------------------