82 lines
2.4 KiB
Rust
82 lines
2.4 KiB
Rust
|
|
/// Network topology shapes for simulation.
|
||
|
|
#[derive(Debug, Clone)]
|
||
|
|
pub enum Topology {
|
||
|
|
/// Each node gossips to the next; last gossips to first.
|
||
|
|
Ring,
|
||
|
|
/// Node 0 is the hub; all others gossip to/from it.
|
||
|
|
Star,
|
||
|
|
/// Every node gossips to every other node.
|
||
|
|
FullMesh,
|
||
|
|
/// Unidirectional chain: 0→1→2→…→(n-1).
|
||
|
|
Chain,
|
||
|
|
/// Two halves with no cross-links (healed later via `heal_after_round`).
|
||
|
|
Partitioned,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Topology {
|
||
|
|
/// Compute abstract index-pair edges for `num_nodes` nodes.
|
||
|
|
pub fn edges(&self, num_nodes: usize) -> Vec<(usize, usize)> {
|
||
|
|
let n = num_nodes;
|
||
|
|
let mut edges = Vec::new();
|
||
|
|
|
||
|
|
match self {
|
||
|
|
Topology::Ring => {
|
||
|
|
for i in 0..n {
|
||
|
|
edges.push((i, (i + 1) % n));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Topology::Star => {
|
||
|
|
for i in 1..n {
|
||
|
|
edges.push((0, i));
|
||
|
|
edges.push((i, 0));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Topology::FullMesh => {
|
||
|
|
for i in 0..n {
|
||
|
|
for j in 0..n {
|
||
|
|
if i != j {
|
||
|
|
edges.push((i, j));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Topology::Chain => {
|
||
|
|
for i in 0..n.saturating_sub(1) {
|
||
|
|
edges.push((i, i + 1));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Topology::Partitioned => {
|
||
|
|
let half = n / 2;
|
||
|
|
for i in 0..half {
|
||
|
|
for j in 0..half {
|
||
|
|
if i != j {
|
||
|
|
edges.push((i, j));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for i in half..n {
|
||
|
|
for j in half..n {
|
||
|
|
if i != j {
|
||
|
|
edges.push((i, j));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
edges
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Partition healing edges: bidirectional links between the two halves.
|
||
|
|
pub fn heal_edges(&self, num_nodes: usize) -> Vec<(usize, usize)> {
|
||
|
|
if !matches!(self, Topology::Partitioned) {
|
||
|
|
return Vec::new();
|
||
|
|
}
|
||
|
|
let half = num_nodes / 2;
|
||
|
|
if half > 0 && half < num_nodes {
|
||
|
|
vec![(half - 1, half), (half, half - 1)]
|
||
|
|
} else {
|
||
|
|
Vec::new()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|