Aleph-w  1.9
General library for algorithms and data structures
Floyd.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 # ifndef FLOYD_H
28 # define FLOYD_H
29 
30 # include <sstream>
31 # include <ahFunction.H>
32 # include <ahSort.H>
33 # include <tpl_indexArc.H>
34 # include <tpl_dynMat.H>
35 
36 namespace Aleph
37 {
38 
93  template <class GT,
94  class Distance = Dft_Dist<GT>,
95  class SA = Dft_Show_Arc<GT>>
97 {
98  typedef typename GT::Node Node;
99  typedef typename GT::Arc Arc;
100  typedef typename Distance::Distance_Type Distance_Type;
101 
102  DynArray<Node*> nodes;
103  GT & g;
104  const long n;
105  const Distance_Type Inf;
106  bool negative_cycle = false;
107  DynMatrix<long> path_mat;
109  SA & sa;
110 
111 public:
112 
113  bool has_negative_cycle() const noexcept { return negative_cycle; }
114 
115  const DynMatrix<long> & get_path_mat() const noexcept { return path_mat; }
116 
117  const DynMatrix<Distance_Type> & get_dist_mat() const noexcept
118  {
119  return dist;
120  }
121 
122  const DynArray<Node*> get_nodes() const noexcept { return nodes; }
123 
126  Node * select_node(long i) const noexcept { return nodes(i); }
127 
130  long index_node(Node * p) const noexcept
131  {
132  auto i = binary_search(nodes, p);
133  if (i < 0 or i > nodes.size() or nodes(i) != p)
134  throw domain_error("Floyd_All_Shortest_Paths::index_node() not found");
135  return i;
136  }
137 
138 public:
139 
140  Floyd_All_Shortest_Paths(const GT & __g, SA & __sa)
141  : g(const_cast<GT&>(__g)), n(g.get_num_nodes()),
142  Inf(std::numeric_limits<Distance_Type>::max()),
143  path_mat(n, n), dist(n, n), sa(__sa)
144  {
145  int i = 0;
146  nodes.reserve(g.get_num_nodes());
147  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next_ne())
148  nodes.access(i++) = it.get_curr_ne();
149  in_place_sort(nodes); // ordena por punteros a nodo
150 
151  dist.allocate();
152  path_mat.allocate();
153 
154  { // inicializa matrices
155  IndexArc<GT, Rand_Tree, SA> arcs(g, true, sa);
156 
157  for (long i = 0; i < n; ++i)
158  {
159  Node * src = nodes(i);
160  for (long j = 0; j < n; ++j)
161  {
162  if (i == j)
163  {
164  dist(i, j) = 0;
165  continue;
166  }
167 
168  Node * tgt = nodes(j);
169  Arc * arc = arcs.search_directed(src, tgt);
170  if (arc == nullptr)
171  {
172  dist(i, j) = Inf;
173  continue;
174  }
175 
176  dist(i, j) = Distance () (arc);
177  path_mat(i, j) = j;
178  }
179  }
180  }
181 
182  for (long k = 0; k < n; ++k)
183  for (long i = 0; i < n; ++i)
184  {
185  const Distance_Type & dik = dist(i, k);
186  for (long j = 0; j < n; ++j)
187  {
188  const Distance_Type & dij = dist(i, j);
189  if (dik == Inf)
190  continue;
191 
192  const Distance_Type & dkj = dist(k, j);
193  if (dkj == Inf)
194  continue;
195 
196  // calcule nueva distancia pasando por k
197  Distance_Type new_dist = dik + dkj;
198  if (new_dist < dij)
199  {
200  dist(i, j) = new_dist; // actualice menor distancia
201  path_mat(i, j) = path_mat(i, k);
202  }
203  }
204  }
205 
206  for (i = 0; i < n; ++i)
207  if (dist(i, i) < 0) // ciclo negativo?
208  {
209  negative_cycle = true;
210  break;
211  }
212  }
213 
214  Floyd_All_Shortest_Paths(const GT & g, SA && sa = SA())
215  : Floyd_All_Shortest_Paths(g, sa) {}
216 
217  string entry(const Distance_Type & e)
218  {
219  if (e == Inf)
220  return "Inf";
221 
222  std::stringstream ss;
223  ss << e;
224  return ss.str();
225  }
226 
227  static void print(DynMatrix<Distance_Type> & dist)
228  {
229  Distance_Type Inf = std::numeric_limits<Distance_Type>::max();
230  const int n = dist.rows();
231  for (int i = 0; i < n; ++i)
232  {
233  for (int j = 0; j < n; ++j)
234  if (dist.access(i,j) == Inf)
235  cout << "inf ";
236  else
237  cout << dist.access(i,j) << " ";
238  cout << endl;
239  }
240  cout << endl;
241  }
242 
243  Path<GT> get_min_path(const long src_idx, const long tgt_idx) const
244  {
245  auto src = nodes(src_idx);
246 
247  Path<GT> path(g, src);
248 
249  if (src_idx == tgt_idx)
250  return path;
251 
252  long i = src_idx;
253  while (true)
254  {
255  const auto & k = path_mat(i, tgt_idx);
256  auto p = nodes(k);
257  path.append_directed(p);
258  if (k == tgt_idx)
259  break;
260  else
261  i = k;
262  }
263 
264  return path;
265  }
266 
267  Path<GT> get_min_path(typename GT::Node * src, typename GT::Node * tgt) const
268  {
269  return get_min_path(index_node(src), index_node(tgt));
270  }
271 };
272 
273 } // end namespace Aleph
274 
275 # endif // FLOYD_H
276 
GT_Arc * search_directed(void *src, void *tgt)
Definition: tpl_indexArc.H:139
void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:998
const size_t & rows() const noexcept
Return the number of rows.
Definition: tpl_dynMat.H:180
T & access(const size_t i) const noexcept
Definition: tpl_dynArray.H:874
Definition: Floyd.H:96
T & access(const size_t i, const size_t j) const
Fast access to i-th row j-th column.
Definition: tpl_dynMat.H:209
Definition: tpl_graph.H:53
DynList< typename GT::Arc * > arcs(typename GT::Node *p, SA sa=SA())
Definition: tpl_graph.H:1893
Definition: ah-comb.H:35
Node * select_node(long i) const noexcept
Definition: Floyd.H:126
Definition: tpl_graph.H:1063
void append_directed(Node *p)
Definition: tpl_graph.H:2880
Definition: tpl_indexArc.H:67
Definition: tpl_graph_utils.H:1753
size_t size() const noexcept
Definition: tpl_dynArray.H:641
Definition: tpl_dynArray.H:159
long index_node(Node *p) const noexcept
Definition: Floyd.H:130
void allocate()
Definition: tpl_dynMat.H:111

Leandro Rabindranath León