27 # ifndef RANDOM_GRAPH_H 28 # define RANDOM_GRAPH_H 30 # include <gsl/gsl_rng.h> 32 # include <tpl_indexArc.H> 33 # include <tpl_graph_utils.H> 34 # include <tpl_components.H> 35 # include <single_graph.H> 42 struct Dft_Init_Rand_Node
44 void operator () (GT &,
typename GT::Node *)
const noexcept
52 struct Dft_Init_Rand_Arc
54 void operator () (GT &,
typename GT::Arc *)
const noexcept
62 template <
class GT,
class Init_Node,
class Init_Arc>
63 class Random_Graph_Base
67 typedef typename GT::Node GT_Node;
68 typedef typename GT::Arc GT_Arc;
72 Init_Node & init_node;
75 unique_ptr<DynArray<GT_Node*>> nodes;
79 unique_ptr<IndexArc<GT>> idx_arc;
81 mutable size_t num_nodes;
82 mutable size_t num_arcs;
83 mutable unsigned long rand_max;
92 update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt) = 0;
94 GT_Arc * insert_arc(GT_Node * src, GT_Node * tgt)
96 auto a = idx_arc->insert(g.insert_arc(src, tgt));
98 update_parity_after_arc_insertion(src, tgt);
103 GT_Node * select_random_node(GT_Node * excluded =
nullptr) noexcept
105 assert(nodes.get() !=
nullptr);
108 GT_Node * ret_val =
nullptr;
111 idx = gsl_rng_uniform_int(r, num_nodes);
112 ret_val = nodes->access(idx);
113 if (excluded ==
nullptr or ret_val != excluded)
123 const unsigned long k = gsl_rng_uniform_int(r,
list.
size());
125 for (
int i = 0; i < k; ++i, it.next_ne()) ;
127 return it.get_curr_ne();
130 virtual void create_nodes_and_initialize_arc_index() = 0;
132 virtual void connect() = 0;
134 void initialize_and_create_nodes(
const size_t & __num_nodes,
135 const size_t & __num_arcs)
137 num_nodes = __num_nodes;
139 const size_t num_nodes_2 = num_nodes*num_nodes;
141 num_arcs = std::min(__num_arcs, num_nodes_2 - num_nodes);
143 num_arcs = std::min(__num_arcs, (num_nodes_2 - num_nodes)/2);
145 create_nodes_and_initialize_arc_index();
148 Random_Graph_Base(
unsigned long seed,
149 const Init_Node & __init_node,
150 const Init_Arc & __init_arc)
151 : r(gsl_rng_alloc (gsl_rng_mt19937)),
152 init_node(const_cast<Init_Node&>(__init_node)),
153 init_arc(const_cast<Init_Arc&>(__init_arc)),
154 num_nodes(0), num_arcs(0),
155 rand_max(gsl_rng_max(r)), save_parity(false)
158 throw std::bad_alloc();
160 gsl_rng_set(r, seed % rand_max);
170 GT create(
const size_t & __num_nodes,
const size_t & __num_arcs,
173 initialize_and_create_nodes(__num_nodes, __num_arcs);
176 for (
int i = 0; i < num_arcs; ++i)
178 auto src = select_random_node();
179 auto tgt = select_random_node(src);
180 if (idx_arc->search(src, tgt) ==
nullptr)
181 insert_arc(src, tgt);
190 virtual GT create_p(
const size_t & __num_nodes,
const double & p,
193 virtual void make_eulerian() = 0;
195 virtual void make_hamiltonian () = 0;
215 GT eulerian(
const size_t & __num_nodes,
const size_t & __num_arcs)
218 g = this->create(__num_nodes, __num_arcs,
true);
243 GT eulerian (
const size_t & __num_nodes,
const double & p)
246 g = this->create_p(__num_nodes, p,
true);
280 const double & p = 0.5)
282 g = this->create_p(__num_nodes, p,
true);
333 class Init_Node = Dft_Init_Rand_Node<GT>,
334 class Init_Arc = Dft_Init_Rand_Arc<GT> >
337 typedef typename GT::Node GT_Node;
338 typedef typename GT::Arc GT_Arc;
343 virtual void update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt)
345 if (not this->save_parity)
348 if (is_even(this->g.get_num_arcs(src)))
350 this->odd_nodes.
remove(src);
351 this->even_nodes.
insert(src);
355 this->even_nodes.
remove(src);
356 this->odd_nodes.
insert(src);
359 if (is_even(this->g.get_num_arcs(tgt)))
361 this->odd_nodes.
remove(tgt);
362 this->even_nodes.
insert(tgt);
366 this->even_nodes.
remove(tgt);
367 this->odd_nodes.
insert(tgt);
371 virtual void create_nodes_and_initialize_arc_index()
373 this->nodes = unique_ptr<DynArray<GT_Node*>>
376 this->nodes->reserve(this->num_nodes);
378 for (
int i = 0; i < this->num_nodes; ++i)
380 auto p = this->g.insert_node(
new GT_Node);
381 this->nodes->access(i) = p;
382 this->init_node(this->g, p);
383 if (this->save_parity)
385 this->even_nodes.
insert(p);
390 this->idx_arc = unique_ptr<IndexArc<GT>> (
new IndexArc<GT>(this->g) );
393 virtual void connect()
399 const size_t & num_subs = subgraphs.
size();
407 it.has_curr(); it.next_ne())
408 block_nodes.
append(this->select_random_node(it.get_curr_ne()));
410 for (
int i = 1; i < num_subs; ++i)
412 auto src = block_nodes.
access(i - 1);
413 auto tgt = block_nodes.
access(i);
414 this->insert_arc(src, tgt);
420 virtual GT create_p (
const size_t & __num_nodes,
const double & p,
423 if (p > 1.0 or p <= 0.0)
424 throw std::domain_error(
"Invalid value for p");
426 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
428 for (
int i = 0; i < this->num_nodes - 1; ++i)
430 auto src = this->nodes->access(i);
431 for (
int j = i + 1; j < this->num_nodes; ++j)
432 if (gsl_rng_uniform(this->r) <= p)
434 auto tgt = this->nodes->access(j);
436 this->insert_arc(src, tgt);
443 return move(this->g);
455 const Init_Node & __init_node,
456 const Init_Arc & __init_arc)
457 : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
459 if (this->g.is_digraph())
460 throw std::domain_error(
"Building of random digraph through a graph");
464 const Init_Node && __init_node = Init_Node(),
465 const Init_Arc && __init_arc = Init_Arc())
466 : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
468 if (this->g.is_digraph())
469 throw std::domain_error(
"Building of random digraph through a graph");
489 GT operator () (
const size_t & __num_nodes,
const size_t & __num_arcs,
490 bool connected =
true)
492 return this->create(__num_nodes, __num_arcs, connected);
521 GT operator () (
const size_t & __num_nodes,
const double & p,
522 bool connected =
true)
524 return create_p(__num_nodes, p, connected);
529 virtual void make_eulerian()
531 while (this->odd_nodes.
size() > 1)
533 GT_Node * src =
nullptr;
534 GT_Node * tgt =
nullptr;
538 src = this->odd_nodes.
select 539 (gsl_rng_uniform_int(this->r, this->odd_nodes.
size()));
541 tgt = this->odd_nodes.
select 542 (gsl_rng_uniform_int(this->r, this->odd_nodes.
size()));
545 if (this->idx_arc->search(src, tgt) ==
nullptr)
547 else if (this->odd_nodes.
size() == 2)
549 GT_Node * p =
nullptr;
551 p = this->even_nodes.
select 552 (gsl_rng_uniform_int(this->r, this->even_nodes.
size()));
553 while (this->idx_arc->search(src, p) !=
nullptr or
554 this->idx_arc->search(tgt, p) !=
nullptr);
555 this->insert_arc(src, p);
556 this->insert_arc(p, tgt);
562 this->insert_arc(src, tgt);
565 assert(this->odd_nodes.
size() == 0);
568 void balance_graph_nodes_degree(GT_Node * src, GT_Node * tgt)
570 if (this->idx_arc->search(src, tgt) ==
nullptr)
571 this->insert_arc(src, tgt);
573 const size_t & n = this->g.get_num_nodes();
575 while (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) < n)
577 auto p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
578 if (p == src or p == tgt)
581 if (this->idx_arc->search(src, p) ==
nullptr)
582 this->insert_arc(src, p);
584 if (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) == n)
587 if (this->idx_arc->search(tgt, p) ==
nullptr)
588 this->insert_arc(tgt, p);
592 virtual void make_hamiltonian ()
594 const size_t & n = this->g.get_num_nodes();
595 for (
int i = 0; i < n - 1; ++i)
597 auto src = this->nodes->access(i);
598 for (
int j = i + 1; j < n; ++j)
599 balance_graph_nodes_degree(src, this->nodes->access(j));
621 GT
eulerian (
const size_t & __num_nodes,
const size_t & __num_arcs)
623 this->save_parity =
true;
624 this->g = this->create(__num_nodes, __num_arcs,
true);
627 return std::move(this->g);
649 GT
eulerian (
const size_t & __num_nodes,
const double & p)
651 this->save_parity =
true;
652 this->g = this->create_p(__num_nodes, p,
true);
655 return std::move(this->g);
686 const double & p = 0.5)
688 this->g = this->create_p(__num_nodes, p,
true);
691 return std::move(this->g);
697 class Init_Node = Dft_Init_Rand_Node<GT>,
698 class Init_Arc = Dft_Init_Rand_Arc<GT>>
699 class Random_Digraph :
public Random_Graph_Base<GT, Init_Node, Init_Arc>
701 typedef typename GT::Node GT_Node;
702 typedef typename GT::Arc GT_Arc;
710 const size_t & n = this->nodes->size();
712 if (n != this->g.get_num_nodes())
713 cout <<
"Warning num of nodes of graph does not match with array " 714 << this->g.get_num_nodes() <<
"!=" << n << endl;
716 size_t total = greater.
size() + smaller.
size() + equal.
size();
717 if (total != this->g.get_num_nodes())
718 cout <<
"Inconsistency with nodes parity" << endl
719 <<
"greater = " << greater.
size() << endl
720 <<
"smaller = " << smaller.
size() << endl
721 <<
"equal = " << equal.
size() << endl
722 <<
"total = " << total << endl
723 <<
"|V| = " << this->g.get_num_nodes();
725 for (
int i = 0; i < n; ++i)
727 auto p = this->nodes->access(i);
730 const size_t & out_sz = this->g.get_num_arcs(p);
734 if (smaller.
search(p) !=
nullptr)
735 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found " 736 <<
" in smaller table" << endl;
738 if (greater.
search(p) !=
nullptr)
739 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found " 740 <<
" in greater table" << endl;
742 if (equal.
search(p) ==
nullptr)
744 cout <<
"node of same in/out degree is not in equal table" 750 else if (in_sz > out_sz)
752 if (greater.
search(p) !=
nullptr)
753 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found " 754 <<
" in greater table" << endl;
756 if (equal.
search(p) !=
nullptr)
757 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found " 760 if (smaller.
search(p) ==
nullptr)
762 cout <<
"node with " << in_sz <<
"/" << out_sz <<
" not found " 763 <<
"smaller table" << endl;
770 if (smaller.
search(p) !=
nullptr)
771 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found " 772 <<
" in smaller table" << endl;
774 if (equal.
search(p) !=
nullptr)
775 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found " 778 if (greater.
search(p) ==
nullptr)
780 cout <<
"node with " << in_sz <<
"/" << out_sz <<
" not found " 781 <<
"greater table" << endl;
794 virtual void update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt)
796 if (not this->save_parity)
799 const size_t & src_out_degree = this->g.get_num_arcs(src);
802 if (src_out_degree == src_in_degree)
804 assert(this->smaller.
search(src) !=
nullptr);
805 this->smaller.
remove(src);
808 else if (src_out_degree > src_in_degree)
809 if (src_out_degree == src_in_degree + 1)
811 assert(this->equal.
search(src) !=
nullptr);
813 this->greater.
insert(src);
816 assert(this->greater.
search(src) !=
nullptr);
818 assert(this->smaller.
search(src) !=
nullptr);
820 const size_t & tgt_out_degree = this->g.get_num_arcs(tgt);
823 if (tgt_out_degree == tgt_in_degree)
825 assert(this->greater.
search(tgt));
826 this->greater.
remove(tgt);
829 else if (tgt_out_degree > tgt_in_degree)
830 assert(this->greater.
search(tgt));
833 if (tgt_in_degree - 1 == tgt_out_degree)
835 assert(this->equal.
search(tgt) !=
nullptr);
836 this->smaller.
insert(tgt);
840 assert(this->smaller.
search(tgt) !=
nullptr);
844 virtual void create_nodes_and_initialize_arc_index()
846 this->nodes = unique_ptr<DynArray<GT_Node*>>
849 this->nodes->reserve(this->num_nodes);
851 for (
int i = 0; i < this->num_nodes; ++i)
853 typename GT::Node * p = this->g.insert_node(
new GT_Node);
854 this->nodes->access(i) = p;
855 this->init_node(this->g, p);
857 if (this->save_parity)
864 this->idx_arc = unique_ptr<IndexArc<GT>> (
new IndexArc<GT>(this->g) );
867 virtual void connect()
874 in_degree.
reserve(this->g.get_num_nodes());
876 typename GT::Node_Iterator it(this->g);
877 for (
int i = 0; it.has_curr(); it.next_ne(), ++i)
883 for (
int i = 0; it.has_curr(); it.next_ne(), ++i)
887 const size_t & num_blocks = blk_list.
size();
898 for (
int i = 0; it.has_curr(); it.next_ne(), ++i)
901 b1.
access(i) = this->select_random_node(list);
902 b2.
access(i) = this->select_random_node(list);
906 for (
int i = 0; i < num_blocks - 1; ++i)
909 auto tgt = b1.
access((i + 1) % num_blocks);
911 if (this->idx_arc->search_directed(src, tgt) ==
nullptr)
912 this->insert_arc(src, tgt);
915 tgt = b2.
access((i + 1) % num_blocks);
917 if (this->idx_arc->search_directed(tgt, src) ==
nullptr)
918 this->insert_arc(tgt, src);
924 virtual GT create_p(
const size_t & __num_nodes,
const double & p,
927 if (p > 1.0 or p <= 0.0)
928 throw std::domain_error(
"Invalid value for p");
930 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
932 for (
int i = 0; i < this->num_nodes; ++i)
934 auto src = this->nodes->access(i);
935 for (
int j = 0; j < this->num_nodes; ++j)
936 if (i != j and gsl_rng_uniform(this->r) <= p)
938 auto tgt = this->nodes->access(j);
939 assert(this->idx_arc->search_directed(src, tgt) ==
nullptr);
940 this->insert_arc(src, tgt);
947 return move(this->g);
958 Random_Digraph(
unsigned long seed,
959 const Init_Node & __init_node,
960 const Init_Arc & __init_arc)
961 : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
963 this->g.set_digraph(
true);
966 Random_Digraph(
unsigned long seed = time(
nullptr),
967 const Init_Node && __init_node = Init_Node(),
968 const Init_Arc && __init_arc = Init_Arc())
969 : Random_Digraph(seed, __init_node, __init_arc)
974 Random_Digraph(
const Init_Node & __init_node,
975 const Init_Arc & __init_arc)
976 : Random_Digraph(time(
nullptr), __init_node, __init_arc)
983 this->g.set_digraph(
false);
1002 GT operator () (
const size_t & __num_nodes,
const size_t & __num_arcs,
1003 bool connected =
true)
1005 return this->create(__num_nodes, __num_arcs, connected);
1034 GT operator () (
const size_t & __num_nodes,
const double & p,
1035 bool connected =
true)
1037 return this->create_p(__num_nodes, p, connected);
1042 virtual void make_eulerian()
1044 GT_Node * src =
nullptr;
1045 GT_Node * tgt =
nullptr;
1047 while (this->greater.
size() > 0 and this->smaller.
size() > 0)
1051 tgt = this->greater.
select 1052 (gsl_rng_uniform_int(this->r, this->greater.
size()));
1053 src = this->smaller.
select 1054 (gsl_rng_uniform_int(this->r, this->smaller.
size()));
1058 if (this->idx_arc->search_directed(src, tgt) ==
nullptr)
1059 this->insert_arc(src, tgt);
1063 this->equal.
select(gsl_rng_uniform_int(this->r,
1064 this->equal.
size()));
1066 while (this->idx_arc->search_directed(src, mid) !=
nullptr or
1067 this->idx_arc->search_directed(mid, tgt) !=
nullptr)
1069 (gsl_rng_uniform_int(this->r, this->equal.
size()));
1071 this->insert_arc(src, mid);
1072 this->insert_arc(mid, tgt);
1077 void balance_digraph_node(GT_Node * p)
1079 const size_t & n = this->g.get_num_nodes();
1080 const size_t n2 = n/2;
1082 while (not (this->g.get_num_arcs(p) >= n2 and
NODE_COUNTER(p) >= n2))
1084 auto q = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1088 if (this->idx_arc->search_directed(p, q) ==
nullptr)
1090 this->insert_arc(p, q);
1094 if (this->idx_arc->search_directed(q, p) ==
nullptr)
1096 this->insert_arc(q, p);
1104 void balance_digraph_nodes_degree(GT_Node * src, GT_Node * tgt)
1106 if (this->idx_arc->search_directed(src, tgt) !=
nullptr)
1108 balance_digraph_node(src);
1109 balance_digraph_node(tgt);
1114 const size_t & n = this->g.get_num_nodes();
1116 while (this->g.get_num_arcs(src) +
NODE_COUNTER(tgt) < n)
1118 auto p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1119 if (p == src or p == tgt)
1122 if (this->idx_arc->search_directed(src, p) ==
nullptr)
1124 this->insert_arc(src, p);
1127 if (this->g.get_num_arcs(src) +
NODE_COUNTER(tgt) == n)
1131 if (this->idx_arc->search_directed(p, tgt) ==
nullptr)
1133 this->insert_arc(p, tgt);
1138 assert(this->g.get_num_arcs(src) +
NODE_COUNTER(tgt) >= n);
1141 virtual void make_hamiltonian ()
1143 this->g.reset_counter_nodes();
1146 for (
typename GT::Arc_Iterator it(this->g); it.has_curr(); it.next_ne())
1149 const size_t & n = this->g.get_num_nodes();
1151 for (
int i = 0; i < n; ++i)
1153 auto src = this->nodes->access(i);
1154 for (
int j = 0; j < n; ++j)
1159 auto tgt = this->nodes->access(j);
1160 balance_digraph_nodes_degree(src, tgt);
1168 # endif // RANDOM_GRAPH_H void reserve(const size_t l, const size_t r)
Definition: tpl_dynArray.H:998
size_t size() const noexcept
Definition: htlist.H:1240
Random_Graph(unsigned long seed, const Init_Node &__init_node, const Init_Arc &__init_arc)
Definition: random_graph.H:454
GT eulerian(const size_t &__num_nodes, const double &p)
Definition: random_graph.H:649
GT sufficient_hamiltonian(const size_t &__num_nodes, const double &p=0.5)
Definition: random_graph.H:685
size_t remove(const Key &key)
Definition: tpl_dynSetTree.H:327
size_type size()
Retorna la cantidad de elementos que tiene la lista.
Definition: List.H:366
T & access(const size_t i) const noexcept
Definition: tpl_dynArray.H:874
Key & select(const size_t &i)
Definition: tpl_dynSetTree.H:561
size_t in_degree(typename GT::Node *p, SA sa=SA())
Definition: tpl_graph.H:1948
#define NODE_COUNTER(p)
Definition: aleph-graph.H:311
GT eulerian(const size_t &__num_nodes, const size_t &__num_arcs)
Definition: random_graph.H:621
GT sufficient_hamiltonian(const size_t &__num_nodes, const double &p=0.5)
Definition: random_graph.H:279
Definition: tpl_dynSetTree.H:991
Definition: random_graph.H:335
const size_t & size() const
Retorna la cardinalidad del conjunto.
Definition: tpl_dynSetTree.H:502
Definition: tpl_indexArc.H:67
T & append()
Definition: tpl_dynArray.H:1149
Definition: tpl_dynArray.H:159
Definition: tpl_components.H:207
Key * insert(const Key &key)
Definition: tpl_dynSetTree.H:195
Key * search(const Key &key) const
Definition: tpl_dynSetTree.H:462