1#ifndef UTOPIA_CORE_GRAPH_CREATION_HH
2#define UTOPIA_CORE_GRAPH_CREATION_HH
8#include <boost/graph/adjacency_list.hpp>
9#include <boost/graph/adjacency_matrix.hpp>
10#include <boost/graph/small_world_generator.hpp>
11#include <boost/graph/random.hpp>
12#include <boost/property_map/dynamic_property_map.hpp>
14#include <spdlog/spdlog.h>
42template <
typename Graph>
46 using namespace boost;
103template<
typename Graph,
typename RNG>
115 if (boost::is_directed(
g)) {
125 boost::generate_random_graph(
g,
153template <
typename Graph>
159 using namespace boost;
169 throw std::invalid_argument(
"For undirected regular graphs, the mean "
170 "degree needs to be even!");
173 else if (is_directed(
g) && !
oriented &&
k % 2){
174 throw std::invalid_argument(
"For directed regular graphs, the mean "
175 "degree can only be uneven if the graph is oriented! Set "
176 "'oriented = true', or choose an even mean degree.");
243template <
typename Graph,
typename RNG>
249 using vertex_size_type =
typename boost::graph_traits<Graph>::vertices_size_type;
250 using vertex_desc_type =
typename boost::graph_traits<Graph>::vertex_descriptor;
251 using namespace boost;
253 if (
mu > 1.
or mu < 0.) {
254 throw std::invalid_argument(
"The parameter 'mu' must be a probability!");
257 throw std::invalid_argument(
"This algorithm requires a mean degree of"
267 std::uniform_real_distribution<double>
distr(0, 1);
277 const std::size_t
m = [&]() -> std::size_t {
284 return std::round(
a);
295 const auto log = spdlog::get(
"core");
297 throw std::runtime_error(
298 "Logger 'core' was not set up but is needed for "
299 "Utopia::Graph::create_KlemmEguiluz_graph !"
311 log->info(
"The desired mean degree of this graph is {}; the actual mean"
316 std::vector<vertex_desc_type>
actives;
327 std::deque<vertex_desc_type>());
367 else if (
mu == 1
and is_directed(
g)){
374 auto get_degree = [&](
const size_t norm) -> std::pair<std::size_t, std::size_t>
378 std::pair<std::size_t, size_t>
res = {0, 0};
394 const auto v = vertex(
n,
g);
395 for (std::size_t
i = 0;
i <
m; ++
i) {
401 while (
w ==
v or edge(
v,
w,
g).second){
420 [](
const auto&
a,
const auto&
b) ->
bool {
421 return a.first < b.first;
452 std::size_t
norm = 0;
456 const auto v = vertex(
n,
g);
504 [](
const auto&
a,
const auto&
b) ->
bool {
505 return a.first < b.first;
557 [](
const auto&
a,
const auto&
b) ->
bool {
558 return a.first < b.first;
604template <
typename Graph,
typename RNG>
611 typename boost::graph_traits<Graph>::vertex_descriptor;
624 boost::add_vertex(
g);
625 for (
unsigned v1 = 0; v1 <
v0; ++v1){
626 boost::add_edge(boost::vertex(
v0,
g), boost::vertex(v1,
g),
g);
642 std::size_t
counter = boost::num_vertices(
g);
698template <
typename Graph,
typename RNG>
713 if (boost::is_directed(
g)){
714 throw std::runtime_error(
"This scale-free generator algorithm "
715 "only works for undirected graphs! "
716 "But the provided graph is directed.");
719 throw std::invalid_argument(
"The mean degree has to be smaller than "
720 "the total number of vertices!");
723 throw std::invalid_argument(
"The mean degree needs to be even but "
724 "is not an even number!");
763template <
typename Graph,
typename RNG>
777 > std::numeric_limits<double>::epsilon()) {
778 throw std::invalid_argument(
"The probabilities alpha, beta and gamma "
779 "have to add up to 1!");
781 if (
not boost::is_directed(
g)) {
782 throw std::runtime_error(
"This algorithm only works for directed "
783 "graphs but the graph type specifies an "
784 "undirected graph!");
787 throw std::invalid_argument(
"The probability beta must not be 1!");
791 const auto v0 = boost::add_vertex(
g);
792 const auto v1 = boost::add_vertex(
g);
793 const auto v2 = boost::add_vertex(
g);
794 boost::add_edge(
v0, v1,
g);
795 boost::add_edge(v1, v2,
g);
796 boost::add_edge(v2,
v0,
g);
798 std::uniform_real_distribution<>
distr(0, 1);
811 auto v = boost::vertex(0,
g);
812 auto w = boost::vertex(0,
g);
825 const auto r =
distr(rng);
835 v = boost::add_vertex(
g);
881 const auto r =
distr(rng);
891 w = boost::add_vertex(
g);
895 boost::add_edge(
v,
w,
g);
923template <
typename Graph,
typename RNG>
930 using namespace boost;
938 std::uniform_real_distribution<double>
distr(0, 1);
947 throw std::invalid_argument(
"For undirected Watts-Strogatz graphs, the "
948 "mean degree needs to be even!");
951 else if (is_directed(
g) && !
oriented &&
k % 2){
952 throw std::invalid_argument(
"For directed Watts-Strogatz graphs, the mean "
953 "degree can only be uneven if the graph is oriented! Set "
954 "'oriented = true', or choose an even mean degree.");
965 const std::size_t
limit,
1009 const std::size_t
limit =
k/2;
1022 const std::size_t
limit =
k/2;
1038 const std::size_t
limit =
k;
1073template<
typename Graph,
typename RNG>
1076 boost::dynamic_properties
pmaps
1077 = {boost::ignore_other_properties})
1085 if (
model ==
"complete")
1091 else if (
model ==
"regular")
1102 else if (
model ==
"ErdosRenyi")
1114 else if (
model ==
"KlemmEguiluz")
1125 else if (
model ==
"WattsStrogatz")
1137 else if (
model ==
"BarabasiAlbert")
1148 else if (
model ==
"BollobasRiordan")
1162 else if (
model ==
"load_from_file")
1168 return Utopia::DataIO::GraphLoad::load_graph<Graph>(
cfg_lff,
pmaps);
1172 throw std::invalid_argument(
"The given graph model '" +
model +
1173 "'does not exist! Valid options are: "
1174 "'complete', 'regular', 'ErdosRenyi', "
1175 "'WattsStrogatz', 'BarabasiAlbert', "
1176 "'KlemmEguiluz','BollobasRiordan', "
1177 "'load_from_file'.");
Container select_entities(const Manager &mngr, const DataIO::Config &sel_cfg)
Select entities according to parameters specified in a configuration.
Definition select.hh:213
Graph create_BarabasiAlbert_graph(std::size_t num_vertices, std::size_t mean_degree, bool parallel, RNG &rng)
Create a Barabási-Albert scale-free graph.
Definition creation.hh:699
Graph create_complete_graph(const std::size_t n)
Create a complete graph.
Definition creation.hh:43
Graph create_graph(const Config &cfg, RNG &rng, boost::dynamic_properties pmaps={boost::ignore_other_properties})
Create a graph from a configuration node.
Definition creation.hh:1074
Graph create_BollobasRiordan_graph(std::size_t num_vertices, double alpha, double beta, double gamma, double del_in, double del_out, RNG &rng)
Create a scale-free directed graph.
Definition creation.hh:764
Graph create_KlemmEguiluz_graph(const std::size_t num_vertices, const std::size_t mean_degree, const double mu, RNG &rng)
Create a Klemm-Eguíluz scale-free small-world highly-clustered graph.
Definition creation.hh:244
Graph BarabasiAlbert_parallel_generator(std::size_t num_vertices, std::size_t mean_degree, RNG &rng)
Generate a Barabási-Albert scale-free graph with parallel edges.
Definition creation.hh:605
Graph create_WattsStrogatz_graph(const std::size_t n, const std::size_t k, const double p_rewire, const bool oriented, RNG &rng)
Create a Watts-Strogatz small-world graph.
Definition creation.hh:924
Graph create_regular_graph(const std::size_t n, const std::size_t k, const bool oriented)
Create a regular lattice graph.
Definition creation.hh:154
Graph create_ErdosRenyi_graph(const std::size_t num_vertices, const std::size_t mean_degree, bool allow_parallel, bool self_edges, RNG &rng)
Create a Erdös-Rényi random graph.
Definition creation.hh:104
DataIO::Config Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition types.hh:80