Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dijkstra.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file dijkstra.cpp
1 /* This software is distributed under the GNU Lesser General Public License */
2 //==========================================================================
3 //
4 // dijkstra.cpp
5 //
6 //==========================================================================
7 //$Id: dijkstra.cpp,v 1.6 2002/12/23 13:46:41 chris Exp $
8 
9 #include <GTL/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] == dijkstra::black) &&
53  ((*mark)[n2] == dijkstra::black))
54  {
55  return false;
56  }
57  else if ((*mark)[n1] == dijkstra::black)
58  {
59  return false;
60  }
61  else if ((*mark)[n2] == dijkstra::black)
62  {
63  return true;
64  }
65  return (*dist)[n1] < (*dist)[n2];
66  }
67 private:
72  const node_map<double>* dist;
73 
78  const node_map<int>* mark;
79 };
80 
81 
83 {
85 }
86 
87 
89 {
90 }
91 
92 
93 void dijkstra::source(const node& n)
94 {
95  s = n;
96 }
97 
98 
99 void dijkstra::target(const node& n)
100 {
101  t = n;
102 }
103 
104 
106 {
107  this->weight = weight;
108  weights_set = true;
109 }
110 
111 
112 void dijkstra::store_preds(bool set)
113 {
114  preds_set = set;
115 }
116 
117 
119 {
120  if ((s == node()) || (!weights_set))
121  {
122  return GTL_ERROR;
123  }
124 
125  bool source_found = false;
126  graph::node_iterator node_it;
127  graph::node_iterator nodes_end = G.nodes_end();
128  for (node_it = G.nodes_begin(); node_it != nodes_end; ++node_it)
129  {
130  if (*node_it == s)
131  {
132  source_found = true;
133  break;
134  }
135  }
136  if (!source_found)
137  {
138  return(GTL_ERROR);
139  }
140 
141  graph::edge_iterator edge_it;
142  graph::edge_iterator edges_end = G.edges_end();
143  for(edge_it = G.edges_begin(); edge_it != edges_end; ++edge_it)
144  {
145  if (weight[*edge_it] < 0.0)
146  {
147  return false;
148  }
149  }
150 
151  return GTL_OK;
152 }
153 
154 
156 {
157  init(G);
158 
159  less_dist prd(&dist, &mark);
160  bin_heap<node, less_dist> node_heap(prd, G.number_of_nodes());
161  mark[s] = grey;
162  dist[s] = 0.0;
163  node_heap.push(s);
164  while (!node_heap.is_empty())
165  {
166 
167  // debug:
168  // node_heap.print_data_container();
169 
170  node cur_node = node_heap.top();
171  node_heap.pop();
172 
173  // debug:
174  // node_heap.print_data_container();
175 
176  mark[cur_node] = white;
177  if (cur_node == t)
178  {
179  // if @a t is set through #target we are ready
180  return GTL_OK;
181  }
182 
183  node::adj_edges_iterator adj_edge_it;
184  node::adj_edges_iterator adj_edges_end = cur_node.adj_edges_end();
185  for (adj_edge_it = cur_node.adj_edges_begin();
186  adj_edge_it != adj_edges_end;
187  ++adj_edge_it)
188  {
189  node op_node = (*adj_edge_it).opposite(cur_node);
190  if (mark[op_node] == black)
191  {
192  mark[op_node] = grey;
193  dist[op_node] = dist[cur_node] + weight[*adj_edge_it];
194  node_heap.push(op_node);
195 
196  // debug:
197  // node_heap.print_data_container();
198 
199  if (preds_set)
200  {
201  pred[op_node] = *adj_edge_it;
202  }
203  }
204  else if (mark[op_node] == grey)
205  {
206  if (dist[op_node] > dist[cur_node] + weight[*adj_edge_it])
207  {
208  dist[op_node] = dist[cur_node] + weight[*adj_edge_it];
209  node_heap.changeKey(op_node);
210 
211  // debug:
212  // node_heap.print_data_container();
213 
214  if (preds_set)
215  {
216  pred[op_node] = *adj_edge_it;
217  }
218  }
219  }
220  else // (mark[op_node] == white)
221  {
222  // nothing to do: shortest distance to op_node is already
223  // computed
224  }
225  }
226  }
227 
228  return GTL_OK;
229 }
230 
231 
233 {
234  return s;
235 }
236 
237 
239 {
240  return t;
241 }
242 
243 
245 {
246  return preds_set;
247 }
248 
249 
250 bool dijkstra::reached(const node& n) const
251 {
252  return mark[n] != black;
253 }
254 
255 
256 double dijkstra::distance(const node& n) const
257 {
258  return dist[n];
259 }
260 
261 
263 {
264  assert(preds_set);
265  if ((n == s) || (!reached(n)))
266  {
267  return node();
268  }
269  return pred[n].opposite(n);
270 }
271 
272 
274 {
275  assert(preds_set);
276  return pred[n];
277 }
278 
279 
281  const node& dest)
282 {
283  assert(preds_set);
284  if ((shortest_path_node_list[dest].empty()) &&
285  (dest != s) &&
286  (reached(dest)))
287  {
288  fill_node_list(dest);
289  }
290  return shortest_path_node_list[dest].begin();
291 }
292 
293 
295  const node& dest)
296 {
297  assert(preds_set);
298  if ((shortest_path_node_list[dest].empty()) &&
299  (dest != s) &&
300  (reached(dest)))
301  {
302  fill_node_list(dest);
303  }
304  return shortest_path_node_list[dest].end();
305 }
306 
307 
309  const node& dest)
310 {
311  assert(preds_set);
312  if ((shortest_path_edge_list[dest].empty()) &&
313  (dest != s) &&
314  (reached(dest)))
315  {
316  fill_edge_list(dest);
317  }
318  return shortest_path_edge_list[dest].begin();
319 }
320 
321 
323  const node& dest)
324 {
325  assert(preds_set);
326  if ((shortest_path_edge_list[dest].empty()) &&
327  (dest != s) &&
328  (reached(dest)))
329  {
330  fill_edge_list(dest);
331  }
332  return shortest_path_edge_list[dest].end();
333 }
334 
335 
337 {
338  reset_algorithm();
339 }
340 
341 
343 {
344  s = node();
345  t = node();
346  weights_set = false;
347  preds_set = false;
348 }
349 
350 
352 {
353  dist.init(G, -1.0);
354  mark.init(G, black);
355 
356  if (preds_set)
357  {
358  pred.init(G, edge());
359  graph::node_iterator node_it;
360  graph::node_iterator nodes_end = G.nodes_end();
361  for (node_it = G.nodes_begin(); node_it != nodes_end; ++node_it)
362  {
363  shortest_path_node_list[(*node_it)].clear();
364  shortest_path_edge_list[(*node_it)].clear();
365  }
366  }
367 }
368 
369 
371 {
372  if ((dest == s) || (!reached(dest)))
373  {
374  return;
375  }
376 
377  node cur_node = dest;
378  while (cur_node != node())
379  {
380  shortest_path_node_list[dest].push_front(cur_node);
381  cur_node = predecessor_node(cur_node);
382  }
383 }
384 
385 
387 {
388  if ((dest == s) || (!reached(dest)))
389  {
390  return;
391  }
392 
393  node cur_node = dest;
394  edge cur_edge = predecessor_edge(dest);
395  while (cur_edge != edge())
396  {
397  shortest_path_edge_list[dest].push_front(cur_edge);
398  cur_node = predecessor_node(cur_node);
399  cur_edge = predecessor_edge(cur_node);
400  }
401 }
402 
404 
405 //--------------------------------------------------------------------------
406 // end of file
407 //--------------------------------------------------------------------------