Aleph-w  1.9
General library for algorithms and data structures
tpl_agraph.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 TPL_AGRAPH_H
28 # define TPL_AGRAPH_H
29 
30 # include <tpl_dynSetTree.H>
31 # include <array_it.H>
32 # include <tpl_sgraph.H>
33 
34 namespace Aleph {
35 
36 using namespace Aleph;
37 
42  template <typename Node_Info = Empty_Class>
44  : public Dlink,
45  public GTNodeCommon<Node_Info>
46 {
48  friend class GTNodeCommon<Node_Info>;
49 
50  static const size_t Contract_Factor = 4;
51  static const size_t Default_Cap = 4;
52 
53  void init(size_t dim)
54  {
55  arcs_dim = dim;
56  this->num_arcs = 0;
57  contract_threshold = arcs_dim/Contract_Factor;
58  arc_array = nullptr;
59  if (arcs_dim == 0)
60  return;
61 
62  arc_array = (void**) malloc(arcs_dim*sizeof(void*));
63  if (arc_array == nullptr)
64  throw std::bad_alloc();
65  }
66 
67 public:
68 
69  void ** arc_array;
70  size_t arcs_dim;
71  size_t contract_threshold;
72 
73  Graph_Anode()
74  {
75  init(0);
76  }
77 
78  Graph_Anode(const Node_Info & info) : Base(info)
79  {
80  init(Default_Cap);
81  }
82 
83  Graph_Anode(Node_Info && info) : Base(move(info))
84  {
85  init(Default_Cap);
86  }
87 
88  Graph_Anode(const Graph_Anode & node) : Base(node.node_info)
89  {
90  init(0);
91  }
92 
93  Graph_Anode & operator = (const Graph_Anode & node)
94  noexcept(std::is_nothrow_copy_assignable<Node_Info>::value)
95  {
96  if (&node == this)
97  return *this;
98  this->node_info = node.node_info;
99  return *this;
100  }
101 
102  Graph_Anode(Graph_Anode * p) : Base(p->get_info())
103  {
104  init(0);
105  }
106 
107  virtual ~Graph_Anode()
108  {
109  if (arc_array != nullptr)
110  free(arc_array);
111  }
112 
113  void allocate_more(size_t new_size)
114  {
115  if (new_size == 0)
116  new_size = 1;
117 
118  void ** new_array = (void**) realloc(arc_array, new_size*sizeof(void*));
119  if (new_array == nullptr)
120  throw std::bad_alloc();
121 
122  arc_array = new_array;
123  arcs_dim = new_size;
124  contract_threshold = arcs_dim/Contract_Factor;
125  }
126 
127  void * insert_arc(void * arc)
128  {
129  if (this->num_arcs == arcs_dim)
130  allocate_more(arcs_dim << 1); // 2*arcs_dim
131 
132  arc_array[this->num_arcs++] = arc;
133 
134  return arc;
135  }
136 
137  void remove_arc_ne(void * arc) noexcept
138  {
139  bool removed = false;
140  for (size_t i = 0; i < this->num_arcs; ++i)
141  if (arc_array[i] == arc)
142  {
143  arc_array[i] = arc_array[--(this->num_arcs)];
144  removed = true;
145  break;
146  }
147 
148  if (this->num_arcs > contract_threshold)
149  return;
150 
151  // contraction
152  size_t new_sz = arcs_dim >> 1; // num_arcs/2
153  arc_array = (void**) realloc(arc_array, new_sz*sizeof(void*));
154  arcs_dim = new_sz;
155  contract_threshold = arcs_dim/Contract_Factor;
156  }
157 
158  void remove_arc(void * arc)
159  {
160  bool removed = false;
161  for (size_t i = 0; i < this->num_arcs; ++i)
162  if (arc_array[i] == arc)
163  {
164  arc_array[i] = arc_array[--(this->num_arcs)];
165  removed = true;
166  break;
167  }
168 
169  if (not removed)
170  throw std::domain_error("arc for deleting not found");
171 
172  if (this->num_arcs > contract_threshold)
173  return;
174 
175  // contraction
176  size_t new_sz = arcs_dim >> 1; // num_arcs/2
177  arc_array = (void**) realloc(arc_array, new_sz*sizeof(void*));
178  arcs_dim = new_sz;
179  contract_threshold = arcs_dim/Contract_Factor;
180  }
181 
182  bool compress() noexcept
183  {
184  void ** new_array = (void**) realloc(arc_array,
185  this->num_arcs*sizeof(void*));
186  if (new_array == nullptr)
187  return false;
188 
189  arc_array = new_array;
190  arcs_dim = this->num_arcs;
191  contract_threshold = this->num_arcs/Contract_Factor;
192 
193  return true;
194  }
195 };
196 
197 
198  template <typename Arc_Info = Empty_Class>
199 class Graph_Aarc
200  : public Dlink,
201  public GTArcCommon<Arc_Info>
202 {
203  friend class GTArcCommon<Arc_Info>;
204  using Base = GTArcCommon<Arc_Info>;
205 
206 public:
207 
208  Graph_Aarc(const Arc_Info & info)
209  noexcept(std::is_nothrow_copy_constructible<Arc_Info>::value) : Base(info)
210  {
211  /* empty */
212  }
213 
214  Graph_Aarc(Arc_Info && info = Arc_Info())
215  noexcept(std::is_nothrow_copy_constructible<Arc_Info>::value)
216  : Base(move(info))
217  {
218  /* empty */
219  }
220 
221  Graph_Aarc(const Graph_Aarc & arc)
222  noexcept(std::is_nothrow_copy_constructible<Arc_Info>::value)
223  : Graph_Aarc(arc.arc_info) { /* empty */ }
224 
225  Graph_Aarc & operator = (const Graph_Aarc & arc)
226  noexcept(std::is_nothrow_copy_assignable<Arc_Info>::value)
227  {
228  if (&arc == this)
229  return *this;
230  this->arc_info = arc.arc_info;
231  return *this;
232  }
233 
234  Graph_Aarc(void * src, void * tgt, const Arc_Info & data)
235  noexcept(std::is_nothrow_copy_constructible<Arc_Info>::value)
236  : Base(src, tgt, data)
237  {
238  // empty
239  }
240 
241  Graph_Aarc(void * src, void * tgt, Arc_Info && data = Arc_Info())
242  noexcept(std::is_nothrow_copy_constructible<Arc_Info>::value)
243  : Base(src, tgt, move(data))
244  {
245  // empty
246  }
247 };
248 
249 
250  template <class __Graph_Node = Graph_Anode<unsigned long>,
251  class __Graph_Arc = Graph_Aarc<unsigned long>>
252 class Array_Graph
253  : public GraphCommon<Array_Graph<__Graph_Node, __Graph_Arc>,
254  __Graph_Node, __Graph_Arc>
255 {
256 public:
257 
258  using Node = __Graph_Node;
259  using Arc = __Graph_Arc;
260  using Node_Type = typename Node::Node_Type;
261  using Arc_Type = typename Arc::Arc_Type;
262 
263  friend class GraphCommon<Array_Graph<__Graph_Node, __Graph_Arc>,
264  __Graph_Node, __Graph_Arc>;
265 
267  __Graph_Node, __Graph_Arc>;
268 
269  using CommonBase::insert_node;
270  using CommonBase::insert_arc;
271 
272 private:
273 
274  // using DynSetNode = DynSetTree<Node*, Avl_Tree>;
275  using DynSetArc = DynSetTree<Arc*, Rand_Tree>;
276 
277  Dlink node_set;
278  Dlink arc_set;
279 
280 public:
281 
282  struct Node_Iterator : public GTNodeIterator<Array_Graph>
283  {
285  using Base::Base;
286 
287  Node_Iterator(const Array_Graph & g) noexcept
288  : Base(const_cast<Dlink&>(g.node_set))
289  {
290  // empty
291  }
292  };
293 
301  struct Arc_Iterator : public GTArcIterator<Array_Graph>
302  {
304  using Base::Base;
305 
306  Arc_Iterator(const Array_Graph & g)
307  : Base(const_cast<Dlink&>(g.arc_set))
308  {
309  // empty
310  }
311  };
312 
313  class Node_Arc_Iterator : public Array_Iterator<void*>
314  {
315  Node * src_node = nullptr;
316 
317  public:
318 
320  using Item_Type = Arc *;
321 
323  using Set_Type = Node *;
324 
326  Node_Arc_Iterator() noexcept { /* empty */ }
327 
329  Node_Arc_Iterator(Node * src) noexcept
330  : Array_Iterator<void*>(no_exception_ctor,
331  src->arc_array, src->arcs_dim, src->num_arcs),
332  src_node(src)
333  {
334  // empty
335  }
336 
337  Arc * get_curr() const
338  {
339  return (Arc*) const_cast<Node_Arc_Iterator*>(this)->
341  }
342 
343  Arc * get_curr_ne() const noexcept
344  {
345  return (Arc*) const_cast<Node_Arc_Iterator*>(this)->
347  }
348 
350  Arc * get_current_arc_ne() const noexcept { return get_curr_ne(); }
351 
353  Arc * get_current_arc() const { return get_curr(); }
354 
356  Node * get_tgt_node_ne() const
357  {
358  Arc * a = get_curr_ne();
359  return (Node*) a->get_connected_node(src_node);
360  }
361 
362  Node * get_tgt_node() const
363  {
364  Arc * a = get_curr();
365  return (Node*) a->get_connected_node(src_node);
366  }
367  };
368 
369  virtual Node * insert_node(Node * p)
370  {
371  assert(p != nullptr);
372  assert(p->num_arcs == 0);
373 
374  node_set.append(p);
375  this->num_nodes++;
376 
377  return p;
378  }
379 
380  void compress()
381  {
382  for (Node_Iterator it(*this); it.has_curr(); it.next_ne())
383  it.get_curr_ne()->compress();
384  }
385 
386 private:
387 
388  Arc * try_insert_arc(Node * src, Node * tgt, void * a)
389  {
390  Arc * aptr = (Arc*) a;
391 
392  aptr->src_node = src;
393  aptr->tgt_node = tgt;
394  src->insert_arc(aptr);
395 
396  if (not this->digraph and src != tgt)
397  {
398  try
399  {
400  tgt->insert_arc(aptr);
401  }
402  catch (std::bad_alloc)
403  {
404  src->remove_arc(aptr);
405  throw;
406  }
407  }
408 
409  try
410  {
411  arc_set.append(aptr);
412  this->num_arcs++;
413  }
414  catch (std::bad_alloc)
415  {
416  src->remove_arc(aptr);
417  if (not this->digraph and src != tgt)
418  tgt->remove_arc(aptr);
419  throw;
420  }
421 
422  return aptr;
423  }
424 
425 public:
426 
427  Arc * connect_arc(Arc * arc)
428  {
429  return
430  try_insert_arc(this->get_src_node(arc), this->get_tgt_node(arc), arc);
431  }
432 
433 private:
434 
435  Arc * insert_arc(Node * src, Node * tgt, void * a)
436  {
437  bool compress_done = false;
438 
439  retry:
440  try
441  {
442  return try_insert_arc(src, tgt, a);
443  }
444  catch (bad_alloc)
445  {
446  if (compress_done)
447  throw;
448 
449  compress();
450  compress_done = true;
451  goto retry;
452  }
453  }
454 
455 public:
456 
457  Arc * disconnect_arc(Arc * arc)
458  {
459  Node * src = (Node*) arc->src_node;
460  Node * tgt = (Node*) arc->tgt_node;
461 
462  src->remove_arc_ne(arc);
463  if (not this->digraph and src != tgt)
464  tgt->remove_arc_ne(arc);
465 
466  arc->del(); // delete it from arc_set
467  this->num_arcs--;
468 
469  return arc;
470  }
471 
472  virtual void remove_arc(Arc * a)
473  {
474  delete disconnect_arc(a);
475  }
476 
477  virtual void remove_node(Node * p)
478  {
479  DynList<Arc*> arcs; // store arcs to delete
480  if (this->digraph)
481  // traverse all arcs of graph and store those whose source or target is p
482  for (Arc_Iterator it(*this); it.has_curr(); it.next_ne())
483  {
484  Arc * arc = it.get_curr_ne();
485  if (this->get_src_node(arc) == p or this->get_tgt_node(arc) == p)
486  arcs.append(arc);
487  }
488  else
489  // traverse arc of node
490  for (size_t i = 0, n = p->num_arcs; i < n; ++i)
491  {
492  Arc * arc = (Arc*) p->arc_array[i];
493  arcs.append(arc);
494  }
495 
496  arcs.for_each([this] (auto arc) { this->remove_arc(arc); });
497 
498  p->del(); // remove from node_set
499  this->num_nodes--;
500 
501  delete p;
502  }
503 
504  Node * get_first_node() const
505  {
506  return (Node*) const_cast<Dlink&>(node_set).get_first();
507  }
508 
509  Arc * get_first_arc() const
510  {
511  return (Arc*) const_cast<Dlink&>(arc_set).get_first();
512  }
513 
514  Arc * get_first_arc(Node * p) const
515  {
516  if (get_num_arcs(p) == 0)
517  throw std::range_error("Node has not arcs");
518  return (Arc*) p->arc_array[0];
519  }
520 
521  Array_Graph()
522  {
523  assert(this->num_nodes == 0 and this->num_arcs == 0 and
524  node_set.is_empty() and arc_set.is_empty());
525  }
526 
527 private:
528 
529  void clear() noexcept
530  {
531  while (not arc_set.is_empty())
532  delete static_cast<Arc*>(arc_set.remove_first());
533 
534  while (not node_set.is_empty())
535  delete static_cast<Node*>(node_set.remove_first());
536 
537  this->num_nodes = this->num_arcs = 0;
538  }
539 
540 public:
541 
542  virtual ~Array_Graph() noexcept
543  {
544  clear();
545  }
546 
547  Array_Graph(const Array_Graph & g)
548  {
549  assert(this->num_nodes == 0 and this->num_arcs == 0);
550  copy_graph(*this, g, false);
551  }
552 
553  void swap(Array_Graph & g) noexcept
554  {
555  this->common_swap(g);
556  node_set.swap(g.node_set);
557  arc_set.swap(g.arc_set);
558  }
559 
560  Array_Graph(Array_Graph && g) noexcept
561  {
562  swap(g);
563  }
564 
565  Array_Graph & operator = (const Array_Graph & g)
566  {
567  if (&g == this)
568  return *this;
569 
570  copy_graph(*this, g, false);
571 
572  return *this;
573  }
574 
575  Array_Graph & operator = (Array_Graph && g) noexcept
576  {
577  swap(g);
578  return *this;
579  }
580 
581 private:
582 
583  template <class Cmp>
584  struct Cmp_Arc
585  {
586  Cmp & cmp;
587 
588  Cmp_Arc(Cmp && __cmp = Cmp())
589  noexcept(std::is_nothrow_constructible<Cmp>::value and
590  std::is_nothrow_move_assignable<Cmp>::value)
591  : cmp(__cmp) { /* empty */ }
592 
593  Cmp_Arc(Cmp & __cmp) noexcept(std::is_nothrow_copy_assignable<Cmp>::value)
594  : cmp(__cmp) { /* empty */ }
595 
596  bool operator () (Arc * a1, Arc * a2) const noexcept
597  {
598  return cmp(a1, a2);
599  }
600  };
601 
602 public:
603 
625  template <class Compare> inline
626  void sort_nodes(Compare & cmp) noexcept
627  {
629  mergesort(node_set, c);
630  }
631 
633  template <class Compare> inline
634  void sort_nodes(Compare && cmp = Compare()) noexcept
635  {
636  sort_nodes(cmp);
637  }
638 
660  template <class Compare>
661  void sort_arcs(Compare & cmp)
662  {
664  mergesort(arc_set, c);
665  }
666 
668  template <class Compare>
669  void sort_arcs(Compare && cmp) { sort_arcs(cmp); }
670 };
671 
689 template <typename __Graph_Node = Graph_Anode<int>,
690  typename __Graph_Arc = Graph_Aarc<int>>
691 class Array_Digraph : public Array_Graph<__Graph_Node, __Graph_Arc>
692 {
693  using GT = Array_Graph<__Graph_Node, __Graph_Arc>;
694 
695 public:
696 
697  using Node = __Graph_Node;
698 
699  using Arc = __Graph_Arc;
700 
701  Array_Digraph() noexcept
702  {
703  this->digraph = true;
704  }
705 
706  Array_Digraph(const Array_Digraph & dg)
707  : Array_Graph<Node, Arc>((Array_Digraph&) dg)
708  {
709  this->digraph = true;
710  }
711 
712  Array_Digraph & operator = (const Array_Digraph<Node, Arc> & g)
713  {
714  if (this == &g)
715  return *this;
716 
717  copy_graph(*this, g, false);
718 
719  return *this;
720  }
721 
722  Array_Digraph(Array_Digraph && dg) noexcept : GT()
723  {
724  this->digraph = true;
725  this->swap(dg);
726  }
727 
728  Array_Digraph & operator = (Array_Digraph<Node, Arc> && g) noexcept
729  {
730  this->swap(g);
731 
732  return *this;
733  }
734 };
735 
736 
737 } // namespace Aleph {
738 
739 # endif // TPL_AGRAPH_H
NodeInfo & get_info() noexcept
Return a modifiable reference to the data contained in the node.
Definition: graph-dry.H:242
Definition: tpl_agraph.H:691
Definition: tpl_agraph.H:301
Array_Graph Set_Type
The type of container on which iterate.
Definition: graph-dry.H:92
void for_each(Operation &operation) noexcept(noexcept(operation))
Definition: htlist.H:589
Definition: array_it.H:45
void copy_graph(GT &gtgt, const GT &gsrc, const bool cookie_map=false)
Definition: tpl_graph.H:3482
Definition: graph-dry.H:83
Definition: graph-dry.H:272
Definition: graph-dry.H:329
size_t num_arcs
data associated to the node. Access it with get_info()
Definition: graph-dry.H:227
Definition: tpl_agraph.H:43
Definition: graph-dry.H:42
DynList< typename GT::Arc * > arcs(typename GT::Node *p, SA sa=SA())
Definition: tpl_graph.H:1893
Definition: ah-comb.H:35
Definition: graph-dry.H:206
Arc * Item_Type
The type of item that returns the iterator.
Definition: graph-dry.H:89
Node_Info Node_Type
The node.
Definition: graph-dry.H:233
Definition: tpl_graph.H:1270
Definition: ahDry.H:41
T & append(const T &item)
Definition: htlist.H:1471

Leandro Rabindranath León