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 <ah-graph-concepts.H>
48
49# include <gsl/gsl_rng.h>
50# include <memory>
51# include <tpl_indexArc.H>
52# include <tpl_graph_utils.H>
53# include <tpl_components.H>
54# include <single_graph.H>
55# include <Tarjan.H>
56# include <ah-errors.H>
57
58namespace Aleph
59{
69 template <class GT>
71 {
72 void operator ()(GT &, typename GT::Node *) const noexcept
73 {
74 // empty
75 }
76 };
77
78
88 template <class GT>
90 {
91 void operator ()(GT &, typename GT::Arc *) const noexcept
92 {
93 // empty
94 }
95 };
96
97 // TODO: consider replacing Init_Node and Init_Arc classes with lambdas
98
99 template <AlephGraph GT, class Init_Node, class Init_Arc>
101 {
102 protected:
103 typedef typename GT::Node GT_Node;
104 typedef typename GT::Arc GT_Arc;
105
107
108 Init_Node & init_node;
110
111 std::unique_ptr<DynArray<GT_Node *>> nodes; // pointer to save directory
112 // space when not used
113
114 std::unique_ptr<IndexArc<GT>> idx_arc; // pointer because constructor
115 // requires the graph
116 mutable size_t num_nodes;
117 mutable size_t num_arcs;
118 mutable unsigned long rand_max;
119
121
122 bool save_parity; // indicates whether to track parity relations
123 // among nodes (only for building Eulerian
124 // and Hamiltonian graphs)
125
126 virtual void
128
130 {
131 auto a = idx_arc->insert(g.insert_arc(src, tgt));
132 init_arc(g, a);
134 return a;
135 }
136
139 {
140 assert(nodes.get() != nullptr);
141 assert(num_nodes > 0);
142 assert(excluded == nullptr or num_nodes > 1); // avoid infinite loop
143
144 GT_Node *ret_val = nullptr;
145 while (true)
146 {
147 unsigned long idx = gsl_rng_uniform_int(r, num_nodes);
148 ret_val = nodes->access(idx);
149 if (excluded == nullptr or ret_val != excluded)
150 break;
151 }
152
153 return ret_val;
154 }
155
158 {
159 const unsigned long k = gsl_rng_uniform_int(r, list.size());
160 typename DynList<GT_Node *>::Iterator it(list);
161 for (unsigned long i = 0; i < k; ++i, it.next_ne()) {}
162
163 return it.get_curr_ne();
164 }
165
167
168 virtual void connect() = 0;
169
171 const size_t & __num_arcs)
172 {
174 << "Number of nodes must be greater than 0";
175
177
178 const size_t num_nodes_2 = num_nodes * num_nodes;
179 if (g.is_digraph())
181 else
182 num_arcs = std::min(__num_arcs, (num_nodes_2 - num_nodes) / 2);
183
185 }
186
187 Random_Graph_Base(const unsigned long seed,
188 const Init_Node & __init_node,
189 const Init_Arc & __init_arc)
191 init_node(const_cast<Init_Node &>(__init_node)),
193 num_nodes(0), num_arcs(0),
195 {
196 ah_bad_alloc_if(r == nullptr);
197
199 }
200
202 {
203 if (r != nullptr)
205 }
206
208 GT create(const size_t & __num_nodes, const size_t & __num_arcs,
209 const bool connected)
210 {
212
213 // randomly insert arcs by selecting random node pairs
214 for (size_t i = 0; i < num_arcs; ++i)
215 {
216 auto src = select_random_node();
217 auto tgt = select_random_node(src);
218 if (idx_arc->search(src, tgt) == nullptr) // arc already exists?
219 insert_arc(src, tgt);
220 }
221
222 if (connected)
223 connect();
224
225 return std::move(g);
226 }
227
228 virtual GT create_p(const size_t & __num_nodes, const double & p,
229 bool connected) = 0;
230
231 virtual void make_eulerian() = 0;
232
233 virtual void make_hamiltonian() = 0;
234
235 public:
250 GT eulerian(const size_t & __num_nodes, const size_t & __num_arcs)
251 {
252 save_parity = true;
253 g = this->create(__num_nodes, __num_arcs, true);
255
256 return std::move(g);
257 }
258
276 GT eulerian(const size_t & __num_nodes, const double & p)
277 {
278 save_parity = true;
279 g = this->create_p(__num_nodes, p, true);
281
282 return std::move(g);
283 }
284
313 const double & p = 0.5)
314 {
315 g = this->create_p(__num_nodes, p, true);
317
318 return std::move(g);
319 }
320 };
321
322
367 template <AlephGraph GT,
368 class Init_Node = Dft_Init_Rand_Node<GT>,
370 class Random_Graph : public Random_Graph_Base<GT, Init_Node, Init_Arc>
371 {
372 typedef typename GT::Node GT_Node;
373 typedef typename GT::Arc GT_Arc;
374
375 DynSetRandTree<GT_Node *> odd_nodes; // nodes with odd degree
376 DynSetRandTree<GT_Node *> even_nodes; // nodes with even degree
377
379 {
380 if (not this->save_parity)
381 return;
382
383 if (is_even(this->g.get_num_arcs(src)))
384 { // was odd before the insertion
385 this->odd_nodes.remove(src);
386 this->even_nodes.insert(src);
387 }
388 else
389 {
390 this->even_nodes.remove(src);
391 this->odd_nodes.insert(src);
392 }
393
394 if (is_even(this->g.get_num_arcs(tgt)))
395 { // was odd before the insertion
396 this->odd_nodes.remove(tgt);
397 this->even_nodes.insert(tgt);
398 }
399 else
400 {
401 this->even_nodes.remove(tgt);
402 this->odd_nodes.insert(tgt);
403 }
404 }
405
407 {
408 this->nodes = std::unique_ptr<DynArray<GT_Node *>>
409 (new DynArray<GT_Node *>(this->num_nodes));
410
411 this->nodes->reserve(this->num_nodes);
412
413 for (size_t i = 0; i < this->num_nodes; ++i)
414 {
415 auto p = this->g.insert_node(new GT_Node);
416 this->nodes->access(i) = p;
417 this->init_node(this->g, p);
418 if (this->save_parity)
419 {
420 this->even_nodes.insert(p);
421 NODE_COUNTER(p) = 0;
422 }
423 }
424
425 this->idx_arc = std::unique_ptr<IndexArc<GT>>(new IndexArc<GT>(this->g));
426 }
427
428 void connect() override
429 {
430 DynList<DynList<GT_Node *>> subgraphs; // list of subgraphs
431
433
434 const size_t & num_subs = subgraphs.size();
435
436 if (num_subs == 1)
437 return;
438
440
441 for (typename DynList<DynList<GT_Node *>>::Iterator it(subgraphs);
442 it.has_curr(); it.next_ne())
443 block_nodes.append(this->select_random_node(it.get_curr_ne()));
444
445 for (size_t i = 1; i < num_subs; ++i)
446 {
447 auto src = block_nodes.access(i - 1);
448 auto tgt = block_nodes.access(i);
449 this->insert_arc(src, tgt);
450 }
451 }
452
453 // Create a random graph where the probability of an arc between
454 // any pair of nodes is p
455 GT create_p(const size_t & __num_nodes, const double & p,
456 const bool connected) override
457 {
458 ah_domain_error_if(p > 1.0 or p <= 0.0) << "Invalid value for p";
459
460 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
461
462 for (size_t i = 0; i + 1 < this->num_nodes; ++i)
463 {
464 auto src = this->nodes->access(i);
465 for (size_t j = i + 1; j < this->num_nodes; ++j)
466 if (gsl_rng_uniform(this->r) <= p) // random draw
467 {
468 auto tgt = this->nodes->access(j);
469 assert(src != tgt);
470 this->insert_arc(src, tgt);
471 }
472 }
473
474 if (connected)
475 connect();
476
477 return std::move(this->g);
478 }
479
480 public:
487 Random_Graph(unsigned long seed,
488 const Init_Node & __init_node,
489 const Init_Arc & __init_arc)
491 {
493 << "Building of random digraph through a graph";
494 }
495
496 Random_Graph(unsigned long seed = time(nullptr),
497 const Init_Node && __init_node = Init_Node(),
498 const Init_Arc && __init_arc = Init_Arc())
500 {
502 << "Building of random digraph through a graph";
503 }
504
505
522 GT operator ()(const size_t & __num_nodes, const size_t & __num_arcs,
523 bool connected = true)
524 {
525 return this->create(__num_nodes, __num_arcs, connected);
526 }
527
551 GT operator ()(const size_t & __num_nodes, const double & p,
552 bool connected = true)
553 {
554 return create_p(__num_nodes, p, connected);
555 }
556
557 private:
558 void make_eulerian() override
559 {
560 while (this->odd_nodes.size() > 1)
561 {
562 GT_Node *src = nullptr;
563 GT_Node *tgt = nullptr;
564
565 while (true)
566 {
567 src = this->odd_nodes.select
568 (gsl_rng_uniform_int(this->r, this->odd_nodes.size()));
569 do
570 tgt = this->odd_nodes.select
571 (gsl_rng_uniform_int(this->r, this->odd_nodes.size()));
572 while (tgt == src);
573
574 if (this->idx_arc->search(src, tgt) == nullptr)
575 break;
576 else if (this->odd_nodes.size() == 2)
577 { // select random node that has no arc to src or tgt
578 GT_Node *p = nullptr;
579 do
580 p = this->even_nodes.select
581 (gsl_rng_uniform_int(this->r, this->even_nodes.size()));
582 while (this->idx_arc->search(src, p) != nullptr or
583 this->idx_arc->search(tgt, p) != nullptr);
584 this->insert_arc(src, p);
585 this->insert_arc(p, tgt);
586
587 return;
588 }
589 }
590
591 this->insert_arc(src, tgt);
592 }
593
594 assert(this->odd_nodes.size() == 0);
595 }
596
598 {
599 if (this->idx_arc->search(src, tgt) == nullptr)
600 this->insert_arc(src, tgt);
601
602 const size_t & n = this->g.get_num_nodes();
603
604 while (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) < n)
605 {
606 auto p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
607 if (p == src or p == tgt)
608 continue;
609
610 if (this->idx_arc->search(src, p) == nullptr)
611 this->insert_arc(src, p);
612
613 if (this->g.get_num_arcs(src) + this->g.get_num_arcs(tgt) == n)
614 break;
615
616 if (this->idx_arc->search(tgt, p) == nullptr)
617 this->insert_arc(tgt, p);
618 }
619 }
620
621 void make_hamiltonian() override
622 {
623 const size_t & n = this->g.get_num_nodes();
624 for (size_t i = 0; i + 1 < n; ++i)
625 {
626 auto src = this->nodes->access(i);
627 for (size_t j = i + 1; j < n; ++j)
628 balance_graph_nodes_degree(src, this->nodes->access(j));
629 }
630 }
631
632 public:
647 GT eulerian(const size_t & __num_nodes, const size_t & __num_arcs)
648 {
649 this->save_parity = true;
650 this->g = this->create(__num_nodes, __num_arcs, true);
652
653 return std::move(this->g);
654 }
655
673 GT eulerian(const size_t & __num_nodes, const double & p)
674 {
675 this->save_parity = true;
676 this->g = this->create_p(__num_nodes, p, true);
678
679 return std::move(this->g);
680 }
681
710 const double & p = 0.5)
711 {
712 this->g = this->create_p(__num_nodes, p, true);
714
715 return std::move(this->g);
716 }
717 };
718
719
738 template <AlephGraph GT,
739 class Init_Node = Dft_Init_Rand_Node<GT>,
741 class Random_Digraph : public Random_Graph_Base<GT, Init_Node, Init_Arc>
742 {
743 typedef typename GT::Node GT_Node;
744 typedef typename GT::Arc GT_Arc;
745
746 DynSetRandTree<GT_Node *> greater; // nodes with out-degree > in-degree
747 DynSetRandTree<GT_Node *> smaller; // nodes with out-degree < in-degree
748 DynSetRandTree<GT_Node *> equal; // nodes with out-degree == in-degree
749
751 {
752 const size_t & n = this->nodes->size();
753
754 if (n != this->g.get_num_nodes())
755 std::cout << "Warning num of nodes of graph does not match with array "
756 << this->g.get_num_nodes() << "!=" << n << std::endl;
757
758 size_t total = greater.size() + smaller.size() + equal.size();
759 if (total != this->g.get_num_nodes())
760 std::cout << "Inconsistency with nodes parity" << std::endl
761 << "greater = " << greater.size() << std::endl
762 << "smaller = " << smaller.size() << std::endl
763 << "equal = " << equal.size() << std::endl
764 << "total = " << total << std::endl
765 << "|V| = " << this->g.get_num_nodes();
766
767 for (size_t i = 0; i < n; ++i)
768 {
769 auto p = this->nodes->access(i);
770
771 const long & in_sz = NODE_COUNTER(p);
772 const size_t & out_sz = this->g.get_num_arcs(p);
773
774 if (in_sz == out_sz)
775 {
776 if (smaller.search(p) != nullptr)
777 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
778 << " in smaller table" << std::endl;
779
780 if (greater.search(p) != nullptr)
781 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
782 << " in greater table" << std::endl;
783
784 if (equal.search(p) == nullptr)
785 {
786 std::cout << "node of same in/out degree is not in equal table"
787 << std::endl;
788
789 return false;
790 }
791 }
792 else if (in_sz > out_sz)
793 {
794 if (greater.search(p) != nullptr)
795 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
796 << " in greater table" << std::endl;
797
798 if (equal.search(p) != nullptr)
799 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
800 << std::endl;
801
802 if (smaller.search(p) == nullptr)
803 {
804 std::cout << "node with " << in_sz << "/" << out_sz << " not found "
805 << "smaller table" << std::endl;
806
807 return false;
808 }
809 }
810 else
811 {
812 if (smaller.search(p) != nullptr)
813 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
814 << " in smaller table" << std::endl;
815
816 if (equal.search(p) != nullptr)
817 std::cout << "Inconsistency " << in_sz << "/" << out_sz << " found "
818 << std::endl;
819
820 if (greater.search(p) == nullptr)
821 {
822 std::cout << "node with " << in_sz << "/" << out_sz << " not found "
823 << "greater table" << std::endl;
824
825 return false;
826 }
827 }
828 }
829
830 return true;
831 }
832
833 // This call is made right after inserting a new arc src-->tgt.
834 // This implies that out(src) is updated, but in(tgt) is not.
836 {
837 if (not this->save_parity)
838 return;
839
840 const size_t & src_out_degree = this->g.get_num_arcs(src);
841 const long & src_in_degree = NODE_COUNTER(src);
842
844 { // src is in greater ==> remove it and insert into equal
845 assert(this->smaller.search(src) != nullptr);
846 this->smaller.remove(src);
847 this->equal.insert(src);
848 }
849 else if (src_out_degree > src_in_degree)
850 if (src_out_degree == src_in_degree + 1)
851 {
852 assert(this->equal.search(src) != nullptr);
853 this->equal.remove(src);
854 this->greater.insert(src);
855 }
856 else
857 assert(this->greater.search(src) != nullptr);
858 else // src_out_degree < src_in_degree
859 assert(this->smaller.search(src) != nullptr);
860
861 const size_t & tgt_out_degree = this->g.get_num_arcs(tgt);
862 const long tgt_in_degree = ++NODE_COUNTER(tgt);
863
865 {
866 assert(this->greater.search(tgt));
867 this->greater.remove(tgt);
868 this->equal.insert(tgt);
869 }
870 else if (tgt_out_degree > tgt_in_degree)
871 assert(this->greater.search(tgt));
872 else // (tgt_out_degree < tgt_in_degree)
873 {
874 if (tgt_in_degree - 1 == tgt_out_degree)
875 { // tgt is in equal ==> remove it
876 assert(this->equal.search(tgt) != nullptr);
877 this->smaller.insert(tgt);
878 this->equal.remove(tgt);
879 }
880 else
881 assert(this->smaller.search(tgt) != nullptr);
882 }
883 }
884
886 {
887 this->nodes = std::unique_ptr<DynArray<GT_Node *>>
888 (new DynArray<GT_Node *>(this->num_nodes));
889
890 this->nodes->reserve(this->num_nodes);
891
892 for (size_t i = 0; i < this->num_nodes; ++i)
893 {
894 typename GT::Node *p = this->g.insert_node(new GT_Node);
895 this->nodes->access(i) = p;
896 this->init_node(this->g, p);
897
898 if (this->save_parity)
899 {
900 NODE_COUNTER(p) = 0;
901 this->equal.insert(p);
902 }
903 }
904
905 this->idx_arc = std::unique_ptr<IndexArc<GT>>(new IndexArc<GT>(this->g));
906 }
907
908 void connect() override
909 {
910 DynList<DynList<typename GT::Node *>> blk_list; // disconnected subgraphs
911
912 { // save in-degrees since Tarjan's algorithm will modify them
915
916 typename GT::Node_Iterator it(this->g);
917 for (int i = 0; it.has_curr(); it.next_ne(), ++i)
918 in_degree.access(i) = NODE_COUNTER(it.get_curr_ne());
919
921
922 it.reset_first(); // restore in-degrees
923 for (size_t i = 0; it.has_curr(); it.next_ne(), ++i)
924 NODE_COUNTER(it.get_curr_ne()) = in_degree.access(i);
925 }
926
927 const size_t & num_blocks = blk_list.size();
928
929 if (num_blocks == 1)
930 return;
931
932 // each node in this list is a randomly selected node from block i
934 b1.reserve(num_blocks);
936 b2.reserve(num_blocks); {
937 typename DynList<DynList<GT_Node *>>::Iterator it(blk_list);
938 for (size_t i = 0; it.has_curr(); it.next_ne(), ++i)
939 { // select two random nodes from the current component
940 DynList<typename GT::Node *> & list = it.get_curr_ne();
941 b1.access(i) = this->select_random_node(list);
942 b2.access(i) = this->select_random_node(list);
943 }
944 }
945
946 for (size_t i = 0; i + 1 < num_blocks; ++i)
947 {
948 auto src = b1.access(i); // node in block i
949 auto tgt = b1.access((i + 1) % num_blocks); // node in block i + 1
950
951 if (this->idx_arc->search_directed(src, tgt) == nullptr)
952 this->insert_arc(src, tgt);
953
954 src = b2.access(i); // node in block i
955 tgt = b2.access((i + 1) % num_blocks); // node in block i + 1
956
957 if (this->idx_arc->search_directed(tgt, src) == nullptr)
958 this->insert_arc(tgt, src);
959 }
960 }
961
962 // Create a random graph where the probability of an arc between
963 // any pair of nodes is p
964 GT create_p(const size_t & __num_nodes, const double & p,
965 bool connected) override
966 {
967 ah_domain_error_if(p > 1.0 or p <= 0.0) << "Invalid value for p";
968
969 this->initialize_and_create_nodes(__num_nodes, __num_nodes);
970
971 for (size_t i = 0; i < this->num_nodes; ++i)
972 {
973 auto src = this->nodes->access(i);
974 for (size_t j = 0; j < this->num_nodes; ++j)
975 if (i != j and gsl_rng_uniform(this->r) <= p)
976 {
977 auto tgt = this->nodes->access(j);
978 assert(this->idx_arc->search_directed(src, tgt) == nullptr);
979 this->insert_arc(src, tgt);
980 }
981 }
982
983 if (connected)
984 connect();
985
986 return std::move(this->g);
987 }
988
989 public:
996 Random_Digraph(unsigned long seed,
997 const Init_Node & __init_node,
998 const Init_Arc & __init_arc)
1000 {
1001 this->g.set_digraph(true);
1002 }
1003
1004 Random_Digraph(unsigned long seed = time(nullptr),
1005 const Init_Node && __init_node = Init_Node(),
1006 const Init_Arc && __init_arc = Init_Arc())
1008 {
1009 // empty
1010 }
1011
1012 Random_Digraph(const Init_Node & __init_node,
1013 const Init_Arc & __init_arc)
1015 {
1016 // empty
1017 }
1018
1020 {
1021 this->g.set_digraph(false);
1022 }
1023
1040 GT operator ()(const size_t & __num_nodes, const size_t & __num_arcs,
1041 bool connected = true)
1042 {
1043 return this->create(__num_nodes, __num_arcs, connected);
1044 }
1045
1070 GT operator ()(const size_t & __num_nodes, const double & p,
1071 bool connected = true)
1072 {
1073 return this->create_p(__num_nodes, p, connected);
1074 }
1075
1076 private:
1077 void make_eulerian() override
1078 {
1079 GT_Node *src = nullptr;
1080 GT_Node *tgt = nullptr;
1081
1082 while (this->greater.size() > 0 and this->smaller.size() > 0)
1083 {
1084 do
1085 {
1086 tgt = this->greater.select
1087 (gsl_rng_uniform_int(this->r, this->greater.size()));
1088 src = this->smaller.select
1089 (gsl_rng_uniform_int(this->r, this->smaller.size()));
1090 }
1091 while (src == tgt);
1092
1093 if (this->idx_arc->search_directed(src, tgt) == nullptr)
1094 this->insert_arc(src, tgt);
1095 else
1096 {
1097 auto mid =
1098 this->equal.select(gsl_rng_uniform_int(this->r,
1099 this->equal.size()));
1100
1101 while (this->idx_arc->search_directed(src, mid) != nullptr or
1102 this->idx_arc->search_directed(mid, tgt) != nullptr)
1103 mid = this->equal.select
1104 (gsl_rng_uniform_int(this->r, this->equal.size()));
1105
1106 this->insert_arc(src, mid);
1107 this->insert_arc(mid, tgt);
1108 }
1109 }
1110 }
1111
1113 {
1114 const size_t & n = this->g.get_num_nodes();
1115 const size_t n2 = n / 2;
1116
1117 while (not (this->g.get_num_arcs(p) >= n2 and NODE_COUNTER(p) >= n2))
1118 {
1119 auto q = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1120 if (q == p)
1121 continue;
1122
1123 if (this->idx_arc->search_directed(p, q) == nullptr)
1124 {
1125 this->insert_arc(p, q);
1126 NODE_COUNTER(q)++;
1127 }
1128
1129 if (this->idx_arc->search_directed(q, p) == nullptr)
1130 {
1131 this->insert_arc(q, p);
1132 NODE_COUNTER(p)++;
1133 }
1134 }
1135 }
1136
1137 // Balance both nodes so they satisfy the Hamiltonian condition.
1138 // If arc src-->tgt exists, balance each node independently.
1140 {
1141 if (this->idx_arc->search_directed(src, tgt) != nullptr)
1142 {
1145
1146 return;
1147 }
1148
1149 const size_t & n = this->g.get_num_nodes();
1150
1151 while (this->g.get_num_arcs(src) + NODE_COUNTER(tgt) < n)
1152 {
1153 auto p = this->nodes->access(gsl_rng_uniform_int(this->r, n));
1154 if (p == src or p == tgt)
1155 continue;
1156
1157 if (this->idx_arc->search_directed(src, p) == nullptr)
1158 {
1159 this->insert_arc(src, p);
1160 NODE_COUNTER(p)++;
1161
1162 if (this->g.get_num_arcs(src) + NODE_COUNTER(tgt) == n)
1163 break;
1164 }
1165
1166 if (this->idx_arc->search_directed(p, tgt) == nullptr)
1167 {
1168 this->insert_arc(p, tgt);
1169 NODE_COUNTER(tgt)++;
1170 }
1171 }
1172
1173 assert(this->g.get_num_arcs(src) + NODE_COUNTER(tgt) >= n);
1174 }
1175
1176 void make_hamiltonian() override
1177 {
1178 this->g.reset_counter_nodes();
1179
1180 // compute in-degree for each node
1181 for (typename GT::Arc_Iterator it(this->g); it.has_curr(); it.next_ne())
1182 NODE_COUNTER(it.get_tgt_node_ne())++;
1183
1184 const size_t & n = this->g.get_num_nodes();
1185
1186 for (size_t i = 0; i < n; ++i)
1187 {
1188 auto src = this->nodes->access(i);
1189 for (size_t j = 0; j < n; ++j)
1190 {
1191 if (i == j)
1192 continue;
1193
1194 auto tgt = this->nodes->access(j);
1196 }
1197 }
1198 }
1199 };
1200}
1201
1202# 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:527
#define ah_bad_alloc_if(C)
Throws std::bad_alloc if condition holds.
Definition ah-errors.H:434
C++20 concepts for the protocol shared by graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
T & access(const size_t i) const noexcept
Fast access without checking allocation and bound_min_clock checking.
T & append()
Allocate a new entry to the end of array.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Iterator on the items of list.
Definition htlist.H:1420
T & get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
Definition htlist.H:1436
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
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:965
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1065
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:525
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:605
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:737
bool is_digraph() const noexcept
Return true if the graph this is directed.
Definition graph-dry.H:699
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:734
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
Definition graph-dry.H:1112
constexpr size_t get_num_arcs() const noexcept
Definition graph-dry.H:826
#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:2040
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
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
and
Check uniqueness with explicit hash + equality functors.
bool is_even(const long n)
Return true if n is even.
Definition ahUtils.H:105
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
ValueArg< size_t > seed
Definition testHash.C:53
static int * k
Graph connectivity and connected components.
Utility algorithms and operations for graphs.
Arc indexing for fast lookup by endpoint nodes.