1 # ifndef RANDOM_GRAPH_H
2 # define RANDOM_GRAPH_H
4 # include <gsl/gsl_rng.h>
6 # include <tpl_indexArc.H>
7 # include <tpl_graph_utils.H>
8 # include <tpl_components.H>
9 # include <single_graph.H>
18 void operator () (GT &,
typename GT::Node *)
const
28 void operator () (GT &,
typename GT::Arc *)
const
36 template <
class GT,
class Init_Node,
class Init_Arc>
41 typedef typename GT::Node GT_Node;
42 typedef typename GT::Arc GT_Arc;
46 Init_Node & init_node;
49 unique_ptr<DynArray<GT_Node*>> nodes;
53 unique_ptr<IndexArc<GT>> idx_arc;
55 mutable size_t num_nodes;
56 mutable size_t num_arcs;
57 mutable unsigned long rand_max;
66 update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt) = 0;
68 GT_Arc * insert_arc(GT_Node * src, GT_Node * tgt)
70 GT_Arc * a = idx_arc->insert(g.insert_arc(src, tgt));
74 update_parity_after_arc_insertion(src, tgt);
80 GT_Node * select_random_node(GT_Node * excluded = NULL)
82 I(nodes.get() != NULL);
85 GT_Node * ret_val = NULL;
88 idx = gsl_rng_uniform_int(r, num_nodes);
90 ret_val = nodes->access(idx);
92 if (excluded == NULL or ret_val != excluded)
102 const unsigned long k = gsl_rng_uniform_int(r, list.size());
105 for (
int i = 0; i < k; ++i, it.next()) ;
107 return it.get_curr();
110 virtual void create_nodes_and_initialize_arc_index() = 0;
112 virtual void connect() = 0;
114 void initialize_and_create_nodes(
const size_t & __num_nodes,
115 const size_t & __num_arcs)
117 num_nodes = __num_nodes;
119 const size_t num_nodes_2 = num_nodes*num_nodes;
121 num_arcs = std::min(__num_arcs, num_nodes_2 - num_nodes);
123 num_arcs= std::min(__num_arcs, (num_nodes_2 - num_nodes)/2);
125 create_nodes_and_initialize_arc_index();
129 const Init_Node & __init_node,
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)
138 throw std::bad_alloc();
140 gsl_rng_set(r, seed % rand_max);
150 GT create(
const size_t & __num_nodes,
const size_t & __num_arcs,
153 initialize_and_create_nodes(__num_nodes, __num_arcs);
156 for (
int i = 0; i < num_arcs; ++i)
158 GT_Node * src = select_random_node();
159 GT_Node * tgt = select_random_node(src);
161 if (idx_arc->search(src, tgt) == NULL)
162 insert_arc(src, tgt);
171 virtual GT create_p(
const size_t & __num_nodes,
const double & p,
174 virtual void make_eulerian() = 0;
176 virtual void make_hamiltonian () = 0;
196 GT
eulerian(
const size_t & __num_nodes,
const size_t & __num_arcs)
200 g = std::move(this->create(__num_nodes, __num_arcs,
true));
226 GT
eulerian (
const size_t & __num_nodes,
const double & p)
230 g = std::move(this->create_p(__num_nodes, p,
true));
265 const double & p = 0.5)
267 g = std::move(this->create_p(__num_nodes, p,
true));
323 typedef typename GT::Node GT_Node;
324 typedef typename GT::Arc GT_Arc;
329 virtual void update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt)
331 if (not this->save_parity)
334 if (
is_even(this->g.get_num_arcs(src)))
336 this->odd_nodes.
remove(src);
337 this->even_nodes.
insert(src);
341 this->even_nodes.
remove(src);
342 this->odd_nodes.
insert(src);
345 if (
is_even(this->g.get_num_arcs(tgt)))
347 this->odd_nodes.
remove(tgt);
348 this->even_nodes.
insert(tgt);
352 this->even_nodes.
remove(tgt);
353 this->odd_nodes.
insert(tgt);
357 virtual void create_nodes_and_initialize_arc_index()
359 this->nodes = unique_ptr<DynArray<GT_Node*>>
362 this->nodes->reserve(this->num_nodes);
364 for (
int i = 0; i < this->num_nodes; ++i)
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);
370 if (this->save_parity)
372 this->even_nodes.
insert(p);
377 this->idx_arc = unique_ptr<IndexArc<GT>> (
new IndexArc<GT>(this->g) );
380 virtual void connect()
386 const size_t & num_subs = subgraphs.size();
394 it.has_curr(); it.next())
395 block_nodes.
append(this->select_random_node(it.get_curr()));
397 for (
int i = 1; i < num_subs; ++i)
399 typename GT::Node * src = block_nodes.
access(i - 1);
400 typename GT::Node * tgt = block_nodes.
access(i);
402 this->insert_arc(src, tgt);
408 virtual GT create_p (
const size_t & __num_nodes,
const double & p,
411 if (p > 1.0 or p <= 0.0)
412 throw std::domain_error(
"Invalid value for p");
414 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
416 for (
int i = 0; i < this->num_nodes - 1; ++i)
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)
422 GT_Node * tgt = this->nodes->access(j);
423 this->insert_arc(src, tgt);
442 const Init_Node & __init_node,
446 if (this->g.is_digraph())
447 throw std::domain_error(
"Building of random digraph through a graph");
451 const Init_Node && __init_node = Init_Node(),
455 if (this->g.is_digraph())
456 throw std::domain_error(
"Building of random digraph through a graph");
476 GT
operator () (
const size_t & __num_nodes,
const size_t & __num_arcs,
477 bool connected =
true)
479 return this->create(__num_nodes, __num_arcs, connected);
509 bool connected =
true)
511 return create_p(__num_nodes, p, connected);
516 virtual void make_eulerian()
518 while (this->odd_nodes.
size() > 1)
520 GT_Node * src = NULL;
521 GT_Node * tgt = NULL;
525 src = this->odd_nodes.
select
526 (gsl_rng_uniform_int(this->r, this->odd_nodes.
size()));
528 tgt = this->odd_nodes.
select
529 (gsl_rng_uniform_int(this->r, this->odd_nodes.
size()));
532 if (this->idx_arc->search(src, tgt) == NULL)
534 else if (this->odd_nodes.
size() == 2)
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);
549 this->insert_arc(src, tgt);
552 I(this->odd_nodes.
size() == 0);
555 void balance_graph_nodes_degree(GT_Node * src, GT_Node * tgt)
557 if (this->idx_arc->search(src, tgt) == NULL)
558 this->insert_arc(src, tgt);
560 const size_t & n = this->g.get_num_nodes();
562 while (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) < n)
564 GT_Node * p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
566 if (p == src or p == tgt)
569 if (this->idx_arc->search(src, p) == NULL)
570 this->insert_arc(src, p);
572 if (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) == n)
575 if (this->idx_arc->search(tgt, p) == NULL)
576 this->insert_arc(tgt, p);
580 virtual void make_hamiltonian ()
582 const size_t & n = this->g.get_num_nodes();
584 for (
int i = 0; i < n - 1; ++i)
586 GT_Node * src = this->nodes->access(i);
588 for (
int j = i + 1; j < n; ++j)
589 balance_graph_nodes_degree(src, this->nodes->access(j));
611 GT
eulerian (
const size_t & __num_nodes,
const size_t & __num_arcs)
613 this->save_parity =
true;
615 this->g = std::move(this->create(__num_nodes, __num_arcs,
true));
641 GT
eulerian (
const size_t & __num_nodes,
const double & p)
643 this->save_parity =
true;
645 this->g = std::move(this->create_p(__num_nodes, p,
true));
680 const double & p = 0.5)
682 this->g = std::move(this->create_p(__num_nodes, p,
true));
696 typedef typename GT::Node GT_Node;
697 typedef typename GT::Arc GT_Arc;
705 const size_t & n = this->nodes->size();
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;
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();
720 for (
int i = 0; i < n; ++i)
722 GT_Node * p = this->nodes->access(i);
725 const size_t & out_sz = this->g.get_num_arcs(p);
729 if (smaller.
search(p) != NULL)
730 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found "
731 <<
" in smaller table" << endl;
734 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found "
735 <<
" in greater table" << endl;
737 if (equal.
search(p) == NULL)
739 cout <<
"node of same in/out degree is not in equal table"
745 else if (in_sz > out_sz)
748 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found "
749 <<
" in greater table" << endl;
751 if (equal.
search(p) != NULL)
752 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found "
755 if (smaller.
search(p) == NULL)
757 cout <<
"node with " << in_sz <<
"/" << out_sz <<
" not found "
758 <<
"smaller table" << endl;
765 if (smaller.
search(p) != NULL)
766 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found "
767 <<
" in smaller table" << endl;
769 if (equal.
search(p) != NULL)
770 cout <<
"Inconsistency " << in_sz <<
"/" << out_sz <<
" found "
775 cout <<
"node with " << in_sz <<
"/" << out_sz <<
" not found "
776 <<
"greater table" << endl;
789 virtual void update_parity_after_arc_insertion(GT_Node * src, GT_Node * tgt)
791 if (not this->save_parity)
794 const size_t & src_out_degree = this->g.get_num_arcs(src);
797 if (src_out_degree == src_in_degree)
799 I(this->smaller.
search(src) != NULL);
800 this->smaller.
remove(src);
803 else if (src_out_degree > src_in_degree)
804 if (src_out_degree == src_in_degree + 1)
806 I(this->equal.
search(src) != NULL);
811 I(this->
greater.search(src) != NULL);
813 I(this->smaller.
search(src) != NULL);
815 const size_t & tgt_out_degree = this->g.get_num_arcs(tgt);
818 if (tgt_out_degree == tgt_in_degree)
824 else if (tgt_out_degree > tgt_in_degree)
828 if (tgt_in_degree - 1 == tgt_out_degree)
830 I(this->equal.
search(tgt) != NULL);
831 this->smaller.
insert(tgt);
835 I(this->smaller.
search(tgt) != NULL);
839 virtual void create_nodes_and_initialize_arc_index()
841 this->nodes = unique_ptr<DynArray<GT_Node*>>
844 this->nodes->reserve(this->num_nodes);
846 for (
int i = 0; i < this->num_nodes; ++i)
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);
852 if (this->save_parity)
859 this->idx_arc = unique_ptr<IndexArc<GT>> (
new IndexArc<GT>(this->g) );
862 virtual void connect()
869 in_degree.
reserve(this->g.get_num_nodes());
871 typename GT::Node_Iterator it(this->g);
872 for (
int i = 0; it.has_curr(); it.next(), ++i)
878 for (
int i = 0; it.has_curr(); it.next(), ++i)
882 const size_t & num_blocks = blk_list.size();
893 for (
int i = 0; it.has_curr(); it.next(), ++i)
896 b1.
access(i) = this->select_random_node(list);
897 b2.
access(i) = this->select_random_node(list);
901 for (
int i = 0; i < num_blocks - 1; ++i)
903 GT_Node * src = b1.
access(i);
904 GT_Node * tgt = b1.
access((i + 1) % num_blocks);
906 if (this->idx_arc->search(src, tgt) == NULL)
907 this->insert_arc(src, tgt);
910 tgt = b2.
access((i + 1) % num_blocks);
912 if (this->idx_arc->search(tgt, src) == NULL)
913 this->insert_arc(tgt, src);
919 virtual GT create_p(
const size_t & __num_nodes,
const double & p,
922 if (p > 1.0 or p <= 0.0)
923 throw std::domain_error(
"Invalid value for p");
925 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
927 for (
int i = 0; i < this->num_nodes; ++i)
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)
933 GT_Node * tgt = this->nodes->access(j);
934 I(this->idx_arc->search(src, tgt) == NULL);
935 this->insert_arc(src, tgt);
954 const Init_Node && __init_node = Init_Node(),
958 if (not this->g.is_digraph())
959 throw std::domain_error(
"Building of random graph through a digraph");
963 const Init_Node & __init_node,
967 if (not this->g.is_digraph())
968 throw std::domain_error(
"Building of random graph through a digraph");
975 if (not this->g.is_digraph())
976 throw std::domain_error(
"Building of random graph through a digraph");
995 GT
operator () (
const size_t & __num_nodes,
const size_t & __num_arcs,
996 bool connected =
true)
998 return this->create(__num_nodes, __num_arcs, connected);
1028 bool connected =
true)
1030 return this->create_p(__num_nodes, p, connected);
1035 virtual void make_eulerian()
1037 GT_Node * src = NULL;
1038 GT_Node * tgt = NULL;
1040 while (this->
greater.size() > 0 and this->smaller.
size() > 0)
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()));
1051 if (this->idx_arc->search(src, tgt) == NULL)
1052 this->insert_arc(src, tgt);
1056 this->equal.
select(gsl_rng_uniform_int(this->r,
1057 this->equal.
size()));
1059 while (this->idx_arc->search(src, mid) != NULL or
1060 this->idx_arc->search(mid, tgt) != NULL)
1062 (gsl_rng_uniform_int(this->r, this->equal.
size()));
1064 this->insert_arc(src, mid);
1065 this->insert_arc(mid, tgt);
1070 void balance_digraph_node(GT_Node * p)
1072 const size_t & n = this->g.get_num_nodes();
1073 const size_t n2 = n/2;
1075 while (not (this->g.get_num_arcs(p) >= n2 and
NODE_COUNTER(p) >= n2))
1077 GT_Node * q = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1082 if (this->idx_arc->search(p, q) == NULL)
1084 this->insert_arc(p, q);
1088 if (this->idx_arc->search(q, p) == NULL)
1090 this->insert_arc(q, p);
1098 void balance_digraph_nodes_degree(GT_Node * src, GT_Node * tgt)
1100 if (this->idx_arc->search(src, tgt) != NULL)
1102 balance_digraph_node(src);
1103 balance_digraph_node(tgt);
1108 const size_t & n = this->g.get_num_nodes();
1110 while (this->g.get_num_arcs(src) +
NODE_COUNTER(tgt) < n)
1112 GT_Node * p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1114 if (p == src or p == tgt)
1117 if (this->idx_arc->search(src, p) == NULL)
1119 this->insert_arc(src, p);
1122 if (this->g.get_num_arcs(src) +
NODE_COUNTER(tgt) == n)
1126 if (this->idx_arc->search(p, tgt) == NULL)
1128 this->insert_arc(p, tgt);
1136 virtual void make_hamiltonian ()
1138 this->g.reset_counter_nodes();
1141 for (
typename GT::Arc_Iterator it(this->g); it.has_curr(); it.next())
1144 const size_t & n = this->g.get_num_nodes();
1146 for (
int i = 0; i < n; ++i)
1148 GT_Node * src = this->nodes->access(i);
1150 for (
int j = 0; j < n; ++j)
1155 GT_Node * tgt = this->nodes->access(j);
1157 balance_digraph_nodes_degree(src, tgt);
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
GT eulerian(const size_t &__num_nodes, const double &p)
Definition: random_graph.H:226
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
Key * insert(const Key &key)
Definition: tpl_dynSetTree.H:177