Skip to main content

dijkstra_suite/
node.rs

1//! This modules defines types and traits for a graph node
2//!
3//! ## The`Node` type
4//!
5//! `Node` type plays a central role in this suite.
6//!
7//! Each `Node` has an id and a weight, both generic over types implementing `NodeId`
8//! and `NodeWeight` traits respectively. Both have blanket implementations over generic types
9//! so you can use any types you want as long as it implements the required traits
10//!
11//! ```rust
12//! use dijkstra_suite::node::Node;
13//!
14//! let node_a: Node<(i32, i32), f64> = Node {
15//!     weight: 1.0,
16//!     ..Default::default()
17//! };
18//!
19//! let node_b = Node {
20//!     id: (0, 0),
21//!     weight: 1.0,
22//!     neighbours: vec![],
23//! };
24//!
25//! let node_c: Node<(i32, i32), f32> = Node::default();
26//!
27//! assert_eq!(node_a, node_b);
28//! assert_eq!(node_c.weight, 0.0)
29//! ```
30//!
31//! ## The`NodeId` trait
32//!
33//! `Nodeid` is a super trait that ensures the id of the node is comparable and hashable
34//! (current implementation uses an `HashMap` under the hood), requiring the implementing
35//! type also to implement `Hash`, `Eq` and `Default`
36//!
37//!
38//! ## The`NodeWeight` trait
39//!
40//! `NodeWeight` is a super trait that ensures the weight of the node is a number or number-like
41//! types, requiring the implementing type also to implement `Add`, `Div`, `Mul`, `Rem`, `Sub`
42//! and `PartialEq`
43
44use std::{
45    fmt::Debug,
46    hash::Hash,
47    ops::{Add, Deref, Div, Mul, Rem, Sub},
48};
49
50#[derive(Debug, Clone)]
51pub struct Node<I: NodeId, W: NodeWeight> {
52    pub id: I,
53    pub weight: W,
54    pub neighbours: Vec<NodeConnection<I, W>>,
55}
56
57impl<I: NodeId, W: NodeWeight> Default for Node<I, W> {
58    fn default() -> Self {
59        Node {
60            id: I::default(),
61            weight: W::default(),
62            neighbours: vec![],
63        }
64    }
65}
66
67impl<I: NodeId, W: NodeWeight> PartialEq for Node<I, W> {
68    fn eq(&self, other: &Self) -> bool {
69        self.id == other.id && self.weight == other.weight && self.neighbours == other.neighbours
70    }
71}
72
73pub trait NodeId: Debug + Default + Clone + Eq + PartialOrd + Hash {}
74
75impl<T> NodeId for T where T: Debug + Default + Clone + Eq + PartialOrd + Hash {}
76
77pub trait NodeWeight:
78    Debug
79    + Default
80    + Clone
81    + PartialEq
82    + PartialOrd
83    + Add<Output = Self>
84    + Sub<Output = Self>
85    + Mul<Output = Self>
86    + Div<Output = Self>
87    + Rem<Output = Self>
88{
89}
90
91impl<T> NodeWeight for T where
92    T: Debug
93        + Default
94        + Clone
95        + PartialEq
96        + PartialOrd
97        + Add<Output = T>
98        + Sub<Output = T>
99        + Mul<Output = T>
100        + Div<Output = T>
101        + Rem<Output = T>
102{
103}
104
105// #[derive(Debug, Default, Clone, PartialEq)]
106// pub struct Weight<T: NodeWeight>(pub T);
107//
108// impl<T: NodeWeight> Eq for Weight<T> {}
109//
110// impl<T: NodeWeight> Ord for Weight<T> {
111//     fn cmp(&self, other: &Self) -> std::cmp::Ordering {
112//         self.0
113//             .partial_cmp(&other.0)
114//             .expect("Weight contains a value with no defined order (e.g. NaN)")
115//     }
116// }
117//
118// impl<T: NodeWeight> PartialOrd for Weight<T> {
119//     fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
120//         Some(self.cmp(other))
121//     }
122// }
123//
124// impl<T> Deref for Weight<T>
125// where
126//     T: Debug
127//         + Default
128//         + Clone
129//         + PartialEq
130//         + PartialOrd
131//         + Ord
132//         + Add<Output = T>
133//         + Sub<Output = T>
134//         + Mul<Output = T>
135//         + Div<Output = T>
136//         + Rem<Output = T>,
137// {
138//     type Target = T;
139//
140//     fn deref(&self) -> &Self::Target {
141//         &self.0
142//     }
143// }
144//
145// impl<T: NodeWeight> Add for Weight<T> {
146//     type Output = Weight<T>;
147//
148//     fn add(self, rhs: Self) -> Self::Output {
149//         Weight(self.0 + rhs.0)
150//     }
151// }
152//
153// impl<T: NodeWeight> Sub for Weight<T> {
154//     type Output = Weight<T>;
155//
156//     fn sub(self, rhs: Self) -> Self::Output {
157//         Weight(self.0 - rhs.0)
158//     }
159// }
160//
161// impl<T: NodeWeight> Mul for Weight<T> {
162//     type Output = Weight<T>;
163//
164//     fn mul(self, rhs: Self) -> Self::Output {
165//         Weight(self.0 * rhs.0)
166//     }
167// }
168//
169// impl<T: NodeWeight> Div for Weight<T> {
170//     type Output = Weight<T>;
171//
172//     fn div(self, rhs: Self) -> Self::Output {
173//         Weight(self.0 / rhs.0)
174//     }
175// }
176//
177// impl<T: NodeWeight> Rem for Weight<T> {
178//     type Output = Weight<T>;
179//
180//     fn rem(self, rhs: Self) -> Self::Output {
181//         Weight(self.0 % rhs.0)
182//     }
183// }
184
185#[derive(Debug, Clone)]
186pub struct NodeConnection<I: NodeId, W: NodeWeight> {
187    pub from: I,
188    pub to: I,
189    pub weight: W,
190}
191
192impl<I: NodeId, W: NodeWeight> Default for NodeConnection<I, W> {
193    fn default() -> Self {
194        NodeConnection {
195            from: I::default(),
196            to: I::default(),
197            weight: W::default(),
198        }
199    }
200}
201
202impl<I: NodeId, W: NodeWeight> AsRef<NodeConnection<I, W>> for NodeConnection<I, W> {
203    fn as_ref(&self) -> &NodeConnection<I, W> {
204        self
205    }
206}
207
208impl<I: NodeId, W: NodeWeight> PartialEq for NodeConnection<I, W> {
209    fn eq(&self, other: &Self) -> bool {
210        self.from == other.from && self.to == other.to && self.weight == other.weight
211    }
212}
213
214impl<I: NodeId, W: NodeWeight> Eq for NodeConnection<I, W> {}
215
216impl<I: NodeId, W: NodeWeight> Ord for NodeConnection<I, W> {
217    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
218        self.weight.partial_cmp(&other.weight).expect("bla")
219    }
220}
221
222impl<I: NodeId, W: NodeWeight> PartialOrd for NodeConnection<I, W> {
223    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
224        Some(self.cmp(other))
225    }
226}
227
228#[cfg(test)]
229mod test {
230    use super::*;
231
232    #[test]
233    fn test_node() {
234        let node_a = Node {
235            weight: 1,
236            ..Default::default()
237        };
238
239        let node_b = Node {
240            id: (0, 0),
241            weight: 1,
242            neighbours: vec![],
243        };
244
245        let node_c: Node<(i32, i32), i32> = Node::default();
246
247        assert_eq!(node_a, node_b);
248        assert_eq!(node_c.weight, 0)
249    }
250
251    #[test]
252    fn test_node_float() {
253        let node_a: Node<(i32, i32), f64> = Node {
254            weight: 1.0,
255            ..Default::default()
256        };
257
258        let node_b = Node {
259            id: (0, 0),
260            weight: 1.0,
261            neighbours: vec![],
262        };
263
264        let node_c: Node<(i32, i32), f32> = Node::default();
265
266        assert_eq!(node_a, node_b);
267        assert_eq!(node_c.weight, 0.0)
268    }
269}