qsim_core/
topology.rs

1//! Graph-based topology representation
2
3use petgraph::graph::{DiGraph, NodeIndex};
4
5/// Unique identifier for a bus
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub struct BusId(pub usize);
8
9/// Unique identifier for a branch
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub struct BranchId(pub usize);
12
13/// Node data in the topology graph
14#[derive(Debug, Clone)]
15pub struct TopologyNode {
16    pub bus_id: BusId,
17}
18
19/// Edge data in the topology graph
20#[derive(Debug, Clone)]
21pub struct TopologyEdge {
22    pub branch_id: BranchId,
23}
24
25/// Graph-based network topology
26#[derive(Debug, Clone)]
27pub struct Topology {
28    graph: DiGraph<TopologyNode, TopologyEdge>,
29}
30
31impl Topology {
32    /// Create a new empty topology
33    pub fn new() -> Self {
34        Self {
35            graph: DiGraph::new(),
36        }
37    }
38
39    /// Add a bus to the topology
40    pub fn add_bus(&mut self, bus_id: BusId) -> NodeIndex {
41        self.graph.add_node(TopologyNode { bus_id })
42    }
43
44    /// Add a branch between two buses
45    pub fn add_branch(
46        &mut self,
47        from: NodeIndex,
48        to: NodeIndex,
49        branch_id: BranchId,
50    ) {
51        self.graph.add_edge(from, to, TopologyEdge { branch_id });
52        // Add reverse edge for undirected graph behavior
53        self.graph.add_edge(to, from, TopologyEdge { branch_id });
54    }
55
56    /// Number of buses (nodes)
57    pub fn bus_count(&self) -> usize {
58        self.graph.node_count()
59    }
60
61    /// Number of branches (edges / 2 for undirected)
62    pub fn branch_count(&self) -> usize {
63        self.graph.edge_count() / 2
64    }
65
66    /// Get reference to internal graph
67    pub fn graph(&self) -> &DiGraph<TopologyNode, TopologyEdge> {
68        &self.graph
69    }
70}
71
72impl Default for Topology {
73    fn default() -> Self {
74        Self::new()
75    }
76}