floyd_warshall/
matrices.rs

1use std::fmt;
2use std::fmt::Debug;
3
4/// This represents a sequence of nodes. The length is also saved, and when ```exists = false```, this means "there is no path".
5#[derive(Clone, Debug)]
6pub struct Path<T> {
7    v: Vec<T>,
8    len: usize,
9    exists: bool,
10}
11
12impl<T> Path<T> {
13    pub(crate) fn set_vector(&mut self, t: Vec<T>) {
14        self.v = t
15    }
16
17    /// Returns the intermediate nodes on this path as a slice.
18    pub fn get_slice<'a>(&'a self) -> &'a [T] {
19        &self.v
20    }
21
22    /// Returns an iterator of the intermediat enodes on this path.
23    pub fn iter<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a T> {
24        self.v.iter()
25    }
26
27    /// Returns the length of this path.
28    pub fn len(&self) -> usize {
29        assert!(self.exists);
30        self.len
31    }
32
33    /// Updates the length of this path. Also removes the "there is not path here"-flag.
34    pub(crate) fn set_len(&mut self, v: usize) {
35        self.len = v;
36        self.exists = true;
37    }
38
39    /// Has this path finite length?
40    pub fn exists(&self) -> bool {
41        self.exists
42    }
43}
44
45impl<T> AsRef<Vec<T>> for Path<T> {
46    fn as_ref(&self) -> &Vec<T> {
47        &self.v
48    }
49}
50
51impl<T> Default for Path<T> {
52    fn default() -> Self {
53        use std::usize::MAX;
54        Path {
55            v: Vec::new(),
56            len: MAX,
57            exists: false,
58        }
59    }
60}
61
62/// This matrix is a solution to the APSP problem, calculated by the Floyd-Warshall algorithm.
63/// It contains the intermediate nodes on the shortest path between every two nodes.
64#[derive(Debug)]
65pub struct PathMatrix<T> {
66    m: Box<[Path<T>]>,
67    n: usize,
68}
69
70impl<T> PathMatrix<T> {
71    /// Creates a new ```PathMatrix``` with the given dimension (n * n), where no paths were found yet.
72    /// That means, no nodes are yet connected in this matrix.
73    pub fn new(n: usize) -> PathMatrix<T> {
74        let mut m = vec![];
75        let n_elems = 1 + n * (n - 1) / 2;
76
77        for _ in 0..n_elems {
78            m.push(Path::default());
79        }
80
81        let m = m.into();
82
83        PathMatrix { m, n }
84    }
85
86    /// This method computes the "inner index" into the ```Vec``` by using the given X-Y-coordinates into the matrix.
87    fn idx(&self, mut i: usize, mut j: usize) -> usize {
88        // Because we're only supporting undirected graphs and we only fill one half of the matrix,
89        // we can swap the two indices, so that i <= j.
90        if i > j {
91            ::std::mem::swap(&mut i, &mut j);
92        }
93        assert!(i <= j);
94
95        if i == j {
96            0
97        } else {
98            // i + self.n * j // This is for the old n x n matrix.
99            // j + k + i
100            if j < 3 {
101                j + i
102            } else {
103                let k = j - 1;
104                self.idx(0, j - 1) + k + i
105            }
106        }
107    }
108
109    /// This method returns the value at the given position.
110    pub fn get_path_len(&self, i: usize, j: usize) -> usize {
111        let idx = self.idx(i, j);
112        self.m[idx].len()
113    }
114
115    /// This method returns the shortest path possible between i and i.
116    pub fn get_path(&self, i: usize, j: usize) -> &Path<T> {
117        let idx = self.idx(i, j);
118        &self.m[idx]
119    }
120
121    /// This method returns the shortest path possible between i and i as an iterator.
122    pub fn get_path_iter<'a>(
123        &'a self,
124        i: usize,
125        j: usize,
126    ) -> impl DoubleEndedIterator<Item = &'a T> {
127        let idx = self.idx(i, j);
128        self.m[idx].iter()
129    }
130
131    /// If the matrix contains a path between i and j (which means, it has a set length), this returns true.
132    pub fn does_path_exist(&self, i: usize, j: usize) -> bool {
133        let idx = self.idx(i, j);
134        self.m[idx].exists()
135    }
136
137    /// Returns a mutable reference to the path object for the two given nodes.
138    pub(crate) fn get_path_mut(&mut self, i: usize, j: usize) -> &mut Path<T> {
139        let idx = self.idx(i, j);
140        &mut self.m[idx]
141    }
142
143    /// This method updates the value at the given position.
144    pub fn set_path_len(&mut self, i: usize, j: usize, v: usize) {
145        let idx = self.idx(i, j);
146        self.m[idx].set_len(v);
147    }
148}
149
150// impl<T> Debug for PathMatrix<T>
151// where
152//     T: Debug,
153// {
154//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155//         use std::result::Result;
156
157//         for j in 0..self.n {
158//             let from = j * self.n;
159//             let to = j * self.n + j + 1;
160//             writeln!(f, "{:?}", &self.m[from..to])?
161//         }
162
163//         Result::Ok(())
164//     }
165// }
166
167// /// This matrix is a solution to the APSP problem, calculated by the Floyd-Warshall algorithm. It contains the length of the shortest path for every pair of nodes in a given graph.
168// pub struct DistanceMatrix {
169//     m: Box<[usize]>,
170//     n: usize,
171// }
172
173// impl DistanceMatrix {
174//     /// Creates a new ```DistanceMatrix``` with the given dimension (n * n).
175//     pub(crate) fn new(n: usize) -> DistanceMatrix {
176//         use std::usize::MAX;
177//         let m = vec![MAX; n * n].into();
178//         DistanceMatrix { m, n }
179//     }
180
181//     /// This method computes the "inner index" into the ```Vec``` by using the given X-Y-coordinates into the matrix.
182//     fn idx(&self, mut i: usize, mut j: usize) -> usize {
183//         // We only fill one half of the matrix.
184//         if i > j {
185//             ::std::mem::swap(&mut i, &mut j);
186//         }
187//         assert!(i <= j);
188
189//         i + self.n * j
190//     }
191
192//     /// This method returns the value at the given position.
193//     pub fn get(&self, i: usize, j: usize) -> usize {
194//         let idx = self.idx(i, j);
195//         self.m[idx]
196//     }
197
198//     /// This method updates the value at the given position.
199//     pub fn set(&mut self, i: usize, j: usize, v: usize) {
200//         let idx = self.idx(i, j);
201//         self.m[idx] = v;
202//     }
203// }
204
205// impl fmt::Debug for DistanceMatrix {
206//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207//         use std::result::Result;
208
209//         for j in 0..self.n {
210//             let from = j * self.n;
211//             let to = j * self.n + j + 1;
212//             writeln!(f, "{:?}", &self.m[from..to])?
213//         }
214
215//         Result::Ok(())
216//     }
217// }