Random Graph Generation
Overview¶
The RandGraph class in Epiworld is a utility for managing random number generation, which is a foundational component for stochastic processes such as random graph creation. Random graphs are commonly used in epidemiological modeling to represent contact networks, where nodes correspond to agents and edges represent interactions or potential transmission pathways. The structure of these graphs can significantly influence the dynamics of disease spread, making the generation of random graphs a critical step in simulation setup.
The RandGraph class encapsulates a random number generator (std::mt19937) and a uniform distribution sampler (std::uniform_real_distribution<>). These components are used to produce random values in the range $[0, 1)$, which can drive the creation of edges, assign weights, or initialize other stochastic processes. The class is designed to manage the initialization and configuration of the random number generator, ensuring reproducibility and consistency across simulations.
We include methods for seeding the random number generator, setting a custom random engine, and generating random values. These methods provide the basic building blocks for implementing specific random graph generation algorithms, such as Erdős–Rényi or Barabási–Albert models. While the RandGraph class itself does not directly implement graph generation algorithms, it provides the randomization infrastructure required for such processes. The number of nodes in the graph is specified during construction, and the random engine can be shared across multiple components to maintain consistency in stochastic behavior.
Implementation¶
The RandGraph class is implemented as a template and encapsulates several key data members and methods that govern its behavior.
Members¶
std::shared_ptr<std::mt19937> engine: A shared pointer to the random number generator.std::uniform_real_distribution<> unifd: A uniform distribution sampler for generating random values in the range [0, 1).int N: The number of nodes or agents in the graph.bool initialized: A flag indicating whether the random number generator has been initialized.
Methods¶
RandGraph(int N_): Constructor that initializes the graph with a specified number of nodes.void init(int s): Initializes the random number generator with a seed value.void set_rand_engine(std::shared_ptr<std::mt19937> & e): Sets a custom random number generator engine.epiworld_double runif(): Generates a random value from the uniform distribution.
Usage Example¶
This example initializes a RandGraph instance with 100 nodes, seeds the random number generator with 42, and generates five random values using the runif method.
#include "epiworld/random_graph.hpp"
#include <iostream>
int main() {
RandGraph rg(100);
rg.init(42);
for (int i = 0; i < 5; ++i) {
std::cout << "Random value " << i + 1 << ": " << rg.runif() << "\n";
}
return 0;
}
Extension Example¶
The RandGraph class can be extended to implement specific random graph generation algorithms. For example, the Erdős–Rényi model, where each pair of nodes is connected with a fixed probability, can be implemented as follows.
The RandGraph instance is used to generate random values for edge creation. The generate_edges method iterates over all pairs of nodes and connects them with a probability p. The adjacency list representation of the graph is printed to the console.
#include "epiworld/random_graph.hpp"
#include <vector>
#include <iostream>
class ErdosRenyiGraph {
private:
RandGraph rg;
std::vector<std::vector<int>> adjacency_list;
public:
ErdosRenyiGraph(int N, double p, int seed) : rg(N), adjacency_list(N) {
rg.init(seed);
generate_edges(p);
}
void generate_edges(double p) {
for (int i = 0; i < adjacency_list.size(); ++i) {
for (int j = i + 1; j < adjacency_list.size(); ++j) {
if (rg.runif() < p) {
adjacency_list[i].push_back(j);
adjacency_list[j].push_back(i);
}
}
}
}
void print_graph() const {
for (int i = 0; i < adjacency_list.size(); ++i) {
std::cout << "Node " << i << ": ";
for (int neighbor : adjacency_list[i]) {
std::cout << neighbor << " ";
}
std::cout << std::endl;
}
}
};
int main() {
ErdosRenyiGraph graph(10, 0.2, 42);
graph.print_graph();
return 0;
}