Skip to content

Commit be1694d

Browse files
committed
Checkpoint 1
1 parent edca4bc commit be1694d

File tree

6 files changed

+753
-143
lines changed

6 files changed

+753
-143
lines changed

src/graph/generators.rs_

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
use crate::graph::types::{BaseGraph, GraphConstructor, MyEdgeType};
2+
use petgraph::EdgeType;
3+
use rand::rngs::StdRng;
4+
use rand::{Rng, SeedableRng};
5+
6+
/// Generates an Erdős–Rényi graph.
7+
///
8+
/// # Arguments
9+
///
10+
/// * `n` - The number of nodes.
11+
/// * `p` - The probability of edge creation.
12+
/// * `seed` - The seed for the random number generator.
13+
///
14+
/// # Type Parameters
15+
///
16+
/// * `Ty` - The edge type of the graph, which must implement
17+
/// `GraphConstructor<i32, f32> + MyEdgeType + EdgeType`.
18+
///
19+
/// # Returns
20+
///
21+
/// * `BaseGraph<i32, f32, Ty>` - The generated graph.
22+
pub fn erdos_renyi_graph<Ty>(n: usize, p: f64, seed: u64) -> BaseGraph<i32, f32, Ty>
23+
where
24+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
25+
{
26+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
27+
let mut nodes = Vec::with_capacity(n);
28+
for i in 0..n {
29+
nodes.push(graph.add_node(i as i32));
30+
}
31+
let mut rng = StdRng::seed_from_u64(seed);
32+
if <Ty as GraphConstructor<i32, f32>>::is_directed() {
33+
for i in 0..n {
34+
for j in 0..n {
35+
if i != j && rng.random_bool(p) {
36+
graph.add_edge(nodes[i], nodes[j], 1.0);
37+
}
38+
}
39+
}
40+
} else {
41+
for i in 0..n {
42+
for j in (i + 1)..n {
43+
if rng.random_bool(p) {
44+
graph.add_edge(nodes[i], nodes[j], 1.0);
45+
}
46+
}
47+
}
48+
}
49+
graph
50+
}
51+
52+
/// Generates a complete graph.
53+
pub fn complete_graph<Ty>(n: usize) -> BaseGraph<i32, f32, Ty>
54+
where
55+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
56+
{
57+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
58+
let mut nodes = Vec::with_capacity(n);
59+
for i in 0..n {
60+
nodes.push(graph.add_node(i as i32));
61+
}
62+
if <Ty as GraphConstructor<i32, f32>>::is_directed() {
63+
for i in 0..n {
64+
for j in 0..n {
65+
if i != j {
66+
graph.add_edge(nodes[i], nodes[j], 1.0);
67+
}
68+
}
69+
}
70+
} else {
71+
for i in 0..n {
72+
for j in (i + 1)..n {
73+
graph.add_edge(nodes[i], nodes[j], 1.0);
74+
}
75+
}
76+
}
77+
graph
78+
}
79+
80+
/// Generates a bipartite graph.
81+
pub fn bipartite_graph<Ty>(n1: usize, n2: usize, p: f64, seed: u64) -> BaseGraph<i32, f32, Ty>
82+
where
83+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
84+
{
85+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
86+
let mut group1 = Vec::with_capacity(n1);
87+
let mut group2 = Vec::with_capacity(n2);
88+
for i in 0..n1 {
89+
group1.push(graph.add_node(i as i32));
90+
}
91+
for j in 0..n2 {
92+
group2.push(graph.add_node((n1 + j) as i32));
93+
}
94+
let mut rng = StdRng::seed_from_u64(seed);
95+
for &u in &group1 {
96+
for &v in &group2 {
97+
if rng.random_bool(p) {
98+
graph.add_edge(u, v, 1.0);
99+
}
100+
}
101+
}
102+
graph
103+
}
104+
105+
/// Generates a star graph.
106+
pub fn star_graph<Ty>(n: usize) -> BaseGraph<i32, f32, Ty>
107+
where
108+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
109+
{
110+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
111+
if n == 0 {
112+
return graph;
113+
}
114+
let center = graph.add_node(0);
115+
for i in 1..n {
116+
let node = graph.add_node(i as i32);
117+
graph.add_edge(center, node, 1.0);
118+
}
119+
graph
120+
}
121+
122+
/// Generates a cycle graph.
123+
pub fn cycle_graph<Ty>(n: usize) -> BaseGraph<i32, f32, Ty>
124+
where
125+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
126+
{
127+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
128+
if n == 0 {
129+
return graph;
130+
}
131+
let mut nodes = Vec::with_capacity(n);
132+
for i in 0..n {
133+
nodes.push(graph.add_node(i as i32));
134+
}
135+
for i in 0..n {
136+
let j = (i + 1) % n;
137+
graph.add_edge(nodes[i], nodes[j], 1.0);
138+
}
139+
graph
140+
}
141+
142+
/// Generates a Watts–Strogatz small-world graph.
143+
pub fn watts_strogatz_graph<Ty>(n: usize, k: usize, beta: f64, seed: u64) -> BaseGraph<i32, f32, Ty>
144+
where
145+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
146+
{
147+
// Watts–Strogatz is defined for undirected graphs.
148+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
149+
let mut nodes = Vec::with_capacity(n);
150+
for i in 0..n {
151+
nodes.push(graph.add_node(i as i32));
152+
}
153+
let mut rng = StdRng::seed_from_u64(seed);
154+
let half_k = k / 2;
155+
// Create ring lattice.
156+
for i in 0..n {
157+
for j in 1..=half_k {
158+
let neighbor = (i + j) % n;
159+
graph.add_edge(nodes[i], nodes[neighbor], 1.0);
160+
}
161+
}
162+
// Rewire each edge with probability beta.
163+
for i in 0..n {
164+
for _ in 1..=half_k {
165+
if rng.random_bool(beta) {
166+
let mut new_target;
167+
loop {
168+
new_target = rng.random_range(0..n);
169+
if new_target != i {
170+
break;
171+
}
172+
}
173+
graph.add_edge(nodes[i], nodes[new_target], 1.0);
174+
}
175+
}
176+
}
177+
graph
178+
}
179+
180+
/// Generates a Barabási–Albert scale-free graph.
181+
pub fn barabasi_albert_graph<Ty>(n: usize, m: usize, seed: u64) -> BaseGraph<i32, f32, Ty>
182+
where
183+
Ty: GraphConstructor<i32, f32> + MyEdgeType + EdgeType,
184+
{
185+
// Barabási–Albert is defined for undirected graphs.
186+
let mut graph = BaseGraph::<i32, f32, Ty>::new();
187+
if n < m || m == 0 {
188+
return graph;
189+
}
190+
// Start with a complete graph of m nodes.
191+
let mut nodes = Vec::with_capacity(n);
192+
for i in 0..m {
193+
nodes.push(graph.add_node(i as i32));
194+
}
195+
for i in 0..m {
196+
for j in (i + 1)..m {
197+
graph.add_edge(nodes[i], nodes[j], 1.0);
198+
}
199+
}
200+
let mut rng = StdRng::seed_from_u64(seed);
201+
let mut degrees: Vec<usize> = vec![m - 1; m];
202+
let mut total_degree = m * (m - 1);
203+
for i in m..n {
204+
let new_node = graph.add_node(i as i32);
205+
nodes.push(new_node);
206+
let mut targets = Vec::new();
207+
while targets.len() < m {
208+
let r = rng.random_range(0..total_degree);
209+
let mut cumulative = 0;
210+
for (idx, &deg) in degrees.iter().enumerate() {
211+
cumulative += deg;
212+
if r < cumulative {
213+
if !targets.contains(&nodes[idx]) {
214+
targets.push(nodes[idx]);
215+
}
216+
break;
217+
}
218+
}
219+
}
220+
for target in &targets {
221+
graph.add_edge(new_node, *target, 1.0);
222+
let idx = nodes.iter().position(|&x| x == *target).unwrap();
223+
degrees[idx] += 1;
224+
}
225+
degrees.push(m);
226+
total_degree += 2 * m;
227+
}
228+
graph
229+
}

0 commit comments

Comments
 (0)