swactor/crates/simulation/src/topology.rs
zacheryasc d817ad952f feat: distributed runtime (#30)
Major feature addition. For full details read `./docs/development_history/DISTRIBUTION.md`
2026-02-12 09:13:50 +00:00

81 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()
}
}
}