Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
random_graph.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
44# ifndef RANDOM_GRAPH_H
45# define RANDOM_GRAPH_H
46
47# include <gsl/gsl_rng.h>
48# include <memory>
49# include <tpl_indexArc.H>
50# include <tpl_graph_utils.H>
51# include <tpl_components.H>
52# include <single_graph.H>
53# include <Tarjan.H>
54# include <ah-errors.H>
55
56namespace Aleph
57{
67 template <class GT>
69 {
70 void operator ()(GT &, typename GT::Node *) const noexcept
71 {
72 // empty
73 }
74 };
75
76
86 template <class GT>
88 {
89 void operator ()(GT &, typename GT::Arc *) const noexcept
90 {
91 // empty
92 }
93 };
94
95 // TODO: consider replacing Init_Node and Init_Arc classes with lambdas
96
97 template <class GT, class Init_Node, class Init_Arc>
99 {
100 protected:
101 typedef typename GT::Node GT_Node;
102 typedef typename GT::Arc GT_Arc;
103
105
106 Init_Node & init_node;
108
109 std::unique_ptr<DynArray<GT_Node *>> nodes; // pointer to save directory
110 // space when not used
111
112 std::unique_ptr<IndexArc<GT>> idx_arc; // pointer because constructor
113 // requires the graph
114 mutable size_t num_nodes;
115 mutable size_t num_arcs;
116 mutable unsigned long rand_max;
117
119
120 bool save_parity; // indicates whether to track parity relations
121 // among nodes (only for building Eulerian
122 // and Hamiltonian graphs)
123
124 virtual void
126
128 {
129 auto a = idx_arc->insert(g.insert_arc(src, tgt));
130 init_arc(g, a);
132 return a;
133 }
134
137 {
138 assert(nodes.get() != nullptr);
139 assert(num_nodes > 0);
140 assert(excluded == nullptr or num_nodes > 1); // avoid infinite loop
141
142 GT_Node *ret_val = nullptr;
143 while (true)
144 {
145 unsigned long idx = gsl_rng_uniform_int(r, num_nodes);
146 ret_val = nodes->access(idx);
147 if (excluded == nullptr or ret_val != excluded)
148 break;
149 }
150
151 return ret_val;
152 }
153
156 {
157 const unsigned long k = gsl_rng_uniform_int(r, list.size());
158 typename DynList<GT_Node *>::Iterator it(list);
159 for (unsigned long i = 0; i < k; ++i, it.next_ne()) {}
160
161 return it.get_curr_ne();
162 }
163
165
166 virtual void connect() = 0;
167
169 const size_t & __num_arcs)
170 {
172 << "Number of nodes must be greater than 0";
173
175
176 const size_t num_nodes_2 = num_nodes * num_nodes;
177 if (g.is_digraph())
179 else
180 num_arcs = std::min(__num_arcs, (num_nodes_2 - num_nodes) / 2);
181
183 }
184
185 Random_Graph_Base(const unsigned long seed,
186 const Init_Node & __init_node,
187 const Init_Arc & __init_arc)
189 init_node(const_cast<Init_Node &>(__init_node)),
191 num_nodes(0), num_arcs(0),
193 {
194 ah_bad_alloc_if(r == nullptr);
195
196 gsl_rng_set(r, seed % rand_max);
197 }
198
200 {
201 if (r != nullptr)
203 }
204
206 GT create(const size_t & __num_nodes, const size_t & __num_arcs,
207 const bool connected)
208 {
210
211 // randomly insert arcs by selecting random node pairs
212 for (size_t i = 0; i < num_arcs; ++i)
213 {
214 auto src = select_random_node();
215 auto tgt = select_random_node(src);
216 if (idx_arc->search(src, tgt) == nullptr) // arc already exists?
217 insert_arc(src, tgt);
218 }
219
220 if (connected)
221 connect();
222
223 return std::move(g);
224 }
225
226 virtual GT create_p(const size_t & __num_nodes, const double & p,
227 bool connected) = 0;
228
229 virtual void make_eulerian() = 0;
230
231 virtual void make_hamiltonian() = 0;
232
233 public:
248 GT eulerian(const size_t & __num_nodes, const size_t & __num_arcs)
249 {
250 save_parity = true;
251 g = this->create(__num_nodes, __num_arcs, true);
253
254 return std::move(g);
255 }
256
274 GT eulerian(const size_t & __num_nodes, const double & p)
275 {
276 save_parity = true;
277 g = this->create_p(__num_nodes, p, true);
279
280 return std::move(g);
281 }
282
311 const double & p = 0.5)
312 {
313 g = this->create_p(__num_nodes, p, true);
315
316 return std::move(g);
317 }
318 };
319
320
365 template <class GT,
366 class Init_Node = Dft_Init_Rand_Node<GT>,
368 class Random_Graph : public Random_Graph_Base<GT, Init_Node, Init_Arc>
369 {
370 typedef typename GT::Node GT_Node;
371 typedef typename GT::Arc GT_Arc;
372
373 DynSetRandTree<GT_Node *> odd_nodes; // nodes with odd degree
374 DynSetRandTree<GT_Node *> even_nodes; // nodes with even degree
375
377 {
378 if (not this->save_parity)
379 return;
380
381 if (is_even(this->g.get_num_arcs(src)))
382 { // was odd before the insertion
383 this->odd_nodes.remove(src);
384 this->even_nodes.insert(src);
385 }
386 else
387 {
388 this->even_nodes.remove(src);
389 this->odd_nodes.insert(src);
390 }
391
392 if (is_even(this->g.get_num_arcs(tgt)))
393 { // was odd before the insertion
394 this->odd_nodes.remove(tgt);
395 this->even_nodes.insert(tgt);
396 }
397 else
398 {
399 this->even_nodes.remove(tgt);
400 this->odd_nodes.insert(tgt);
401 }
402 }
403
405 {
406 this->nodes = std::unique_ptr<DynArray<GT_Node *>>
407 (new DynArray<GT_Node *>(this->num_nodes));
408
409 this->nodes->reserve(this->num_nodes);
410
411 for (size_t i = 0; i < this->num_nodes; ++i)
412 {
413 auto p = this->g.insert_node(new GT_Node);
414 this->nodes->access(i) = p;
415 this->init_node(this->g, p);
416 if (this->save_parity)
417 {
418 this->even_nodes.insert(p);
419 NODE_COUNTER(p) = 0;
420 }
421 }
422
423 this->idx_arc = std::unique_ptr<IndexArc<GT>>(new IndexArc<GT>(this->g));
424 }
425
426 void connect() override
427 {
428 DynList<DynList<GT_Node *>> subgraphs; // list of subgraphs
429
431
432 const size_t & num_subs = subgraphs.size();
433
434 if (num_subs == 1)
435 return;
436
438
439 for (typename DynList<DynList<GT_Node *>>::Iterator it(subgraphs);
440 it.has_curr(); it.next_ne())
441 block_nodes.append(this->select_random_node(it.get_curr_ne()));
442
443 for (size_t i = 1; i < num_subs; ++i)
444 {
445 auto src = block_nodes.access(i - 1);
446 auto tgt = block_nodes.access(i);
447 this->insert_arc(src, tgt);
448 }
449 }
450
451 // Create a random graph where the probability of an arc between
452 // any pair of nodes is p
453 GT create_p(const size_t & __num_nodes, const double & p,
454 const bool connected) override
455 {
456 ah_domain_error_if(p > 1.0 or p <= 0.0) << "Invalid value for p";
457
458 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
459
460 for (size_t i = 0; i + 1 < this->num_nodes; ++i)
461 {
462 auto src = this->nodes->access(i);
463 for (size_t j = i + 1; j < this->num_nodes; ++j)
464 if (gsl_rng_uniform(this->r) <= p) // random draw
465 {
466 auto tgt = this->nodes->access(j);
467 assert(src != tgt);
468 this->insert_arc(src, tgt);
469 }
470 }
471
472 if (connected)
473 connect();
474
475 return std::move(this->g);
476 }
477
478 public:
485 Random_Graph(unsigned long seed,
486 const Init_Node & __init_node,
487 const Init_Arc & __init_arc)
488 : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
489 {
491 << "Building of random digraph through a graph";
492 }
493
494 Random_Graph(unsigned long seed = time(nullptr),
495 const Init_Node && __init_node = Init_Node(),
496 const Init_Arc && __init_arc = Init_Arc())
497 : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
498 {
500 << "Building of random digraph through a graph";
501 }
502
503
520 GT operator ()(const size_t & __num_nodes, const size_t & __num_arcs,
521 bool connected = true)
522 {
523 return this->create(__num_nodes, __num_arcs, connected);
524 }
525
549 GT operator ()(const size_t & __num_nodes, const double & p,
550 bool connected = true)
551 {
552 return create_p(__num_nodes, p, connected);
553 }
554
555 private:
556 void make_eulerian() override
557 {
558 while (this->odd_nodes.size() > 1)
559 {
560 GT_Node *src = nullptr;
561 GT_Node *tgt = nullptr;
562
563 while (true)
564 {
565 src = this->odd_nodes.select
566 (gsl_rng_uniform_int(this->r, this->odd_nodes.size()));
567 do
568 tgt = this->odd_nodes.select
569 (gsl_rng_uniform_int(this->r, this->odd_nodes.size()));
570 while (tgt == src);
571
572 if (this->idx_arc->search(src, tgt) == nullptr)
573 break;
574 else if (this->odd_nodes.size() == 2)
575 { // select random node that has no arc to src or tgt
576 GT_Node *p = nullptr;
577 do
578 p = this->even_nodes.select
579 (gsl_rng_uniform_int(this->r, this->even_nodes.size()));
580 while (this->idx_arc->search(src, p) != nullptr or
581 this->idx_arc->search(tgt, p) != nullptr);
582 this->insert_arc(src, p);
583 this->insert_arc(p, tgt);
584
585 return;
586 }
587 }
588
589 this->insert_arc(src, tgt);
590 }
591
592 assert(this->odd_nodes.size() == 0);
593 }
594
596 {
597 if (this->idx_arc->search(src, tgt) == nullptr)
598 this->insert_arc(src, tgt);
599
600 const size_t & n = this->g.get_num_nodes();
601
602 while (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) < n)
603 {
604 auto p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
605 if (p == src or p == tgt)
606 continue;
607
608 if (this->idx_arc->search(src, p) == nullptr)
609 this->insert_arc(src, p);
610
611 if (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) == n)
612 break;
613
614 if (this->idx_arc->search(tgt, p) == nullptr)
615 this->insert_arc(tgt, p);
616 }
617 }
618
619 void make_hamiltonian() override
620 {
621 const size_t & n = this->g.get_num_nodes();
622 for (size_t i = 0; i + 1 < n; ++i)
623 {
624 auto src = this->nodes->access(i);
625 for (size_t j = i + 1; j < n; ++j)
626 balance_graph_nodes_degree(src, this->nodes->access(j));
627 }
628 }
629
630 public:
645 GT eulerian(const size_t & __num_nodes, const size_t & __num_arcs)
646 {
647 this->save_parity = true;
648 this->g = this->create(__num_nodes, __num_arcs, true);
650
651 return std::move(this->g);
652 }
653
671 GT eulerian(const size_t & __num_nodes, const double & p)
672 {
673 this->save_parity = true;
674 this->g = this->create_p(__num_nodes, p, true);
676
677 return std::move(this->g);
678 }
679
708 const double & p = 0.5)
709 {
710 this->g = this->create_p(__num_nodes, p, true);
712
713 return std::move(this->g);
714 }
715 };
716
717
736 template <class GT,
737 class Init_Node = Dft_Init_Rand_Node<GT>,
739 class Random_Digraph : public Random_Graph_Base<GT, Init_Node, Init_Arc>
740 {
741 typedef typename GT::Node GT_Node;
742 typedef typename GT::Arc GT_Arc;
743
744 DynSetRandTree<GT_Node *> greater; // nodes with out-degree > in-degree
745 DynSetRandTree<GT_Node *> smaller; // nodes with out-degree < in-degree
746 DynSetRandTree<GT_Node *> equal; // nodes with out-degree == in-degree
747
749 {
750 const size_t & n = this->nodes->size();
751
752 if (n != this->g.get_num_nodes())
753 std::cout << "Warning num of nodes of graph does not match with array "
754 << this->g.get_num_nodes() << "!=" << n << std::endl;
755
756 size_t total = greater.size() + smaller.size() + equal.size();
757 if (total != this->g.get_num_nodes())
758 std::cout << "Inconsistency with nodes parity" << std::endl
759 << "greater = " << greater.size() << std::endl
760 << "smaller = " << smaller.size() << std::endl
761 << "equal = " << equal.size() << std::endl
762 << "total = " << total << std::endl
763 << "|V| = " << this->g.get_num_nodes();
764
765 for (size_t i = 0; i < n; ++i)
766 {
767 auto p = this->nodes->access(i);
768
769 const long & in_sz = NODE_COUNTER(p);
770 const size_t & out_sz = this->g.get_num_arcs(p);
771
772 if (in_sz == out_sz)
773 {
774 if (smaller.search(p) != nullptr)
775 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
776 << " in smaller table" << std::endl;
777
778 if (greater.search(p) != nullptr)
779 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
780 << " in greater table" << std::endl;
781
782 if (equal.search(p) == nullptr)
783 {
784 std::cout << "node of same in/out degree is not in equal table"
785 << std::endl;
786
787 return false;
788 }
789 }
790 else if (in_sz > out_sz)
791 {
792 if (greater.search(p) != nullptr)
793 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
794 << " in greater table" << std::endl;
795
796 if (equal.search(p) != nullptr)
797 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
798 << std::endl;
799
800 if (smaller.search(p) == nullptr)
801 {
802 std::cout << "node with " << in_sz << "/" << out_sz << " not found "
803 << "smaller table" << std::endl;
804
805 return false;
806 }
807 }
808 else
809 {
810 if (smaller.search(p) != nullptr)
811 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
812 << " in smaller table" << std::endl;
813
814 if (equal.search(p) != nullptr)
815 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
816 << std::endl;
817
818 if (greater.search(p) == nullptr)
819 {
820 std::cout << "node with " << in_sz << "/" << out_sz << " not found "
821 << "greater table" << std::endl;
822
823 return false;
824 }
825 }
826 }
827
828 return true;
829 }
830
831 // This call is made right after inserting a new arc src-->tgt.
832 // This implies that out(src) is updated, but in(tgt) is not.
834 {
835 if (not this->save_parity)
836 return;
837
838 const size_t & src_out_degree = this->g.get_num_arcs(src);
839 const long & src_in_degree = NODE_COUNTER(src);
840
842 { // src is in greater ==> remove it and insert into equal
843 assert(this->smaller.search(src) != nullptr);
844 this->smaller.remove(src);
845 this->equal.insert(src);
846 }
847 else if (src_out_degree > src_in_degree)
848 if (src_out_degree == src_in_degree + 1)
849 {
850 assert(this->equal.search(src) != nullptr);
851 this->equal.remove(src);
852 this->greater.insert(src);
853 }
854 else
855 assert(this->greater.search(src) != nullptr);
856 else // src_out_degree < src_in_degree
857 assert(this->smaller.search(src) != nullptr);
858
859 const size_t & tgt_out_degree = this->g.get_num_arcs(tgt);
860 const long tgt_in_degree = ++NODE_COUNTER(tgt);
861
863 {
864 assert(this->greater.search(tgt));
865 this->greater.remove(tgt);
866 this->equal.insert(tgt);
867 }
868 else if (tgt_out_degree > tgt_in_degree)
869 assert(this->greater.search(tgt));
870 else // (tgt_out_degree < tgt_in_degree)
871 {
872 if (tgt_in_degree - 1 == tgt_out_degree)
873 { // tgt is in equal ==> remove it
874 assert(this->equal.search(tgt) != nullptr);
875 this->smaller.insert(tgt);
876 this->equal.remove(tgt);
877 }
878 else
879 assert(this->smaller.search(tgt) != nullptr);
880 }
881 }
882
884 {
885 this->nodes = std::unique_ptr<DynArray<GT_Node *>>
886 (new DynArray<GT_Node *>(this->num_nodes));
887
888 this->nodes->reserve(this->num_nodes);
889
890 for (size_t i = 0; i < this->num_nodes; ++i)
891 {
892 typename GT::Node *p = this->g.insert_node(new GT_Node);
893 this->nodes->access(i) = p;
894 this->init_node(this->g, p);
895
896 if (this->save_parity)
897 {
898 NODE_COUNTER(p) = 0;
899 this->equal.insert(p);
900 }
901 }
902
903 this->idx_arc = std::unique_ptr<IndexArc<GT>>(new IndexArc<GT>(this->g));
904 }
905
906 void connect() override
907 {
908 DynList<DynList<typename GT::Node *>> blk_list; // disconnected subgraphs
909
910 { // save in-degrees since Tarjan's algorithm will modify them
913
914 typename GT::Node_Iterator it(this->g);
915 for (int i = 0; it.has_curr(); it.next_ne(), ++i)
916 in_degree.access(i) = NODE_COUNTER(it.get_curr_ne());
917
919
920 it.reset_first(); // restore in-degrees
921 for (size_t i = 0; it.has_curr(); it.next_ne(), ++i)
922 NODE_COUNTER(it.get_curr_ne()) = in_degree.access(i);
923 }
924
925 const size_t & num_blocks = blk_list.size();
926
927 if (num_blocks == 1)
928 return;
929
930 // each node in this list is a randomly selected node from block i
932 b1.reserve(num_blocks);
934 b2.reserve(num_blocks); {
935 typename DynList<DynList<GT_Node *>>::Iterator it(blk_list);
936 for (size_t i = 0; it.has_curr(); it.next_ne(), ++i)
937 { // select two random nodes from the current component
938 DynList<typename GT::Node *> & list = it.get_curr_ne();
939 b1.access(i) = this->select_random_node(list);
940 b2.access(i) = this->select_random_node(list);
941 }
942 }
943
944 for (size_t i = 0; i + 1 < num_blocks; ++i)
945 {
946 auto src = b1.access(i); // node in block i
947 auto tgt = b1.access((i + 1) % num_blocks); // node in block i + 1
948
949 if (this->idx_arc->search_directed(src, tgt) == nullptr)
950 this->insert_arc(src, tgt);
951
952 src = b2.access(i); // node in block i
953 tgt = b2.access((i + 1) % num_blocks); // node in block i + 1
954
955 if (this->idx_arc->search_directed(tgt, src) == nullptr)
956 this->insert_arc(tgt, src);
957 }
958 }
959
960 // Create a random graph where the probability of an arc between
961 // any pair of nodes is p
962 GT create_p(const size_t & __num_nodes, const double & p,
963 bool connected) override
964 {
965 ah_domain_error_if(p > 1.0 or p <= 0.0) << "Invalid value for p";
966
967 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
968
969 for (size_t i = 0; i < this->num_nodes; ++i)
970 {
971 auto src = this->nodes->access(i);
972 for (size_t j = 0; j < this->num_nodes; ++j)
973 if (i != j and gsl_rng_uniform(this->r) <= p)
974 {
975 auto tgt = this->nodes->access(j);
976 assert(this->idx_arc->search_directed(src, tgt) == nullptr);
977 this->insert_arc(src, tgt);
978 }
979 }
980
981 if (connected)
982 connect();
983
984 return std::move(this->g);
985 }
986
987 public:
994 Random_Digraph(unsigned long seed,
995 const Init_Node & __init_node,
996 const Init_Arc & __init_arc)
997 : Random_Graph_Base<GT, Init_Node, Init_Arc>(seed, __init_node, __init_arc)
998 {
999 this->g.set_digraph(true);
1000 }
1001
1002 Random_Digraph(unsigned long seed = time(nullptr),
1003 const Init_Node && __init_node = Init_Node(),
1004 const Init_Arc && __init_arc = Init_Arc())
1006 {
1007 // empty
1008 }
1009
1010 Random_Digraph(const Init_Node & __init_node,
1011 const Init_Arc & __init_arc)
1013 {
1014 // empty
1015 }
1016
1018 {
1019 this->g.set_digraph(false);
1020 }
1021
1038 GT operator ()(const size_t & __num_nodes, const size_t & __num_arcs,
1039 bool connected = true)
1040 {
1041 return this->create(__num_nodes, __num_arcs, connected);
1042 }
1043
1068 GT operator ()(const size_t & __num_nodes, const double & p,
1069 bool connected = true)
1070 {
1071 return this->create_p(__num_nodes, p, connected);
1072 }
1073
1074 private:
1075 void make_eulerian() override
1076 {
1077 GT_Node *src = nullptr;
1078 GT_Node *tgt = nullptr;
1079
1080 while (this->greater.size() > 0 and this->smaller.size() > 0)
1081 {
1082 do
1083 {
1084 tgt = this->greater.select
1085 (gsl_rng_uniform_int(this->r, this->greater.size()));
1086 src = this->smaller.select
1087 (gsl_rng_uniform_int(this->r, this->smaller.size()));
1088 }
1089 while (src == tgt);
1090
1091 if (this->idx_arc->search_directed(src, tgt) == nullptr)
1092 this->insert_arc(src, tgt);
1093 else
1094 {
1095 auto mid =
1096 this->equal.select(gsl_rng_uniform_int(this->r,
1097 this->equal.size()));
1098
1099 while (this->idx_arc->search_directed(src, mid) != nullptr or
1100 this->idx_arc->search_directed(mid, tgt) != nullptr)
1101 mid = this->equal.select
1102 (gsl_rng_uniform_int(this->r, this->equal.size()));
1103
1104 this->insert_arc(src, mid);
1105 this->insert_arc(mid, tgt);
1106 }
1107 }
1108 }
1109
1111 {
1112 const size_t & n = this->g.get_num_nodes();
1113 const size_t n2 = n / 2;
1114
1115 while (not (this->g.get_num_arcs(p) >= n2 and NODE_COUNTER(p) >= n2))
1116 {
1117 auto q = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1118 if (q == p)
1119 continue;
1120
1121 if (this->idx_arc->search_directed(p, q) == nullptr)
1122 {
1123 this->insert_arc(p, q);
1124 NODE_COUNTER(q)++;
1125 }
1126
1127 if (this->idx_arc->search_directed(q, p) == nullptr)
1128 {
1129 this->insert_arc(q, p);
1130 NODE_COUNTER(p)++;
1131 }
1132 }
1133 }
1134
1135 // Balance both nodes so they satisfy the Hamiltonian condition.
1136 // If arc src-->tgt exists, balance each node independently.
1138 {
1139 if (this->idx_arc->search_directed(src, tgt) != nullptr)
1140 {
1143
1144 return;
1145 }
1146
1147 const size_t & n = this->g.get_num_nodes();
1148
1149 while (this->g.get_num_arcs(src) + NODE_COUNTER(tgt) < n)
1150 {
1151 auto p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1152 if (p == src or p == tgt)
1153 continue;
1154
1155 if (this->idx_arc->search_directed(src, p) == nullptr)
1156 {
1157 this->insert_arc(src, p);
1158 NODE_COUNTER(p)++;
1159
1160 if (this->g.get_num_arcs(src) + NODE_COUNTER(tgt) == n)
1161 break;
1162 }
1163
1164 if (this->idx_arc->search_directed(p, tgt) == nullptr)
1165 {
1166 this->insert_arc(p, tgt);
1167 NODE_COUNTER(tgt)++;
1168 }
1169 }
1170
1171 assert(this->g.get_num_arcs(src) + NODE_COUNTER(tgt) >= n);
1172 }
1173
1174 void make_hamiltonian() override
1175 {
1176 this->g.reset_counter_nodes();
1177
1178 // compute in-degree for each node
1179 for (typename GT::Arc_Iterator it(this->g); it.has_curr(); it.next_ne())
1180 NODE_COUNTER(it.get_tgt_node_ne())++;
1181
1182 const size_t & n = this->g.get_num_nodes();
1183
1184 for (size_t i = 0; i < n; ++i)
1185 {
1186 auto src = this->nodes->access(i);
1187 for (size_t j = 0; j < n; ++j)
1188 {
1189 if (i == j)
1190 continue;
1191
1192 auto tgt = this->nodes->access(j);
1194 }
1195 }
1196 }
1197 };
1198}
1199
1200# endif // RANDOM_GRAPH_H
Tarjan's algorithm for strongly connected components.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_bad_alloc_if(C)
Throws std::bad_alloc if condition holds.
Definition ah-errors.H:429
T & access(const size_t i) const noexcept
Fast access without checking allocation and bound_min_clock checking.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Iterator on the items of list.
Definition htlist.H:1714
T & get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
Definition htlist.H:1730
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
Dynamic set implemented using randomized binary search trees of type Rand_Tree<Key>.
const size_t & size() const
Returns the cardinality of the set.
Key * insert(const Key &key)
Inserts a key into the dynamic set.
size_t remove(const Key &key)
Removes a key from the dynamic set.
Key * search(const Key &key) const
Find an element in the set.
Key & select(size_t i)
Returns the ith node in infix position.
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
Definition htlist.H:1190
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Random directed graph (digraph) generator.
DynSetRandTree< GT_Node * > equal
DynSetRandTree< GT_Node * > greater
Random_Digraph(const Init_Node &__init_node, const Init_Arc &__init_arc)
DynSetRandTree< GT_Node * > smaller
virtual void update_parity_after_arc_insertion(GT_Node *src, GT_Node *tgt)
GT create_p(const size_t &__num_nodes, const double &p, bool connected) override
GT operator()(const size_t &__num_nodes, const size_t &__num_arcs, bool connected=true)
Create a sparse random digraph.
void balance_digraph_node(GT_Node *p)
void make_hamiltonian() override
void balance_digraph_nodes_degree(GT_Node *src, GT_Node *tgt)
Random_Digraph(unsigned long seed, const Init_Node &__init_node, const Init_Arc &__init_arc)
Constructor.
void connect() override
void make_eulerian() override
void create_nodes_and_initialize_arc_index() override
Random_Digraph(unsigned long seed=time(nullptr), const Init_Node &&__init_node=Init_Node(), const Init_Arc &&__init_arc=Init_Arc())
virtual void create_nodes_and_initialize_arc_index()=0
std::unique_ptr< DynArray< GT_Node * > > nodes
std::unique_ptr< IndexArc< GT > > idx_arc
void initialize_and_create_nodes(const size_t &__num_nodes, const size_t &__num_arcs)
GT create(const size_t &__num_nodes, const size_t &__num_arcs, const bool connected)
Create a sparse random graph.
Random_Graph_Base(const unsigned long seed, const Init_Node &__init_node, const Init_Arc &__init_arc)
GT eulerian(const size_t &__num_nodes, const size_t &__num_arcs)
Create a random Eulerian graph (sparse version).
virtual void make_hamiltonian()=0
virtual void connect()=0
GT_Arc * insert_arc(GT_Node *src, GT_Node *tgt)
virtual void update_parity_after_arc_insertion(GT_Node *src, GT_Node *tgt)=0
GT eulerian(const size_t &__num_nodes, const double &p)
Create a random Eulerian graph (dense version).
virtual GT create_p(const size_t &__num_nodes, const double &p, bool connected)=0
GT_Node * select_random_node(DynList< GT_Node * > &list) noexcept
Select a random node from the given list.
virtual void make_eulerian()=0
GT_Node * select_random_node(GT_Node *excluded=nullptr) noexcept
Select a random node different from excluded.
Random undirected graph generator.
DynSetRandTree< GT_Node * > odd_nodes
virtual void update_parity_after_arc_insertion(GT_Node *src, GT_Node *tgt)
Random_Graph(unsigned long seed=time(nullptr), const Init_Node &&__init_node=Init_Node(), const Init_Arc &&__init_arc=Init_Arc())
void make_hamiltonian() override
Random_Graph(unsigned long seed, const Init_Node &__init_node, const Init_Arc &__init_arc)
Constructor.
GT operator()(const size_t &__num_nodes, const size_t &__num_arcs, bool connected=true)
Create a sparse random graph.
void create_nodes_and_initialize_arc_index() override
GT create_p(const size_t &__num_nodes, const double &p, const bool connected) override
DynSetRandTree< GT_Node * > even_nodes
void balance_graph_nodes_degree(GT_Node *src, GT_Node *tgt)
GT eulerian(const size_t &__num_nodes, const size_t &__num_arcs)
Create a random Eulerian graph (sparse version).
void connect() override
GT eulerian(const size_t &__num_nodes, const double &p)
Create a random Eulerian graph (dense version).
void make_eulerian() override
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:657
void set_digraph(bool val)
Temporal indication for preventing to other algorithms that an graph must be treated as a directed gr...
Definition graph-dry.H:692
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1064
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:778
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#define NODE_COUNTER(p)
Get the counter of a node.
GT sufficient_hamiltonian(const size_t &__num_nodes, const double &p=0.5)
Create a random Hamiltonian graph.
size_t in_degree(typename GT::Node *p, SA sa=SA())
Compute the filtered in degree of node p.
Definition tpl_graph.H:1958
GT sufficient_hamiltonian(const size_t &__num_nodes, const double &p=0.5)
Create a random Hamiltonian graph.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool is_even(const long n)
Return true if n is even.
Definition ahUtils.H:102
DynList< T > maps(const C &c, Op op)
Classic map operation.
Single graph utilities.
Default arc initializer for random graph generation.
void operator()(GT &, typename GT::Arc *) const noexcept
Default node initializer for random graph generation.
void operator()(GT &, typename GT::Node *) const noexcept
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Graph connectivity and connected components.
Utility algorithms and operations for graphs.
Arc indexing for fast lookup by endpoint nodes.