weavatrix_graph/matrix/
dense.rs1use crate::{GraphError, NodeIndex, Result};
2use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
5pub struct DenseMatrix<T> {
6 node_count: u32,
7 edge_count: usize,
8 cells: Vec<Option<T>>,
9}
10
11impl<T> DenseMatrix<T> {
12 pub fn try_new(node_count: usize) -> Result<Self> {
18 let compact = u32::try_from(node_count).map_err(|_| GraphError::IndexCapacityExceeded {
19 category: "matrix nodes",
20 count: node_count,
21 })?;
22 let cells = node_count
23 .checked_mul(node_count)
24 .ok_or(GraphError::ArithmeticOverflow {
25 operation: "dense matrix dimensions",
26 })?;
27 Ok(Self {
28 node_count: compact,
29 edge_count: 0,
30 cells: std::iter::repeat_with(|| None).take(cells).collect(),
31 })
32 }
33
34 #[must_use]
35 pub const fn node_count(&self) -> usize {
36 self.node_count as usize
37 }
38
39 #[must_use]
40 pub const fn edge_count(&self) -> usize {
41 self.edge_count
42 }
43
44 #[must_use]
45 pub fn get(&self, source: NodeIndex, target: NodeIndex) -> Option<&T> {
46 self.slot(source, target)
47 .ok()
48 .and_then(|slot| self.cells[slot].as_ref())
49 }
50
51 #[must_use]
52 pub fn get_mut(&mut self, source: NodeIndex, target: NodeIndex) -> Option<&mut T> {
53 self.slot(source, target)
54 .ok()
55 .and_then(|slot| self.cells[slot].as_mut())
56 }
57
58 pub fn insert(&mut self, source: NodeIndex, target: NodeIndex, value: T) -> Result<Option<T>> {
64 let slot = self.slot(source, target)?;
65 let previous = self.cells[slot].replace(value);
66 self.edge_count += usize::from(previous.is_none());
67 Ok(previous)
68 }
69
70 pub fn remove(&mut self, source: NodeIndex, target: NodeIndex) -> Option<T> {
71 let slot = self.slot(source, target).ok()?;
72 let previous = self.cells[slot].take();
73 self.edge_count -= usize::from(previous.is_some());
74 previous
75 }
76
77 pub fn outgoing(&self, source: NodeIndex) -> impl Iterator<Item = (NodeIndex, &T)> {
78 let valid = source.index() < self.node_count();
79 (0..self.node_count()).filter_map(move |target| {
80 let target = NodeIndex::new(u32::try_from(target).ok()?);
81 valid
82 .then(|| self.get(source, target))
83 .flatten()
84 .map(|value| (target, value))
85 })
86 }
87
88 pub fn incoming(&self, target: NodeIndex) -> impl Iterator<Item = (NodeIndex, &T)> {
89 let valid = target.index() < self.node_count();
90 (0..self.node_count()).filter_map(move |source| {
91 let source = NodeIndex::new(u32::try_from(source).ok()?);
92 valid
93 .then(|| self.get(source, target))
94 .flatten()
95 .map(|value| (source, value))
96 })
97 }
98
99 pub fn edges(&self) -> impl Iterator<Item = (NodeIndex, NodeIndex, &T)> {
100 self.cells.iter().enumerate().filter_map(|(slot, value)| {
101 let value = value.as_ref()?;
102 let source = u32::try_from(slot / self.node_count()).ok()?;
103 let target = u32::try_from(slot % self.node_count()).ok()?;
104 Some((NodeIndex::new(source), NodeIndex::new(target), value))
105 })
106 }
107
108 fn slot(&self, source: NodeIndex, target: NodeIndex) -> Result<usize> {
109 let count = self.node_count();
110 if source.index() >= count {
111 return Err(GraphError::InvalidNodeIndex {
112 node: source.index(),
113 node_count: count,
114 });
115 }
116 if target.index() >= count {
117 return Err(GraphError::InvalidNodeIndex {
118 node: target.index(),
119 node_count: count,
120 });
121 }
122 Ok(source.index() * count + target.index())
123 }
124}
125
126impl<T: Clone> DenseMatrix<T> {
127 pub fn insert_undirected(
133 &mut self,
134 left: NodeIndex,
135 right: NodeIndex,
136 value: T,
137 ) -> Result<(Option<T>, Option<T>)> {
138 let reverse = value.clone();
139 let first = self.insert(left, right, value)?;
140 let second = if left == right {
141 first.clone()
142 } else {
143 self.insert(right, left, reverse)?
144 };
145 Ok((first, second))
146 }
147}
148
149#[derive(Deserialize)]
150struct DenseWire<T> {
151 node_count: u32,
152 #[serde(rename = "edge_count")]
153 _edge_count: usize,
154 cells: Vec<Option<T>>,
155}
156
157impl<'de, T> Deserialize<'de> for DenseMatrix<T>
158where
159 T: Deserialize<'de>,
160{
161 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
162 where
163 D: Deserializer<'de>,
164 {
165 let wire = DenseWire::deserialize(deserializer)?;
166 let node_count = wire.node_count as usize;
167 let expected = node_count
168 .checked_mul(node_count)
169 .ok_or_else(|| D::Error::custom("dense matrix dimensions overflow"))?;
170 if wire.cells.len() != expected {
171 return Err(D::Error::custom(format!(
172 "dense matrix has {} cells, expected {expected}",
173 wire.cells.len()
174 )));
175 }
176 let edge_count = wire.cells.iter().filter(|cell| cell.is_some()).count();
177 Ok(Self {
178 node_count: wire.node_count,
179 edge_count,
180 cells: wire.cells,
181 })
182 }
183}