Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
random_graph.H
1 # ifndef RANDOM_GRAPH_H
2 # define RANDOM_GRAPH_H
3 
4 # include <gsl/gsl_rng.h>
5 # include <memory>
6 # include <tpl_indexArc.H>
7 # include <tpl_graph_utils.H>
8 # include <tpl_components.H>
9 # include <single_graph.H>
10 # include <Tarjan.H>
11 
12 namespace Aleph
13 {
14 
15  template <class GT>
17 {
18  void operator () (GT &, typename GT::Node *) const
19  {
20  // empty
21  }
22 };
23 
24 
25  template <class GT>
27 {
28  void operator () (GT &, typename GT::Arc *) const
29  {
30  // empty
31  }
32 };
33 
34  // TODO: eliminar clases Init_Node e Init_Arc y en su lugar usar lambdas
35 
36  template <class GT, class Init_Node, class Init_Arc>
38 {
39 protected:
40 
41  typedef typename GT::Node GT_Node;
42  typedef typename GT::Arc GT_Arc;
43 
44  gsl_rng * r;
45 
46  Init_Node & init_node;
47  Init_Arc & init_arc;
48 
49  unique_ptr<DynArray<GT_Node*>> nodes; // puntero para ahorrar
50  // directorio en caso de que no
51  // se utilice
52 
53  unique_ptr<IndexArc<GT>> idx_arc; // puntero porque el constructor
54  // requiere el grafo.
55  mutable size_t num_nodes;
56  mutable size_t num_arcs;
57  mutable unsigned long rand_max;
58 
59  GT g;
60 
61  bool save_parity; // indica si se debe o no guardar relaciones de
62  // paridad entre los nodos. Sólo para construir
63  // eulerianos y hamiltonianos
64 
65  virtual void
66  update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt) = 0;
67 
68  GT_Arc * insert_arc(GT_Node * src, GT_Node * tgt)
69  {
70  GT_Arc * a = idx_arc->insert(g.insert_arc(src, tgt));
71 
72  init_arc (g, a);
73 
74  update_parity_after_arc_insertion(src, tgt);
75 
76  return a;
77  }
78 
79  // selecciona un nodo azar distinto a excluded
80  GT_Node * select_random_node(GT_Node * excluded = NULL)
81  {
82  I(nodes.get() != NULL);
83 
84  unsigned long idx;
85  GT_Node * ret_val = NULL;
86  while (true)
87  {
88  idx = gsl_rng_uniform_int(r, num_nodes);
89 
90  ret_val = nodes->access(idx);
91 
92  if (excluded == NULL or ret_val != excluded)
93  break;
94  }
95 
96  return ret_val;
97  }
98 
99  // selecciona un nodo azar entre los contenidos en la lista list
100  GT_Node * select_random_node(DynList<GT_Node*> & list)
101  {
102  const unsigned long k = gsl_rng_uniform_int(r, list.size());
103 
104  typename DynList<GT_Node*>::Iterator it(list);
105  for (int i = 0; i < k; ++i, it.next()) ;
106 
107  return it.get_curr();
108  }
109 
110  virtual void create_nodes_and_initialize_arc_index() = 0;
111 
112  virtual void connect() = 0;
113 
114  void initialize_and_create_nodes(const size_t & __num_nodes,
115  const size_t & __num_arcs)
116  {
117  num_nodes = __num_nodes;
118 
119  const size_t num_nodes_2 = num_nodes*num_nodes;
120  if (g.is_digraph())
121  num_arcs = std::min(__num_arcs, num_nodes_2 - num_nodes);
122  else
123  num_arcs= std::min(__num_arcs, (num_nodes_2 - num_nodes)/2);
124 
125  create_nodes_and_initialize_arc_index();
126  }
127 
128  Random_Graph_Base(unsigned long seed,
129  const Init_Node & __init_node,
130  const Init_Arc & __init_arc)
131  : r(gsl_rng_alloc (gsl_rng_mt19937)),
132  init_node(const_cast<Init_Node&>(__init_node)),
133  init_arc(const_cast<Init_Arc&>(__init_arc)),
134  num_nodes(0), num_arcs(0),
135  rand_max(gsl_rng_max(r)), save_parity(false)
136  {
137  if (r == NULL)
138  throw std::bad_alloc();
139 
140  gsl_rng_set(r, seed % rand_max);
141  }
142 
144  {
145  if (r != NULL)
146  gsl_rng_free(r);
147  }
148 
149  // Crea un grafo aleatorio esparcido.
150  GT create(const size_t & __num_nodes, const size_t & __num_arcs,
151  bool connected)
152  {
153  initialize_and_create_nodes(__num_nodes, __num_arcs);
154 
155  // inserta al azar los arcos seleccionando al azar pares de nodos
156  for (int i = 0; i < num_arcs; ++i)
157  {
158  GT_Node * src = select_random_node();
159  GT_Node * tgt = select_random_node(src);
160 
161  if (idx_arc->search(src, tgt) == NULL) // se repite el arco?
162  insert_arc(src, tgt);
163  }
164 
165  if (connected)
166  connect();
167 
168  return g;
169  }
170 
171  virtual GT create_p(const size_t & __num_nodes, const double & p,
172  bool connected) = 0;
173 
174  virtual void make_eulerian() = 0;
175 
176  virtual void make_hamiltonian () = 0;
177 
178 public:
179 
196  GT eulerian(const size_t & __num_nodes, const size_t & __num_arcs)
197  {
198  save_parity = true;
199 
200  g = std::move(this->create(__num_nodes, __num_arcs, true));
201 
202  make_eulerian();
203 
204  return g;
205  }
206 
226  GT eulerian (const size_t & __num_nodes, const double & p)
227  {
228  save_parity = true;
229 
230  g = std::move(this->create_p(__num_nodes, p, true));
231 
232  make_eulerian();
233 
234  return g;
235  }
236 
264  GT sufficient_hamiltonian (const size_t & __num_nodes,
265  const double & p = 0.5)
266  {
267  g = std::move(this->create_p(__num_nodes, p, true));
268 
269  make_hamiltonian();
270 
271  return g;
272  }
273 };
274 
275 
318  template <class GT,
319  class Init_Node = Dft_Init_Rand_Node<GT>,
321 class Random_Graph : public Random_Graph_Base<GT, Init_Node, Init_Arc>
322 {
323  typedef typename GT::Node GT_Node;
324  typedef typename GT::Arc GT_Arc;
325 
326  DynSetRandTree<GT_Node*> odd_nodes; // nodos con grado impar
327  DynSetRandTree<GT_Node*> even_nodes; // nodos con grado par
328 
329  virtual void update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt)
330  {
331  if (not this->save_parity)
332  return;
333 
334  if (is_even(this->g.get_num_arcs(src)))
335  { // era impar antes de la inserción
336  this->odd_nodes.remove(src);
337  this->even_nodes.insert(src);
338  }
339  else
340  {
341  this->even_nodes.remove(src);
342  this->odd_nodes.insert(src);
343  }
344 
345  if (is_even(this->g.get_num_arcs(tgt)))
346  { // era impar antes de la inserción
347  this->odd_nodes.remove(tgt);
348  this->even_nodes.insert(tgt);
349  }
350  else
351  {
352  this->even_nodes.remove(tgt);
353  this->odd_nodes.insert(tgt);
354  }
355  }
356 
357  virtual void create_nodes_and_initialize_arc_index()
358  {
359  this->nodes = unique_ptr<DynArray<GT_Node*>>
360  (new DynArray<GT_Node*>(this->num_nodes));
361 
362  this->nodes->reserve(this->num_nodes);
363 
364  for (int i = 0; i < this->num_nodes; ++i)
365  {
366  typename GT::Node * p = this->g.insert_node(new GT_Node);
367  this->nodes->access(i) = p;
368  this->init_node(this->g, p);
369 
370  if (this->save_parity)
371  {
372  this->even_nodes.insert(p);
373  NODE_COUNTER(p) = 0;
374  }
375  }
376 
377  this->idx_arc = unique_ptr<IndexArc<GT>> (new IndexArc<GT>(this->g) );
378  }
379 
380  virtual void connect()
381  {
382  DynList<DynList<GT_Node*>> subgraphs; // lista sufgrafos
383 
384  Inconnected_Components <GT> () (this->g, subgraphs);
385 
386  const size_t & num_subs = subgraphs.size();
387 
388  if (num_subs == 1)
389  return;
390 
391  DynArray<GT_Node*> block_nodes;
392 
393  for (typename DynList<DynList<GT_Node*>>::Iterator it(subgraphs);
394  it.has_curr(); it.next())
395  block_nodes.append(this->select_random_node(it.get_curr()));
396 
397  for (int i = 1; i < num_subs; ++i)
398  {
399  typename GT::Node * src = block_nodes.access(i - 1);
400  typename GT::Node * tgt = block_nodes.access(i);
401 
402  this->insert_arc(src, tgt);
403  }
404  }
405 
406  // crea un grafo aleatorio en el cual la probabilida por arco entre un
407  // par de nodos es p
408  virtual GT create_p (const size_t & __num_nodes, const double & p,
409  bool connected)
410  {
411  if (p > 1.0 or p <= 0.0)
412  throw std::domain_error("Invalid value for p");
413 
414  this->initialize_and_create_nodes(__num_nodes, __num_nodes);
415 
416  for (int i = 0; i < this->num_nodes - 1; ++i)
417  {
418  GT_Node * src = this->nodes->access(i);
419  for (int j = i + 1; j < this->num_nodes; ++j)
420  if (gsl_rng_uniform(this->r) <= p) // sorteo
421  {
422  GT_Node * tgt = this->nodes->access(j);
423  this->insert_arc(src, tgt);
424  }
425  }
426 
427  if (connected)
428  connect();
429 
430  return this->g;
431  }
432 
433 public:
434 
441  Random_Graph(unsigned long seed,
442  const Init_Node & __init_node,
443  const Init_Arc & __init_arc)
444  : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
445  {
446  if (this->g.is_digraph())
447  throw std::domain_error("Building of random digraph through a graph");
448  }
449 
450  Random_Graph(unsigned long seed = time(NULL),
451  const Init_Node && __init_node = Init_Node(),
452  const Init_Arc && __init_arc = Init_Arc())
453  : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
454  {
455  if (this->g.is_digraph())
456  throw std::domain_error("Building of random digraph through a graph");
457  }
458 
459 
476  GT operator () (const size_t & __num_nodes, const size_t & __num_arcs,
477  bool connected = true)
478  {
479  return this->create(__num_nodes, __num_arcs, connected);
480  }
481 
482 public:
483 
508  GT operator () (const size_t & __num_nodes, const double & p,
509  bool connected = true)
510  {
511  return create_p(__num_nodes, p, connected);
512  }
513 
514 private:
515 
516  virtual void make_eulerian()
517  {
518  while (this->odd_nodes.size() > 1)
519  {
520  GT_Node * src = NULL;
521  GT_Node * tgt = NULL;
522 
523  while (true)
524  {
525  src = this->odd_nodes.select
526  (gsl_rng_uniform_int(this->r, this->odd_nodes.size()));
527  do
528  tgt = this->odd_nodes.select
529  (gsl_rng_uniform_int(this->r, this->odd_nodes.size()));
530  while (tgt == src);
531 
532  if (this->idx_arc->search(src, tgt) == NULL)
533  break;
534  else if (this->odd_nodes.size() == 2)
535  { // seleccionar nodo al azar que no tenga arco hacia src o tgt
536  GT_Node * p = NULL;
537  do
538  p = this->even_nodes.select
539  (gsl_rng_uniform_int(this->r, this->even_nodes.size()));
540  while (this->idx_arc->search(src, p) != NULL or
541  this->idx_arc->search(tgt, p) != NULL);
542  this->insert_arc(src, p);
543  this->insert_arc(p, tgt);
544 
545  return;
546  }
547  }
548 
549  this->insert_arc(src, tgt);
550  }
551 
552  I(this->odd_nodes.size() == 0);
553  }
554 
555  void balance_graph_nodes_degree(GT_Node * src, GT_Node * tgt)
556  {
557  if (this->idx_arc->search(src, tgt) == NULL)
558  this->insert_arc(src, tgt);
559 
560  const size_t & n = this->g.get_num_nodes();
561 
562  while (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) < n)
563  {
564  GT_Node * p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
565 
566  if (p == src or p == tgt)
567  continue;
568 
569  if (this->idx_arc->search(src, p) == NULL)
570  this->insert_arc(src, p);
571 
572  if (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) == n)
573  break;
574 
575  if (this->idx_arc->search(tgt, p) == NULL)
576  this->insert_arc(tgt, p);
577  }
578  }
579 
580  virtual void make_hamiltonian ()
581  {
582  const size_t & n = this->g.get_num_nodes();
583 
584  for (int i = 0; i < n - 1; ++i)
585  {
586  GT_Node * src = this->nodes->access(i);
587 
588  for (int j = i + 1; j < n; ++j)
589  balance_graph_nodes_degree(src, this->nodes->access(j));
590  }
591  }
592 
593 public:
594 
611  GT eulerian (const size_t & __num_nodes, const size_t & __num_arcs)
612  {
613  this->save_parity = true;
614 
615  this->g = std::move(this->create(__num_nodes, __num_arcs, true));
616 
617  make_eulerian();
618 
619  return this->g;
620  }
621 
641  GT eulerian (const size_t & __num_nodes, const double & p)
642  {
643  this->save_parity = true;
644 
645  this->g = std::move(this->create_p(__num_nodes, p, true));
646 
647  make_eulerian();
648 
649  return this->g;
650  }
651 
679  GT sufficient_hamiltonian (const size_t & __num_nodes,
680  const double & p = 0.5)
681  {
682  this->g = std::move(this->create_p(__num_nodes, p, true));
683 
684  make_hamiltonian();
685 
686  return this->g;
687  }
688 };
689 
690 
691  template <class GT,
692  class Init_Node = Dft_Init_Rand_Node<GT>,
694 class Random_Digraph : public Random_Graph_Base<GT, Init_Node, Init_Arc>
695 {
696  typedef typename GT::Node GT_Node;
697  typedef typename GT::Arc GT_Arc;
698 
699  DynSetRandTree<GT_Node*> greater; // nodos con grado out mayor que in
700  DynSetRandTree<GT_Node*> smaller; // nodos con grado out menor que in
701  DynSetRandTree<GT_Node*> equal; // nodos con grado out igual a in
702 
703  bool verify_tables()
704  {
705  const size_t & n = this->nodes->size();
706 
707  if (n != this->g.get_num_nodes())
708  cout << "Warning num of nodes of graph does not match with array "
709  << this->g.get_num_nodes() << "!=" << n << endl;
710 
711  size_t total = greater.size() + smaller.size() + equal.size();
712  if (total != this->g.get_num_nodes())
713  cout << "Inconsistency with nodes parity" << endl
714  << "greater = " << greater.size() << endl
715  << "smaller = " << smaller.size() << endl
716  << "equal = " << equal.size() << endl
717  << "total = " << total << endl
718  << "|V| = " << this->g.get_num_nodes();
719 
720  for (int i = 0; i < n; ++i)
721  {
722  GT_Node * p = this->nodes->access(i);
723 
724  const long & in_sz = NODE_COUNTER(p);
725  const size_t & out_sz = this->g.get_num_arcs(p);
726 
727  if (in_sz == out_sz)
728  {
729  if (smaller.search(p) != NULL)
730  cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
731  << " in smaller table" << endl;
732 
733  if (greater.search(p) != NULL)
734  cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
735  << " in greater table" << endl;
736 
737  if (equal.search(p) == NULL)
738  {
739  cout << "node of same in/out degree is not in equal table"
740  << endl;
741 
742  return false;
743  }
744  }
745  else if (in_sz > out_sz)
746  {
747  if (greater.search(p) != NULL)
748  cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
749  << " in greater table" << endl;
750 
751  if (equal.search(p) != NULL)
752  cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
753  << endl;
754 
755  if (smaller.search(p) == NULL)
756  {
757  cout << "node with " << in_sz << "/" << out_sz << " not found "
758  << "smaller table" << endl;
759 
760  return false;
761  }
762  }
763  else
764  {
765  if (smaller.search(p) != NULL)
766  cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
767  << " in smaller table" << endl;
768 
769  if (equal.search(p) != NULL)
770  cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
771  << endl;
772 
773  if (greater.search(p) == NULL)
774  {
775  cout << "node with " << in_sz << "/" << out_sz << " not found "
776  << "greater table" << endl;
777 
778  return false;
779  }
780  }
781  }
782 
783  return true;
784  }
785 
786  // Esta llamada se efectúa justo después de insertar un nuevo
787  // arco src-->tgt. Esto implica que out(src) está actualizado, pero
788  // in(tgt) no
789  virtual void update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt)
790  {
791  if (not this->save_parity)
792  return;
793 
794  const size_t & src_out_degree = this->g.get_num_arcs(src);
795  const long & src_in_degree = NODE_COUNTER(src);
796 
797  if (src_out_degree == src_in_degree)
798  { // src está en greater ==> sacarlo y meterlo en equal
799  I(this->smaller.search(src) != NULL);
800  this->smaller.remove(src);
801  this->equal.insert(src);
802  }
803  else if (src_out_degree > src_in_degree)
804  if (src_out_degree == src_in_degree + 1)
805  {
806  I(this->equal.search(src) != NULL);
807  this->equal.remove(src);
808  this->greater.insert(src);
809  }
810  else
811  I(this->greater.search(src) != NULL);
812  else // src_out_degree < src_in_degree
813  I(this->smaller.search(src) != NULL);
814 
815  const size_t & tgt_out_degree = this->g.get_num_arcs(tgt);
816  const long tgt_in_degree = ++NODE_COUNTER(tgt);
817 
818  if (tgt_out_degree == tgt_in_degree)
819  {
820  I(this->greater.search(tgt));
821  this->greater.remove(tgt);
822  this->equal.insert(tgt);
823  }
824  else if (tgt_out_degree > tgt_in_degree)
825  I(this->greater.search(tgt));
826  else // (tgt_out_degree < tgt_in_degree)
827  {
828  if (tgt_in_degree - 1 == tgt_out_degree)
829  { // tgt está en equal ==> sacarlo
830  I(this->equal.search(tgt) != NULL);
831  this->smaller.insert(tgt);
832  this->equal.remove(tgt);
833  }
834  else
835  I(this->smaller.search(tgt) != NULL);
836  }
837  }
838 
839  virtual void create_nodes_and_initialize_arc_index()
840  {
841  this->nodes = unique_ptr<DynArray<GT_Node*>>
842  (new DynArray<GT_Node*>(this->num_nodes));
843 
844  this->nodes->reserve(this->num_nodes);
845 
846  for (int i = 0; i < this->num_nodes; ++i)
847  {
848  typename GT::Node * p = this->g.insert_node(new GT_Node);
849  this->nodes->access(i) = p;
850  this->init_node(this->g, p);
851 
852  if (this->save_parity)
853  {
854  NODE_COUNTER(p) = 0;
855  this->equal.insert(p);
856  }
857  }
858 
859  this->idx_arc = unique_ptr<IndexArc<GT>> (new IndexArc<GT>(this->g) );
860  }
861 
862  virtual void connect()
863  {
864  DynList<DynList<typename GT::Node*>> blk_list; // subgrafos inconexos
865 
866  { // guarda los grados de entrada puesto que el algoritmo de Tarjan
867  // los va a modificar
868  DynArray<int> in_degree;
869  in_degree.reserve(this->g.get_num_nodes());
870 
871  typename GT::Node_Iterator it(this->g);
872  for (int i = 0; it.has_curr(); it.next(), ++i)
873  in_degree.access(i) = NODE_COUNTER(it.get_curr());
874 
875  Tarjan_Connected_Components <GT> () (this->g, blk_list);
876 
877  it.reset_first(); // restaurar los grados de entrada
878  for (int i = 0; it.has_curr(); it.next(), ++i)
879  NODE_COUNTER(it.get_curr()) = in_degree.access(i);
880  }
881 
882  const size_t & num_blocks = blk_list.size();
883 
884  if (num_blocks == 1)
885  return;
886 
887  // cada nodo de esta lista es un nodo del bloque i seleccionado
888  // aleatoriamente
889  DynArray<typename GT::Node*> b1; b1.reserve(num_blocks);
890  DynArray<typename GT::Node*> b2; b2.reserve(num_blocks);
891  {
892  typename DynList<DynList<GT_Node*> >::Iterator it(blk_list);
893  for (int i = 0; it.has_curr(); it.next(), ++i)
894  { // seleccione dos nodos al azar del componente actual
895  DynList<typename GT::Node*> & list = it.get_curr();
896  b1.access(i) = this->select_random_node(list);
897  b2.access(i) = this->select_random_node(list);
898  }
899  }
900 
901  for (int i = 0; i < num_blocks - 1; ++i)
902  {
903  GT_Node * src = b1.access(i); // nodo en bloque i
904  GT_Node * tgt = b1.access((i + 1) % num_blocks); // nodo en bloque i + 1
905 
906  if (this->idx_arc->search(src, tgt) == NULL)
907  this->insert_arc(src, tgt);
908 
909  src = b2.access(i); // nodo en bloque i
910  tgt = b2.access((i + 1) % num_blocks); // nodo en bloque i + 1
911 
912  if (this->idx_arc->search(tgt, src) == NULL)
913  this->insert_arc(tgt, src);
914  }
915  }
916 
917  // crea un grafo aleatorio en el cual la probabilidad por arco entre un
918  // par de nodos es p
919  virtual GT create_p(const size_t & __num_nodes, const double & p,
920  bool connected)
921  {
922  if (p > 1.0 or p <= 0.0)
923  throw std::domain_error("Invalid value for p");
924 
925  this->initialize_and_create_nodes(__num_nodes, __num_nodes);
926 
927  for (int i = 0; i < this->num_nodes; ++i)
928  {
929  GT_Node * src = this->nodes->access(i);
930  for (int j = 0; j < this->num_nodes; ++j)
931  if (i != j and gsl_rng_uniform(this->r) <= p)
932  {
933  GT_Node * tgt = this->nodes->access(j);
934  I(this->idx_arc->search(src, tgt) == NULL);
935  this->insert_arc(src, tgt);
936  }
937  }
938 
939  if (connected)
940  connect();
941 
942  return this->g;
943  }
944 
945 public:
946 
953  Random_Digraph(unsigned long seed = time(NULL),
954  const Init_Node && __init_node = Init_Node(),
955  const Init_Arc && __init_arc = Init_Arc())
956  : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
957  {
958  if (not this->g.is_digraph())
959  throw std::domain_error("Building of random graph through a digraph");
960  }
961 
962  Random_Digraph(unsigned long seed,
963  const Init_Node & __init_node,
964  const Init_Arc & __init_arc)
965  : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
966  {
967  if (not this->g.is_digraph())
968  throw std::domain_error("Building of random graph through a digraph");
969  }
970 
971  Random_Digraph(const Init_Node & __init_node,
972  const Init_Arc & __init_arc)
973  : Random_Graph_Base<GT, Init_Node, Init_Arc>(time(NULL), __init_node, __init_arc)
974  {
975  if (not this->g.is_digraph())
976  throw std::domain_error("Building of random graph through a digraph");
977  }
978 
995  GT operator () (const size_t & __num_nodes, const size_t & __num_arcs,
996  bool connected = true)
997  {
998  return this->create(__num_nodes, __num_arcs, connected);
999  }
1000 
1001 public:
1002 
1027  GT operator () (const size_t & __num_nodes, const double & p,
1028  bool connected = true)
1029  {
1030  return this->create_p(__num_nodes, p, connected);
1031  }
1032 
1033 private:
1034 
1035  virtual void make_eulerian()
1036  {
1037  GT_Node * src = NULL;
1038  GT_Node * tgt = NULL;
1039 
1040  while (this->greater.size() > 0 and this->smaller.size() > 0)
1041  {
1042  do
1043  {
1044  tgt = this->greater.select
1045  (gsl_rng_uniform_int(this->r, this->greater.size()));
1046  src = this->smaller.select
1047  (gsl_rng_uniform_int(this->r, this->smaller.size()));
1048  }
1049  while (src == tgt);
1050 
1051  if (this->idx_arc->search(src, tgt) == NULL)
1052  this->insert_arc(src, tgt);
1053  else
1054  {
1055  GT_Node * mid =
1056  this->equal.select(gsl_rng_uniform_int(this->r,
1057  this->equal.size()));
1058 
1059  while (this->idx_arc->search(src, mid) != NULL or
1060  this->idx_arc->search(mid, tgt) != NULL)
1061  mid = this->equal.select
1062  (gsl_rng_uniform_int(this->r, this->equal.size()));
1063 
1064  this->insert_arc(src, mid);
1065  this->insert_arc(mid, tgt);
1066  }
1067  }
1068  }
1069 
1070  void balance_digraph_node(GT_Node * p)
1071  {
1072  const size_t & n = this->g.get_num_nodes();
1073  const size_t n2 = n/2;
1074 
1075  while (not (this->g.get_num_arcs(p) >= n2 and NODE_COUNTER(p) >= n2))
1076  {
1077  GT_Node * q = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1078 
1079  if (q == p)
1080  continue;
1081 
1082  if (this->idx_arc->search(p, q) == NULL)
1083  {
1084  this->insert_arc(p, q);
1085  NODE_COUNTER(q)++;
1086  }
1087 
1088  if (this->idx_arc->search(q, p) == NULL)
1089  {
1090  this->insert_arc(q, p);
1091  NODE_COUNTER(p)++;
1092  }
1093  }
1094  }
1095 
1096  // balancea los dos nodos para que satisfagan la condición de
1097  // hamiltoniano. Si existe arco src-->tgt
1098  void balance_digraph_nodes_degree(GT_Node * src, GT_Node * tgt)
1099  {
1100  if (this->idx_arc->search(src, tgt) != NULL)
1101  {
1102  balance_digraph_node(src);
1103  balance_digraph_node(tgt);
1104 
1105  return;
1106  }
1107 
1108  const size_t & n = this->g.get_num_nodes();
1109 
1110  while (this->g.get_num_arcs(src) + NODE_COUNTER(tgt) < n)
1111  {
1112  GT_Node * p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1113 
1114  if (p == src or p == tgt)
1115  continue;
1116 
1117  if (this->idx_arc->search(src, p) == NULL)
1118  {
1119  this->insert_arc(src, p);
1120  NODE_COUNTER(p)++;
1121 
1122  if (this->g.get_num_arcs(src) + NODE_COUNTER(tgt) == n)
1123  break;
1124  }
1125 
1126  if (this->idx_arc->search(p, tgt) == NULL)
1127  {
1128  this->insert_arc(p, tgt);
1129  NODE_COUNTER(tgt)++;
1130  }
1131  }
1132 
1133  I(this->g.get_num_arcs(src) + NODE_COUNTER(tgt) >= n);
1134  }
1135 
1136  virtual void make_hamiltonian ()
1137  {
1138  this->g.reset_counter_nodes();
1139 
1140  // contabiliza el grado de entrada por cada nodo
1141  for (typename GT::Arc_Iterator it(this->g); it.has_curr(); it.next())
1142  NODE_COUNTER(it.get_tgt_node())++;
1143 
1144  const size_t & n = this->g.get_num_nodes();
1145 
1146  for (int i = 0; i < n; ++i)
1147  {
1148  GT_Node * src = this->nodes->access(i);
1149 
1150  for (int j = 0; j < n; ++j)
1151  {
1152  if (i == j)
1153  continue;
1154 
1155  GT_Node * tgt = this->nodes->access(j);
1156 
1157  balance_digraph_nodes_degree(src, tgt);
1158  }
1159  }
1160  }
1161 };
1162 
1163 }
1164 
1165 # endif // RANDOM_GRAPH_H
void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:960
Random_Graph(unsigned long seed, const Init_Node &__init_node, const Init_Arc &__init_arc)
Definition: random_graph.H:441
GT eulerian(const size_t &__num_nodes, const double &p)
Definition: random_graph.H:641
GT sufficient_hamiltonian(const size_t &__num_nodes, const double &p=0.5)
Definition: random_graph.H:679
size_t remove(const Key &key)
Definition: tpl_dynSetTree.H:274
const size_t & size() const
Retorna la cardinalidad del conjunto.
Definition: tpl_dynSetTree.H:408
Definition: random_graph.H:694
Definition: random_graph.H:16
bool is_even(long n)
Definition: ahUtils.H:41
Key * search(const Key &key) const
Definition: tpl_dynSetTree.H:364
Key & select(const size_t &i)
Definition: tpl_dynSetTree.H:464
Definition: ahFunction.H:135
Definition: random_graph.H:26
#define NODE_COUNTER(p)
Definition: aleph-graph.H:226
GT eulerian(const size_t &__num_nodes, const size_t &__num_arcs)
Definition: random_graph.H:611
Definition: random_graph.H:37
GT sufficient_hamiltonian(const size_t &__num_nodes, const double &p=0.5)
Definition: random_graph.H:264
GT operator()(const size_t &__num_nodes, const size_t &__num_arcs, bool connected=true)
Definition: random_graph.H:995
GT operator()(const size_t &__num_nodes, const size_t &__num_arcs, bool connected=true)
Definition: random_graph.H:476
Definition: random_graph.H:321
Definition: tpl_indexArc.H:41
T & append()
Definition: tpl_dynArray.H:1115
Definition: euclidian-graph-common.H:52
Random_Digraph(unsigned long seed=time(NULL), const Init_Node &&__init_node=Init_Node(), const Init_Arc &&__init_arc=Init_Arc())
Definition: random_graph.H:953
Definition: tpl_dynArray.H:70
Definition: tpl_components.H:198
Definition: htlist.H:769
GT eulerian(const size_t &__num_nodes, const double &p)
Definition: random_graph.H:226
Definition: ahDry.H:13
GT eulerian(const size_t &__num_nodes, const size_t &__num_arcs)
Definition: random_graph.H:196
T & access(const size_t i)
Definition: tpl_dynArray.H:793
Definition: List.H:23
Key * insert(const Key &key)
Definition: tpl_dynSetTree.H:177
Definition: Tarjan.H:24

Leandro Rabindranath León