44# ifndef RANDOM_GRAPH_H
45# define RANDOM_GRAPH_H
49# include <gsl/gsl_rng.h>
99 template <AlephGraph GT,
class Init_Node,
class Init_Arc>
111 std::unique_ptr<DynArray<GT_Node *>>
nodes;
161 for (
unsigned long i = 0; i <
k; ++i, it.
next_ne()) {}
174 <<
"Number of nodes must be greater than 0";
209 const bool connected)
214 for (
size_t i = 0; i <
num_arcs; ++i)
218 if (
idx_arc->search(src, tgt) ==
nullptr)
279 g = this->
create_p(__num_nodes, p,
true);
313 const double & p = 0.5)
315 g = this->
create_p(__num_nodes, p,
true);
367 template <AlephGraph
GT,
385 this->odd_nodes.
remove(src);
386 this->even_nodes.
insert(src);
390 this->even_nodes.
remove(src);
391 this->odd_nodes.
insert(src);
396 this->odd_nodes.
remove(tgt);
397 this->even_nodes.
insert(tgt);
401 this->even_nodes.
remove(tgt);
402 this->odd_nodes.
insert(tgt);
408 this->
nodes = std::unique_ptr<DynArray<GT_Node *>>
413 for (
size_t i = 0; i < this->
num_nodes; ++i)
416 this->
nodes->access(i) = p;
420 this->even_nodes.
insert(p);
442 it.has_curr(); it.next_ne())
445 for (
size_t i = 1; i <
num_subs; ++i)
456 const bool connected)
override
462 for (
size_t i = 0; i + 1 < this->
num_nodes; ++i)
464 auto src = this->
nodes->access(i);
465 for (
size_t j = i + 1; j < this->
num_nodes; ++j)
468 auto tgt = this->
nodes->access(j);
477 return std::move(this->
g);
493 <<
"Building of random digraph through a graph";
502 <<
"Building of random digraph through a graph";
523 bool connected =
true)
552 bool connected =
true)
560 while (this->odd_nodes.
size() > 1)
567 src = this->odd_nodes.
select
570 tgt = this->odd_nodes.
select
574 if (this->
idx_arc->search(src, tgt) ==
nullptr)
576 else if (this->odd_nodes.
size() == 2)
580 p = this->even_nodes.
select
582 while (this->
idx_arc->search(src, p) !=
nullptr or
583 this->idx_arc->search(tgt, p) !=
nullptr);
599 if (this->
idx_arc->search(src, tgt) ==
nullptr)
607 if (p == src
or p == tgt)
610 if (this->
idx_arc->search(src, p) ==
nullptr)
616 if (this->
idx_arc->search(tgt, p) ==
nullptr)
624 for (
size_t i = 0; i + 1 < n; ++i)
626 auto src = this->
nodes->access(i);
627 for (
size_t j = i + 1; j < n; ++j)
653 return std::move(this->
g);
676 this->
g = this->
create_p(__num_nodes, p,
true);
679 return std::move(this->
g);
710 const double & p = 0.5)
712 this->
g = this->
create_p(__num_nodes, p,
true);
715 return std::move(this->
g);
738 template <AlephGraph
GT,
752 const size_t & n = this->
nodes->size();
755 std::cout <<
"Warning num of nodes of graph does not match with array "
760 std::cout <<
"Inconsistency with nodes parity" << std::endl
761 <<
"greater = " <<
greater.size() << std::endl
763 <<
"equal = " <<
equal.
size() << std::endl
764 <<
"total = " <<
total << std::endl
767 for (
size_t i = 0; i < n; ++i)
769 auto p = this->
nodes->access(i);
777 std::cout <<
"Inconsistency " <<
in_sz <<
"/" <<
out_sz <<
" found "
778 <<
" in smaller table" << std::endl;
780 if (
greater.search(p) !=
nullptr)
781 std::cout <<
"Inconsistency " <<
in_sz <<
"/" <<
out_sz <<
" found "
782 <<
" in greater table" << std::endl;
786 std::cout <<
"node of same in/out degree is not in equal table"
794 if (
greater.search(p) !=
nullptr)
795 std::cout <<
"Inconsistency " <<
in_sz <<
"/" <<
out_sz <<
" found "
796 <<
" in greater table" << std::endl;
799 std::cout <<
"Inconsistency " <<
in_sz <<
"/" <<
out_sz <<
" found "
804 std::cout <<
"node with " <<
in_sz <<
"/" <<
out_sz <<
" not found "
805 <<
"smaller table" << std::endl;
813 std::cout <<
"Inconsistency " <<
in_sz <<
"/" <<
out_sz <<
" found "
814 <<
" in smaller table" << std::endl;
817 std::cout <<
"Inconsistency " <<
in_sz <<
"/" <<
out_sz <<
" found "
820 if (
greater.search(p) ==
nullptr)
822 std::cout <<
"node with " <<
in_sz <<
"/" <<
out_sz <<
" not found "
823 <<
"greater table" << std::endl;
846 this->smaller.
remove(src);
854 this->greater.
insert(src);
867 this->greater.
remove(tgt);
877 this->smaller.
insert(tgt);
887 this->
nodes = std::unique_ptr<DynArray<GT_Node *>>
892 for (
size_t i = 0; i < this->
num_nodes; ++i)
895 this->
nodes->access(i) = p;
916 typename GT::Node_Iterator it(this->
g);
917 for (
int i = 0; it.has_curr(); it.next_ne(), ++i)
923 for (
size_t i = 0; it.has_curr(); it.next_ne(), ++i)
927 const size_t & num_blocks =
blk_list.size();
938 for (
size_t i = 0; it.has_curr(); it.next_ne(), ++i)
946 for (
size_t i = 0; i + 1 < num_blocks; ++i)
949 auto tgt = b1.
access((i + 1) % num_blocks);
951 if (this->
idx_arc->search_directed(src, tgt) ==
nullptr)
955 tgt = b2.
access((i + 1) % num_blocks);
957 if (this->
idx_arc->search_directed(tgt, src) ==
nullptr)
965 bool connected)
override
971 for (
size_t i = 0; i < this->
num_nodes; ++i)
973 auto src = this->
nodes->access(i);
974 for (
size_t j = 0; j < this->
num_nodes; ++j)
977 auto tgt = this->
nodes->access(j);
986 return std::move(this->
g);
1041 bool connected =
true)
1071 bool connected =
true)
1073 return this->
create_p(__num_nodes, p, connected);
1082 while (this->greater.
size() > 0
and this->smaller.size() > 0)
1086 tgt = this->greater.
select
1088 src = this->smaller.
select
1093 if (this->
idx_arc->search_directed(src, tgt) ==
nullptr)
1099 this->equal.
size()));
1101 while (this->
idx_arc->search_directed(src,
mid) !=
nullptr or
1102 this->idx_arc->search_directed(
mid, tgt) !=
nullptr)
1115 const size_t n2 = n / 2;
1123 if (this->
idx_arc->search_directed(p, q) ==
nullptr)
1129 if (this->
idx_arc->search_directed(q, p) ==
nullptr)
1141 if (this->
idx_arc->search_directed(src, tgt) !=
nullptr)
1154 if (p == src
or p == tgt)
1157 if (this->
idx_arc->search_directed(src, p) ==
nullptr)
1166 if (this->
idx_arc->search_directed(p, tgt) ==
nullptr)
1181 for (
typename GT::Arc_Iterator it(this->
g); it.has_curr(); it.next_ne())
1186 for (
size_t i = 0; i < n; ++i)
1188 auto src = this->
nodes->access(i);
1189 for (
size_t j = 0; j < n; ++j)
1194 auto tgt = this->
nodes->access(j);
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.
#define ah_bad_alloc_if(C)
Throws std::bad_alloc if condition holds.
C++20 concepts for the protocol shared by graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
void insert(Dlink *node) noexcept
Insert node after this.
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.
T & get_curr_ne() const noexcept
Return the current link guaranteeing no exception. Be careful.
Doubly-linked list (defined in tpl_dynList.H).
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.
size_t size() const noexcept
Count the number of elements of the list.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
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 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
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 ~Random_Graph_Base()
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).
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.
bool is_digraph() const noexcept
Return true if the graph this is directed.
void set_digraph(bool val)
Temporal indication for preventing to other algorithms that an graph must be treated as a directed gr...
void reset_counter_nodes() const noexcept
Reset all the counters to zero for all the nodes of graph.
constexpr size_t get_num_arcs() const noexcept
#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.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
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.
and
Check uniqueness with explicit hash + equality functors.
bool is_even(const long n)
Return true if n is even.
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
Graph connectivity and connected components.
Utility algorithms and operations for graphs.
Arc indexing for fast lookup by endpoint nodes.