Aleph-w  1.9
General library for algorithms and data structures
Prim.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 PRIM_H
28 # define PRIM_H
29 
30 # include <tpl_agraph.H>
31 # include <tpl_graph_utils.H>
32 # include <archeap.H>
33 
34 namespace Aleph {
35 
36 using namespace Aleph;
37 
38  template <class GT>
39 struct Prim_Info
40 {
41  typename GT::Node * tree_node = nullptr; // imagen en el árbol abarcador
42  void * heap_node = nullptr; // puntero en el heap exclusivo
43 
44  Prim_Info() : tree_node(nullptr), heap_node(nullptr) { /* empty */ }
45 };
46 
47 # define PRIMINFO(p) static_cast<Prim_Info<GT>*>(NODE_COOKIE(p))
48 # define TREENODE(p) (PRIMINFO(p)->tree_node)
49 # define HEAPNODE(p) (PRIMINFO(p)->heap_node)
50 
51  template <class GT, class Distance>
52 struct Prim_Heap_Info
53 {
54  typedef typename ArcHeap<GT, Distance, Prim_Heap_Info>::Node Node;
55 
56  Node *& operator () (typename GT::Node * p)
57  {
58  return (Node*&) HEAPNODE(p);
59  }
60 };
61 
62  template <class GT, class Distance>
63 struct Simple_Prim_Heap
64 {
65  typedef typename ArcHeap<GT, Distance, Simple_Prim_Heap>::Node Node;
66 
67  Node *& operator () (typename GT::Node * p)
68  {
69  return (Node*&) NODE_COOKIE(p);
70  }
71 };
72 
73  template <class GT>
74 struct Init_Prim_Info
75 {
76  GT & tree;
77 
78  Init_Prim_Info(GT & __tree) : tree(__tree) { /* empty */ }
79 
80  void operator () (const GT & g, typename GT::Node * p)
81  {
82  g.reset_bit(p, Aleph::Spanning_Tree);
83  NODE_COOKIE(p) = new Prim_Info<GT>;
84  TREENODE(p) = tree.insert_node(p->get_info());
85  }
86 };
87 
88  template <class GT>
89 struct Uninit_Prim_Info
90 {
91  void operator () (const GT &, typename GT::Node * p)
92  {
93  Prim_Info<GT> * aux = PRIMINFO(p);
94  GT::map_nodes(p, TREENODE(p));
95  delete aux;
96  }
97 };
98 
99 
142  template <class GT,
143  class Distance = Dft_Dist<GT>,
144  class SA = Dft_Show_Arc<GT>>
146 {
147  typedef Prim_Heap_Info<GT, Distance> Acc_Heap;
148 
149  typedef Simple_Prim_Heap<GT, Distance> Acc_Simple_Heap;
150 
151  typedef ArcHeap<GT, Distance, Acc_Heap> Heap;
152 
153  typedef ArcHeap<GT, Distance, Acc_Simple_Heap> Simple_Heap;
154 
155  Distance dist;
156  SA sa;
157 
158 public:
159 
166  Prim_Min_Spanning_Tree(Distance __dist = Distance(), SA __sa = SA())
167  : dist(__dist), sa(__sa)
168  {
169  // empty
170  }
171 
172 private:
173 
174  void paint_min_spanning_tree(const GT & g, typename GT::Node * first)
175  {
176  if (g.is_digraph())
177  throw std::domain_error("g is a digraph");
178 
179  g.reset_nodes();
180  g.reset_arcs();
181 
182  NODE_BITS(first).set_bit(Aleph::Spanning_Tree, true); // visitado
183 
184  Simple_Heap heap(dist, Acc_Simple_Heap());
185  for (Node_Arc_Iterator<GT, SA> it(first, sa); it.has_curr(); it.next_ne())
186  {
187  typename GT::Arc * arc = it.get_current_arc_ne();
188  heap.put_arc(arc, it.get_tgt_node_ne());
189  }
190 
191  const size_t V1 = g.get_num_nodes() - 1;
192  size_t count = 0;
193 
194  while (count < V1 and not heap.is_empty())
195  { // obtenga siguiente menor arco
196  typename GT::Arc * min_arc = heap.get_min_arc();
197  if (IS_ARC_VISITED(min_arc, Aleph::Spanning_Tree))
198  continue;
199 
200  ARC_BITS(min_arc).set_bit(Aleph::Spanning_Tree, true);
201 
202  typename GT::Node * src = g.get_src_node(min_arc);
203  typename GT::Node * tgt = g.get_tgt_node(min_arc);
204  if (IS_NODE_VISITED(src, Aleph::Spanning_Tree) and
205  IS_NODE_VISITED(tgt, Aleph::Spanning_Tree))
206  continue; // este arco cerraría un ciclo en el árbol
207 
208  typename GT::Node * tgt_node =
209  IS_NODE_VISITED(src, Aleph::Spanning_Tree) ? tgt : src;
210 
211  NODE_BITS(tgt_node).set_bit(Aleph::Spanning_Tree, true);
212 
213  // insertar en heap arcos no visitados de tgt_node
214  for (Node_Arc_Iterator<GT, SA> it(tgt_node, sa); it.has_curr();
215  it.next_ne())
216  {
217  typename GT::Arc * arc = it.get_current_arc_ne();
218  if (IS_ARC_VISITED(arc, Aleph::Spanning_Tree))
219  continue;
220 
221  typename GT::Node * tgt = it.get_tgt_node_ne();
222  if (IS_NODE_VISITED(tgt, Aleph::Spanning_Tree))
223  continue; // nodo visitado ==> causará ciclo
224 
225  heap.put_arc(arc, tgt);
226  }
227 
228  ++count;
229  ARC_BITS(min_arc).set_bit(Aleph::Spanning_Tree, true);
230  }
231  }
232 
233  void min_spanning_tree(const GT & g, typename GT::Node * first, GT & tree)
234  {
235  if (g.is_digraph())
236  throw std::domain_error("g is a digraph");
237 
238  clear_graph(tree);
239 
240  Init_Prim_Info <GT> init(tree);
242  g.reset_arcs();
243 
244  NODE_BITS(first).set_bit(Aleph::Spanning_Tree, true); // visitado
245 
246  Heap heap(dist, Acc_Heap()) ;
247  // meter en heap arcos iniciales del primer nodo
248  for (Node_Arc_Iterator<GT, SA> it(first, sa); it.has_curr(); it.next_ne())
249  {
250  typename GT::Arc * arc = it.get_current_arc_ne();
251  heap.put_arc(arc, it.get_tgt_node_ne());
252  }
253 
254  const size_t V1 = g.get_num_nodes() - 1;
255 
256  while (tree.get_num_arcs() < V1 and not heap.is_empty())
257  { // obtenga siguiente menor arco
258  typename GT::Arc * min_arc = heap.get_min_arc();
259  if (IS_ARC_VISITED(min_arc, Aleph::Spanning_Tree))
260  continue;
261 
262  ARC_BITS(min_arc).set_bit(Aleph::Spanning_Tree, true);
263 
264  typename GT::Node * src = g.get_src_node(min_arc);
265  typename GT::Node * tgt = g.get_tgt_node(min_arc);
266  if (IS_NODE_VISITED(src, Aleph::Spanning_Tree) and
267  IS_NODE_VISITED(tgt, Aleph::Spanning_Tree))
268  continue; // este arco cerraría un ciclo en el árbol
269 
270  typename GT::Node * tgt_node =
271  IS_NODE_VISITED(src, Aleph::Spanning_Tree) ? tgt : src;
272 
273  NODE_BITS(tgt_node).set_bit(Aleph::Spanning_Tree, true);
274 
275  // insertar en heap arcos no visitados de tgt_node
276  for (Node_Arc_Iterator<GT, SA> it(tgt_node, sa); it.has_curr();
277  it.next_ne())
278  {
279  typename GT::Arc * arc = it.get_current_arc_ne();
280  if (IS_ARC_VISITED(arc, Aleph::Spanning_Tree))
281  continue;
282 
283  typename GT::Node * tgt = it.get_tgt_node_ne();
284  if (IS_NODE_VISITED(tgt, Aleph::Spanning_Tree))
285  continue; // nodo visitado ==> causará ciclo
286 
287  heap.put_arc(arc, tgt);
288  }
289 
290  // insertar nuevo arco en tree y mapearlo
291  typename GT::Arc * tree_arc =
292  tree.insert_arc(TREENODE(src), TREENODE(tgt), min_arc->get_info());
293  GT::map_arcs(min_arc, tree_arc);
294  }
295 
297  }
298 
299 public:
300 
313  void operator () (const GT & g, GT & tree)
314  {
315  min_spanning_tree(g, g.get_first_node(), tree);
316  }
317 
331  void operator () (const GT & g, typename GT::Node * start, GT & tree)
332  {
333  min_spanning_tree(g, start, tree);
334  }
335 
337  void operator () (const GT & g)
338  {
339  paint_min_spanning_tree(g, g.get_first_node());
340  }
341 
342  void operator () (const GT & g, typename GT::Node * start)
343  {
344  paint_min_spanning_tree(g, start);
345  }
346 };
347 
348 
349 
350 # undef HEAPNODE
351 # undef TREENODE
352 # undef PRIMINFO
353 } // end namespace Aleph
354 
355 # endif // PRIM_H
void clear_graph(GT &g) noexcept
Definition: tpl_graph.H:3463
#define NODE_COOKIE(p)
Definition: aleph-graph.H:333
Definition: tpl_graph.H:2493
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:327
void map_arcs(typename GTS::Arc *p, typename GTT::Arc *q) noexcept
Definition: tpl_graph.H:3445
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:360
void map_nodes(typename GTS::Node *p, typename GTT::Node *q) noexcept
Definition: tpl_graph.H:3419
Definition: ah-comb.H:35
Prim_Min_Spanning_Tree(Distance __dist=Distance(), SA __sa=SA())
Definition: Prim.H:166
Definition: tpl_graph.H:1063
#define NODE_BITS(p)
Definition: aleph-graph.H:305
Definition: Prim.H:145
Definition: tpl_graph_utils.H:1753
#define ARC_BITS(p)
Definition: aleph-graph.H:351
Definition: tpl_graph.H:1177

Leandro Rabindranath León