├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE.txt ├── README.md ├── benches-compare.sh ├── benches └── benchmark.rs ├── examples ├── dot.rs └── example1.dot └── src ├── dot.rs ├── edge.rs ├── graph.rs ├── iterators ├── bfs.rs ├── dfs.rs ├── dijkstra.rs ├── mod.rs ├── owning_iterator.rs ├── topo.rs ├── values.rs └── vertices.rs ├── lib.rs ├── macros.rs └── vertex_id.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | liberapay: octavonce 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | 4 | Cargo.lock 5 | example1.dot 6 | .DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | cache: cargo 4 | 5 | rust: 6 | - stable 7 | - nightly 8 | 9 | matrix: 10 | allow_failures: 11 | - rust: nightly 12 | fast_finish: true 13 | 14 | git: 15 | depth: 10 16 | 17 | before_script: 18 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then chmod +x benches-compare.sh; fi 19 | 20 | script: 21 | - cargo build --verbose --all 22 | - cargo build --verbose --all --features "dot" 23 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then 24 | cargo +nightly build --features "no_std dot" --verbose --all; 25 | fi 26 | - cargo test --verbose --all 27 | - cargo test --verbose --all --features "dot" 28 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then 29 | cargo +nightly test --features "no_std dot" --verbose --all; 30 | fi 31 | 32 | after_script: 33 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then chmod +x benches-compare.sh; fi 34 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "graphlib" 3 | version = "0.6.3" 4 | authors = ["Octavian Oncescu "] 5 | edition = "2018" 6 | repository = "https://github.com/purpleprotocol/graphlib" 7 | keywords = ["graph", "data-structures", "mutable", "graph-algorithm", "no-std"] 8 | categories = ["data-structures", "no-std"] 9 | description = "Graphlib is a simple and powerful rust library for the graph data-structure." 10 | license = "MIT" 11 | readme = "README.md" 12 | 13 | [badges] 14 | travis-ci = { repository = "purpleprotocol/graphlib", branch = "master" } 15 | 16 | [dependencies] 17 | rand = { version = "0.7.3", default-features = false } 18 | rand_core = { version = "0.5.1", default-features = false } 19 | rand_isaac = { version = "0.2.0", default-features = false } 20 | hex = { version = "0.4.0", default-features = false } 21 | hashbrown = { version = "0.6.3", default-features = false, features = ["inline-more", "ahash"] } 22 | dot = { version = "0.1.4", optional = true } 23 | 24 | [dev-dependencies] 25 | criterion = "0.3.0" 26 | 27 | [[bench]] 28 | name = "benchmark" 29 | harness = false 30 | 31 | [features] 32 | default = [] 33 | # use `cargo bench --features sbench` only if you want benchmarks with 10 million 34 | # iterations (may fail on some systems) 35 | sbench = [] 36 | 37 | # nightly feature for `no_std` 38 | # for build use `cargo +nightly build --features no_std` 39 | no_std = ["hashbrown/nightly"] 40 | 41 | [package.metadata.docs.rs] 42 | features = ["dot"] 43 | no-default-features = true 44 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2019 Octavian Oncescu 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Graphlib 2 | [![Build Status]][travis] [![Discord Badge]][Discord] [![Latest Version]][crates.io] [![Documentation]][docs.rs] 3 | 4 | Graphlib is a simple and powerful Rust graph library. 5 | 6 | --- 7 | 8 | This library attempts to provide a generic api for building, mutating and iterating over graphs that is similar to that of other data-structures found in Rust i.e. `Vec`, `HashMap`, `VecDeque`, etc. 9 | 10 | ### Using Graphlib 11 | ```rust 12 | use graphlib::Graph; 13 | 14 | let mut graph: Graph = Graph::new(); 15 | 16 | // Add two vertices to the graph 17 | let id1 = graph.add_vertex(1); 18 | let id2 = graph.add_vertex(2); 19 | 20 | // Add an edge between the two vertices 21 | graph.add_edge(&id1, &id2); 22 | 23 | assert_eq!(*graph.fetch(&id1).unwrap(), 1); 24 | assert_eq!(*graph.fetch(&id2).unwrap(), 2); 25 | 26 | // The graph has 2 vertices and one edge at this point 27 | assert_eq!(graph.vertex_count(), 2); 28 | assert_eq!(graph.edge_count(), 1); 29 | 30 | // Remove one of the connected vertices 31 | graph.remove(&id1); 32 | 33 | assert_eq!(graph.vertex_count(), 1); 34 | assert_eq!(graph.edge_count(), 0); 35 | ``` 36 | 37 | ### Using without `std` 38 | In `Cargo.toml`: 39 | ```toml 40 | [dependencies] 41 | graphlib = { version = "*", features = ["no_std"] } 42 | ``` 43 | 44 | ### Contributing 45 | We welcome anyone wishing to contribute to Graphlib! Check out the [issues section][issues] of the repository before starting out. 46 | 47 | ### License 48 | 49 | Graphlib is licensed under the MIT license. 50 | 51 | [Build Status]: https://travis-ci.org/purpleprotocol/graphlib.svg?branch=master 52 | [Discord Badge]: https://img.shields.io/discord/435827644915777536.svg 53 | [Discord]: https://discord.gg/eGBzyaA 54 | [travis]: https://travis-ci.org/purpleprotocol/graphlib 55 | [crates.io]: https://crates.io/crates/graphlib 56 | [Latest Version]: https://img.shields.io/crates/v/graphlib.svg 57 | [Documentation]: https://docs.rs/graphlib/badge.svg 58 | [docs.rs]: https://docs.rs/graphlib 59 | [issues]: https://github.com/purpleprotocol/graphlib/issues 60 | 61 | -------------------------------------------------------------------------------- /benches-compare.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Clone the repository 4 | REMOTE_URL="$(git config --get remote.origin.url)"; 5 | cd ${TRAVIS_BUILD_DIR}/.. && \ 6 | git clone ${REMOTE_URL} "${TRAVIS_REPO_SLUG}-bench" && \ 7 | cd "${TRAVIS_REPO_SLUG}-bench" && \ 8 | 9 | # Bench master 10 | git checkout master && \ 11 | cargo bench --bench benchmark -- --noplot --save-baseline before && \ 12 | 13 | # Bench current branch 14 | git checkout ${TRAVIS_COMMIT} && \ 15 | cargo bench --bench benchmark -- --noplot --save-baseline after && \ 16 | 17 | # Install https://github.com/BurntSushi/critcmp 18 | cargo install critcmp --force && \ 19 | 20 | # Compare the two generated benches 21 | critcmp before after; 22 | -------------------------------------------------------------------------------- /benches/benchmark.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | 4 | use criterion::Criterion; 5 | use graphlib::*; 6 | 7 | // use `cargo bench --features sbench` for benching with GraphCapacity of 10_000_000 8 | 9 | // includes benches for : 10 | // 1. new() -> Graph 11 | // 2. with_capacity(capacity: usize) -> Graph 12 | fn bench_create(c: &mut Criterion) { 13 | c.bench_function("new", |b| b.iter(Graph::::new)); 14 | 15 | macro_rules! with_capacity { 16 | ($str: tt ,$x: expr) => { 17 | c.bench_function($str, |b| b.iter(|| Graph::::with_capacity($x))); 18 | }; 19 | } 20 | with_capacity!("with_capacity_10", 10); 21 | with_capacity!("with_capacity_100", 100); 22 | with_capacity!("with_capacity_500", 500); 23 | with_capacity!("with_capacity_1000", 1000); 24 | #[cfg(feature = "sbench")] 25 | with_capacity!("with_capacity_m", 10_000_000); 26 | } 27 | 28 | // includes benches for : 29 | // 1. dfs(&self) -> Dfs 30 | // 2. bfs(&self) -> Bfs 31 | // 3. topo(&self) -> Topo 32 | // 4. vertices(&self) -> VertexIter 33 | // 5. roots(&self) -> VertexIter 34 | fn bench_iterators(c: &mut Criterion) { 35 | macro_rules! dfs { 36 | ($str: tt ,$x: expr) => { 37 | c.bench_function($str, |b| { 38 | let mut graph: Graph = Graph::new(); 39 | let mut vertices = vec![]; 40 | 41 | let mut v1 = graph.add_vertex(0); 42 | 43 | for i in 1..=$x { 44 | let v2 = graph.add_vertex(i); 45 | graph.add_edge(&v1, &v2); 46 | v1 = v2.clone(); 47 | } 48 | b.iter(|| { 49 | for v in graph.dfs() { 50 | vertices.push(v); 51 | } 52 | }) 53 | }); 54 | }; 55 | } 56 | dfs!("dfs_10", 10); 57 | dfs!("dfs_100", 100); 58 | dfs!("dfs_500", 500); 59 | dfs!("dfs_1000", 1000); 60 | #[cfg(feature = "sbench")] 61 | dfs!("dfs_m", 10_000_000); 62 | 63 | macro_rules! bfs { 64 | ($str: tt ,$x: expr) => { 65 | c.bench_function($str, |b| { 66 | let mut graph: Graph = Graph::new(); 67 | let mut vertices = vec![]; 68 | 69 | let mut v1 = graph.add_vertex(0); 70 | 71 | for i in 1..=$x { 72 | let v2 = graph.add_vertex(i); 73 | graph.add_edge(&v1, &v2); 74 | v1 = v2.clone(); 75 | } 76 | 77 | b.iter(|| { 78 | for v in graph.bfs() { 79 | vertices.push(v); 80 | } 81 | }) 82 | }); 83 | }; 84 | } 85 | bfs!("bfs_10", 10); 86 | bfs!("bfs_100", 100); 87 | bfs!("bfs_500", 500); 88 | bfs!("bfs_1000", 1000); 89 | #[cfg(feature = "sbench")] 90 | bfs!("bfs_m", 10_000_000); 91 | 92 | macro_rules! topo { 93 | ($str: tt ,$x: expr) => { 94 | c.bench_function($str, |b| { 95 | let mut graph: Graph = Graph::new(); 96 | let mut vertices = vec![]; 97 | 98 | let mut v1 = graph.add_vertex(0); 99 | 100 | for i in 1..=$x { 101 | let v2 = graph.add_vertex(i); 102 | graph.add_edge(&v1, &v2); 103 | v1 = v2.clone(); 104 | } 105 | b.iter(|| { 106 | for v in graph.topo() { 107 | vertices.push(v); 108 | } 109 | }) 110 | }); 111 | }; 112 | } 113 | topo!("topo_10", 10); 114 | topo!("topo_100", 100); 115 | topo!("topo_500", 500); 116 | topo!("topo_1000", 1000); 117 | #[cfg(feature = "sbench")] 118 | topo!("topo_m", 10_000_000); 119 | 120 | macro_rules! vertices { 121 | ($str: tt ,$x: expr) => { 122 | c.bench_function($str, |b| { 123 | let mut graph: Graph = Graph::new(); 124 | let mut vertices = vec![]; 125 | 126 | for i in 1..=$x { 127 | graph.add_vertex(i); 128 | } 129 | 130 | b.iter(|| { 131 | for v in graph.vertices() { 132 | vertices.push(v); 133 | } 134 | }) 135 | }); 136 | }; 137 | } 138 | vertices!("vertices_10", 10); 139 | vertices!("vertices_100", 100); 140 | vertices!("vertices_500", 500); 141 | vertices!("vertices_1000", 1000); 142 | #[cfg(feature = "sbench")] 143 | vertices!("vertices_m", 10_000_000); 144 | 145 | macro_rules! roots { 146 | ($str: tt ,$x: expr) => { 147 | c.bench_function($str, |b| { 148 | let mut graph: Graph = Graph::new(); 149 | let mut roots = vec![]; 150 | 151 | let mut v1 = graph.add_vertex(0); 152 | 153 | for i in 1..=$x { 154 | let v2 = graph.add_vertex(i); 155 | graph.add_edge(&v1, &v2); 156 | v1 = v2.clone(); 157 | } 158 | 159 | b.iter(|| { 160 | for v in graph.roots() { 161 | roots.push(v); 162 | } 163 | }) 164 | }); 165 | }; 166 | } 167 | 168 | roots!("roots_10", 10); 169 | roots!("roots_100", 100); 170 | roots!("roots_500", 500); 171 | roots!("roots_1000", 1000); 172 | #[cfg(feature = "sbench")] 173 | roots!("roots_m", 10_000_000); 174 | } 175 | 176 | // includes benches for : 177 | // 1. in_neighbors(&self, id: &VertexId) -> VertexIter 178 | // 2. in_neighbors_count(&self, id: &VertexId) -> usize 179 | // 3. neighbors(&self, id: &VertexId) -> VertexIter 180 | // 4. neighbors_count(&self, id: &VertexId) -> usize 181 | // 5. out_neighbors(&self, id: &VertexId) -> VertexIter 182 | // 6. out_neighbors_count(&self, id: &VertexId) -> usize 183 | fn bench_neighbor_functions(c: &mut Criterion) { 184 | macro_rules! neighbors_count { 185 | ($str: tt ,$x: expr) => { 186 | c.bench_function($str, |b| { 187 | let mut graph: Graph = Graph::new(); 188 | 189 | let mut v1 = graph.add_vertex(0); 190 | 191 | for i in 1..=$x { 192 | let v2 = graph.add_vertex(i); 193 | graph.add_edge(&v1, &v2); 194 | v1 = v2.clone(); 195 | } 196 | 197 | b.iter(|| { 198 | let _k = graph.neighbors_count(&v1); 199 | }) 200 | }); 201 | }; 202 | } 203 | neighbors_count!("neighbors_count_10", 10); 204 | neighbors_count!("neighbors_count_100", 100); 205 | neighbors_count!("neighbors_count_500", 500); 206 | neighbors_count!("neighbors_count_1000", 1000); 207 | #[cfg(feature = "sbench")] 208 | neighbors_count!("neighbors_count_m", 10_000_000); 209 | 210 | macro_rules! in_neighbors_count { 211 | ($str: tt ,$x: expr) => { 212 | c.bench_function($str, |b| { 213 | let mut graph: Graph = Graph::new(); 214 | 215 | let mut v1 = graph.add_vertex(0); 216 | 217 | for i in 1..=$x { 218 | let v2 = graph.add_vertex(i); 219 | graph.add_edge(&v1, &v2); 220 | v1 = v2.clone(); 221 | } 222 | b.iter(|| { 223 | let _k = graph.in_neighbors_count(&v1); 224 | }) 225 | }); 226 | }; 227 | } 228 | in_neighbors_count!("in_neighbors_count_10", 10); 229 | in_neighbors_count!("in_neighbors_count_100", 100); 230 | in_neighbors_count!("in_neighbors_count_500", 500); 231 | in_neighbors_count!("in_neighbors_count_1000", 1000); 232 | #[cfg(feature = "sbench")] 233 | in_neighbors_count!("in_neighbors_count_m", 10_000_000); 234 | 235 | macro_rules! out_neighbors_count { 236 | ($str: tt ,$x: expr) => { 237 | c.bench_function($str, |b| { 238 | let mut graph: Graph = Graph::new(); 239 | 240 | let mut v1 = graph.add_vertex(0); 241 | 242 | for i in 1..=$x { 243 | let v2 = graph.add_vertex(i); 244 | graph.add_edge(&v1, &v2); 245 | v1 = v2.clone(); 246 | } 247 | b.iter(|| { 248 | let _k = graph.out_neighbors_count(&v1); 249 | }) 250 | }); 251 | }; 252 | } 253 | 254 | out_neighbors_count!("out_neighbors_count_10", 10); 255 | out_neighbors_count!("out_neighbors_count_100", 100); 256 | out_neighbors_count!("out_neighbors_count_500", 500); 257 | out_neighbors_count!("out_neighbors_count_1000", 1000); 258 | #[cfg(feature = "sbench")] 259 | out_neighbors_count!("out_neighbors_count_m", 10_000_000); 260 | 261 | macro_rules! in_neighbors { 262 | ($str: tt ,$x: expr) => { 263 | c.bench_function($str, |b| { 264 | let mut neighbors = vec![]; 265 | let mut graph: Graph = Graph::new(); 266 | 267 | let mut v1 = graph.add_vertex(0); 268 | 269 | for i in 1..=$x { 270 | let v2 = graph.add_vertex(i); 271 | graph.add_edge(&v1, &v2); 272 | v1 = v2.clone(); 273 | } 274 | b.iter(|| { 275 | for v in graph.in_neighbors(&v1) { 276 | neighbors.push(v); 277 | } 278 | }) 279 | }); 280 | }; 281 | } 282 | in_neighbors!("in_neighbors_10", 10); 283 | in_neighbors!("in_neighbors_100", 100); 284 | in_neighbors!("in_neighbors_500", 500); 285 | in_neighbors!("in_neighbors_1000", 1000); 286 | #[cfg(feature = "sbench")] 287 | in_neighbors!("in_neighbors_m", 10_000_000); 288 | 289 | macro_rules! out_neighbors { 290 | ($str: tt ,$x: expr) => { 291 | c.bench_function($str, |b| { 292 | let mut graph: Graph = Graph::new(); 293 | let mut neighbors = vec![]; 294 | 295 | let mut v1 = graph.add_vertex(0); 296 | 297 | for i in 1..=$x { 298 | let v2 = graph.add_vertex(i); 299 | graph.add_edge(&v1, &v2); 300 | v1 = v2.clone(); 301 | } 302 | b.iter(|| { 303 | for v in graph.out_neighbors(&v1) { 304 | neighbors.push(v); 305 | } 306 | }) 307 | }); 308 | }; 309 | } 310 | 311 | out_neighbors!("out_neighbors_10", 10); 312 | out_neighbors!("out_neighbors_100", 100); 313 | out_neighbors!("out_neighbors_500", 500); 314 | out_neighbors!("out_neighbors_1000", 1000); 315 | #[cfg(feature = "sbench")] 316 | out_neighbors!("out_neighbors_m", 10_000_000); 317 | 318 | macro_rules! neighbors { 319 | ($str: tt ,$x: expr) => { 320 | c.bench_function($str, |b| { 321 | let mut graph: Graph = Graph::new(); 322 | let mut neighbors = vec![]; 323 | 324 | let mut v1 = graph.add_vertex(0); 325 | 326 | for i in 1..=$x { 327 | let v2 = graph.add_vertex(i); 328 | graph.add_edge(&v1, &v2); 329 | v1 = v2.clone(); 330 | } 331 | 332 | b.iter(|| { 333 | for v in graph.neighbors(&v1) { 334 | neighbors.push(v); 335 | } 336 | }) 337 | }); 338 | }; 339 | } 340 | neighbors!("neighbors_10", 10); 341 | neighbors!("neighbors_100", 100); 342 | neighbors!("neighbors_500", 500); 343 | neighbors!("neighbors_1000", 1000); 344 | #[cfg(feature = "sbench")] 345 | neighbors!("neighbors_m", 10_000_000); 346 | } 347 | 348 | // includes benches for : 349 | // 1. add_edge(&mut self, a: &VertexId, b: &VertexId) -> Result<(), GraphErr> 350 | // 2. add_vertex(&mut self, item: T) -> VertexId 351 | // 3. capacity(&self) -> usize 352 | // 4. edge_count(&self) -> usize 353 | // 5. fetch(&self, id: &VertexId) -> Option<&T> 354 | // 6. fetch_mut(&mut self, id: &VertexId) -> Option<&mut T> 355 | // 7. fold(&self, initial: A, fun: impl Fn(&T, A) -> A) -> A 356 | // 8. has_edge(&self, a: &VertexId, b: &VertexId) -> bool 357 | // 9. is_cyclic(&self) -> bool 358 | // 10.remove(&mut self, id: &VertexId) 359 | // 11.remove_edge(&mut self, a: &VertexId, b: &VertexId) 360 | // 12.reserve(&mut self, additional: usize) 361 | // 13.retain(&mut self, fun: impl Fn(&T) -> bool) 362 | // 14.roots_count(&self) -> usize 363 | // 15.shrink_to_fit(&mut self) 364 | // 16.vertex_count(&self) -> usize 365 | fn bench_others(c: &mut Criterion) { 366 | macro_rules! add_edge { 367 | ($str: tt ,$x: expr) => { 368 | c.bench_function($str, |b| { 369 | let mut graph: Graph = Graph::new(); 370 | b.iter(|| { 371 | let mut v1 = graph.add_vertex(0); 372 | 373 | for i in 1..=$x { 374 | let v2 = graph.add_vertex(i); 375 | graph.add_edge(&v1, &v2); 376 | v1 = v2.clone(); 377 | } 378 | }) 379 | }); 380 | }; 381 | } 382 | add_edge!("add_edge_10", 10); 383 | add_edge!("add_edge_100", 100); 384 | add_edge!("add_edge_500", 500); 385 | add_edge!("add_edge_1000", 1000); 386 | #[cfg(feature = "sbench")] 387 | add_edge!("add_edge_m", 10_000_000); 388 | 389 | macro_rules! add_edge_cycle_check { 390 | ($str: tt ,$x: expr) => { 391 | c.bench_function($str, |b| { 392 | let mut graph: Graph = Graph::new(); 393 | b.iter(|| { 394 | let mut v1 = graph.add_vertex(0); 395 | 396 | for i in 1..=$x { 397 | let v2 = graph.add_vertex(i); 398 | graph.add_edge_check_cycle(&v1, &v2); 399 | v1 = v2.clone(); 400 | } 401 | }) 402 | }); 403 | }; 404 | } 405 | add_edge_cycle_check!("add_edge_cycle_check_10", 10); 406 | add_edge_cycle_check!("add_edge_cycle_check_100", 100); 407 | add_edge_cycle_check!("add_edge_cycle_check_500", 500); 408 | add_edge_cycle_check!("add_edge_cycle_check_1000", 1000); 409 | #[cfg(feature = "sbench")] 410 | add_edge_cycle_check!("add_edge_cycle_check_m", 10_000_000); 411 | 412 | macro_rules! add_vertex { 413 | ($str: tt ,$x: expr) => { 414 | c.bench_function($str, |b| { 415 | let mut graph: Graph = Graph::new(); 416 | b.iter(|| { 417 | for i in 1..=$x { 418 | graph.add_vertex(i); 419 | } 420 | }) 421 | }); 422 | }; 423 | } 424 | add_vertex!("add_vertex_10", 10); 425 | add_vertex!("add_vertex_100", 100); 426 | add_vertex!("add_vertex_500", 500); 427 | add_vertex!("add_vertex_1000", 1000); 428 | #[cfg(feature = "sbench")] 429 | add_vertex!("add_vertex_m", 10_000_000); 430 | 431 | macro_rules! capacity { 432 | ($str: tt ,$x: expr) => { 433 | c.bench_function($str, |b| { 434 | let graph: Graph = Graph::with_capacity($x); 435 | b.iter(|| { 436 | let _k = graph.capacity(); 437 | }) 438 | }); 439 | }; 440 | } 441 | 442 | capacity!("capacity_10", 10); 443 | capacity!("capacity_100", 100); 444 | capacity!("capacity_500", 500); 445 | capacity!("capacity_1000", 1000); 446 | #[cfg(feature = "sbench")] 447 | capacity!("capacity_m", 10_000_000); 448 | 449 | macro_rules! edge_count { 450 | ($str: tt ,$x: expr) => { 451 | c.bench_function($str, |b| { 452 | let mut graph: Graph = Graph::new(); 453 | 454 | let mut v1 = graph.add_vertex(0); 455 | 456 | for i in 1..=$x { 457 | let v2 = graph.add_vertex(i); 458 | graph.add_edge(&v1, &v2); 459 | v1 = v2.clone(); 460 | } 461 | b.iter(|| { 462 | let _k = graph.edge_count(); 463 | }) 464 | }); 465 | }; 466 | } 467 | edge_count!("edge_count_10", 10); 468 | edge_count!("edge_count_100", 100); 469 | edge_count!("edge_count_500", 500); 470 | edge_count!("edge_count_1000", 1000); 471 | #[cfg(feature = "sbench")] 472 | edge_count!("edge_count_m", 10_000_000); 473 | 474 | macro_rules! fetch { 475 | ($str: tt ,$x: expr) => { 476 | c.bench_function($str, |b| { 477 | let mut graph: Graph = Graph::new(); 478 | 479 | for i in 1..$x { 480 | graph.add_vertex(i); 481 | } 482 | let id = graph.add_vertex($x); 483 | b.iter(|| { 484 | let _k = *graph.fetch(&id).unwrap(); 485 | }) 486 | }); 487 | }; 488 | } 489 | fetch!("fetch_10", 10); 490 | fetch!("fetch_100", 100); 491 | fetch!("fetch_500", 500); 492 | fetch!("fetch_1000", 1000); 493 | #[cfg(feature = "sbench")] 494 | fetch!("fetch_m", 10_000_000); 495 | 496 | macro_rules! fetch_mut { 497 | ($str: tt ,$x: expr) => { 498 | c.bench_function($str, |b| { 499 | let mut graph: Graph = Graph::new(); 500 | for i in 1..$x { 501 | graph.add_vertex(i); 502 | } 503 | let id = graph.add_vertex($x); 504 | b.iter(|| { 505 | let _v = graph.fetch_mut(&id).unwrap(); 506 | }) 507 | }); 508 | }; 509 | } 510 | fetch_mut!("fetch_mut_10", 10); 511 | fetch_mut!("fetch_mut_100", 100); 512 | fetch_mut!("fetch_mut_500", 500); 513 | fetch_mut!("fetch_mut_1000", 1000); 514 | #[cfg(feature = "sbench")] 515 | fetch_mut!("fetch_mut_m", 10_000_000); 516 | 517 | macro_rules! fold { 518 | ($str: tt ,$x: expr) => { 519 | c.bench_function($str, |b| { 520 | let mut graph: Graph = Graph::new(); 521 | 522 | for i in 1..=$x { 523 | graph.add_vertex(i); 524 | } 525 | 526 | b.iter(|| { 527 | let _result = graph.fold(0, |v, acc| v + acc); 528 | }) 529 | }); 530 | }; 531 | } 532 | fold!("fold_10", 10); 533 | fold!("fold_100", 100); 534 | fold!("fold_500", 500); 535 | fold!("fold_1000", 1000); 536 | #[cfg(feature = "sbench")] 537 | fold!("fold_m", 10_000_000); 538 | 539 | macro_rules! has_edge { 540 | ($str: tt ,$x: expr) => { 541 | c.bench_function($str, |b| { 542 | let mut graph: Graph = Graph::new(); 543 | 544 | let v1 = graph.add_vertex(1); 545 | let v2 = graph.add_vertex(2); 546 | 547 | for i in 3..=$x { 548 | graph.add_vertex(i); 549 | } 550 | let v3 = graph.add_vertex(3); 551 | 552 | graph.add_edge(&v1, &v2).unwrap(); 553 | b.iter(|| { 554 | let _k = graph.has_edge(&v1, &v2); 555 | let _l = graph.has_edge(&v2, &v3); 556 | }) 557 | }); 558 | }; 559 | } 560 | has_edge!("has_edge_10", 10); 561 | has_edge!("has_edge_100", 100); 562 | has_edge!("has_edge_500", 500); 563 | has_edge!("has_edge_1000", 1000); 564 | #[cfg(feature = "sbench")] 565 | has_edge!("has_edge_m", 10_000_000); 566 | 567 | macro_rules! is_cyclic { 568 | ($str: tt ,$x: expr) => { 569 | c.bench_function($str, |b| { 570 | let mut graph: Graph = Graph::new(); 571 | 572 | let v0 = graph.add_vertex(0); 573 | let mut v1 = graph.add_vertex(1); 574 | let mut v2 = graph.add_vertex(2); 575 | graph.add_edge(&v0, &v1); 576 | graph.add_edge(&v1, &v2); 577 | for i in 4..=$x { 578 | v1 = v2.clone(); 579 | v2 = graph.add_vertex(i); 580 | graph.add_edge(&v1, &v2); 581 | } 582 | graph.add_edge(&v2, &v0); 583 | b.iter(|| { 584 | let _k = graph.is_cyclic(); 585 | }) 586 | }); 587 | }; 588 | } 589 | is_cyclic!("is_cyclic_10", 10); 590 | is_cyclic!("is_cyclic_100", 100); 591 | is_cyclic!("is_cyclic_500", 500); 592 | is_cyclic!("is_cyclic_1000", 1000); 593 | #[cfg(feature = "sbench")] 594 | is_cyclic!("is_cyclic_m", 10_000_000); 595 | 596 | macro_rules! remove { 597 | ($str: tt ,$x: expr) => { 598 | c.bench_function($str, |b| { 599 | let mut graph: Graph = Graph::new(); 600 | b.iter(|| { 601 | for i in 1..=$x { 602 | let v1 = graph.add_vertex(i); 603 | graph.remove(&v1); 604 | } 605 | }) 606 | }); 607 | }; 608 | } 609 | remove!("remove_10", 10); 610 | remove!("remove_100", 100); 611 | remove!("remove_500", 500); 612 | remove!("remove_1000", 1000); 613 | #[cfg(feature = "sbench")] 614 | remove!("remove_m", 10_000_000); 615 | 616 | macro_rules! remove_edge { 617 | ($str: tt ,$x: expr) => { 618 | c.bench_function($str, |b| { 619 | let mut graph: Graph = Graph::new(); 620 | b.iter(|| { 621 | let mut v1 = graph.add_vertex(0); 622 | 623 | for i in 1..=$x { 624 | let v2 = graph.add_vertex(i); 625 | graph.add_edge(&v1, &v2); 626 | v1 = v2.clone(); 627 | graph.remove_edge(&v1, &v2); 628 | } 629 | }) 630 | }); 631 | }; 632 | } 633 | 634 | remove_edge!("remove_edge_10", 10); 635 | remove_edge!("remove_edge_100", 100); 636 | remove_edge!("remove_edge_500", 500); 637 | remove_edge!("remove_edge_1000", 1000); 638 | #[cfg(feature = "sbench")] 639 | remove_edge!("remove_edge_m", 10_000_000); 640 | 641 | macro_rules! reserve { 642 | ($str: tt ,$x: expr) => { 643 | c.bench_function($str, |b| { 644 | let mut graph: Graph = Graph::with_capacity($x); 645 | 646 | for i in 1..=$x { 647 | graph.add_vertex(i); 648 | } 649 | 650 | b.iter(|| { 651 | graph.reserve($x); 652 | }) 653 | }); 654 | }; 655 | } 656 | 657 | reserve!("reserve_10", 10); 658 | reserve!("reserve_100", 100); 659 | reserve!("reserve_500", 500); 660 | reserve!("reserve_1000", 1000); 661 | #[cfg(feature = "sbench")] 662 | reserve!("reserve_m", 10_000_000); 663 | 664 | macro_rules! retain { 665 | ($str: tt ,$x: expr) => { 666 | c.bench_function($str, |b| { 667 | let mut graph: Graph = Graph::new(); 668 | 669 | for i in 1..=$x { 670 | graph.add_vertex(i); 671 | } 672 | b.iter(|| { 673 | graph.retain(|v| *v != 2); 674 | }) 675 | }); 676 | }; 677 | } 678 | 679 | retain!("retain_10", 10); 680 | retain!("retain_100", 100); 681 | retain!("retain_500", 500); 682 | retain!("retain_1000", 1000); 683 | #[cfg(feature = "sbench")] 684 | retain!("retain_m", 10_000_000); 685 | 686 | macro_rules! roots_count { 687 | ($str: tt ,$x: expr) => { 688 | c.bench_function($str, |b| { 689 | let mut graph: Graph = Graph::new(); 690 | let mut v1 = graph.add_vertex(0); 691 | 692 | for i in 1..=$x { 693 | let v2 = graph.add_vertex(i); 694 | graph.add_edge(&v1, &v2); 695 | v1 = v2.clone(); 696 | } 697 | b.iter(|| { 698 | let _k = graph.roots_count(); 699 | }) 700 | }); 701 | }; 702 | } 703 | roots_count!("roots_count_10", 10); 704 | roots_count!("roots_count_100", 100); 705 | roots_count!("roots_count_500", 500); 706 | roots_count!("roots_count_1000", 1000); 707 | #[cfg(feature = "sbench")] 708 | roots_count!("roots_count_m", 10_000_000); 709 | 710 | macro_rules! shrink_to_fit { 711 | ($str: tt ,$x: expr) => { 712 | c.bench_function($str, |b| { 713 | let mut graph: Graph = Graph::with_capacity($x); 714 | 715 | b.iter(|| { 716 | graph.shrink_to_fit(); 717 | }) 718 | }); 719 | }; 720 | } 721 | shrink_to_fit!("shrink_to_fit_10", 10); 722 | shrink_to_fit!("shrink_to_fit_100", 100); 723 | shrink_to_fit!("shrink_to_fit_500", 500); 724 | shrink_to_fit!("shrink_to_fit_1000", 1000); 725 | #[cfg(feature = "sbench")] 726 | shrink_to_fit!("shrink_to_fit_m", 10_000_000); 727 | 728 | macro_rules! vertex_count { 729 | ($str: tt ,$x: expr) => { 730 | c.bench_function($str, |b| { 731 | let mut graph: Graph = Graph::new(); 732 | 733 | for i in 1..=$x { 734 | graph.add_vertex(i); 735 | } 736 | b.iter(|| { 737 | let _k = graph.vertex_count(); 738 | }) 739 | }); 740 | }; 741 | } 742 | vertex_count!("vertex_count_10", 10); 743 | vertex_count!("vertex_count_100", 100); 744 | vertex_count!("vertex_count_500", 500); 745 | vertex_count!("vertex_count_1000", 1000); 746 | #[cfg(feature = "sbench")] 747 | vertex_count!("vertex_count_m", 10_000_000); 748 | } 749 | 750 | criterion_group!( 751 | benches, 752 | bench_create, 753 | bench_iterators, 754 | bench_neighbor_functions, 755 | bench_others 756 | ); 757 | 758 | criterion_main!(benches); 759 | -------------------------------------------------------------------------------- /examples/dot.rs: -------------------------------------------------------------------------------- 1 | use graphlib::Graph; 2 | 3 | pub fn main() { 4 | // This example requires the `dot` feature. 5 | use std::fs::File; 6 | let mut f = File::create("example1.dot").unwrap(); 7 | 8 | let mut graph: Graph = Graph::new(); 9 | 10 | let v1 = graph.add_vertex("test1".to_string()); 11 | let v2 = graph.add_vertex("test2".to_string()); 12 | let v3 = graph.add_vertex("test3".to_string()); 13 | let v4 = graph.add_vertex("test4".to_string()); 14 | let v5 = graph.add_vertex("test5".to_string()); 15 | let v6 = graph.add_vertex("test6".to_string()); 16 | 17 | #[cfg(feature = "dot")] 18 | { 19 | graph.add_vertex_label(&v1, "label: test1").unwrap(); 20 | graph.add_vertex_label(&v2, "label: test2").unwrap(); 21 | graph.add_vertex_label(&v3, "label: test3").unwrap(); 22 | graph.add_vertex_label(&v4, "label: test4").unwrap(); 23 | graph.add_vertex_label(&v5, "label: test5").unwrap(); 24 | graph.add_vertex_label(&v6, "label: test6").unwrap(); 25 | } 26 | 27 | graph.add_edge(&v1, &v2).unwrap(); 28 | graph.add_edge(&v3, &v1).unwrap(); 29 | graph.add_edge(&v1, &v4).unwrap(); 30 | graph.add_edge(&v5, &v6).unwrap(); 31 | 32 | #[cfg(feature = "dot")] 33 | { 34 | graph.add_edge_label(&v1, &v2, "V1→V2").unwrap(); 35 | graph.add_edge_label(&v3, &v1, "V3→V1").unwrap(); 36 | graph.add_edge_label(&v1, &v4, "V1→V4").unwrap(); 37 | graph.add_edge_label(&v5, &v6, "V5→V6").unwrap(); 38 | } 39 | 40 | #[cfg(feature = "dot")] 41 | graph.to_dot("example1", &mut f).unwrap(); 42 | } 43 | -------------------------------------------------------------------------------- /examples/example1.dot: -------------------------------------------------------------------------------- 1 | digraph example1 { 2 | test1[label="test1"]; 3 | test2[label="test2"]; 4 | test3[label="test3"]; 5 | test4[label="test4"]; 6 | test5[label="test5"]; 7 | test6[label="test6"]; 8 | test2 -> test1[label=""]; 9 | test1 -> test3[label=""]; 10 | test4 -> test1[label=""]; 11 | test6 -> test5[label=""]; 12 | } 13 | -------------------------------------------------------------------------------- /src/dot.rs: -------------------------------------------------------------------------------- 1 | use crate::{Graph, GraphErr, VertexId}; 2 | 3 | #[cfg(feature = "no_std")] 4 | use core::io::Write; 5 | 6 | #[cfg(not(feature = "no_std"))] 7 | use std::io::Write; 8 | 9 | #[cfg(feature = "no_std")] 10 | use core::borrow::Cow; 11 | 12 | #[cfg(not(feature = "no_std"))] 13 | use std::borrow::Cow; 14 | 15 | #[cfg(feature = "no_std")] 16 | use core::fmt::Debug; 17 | 18 | #[cfg(not(feature = "no_std"))] 19 | use std::fmt::Debug; 20 | 21 | type Nd = VertexId; 22 | type Ed<'a> = (&'a VertexId, &'a VertexId); 23 | 24 | 25 | pub(crate) struct DotGraph<'a, T> { 26 | name: dot::Id<'a>, 27 | graph: &'a Graph, 28 | } 29 | 30 | 31 | impl<'a, T> DotGraph<'a, T> { 32 | pub fn new(graph: &'a Graph, name: &'a str) -> Result, GraphErr> { 33 | let name = dot::Id::new(name) 34 | .map_err(|_| GraphErr::InvalidGraphName)?; 35 | Ok(DotGraph { name, graph }) 36 | } 37 | } 38 | 39 | 40 | impl<'a, T> dot::Labeller<'a, Nd, Ed<'a>> for DotGraph<'a, T> { 41 | fn graph_id(&'a self) -> dot::Id<'a> { 42 | dot::Id::new(self.name.as_slice()).unwrap() 43 | } 44 | 45 | fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { 46 | let hex = format!("N{}", hex::encode(n.bytes())); 47 | dot::Id::new(hex).unwrap() 48 | } 49 | 50 | fn node_label<'b>(&'b self, n: &Nd) -> dot::LabelText<'b> { 51 | let label = self.graph.vertex_label(n).unwrap(); 52 | dot::LabelText::label(Cow::Borrowed(label)) 53 | } 54 | 55 | fn edge_label<'b>(&'b self, e: &Ed) -> dot::LabelText<'b> { 56 | let label = self.graph.edge_label(e.0, e.1).unwrap(); 57 | dot::LabelText::LabelStr(Cow::Borrowed(label)) 58 | } 59 | } 60 | 61 | 62 | impl<'a, T> dot::GraphWalk<'a, Nd, Ed<'a>> for DotGraph<'a, T> { 63 | fn nodes(&self) -> dot::Nodes<'a, Nd> { 64 | let nodes = self.graph.vertices().cloned().collect(); 65 | Cow::Owned(nodes) 66 | } 67 | 68 | fn edges(&'a self) -> dot::Edges<'a, Ed<'a>> { 69 | self.graph.edges() 70 | .map(|e| (e.1, e.0)) 71 | .collect() 72 | } 73 | 74 | fn source(&self, e: &Ed) -> Nd { 75 | *e.0 76 | } 77 | 78 | fn target(&self, e: &Ed) -> Nd { 79 | *e.1 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/edge.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | use crate::vertex_id::VertexId; 4 | #[cfg(not(feature = "no_std"))] 5 | use std::hash::Hash; 6 | #[cfg(not(feature = "no_std"))] 7 | use std::hash::Hasher; 8 | 9 | #[cfg(feature = "no_std")] 10 | extern crate alloc; 11 | #[cfg(feature = "no_std")] 12 | use core::hash::{Hash, Hasher}; 13 | 14 | #[derive(Clone, Debug)] 15 | /// Edge internal struct 16 | pub struct Edge { 17 | inbound: VertexId, 18 | outbound: VertexId, 19 | } 20 | 21 | impl PartialEq for Edge { 22 | fn eq(&self, other: &Edge) -> bool { 23 | self.inbound == other.inbound && self.outbound == other.outbound 24 | } 25 | } 26 | 27 | impl Eq for Edge {} 28 | 29 | impl Hash for Edge { 30 | fn hash(&self, state: &mut H) { 31 | self.inbound.hash(state); 32 | self.outbound.hash(state); 33 | } 34 | } 35 | 36 | impl Edge { 37 | pub fn new(outbound: VertexId, inbound: VertexId) -> Edge { 38 | Edge { inbound, outbound } 39 | } 40 | 41 | /// Returns true if the given vertex ids are the 42 | /// inbound and outbound vertices of the edge. 43 | pub(crate) fn matches(&self, a: &VertexId, b: &VertexId) -> bool { 44 | a == &self.outbound && b == &self.inbound 45 | } 46 | 47 | /// Returns true if either the inbound or outbound 48 | /// vertex is matching the given `VertexId`. 49 | pub(crate) fn matches_any(&self, id: &VertexId) -> bool { 50 | id == &self.inbound || id == &self.outbound 51 | } 52 | 53 | /// Returns the inbound VertexId 54 | pub(crate) fn inbound(&self) -> &VertexId { 55 | &self.inbound 56 | } 57 | 58 | /// Returns the inbound VertexId 59 | pub(crate) fn outbound(&self) -> &VertexId { 60 | &self.outbound 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/graph.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | use crate::edge::Edge; 4 | use crate::iterators::*; 5 | use crate::vertex_id::VertexId; 6 | use hashbrown::{HashMap, HashSet}; 7 | 8 | #[cfg(feature = "no_std")] 9 | use core::iter; 10 | #[cfg(not(feature = "no_std"))] 11 | use std::iter; 12 | 13 | #[cfg(feature = "no_std")] 14 | use core::fmt::Debug; 15 | #[cfg(not(feature = "no_std"))] 16 | use std::fmt::Debug; 17 | 18 | #[cfg(feature = "no_std")] 19 | extern crate alloc; 20 | #[cfg(feature = "no_std")] 21 | use alloc::boxed::Box; 22 | #[cfg(feature = "no_std")] 23 | use alloc::vec; 24 | #[cfg(feature = "no_std")] 25 | use alloc::vec::Vec; 26 | 27 | #[cfg(feature = "dot")] 28 | use super::SEED; 29 | 30 | #[derive(Clone, Debug, PartialEq)] 31 | /// Graph operation error 32 | pub enum GraphErr { 33 | /// There is no vertex with the given id in the graph 34 | NoSuchVertex, 35 | 36 | /// There is no such edge in the graph 37 | NoSuchEdge, 38 | 39 | /// Could not add an edge to the graph 40 | CannotAddEdge, 41 | 42 | /// The given weight is invalid 43 | InvalidWeight, 44 | 45 | /// The operation cannot be performed as it will 46 | /// create a cycle in the graph. 47 | CycleError, 48 | 49 | #[cfg(feature = "dot")] 50 | /// Could not render .dot file 51 | CouldNotRender, 52 | 53 | #[cfg(feature = "dot")] 54 | /// The name of the graph is invalid. Check [this](https://docs.rs/dot/0.1.1/dot/struct.Id.html#method.new) 55 | /// out for more information. 56 | InvalidGraphName, 57 | } 58 | 59 | #[derive(Clone, Debug, Default)] 60 | /// Graph data-structure 61 | pub struct Graph { 62 | /// Mapping of vertex ids and vertex values 63 | vertices: HashMap, 64 | 65 | /// Mapping between edges and weights 66 | edges: HashMap, 67 | 68 | /// Set containing the roots of the graph 69 | roots: HashSet, 70 | 71 | /// Set containing the tips of the graph 72 | tips: HashSet, 73 | 74 | /// Mapping between vertex ids and inbound edges 75 | inbound_table: HashMap>, 76 | 77 | /// Mapping between vertex ids and outbound edges 78 | outbound_table: HashMap>, 79 | 80 | #[cfg(feature = "dot")] 81 | /// Mapping between vertices and labels 82 | vertex_labels: HashMap, 83 | 84 | #[cfg(feature = "dot")] 85 | /// Mapping between edges and labels 86 | edge_labels: HashMap, 87 | } 88 | 89 | impl Graph { 90 | /// Creates a new graph. 91 | /// 92 | /// ## Example 93 | /// ```rust 94 | /// use graphlib::Graph; 95 | /// 96 | /// let mut graph: Graph = Graph::new(); 97 | /// 98 | /// graph.add_vertex(0); 99 | /// assert_eq!(graph.vertex_count(), 1); 100 | /// ``` 101 | pub fn new() -> Graph { 102 | Graph { 103 | vertices: HashMap::new(), 104 | edges: HashMap::new(), 105 | roots: HashSet::new(), 106 | tips: HashSet::new(), 107 | inbound_table: HashMap::new(), 108 | outbound_table: HashMap::new(), 109 | 110 | #[cfg(feature = "dot")] 111 | vertex_labels: HashMap::new(), 112 | #[cfg(feature = "dot")] 113 | edge_labels: HashMap::new(), 114 | } 115 | } 116 | 117 | /// Creates a new graph with the given capacity. 118 | /// 119 | /// ## Example 120 | /// ```rust 121 | /// use graphlib::Graph; 122 | /// 123 | /// let mut graph: Graph = Graph::with_capacity(5); 124 | /// ``` 125 | pub fn with_capacity(capacity: usize) -> Graph { 126 | let edges_capacity = if capacity < 100 { 127 | usize::pow(capacity, 2) 128 | } else { 129 | capacity 130 | }; 131 | 132 | Graph { 133 | vertices: HashMap::with_capacity(capacity), 134 | edges: HashMap::with_capacity(edges_capacity), 135 | roots: HashSet::with_capacity(capacity), 136 | tips: HashSet::with_capacity(capacity), 137 | inbound_table: HashMap::with_capacity(capacity), 138 | outbound_table: HashMap::with_capacity(capacity), 139 | 140 | #[cfg(feature = "dot")] 141 | vertex_labels: HashMap::with_capacity(capacity), 142 | #[cfg(feature = "dot")] 143 | edge_labels: HashMap::with_capacity(capacity), 144 | } 145 | } 146 | 147 | /// Returns the current capacity of the graph. 148 | /// ## Example 149 | /// ```rust 150 | /// use graphlib::Graph; 151 | /// 152 | /// let mut graph: Graph = Graph::with_capacity(5); 153 | /// 154 | /// assert!(graph.capacity() >= 5); 155 | /// ``` 156 | pub fn capacity(&self) -> usize { 157 | min!( 158 | self.vertices.capacity(), 159 | self.edges.capacity(), 160 | self.roots.capacity(), 161 | self.tips.capacity(), 162 | self.inbound_table.capacity(), 163 | self.outbound_table.capacity() 164 | ) 165 | } 166 | 167 | /// Reserves capacity for at least additional more elements to be inserted in the given 168 | /// graph. After calling reserve, capacity will be greater than or equal to `self.vertex_count() + additional`. 169 | /// 170 | /// ## Example 171 | /// ```rust 172 | /// use graphlib::Graph; 173 | /// 174 | /// let mut graph: Graph = Graph::with_capacity(3); 175 | /// 176 | /// assert_eq!(graph.capacity(), 3); 177 | /// 178 | /// graph.add_vertex(0); 179 | /// graph.add_vertex(1); 180 | /// graph.add_vertex(2); 181 | /// 182 | /// graph.reserve(10); 183 | /// assert!(graph.capacity() >= 13); 184 | /// ``` 185 | pub fn reserve(&mut self, additional: usize) { 186 | // Calculate additional value for edges vector 187 | // such that it is always n^2 where n is the 188 | // number of vertices that are currently placed 189 | // in the graph. 190 | let new_capacity = self.vertices.len() + additional; 191 | let edges_capacity = if new_capacity < 100 { 192 | usize::pow(new_capacity, 2) 193 | } else { 194 | new_capacity 195 | }; 196 | let edges_count = self.edges.len(); 197 | let edges_additional = edges_capacity - edges_count; 198 | 199 | self.edges.reserve(edges_additional); 200 | self.roots.reserve(additional); 201 | self.tips.reserve(additional); 202 | self.vertices.reserve(additional); 203 | self.outbound_table.reserve(additional); 204 | self.inbound_table.reserve(additional); 205 | 206 | #[cfg(feature = "dot")] 207 | self.vertex_labels.reserve(additional); 208 | #[cfg(feature = "dot")] 209 | self.edge_labels.reserve(additional); 210 | } 211 | 212 | /// Shrinks the capacity of the graph as much as possible. 213 | /// 214 | /// It will drop down as close as possible to the length but the allocator may still inform the 215 | /// vector that there is space for a few more elements. 216 | /// ## Example 217 | /// ```rust 218 | /// use graphlib::Graph; 219 | /// 220 | /// let mut graph: Graph = Graph::with_capacity(5); 221 | /// 222 | /// assert!(graph.capacity() >= 5); 223 | /// 224 | /// graph.shrink_to_fit(); 225 | /// assert!(graph.capacity() < 5); 226 | /// ``` 227 | pub fn shrink_to_fit(&mut self) { 228 | self.edges.shrink_to_fit(); 229 | self.roots.shrink_to_fit(); 230 | self.tips.shrink_to_fit(); 231 | self.vertices.shrink_to_fit(); 232 | self.outbound_table.shrink_to_fit(); 233 | self.inbound_table.shrink_to_fit(); 234 | 235 | #[cfg(feature = "dot")] 236 | self.vertex_labels.shrink_to_fit(); 237 | #[cfg(feature = "dot")] 238 | self.edge_labels.shrink_to_fit(); 239 | 240 | // Calculate additional value for edges vector 241 | // such that it is always n^2 where n is the 242 | // number of vertices that are currently placed 243 | // in the graph. 244 | let edges_capacity = usize::pow(self.vertices.len(), 2); 245 | let edges_count = self.edges.len(); 246 | let edges_additional = edges_capacity - edges_count; 247 | 248 | self.edges.reserve(edges_additional); 249 | } 250 | 251 | /// Adds a new vertex to the graph and returns the id 252 | /// of the added vertex. 253 | /// 254 | /// ## Example 255 | /// ```rust 256 | /// use graphlib::Graph; 257 | /// 258 | /// let mut graph: Graph = Graph::new(); 259 | /// let id = graph.add_vertex(1); 260 | /// 261 | /// assert_eq!(graph.fetch(&id).unwrap(), &1); 262 | /// ``` 263 | pub fn add_vertex(&mut self, item: T) -> VertexId { 264 | let id = VertexId::random(); 265 | 266 | self.vertices.insert(id, (item, id)); 267 | self.roots.insert(id); 268 | self.tips.insert(id); 269 | 270 | id 271 | } 272 | 273 | /// Attempts to place a new edge in the graph. 274 | /// 275 | /// ## Example 276 | /// ```rust 277 | /// use graphlib::{Graph, GraphErr, VertexId}; 278 | /// 279 | /// let mut graph: Graph = Graph::new(); 280 | /// 281 | /// // Id of vertex that is not place in the graph 282 | /// let id = VertexId::random(); 283 | /// 284 | /// let v1 = graph.add_vertex(1); 285 | /// let v2 = graph.add_vertex(2); 286 | /// 287 | /// // Adding an edge is idempotent 288 | /// graph.add_edge(&v1, &v2); 289 | /// graph.add_edge(&v1, &v2); 290 | /// graph.add_edge(&v1, &v2); 291 | /// 292 | /// // Fails on adding an edge between an 293 | /// // existing vertex and a non-existing one. 294 | /// assert_eq!(graph.add_edge(&v1, &id), Err(GraphErr::NoSuchVertex)); 295 | /// ``` 296 | pub fn add_edge(&mut self, a: &VertexId, b: &VertexId) -> Result<(), GraphErr> { 297 | if self.has_edge(a, b) { 298 | return Ok(()); 299 | } 300 | 301 | self.do_add_edge(a, b, 0.0, false) 302 | } 303 | 304 | /// Attempts to place a new edge in the graph, checking if the specified 305 | /// edge will create a cycle in the graph. If it does, this operation will fail. 306 | /// 307 | /// Note that this operation has a bigger performance hit than `Graph::add_edge()`. 308 | /// 309 | /// ## Example 310 | /// ```rust 311 | /// use graphlib::{Graph, GraphErr, VertexId}; 312 | /// 313 | /// let mut graph: Graph = Graph::new(); 314 | /// 315 | /// // Id of vertex that is not place in the graph 316 | /// let id = VertexId::random(); 317 | /// 318 | /// let v1 = graph.add_vertex(1); 319 | /// let v2 = graph.add_vertex(2); 320 | /// 321 | /// // Adding an edge is idempotent 322 | /// graph.add_edge_check_cycle(&v1, &v2); 323 | /// graph.add_edge_check_cycle(&v1, &v2); 324 | /// graph.add_edge_check_cycle(&v1, &v2); 325 | /// 326 | /// // Fails on adding an edge which creates 327 | /// // a cycle in the graph. 328 | /// assert_eq!(graph.add_edge_check_cycle(&v2, &v1), Err(GraphErr::CycleError)); 329 | /// ``` 330 | pub fn add_edge_check_cycle(&mut self, a: &VertexId, b: &VertexId) -> Result<(), GraphErr> { 331 | if self.has_edge(a, b) { 332 | return Ok(()); 333 | } 334 | 335 | self.do_add_edge(a, b, 0.0, true) 336 | } 337 | 338 | /// Attempts to place a new edge in the graph. 339 | /// 340 | /// ## Example 341 | /// ```rust 342 | /// use graphlib::{Graph, GraphErr, VertexId}; 343 | /// 344 | /// let mut graph: Graph = Graph::new(); 345 | /// 346 | /// // Id of vertex that is not place in the graph 347 | /// let id = VertexId::random(); 348 | /// 349 | /// let v1 = graph.add_vertex(1); 350 | /// let v2 = graph.add_vertex(2); 351 | /// 352 | /// // Adding an edge is idempotent 353 | /// graph.add_edge_with_weight(&v1, &v2, 0.3); 354 | /// 355 | /// // Fails on adding an edge between an 356 | /// // existing vertex and a non-existing one. 357 | /// assert_eq!(graph.weight(&v1, &v2), Some(0.3)); 358 | /// ``` 359 | pub fn add_edge_with_weight( 360 | &mut self, 361 | a: &VertexId, 362 | b: &VertexId, 363 | weight: f32, 364 | ) -> Result<(), GraphErr> { 365 | if self.has_edge(a, b) { 366 | return Ok(()); 367 | } 368 | 369 | if weight > 1.0 || weight < -1.0 { 370 | return Err(GraphErr::InvalidWeight); 371 | } 372 | 373 | self.do_add_edge(a, b, weight, false) 374 | } 375 | 376 | /// Returns the weight of the specified edge 377 | /// if it is listed. 378 | /// 379 | /// ```rust 380 | /// use graphlib::{Graph, GraphErr, VertexId}; 381 | /// 382 | /// let mut graph: Graph = Graph::new(); 383 | /// 384 | /// // Id of vertex that is not place in the graph 385 | /// let id = VertexId::random(); 386 | /// 387 | /// let v1 = graph.add_vertex(1); 388 | /// let v2 = graph.add_vertex(2); 389 | /// let v3 = graph.add_vertex(3); 390 | /// 391 | /// // Adding an edge is idempotent 392 | /// graph.add_edge_with_weight(&v1, &v2, 0.54543); 393 | /// 394 | /// assert_eq!(graph.weight(&v1, &v2), Some(0.54543)); 395 | /// assert_eq!(graph.weight(&v1, &v3), None); 396 | /// ``` 397 | pub fn weight(&self, a: &VertexId, b: &VertexId) -> Option { 398 | if !self.has_edge(a, b) { 399 | return None; 400 | } 401 | 402 | if let Some(result) = self.edges.get(&Edge::new(*a, *b)) { 403 | Some(*result) 404 | } else { 405 | None 406 | } 407 | } 408 | 409 | /// Sets the weight of the edge to the new value 410 | /// if the edge exists in the graph. Note that 411 | /// the given weight must be a number between 412 | /// (and including) `-1.0` and `1.0`. 413 | /// 414 | /// ```rust 415 | /// use graphlib::{Graph, GraphErr, VertexId}; 416 | /// 417 | /// let mut graph: Graph = Graph::new(); 418 | /// 419 | /// // Id of vertex that is not place in the graph 420 | /// let id = VertexId::random(); 421 | /// 422 | /// let v1 = graph.add_vertex(1); 423 | /// let v2 = graph.add_vertex(2); 424 | /// let v3 = graph.add_vertex(3); 425 | /// 426 | /// graph.add_edge_with_weight(&v1, &v2, 0.54543); 427 | /// assert_eq!(graph.weight(&v1, &v2), Some(0.54543)); 428 | /// 429 | /// // Set new weight 430 | /// graph.set_weight(&v1, &v2, 0.123).unwrap(); 431 | /// assert_eq!(graph.weight(&v1, &v2), Some(0.123)); 432 | /// ``` 433 | pub fn set_weight( 434 | &mut self, 435 | a: &VertexId, 436 | b: &VertexId, 437 | new_weight: f32, 438 | ) -> Result<(), GraphErr> { 439 | if !self.has_edge(a, b) { 440 | return Err(GraphErr::NoSuchEdge); 441 | } 442 | 443 | if new_weight > 1.0 || new_weight < -1.0 { 444 | return Err(GraphErr::InvalidWeight); 445 | } 446 | 447 | self.edges.insert(Edge::new(*a, *b), new_weight); 448 | 449 | // Sort outbound vertices after setting a new weight 450 | let mut outbounds = self.outbound_table.get(a).unwrap().clone(); 451 | 452 | self.sort_outbounds(a.clone(), &mut outbounds); 453 | 454 | // Update outbounds 455 | self.outbound_table.insert(a.clone(), outbounds); 456 | 457 | Ok(()) 458 | } 459 | 460 | /// Checks whether or not exists an edge between 461 | /// the vertices with the given ids. 462 | /// 463 | /// ## Example 464 | /// ```rust 465 | /// use graphlib::Graph; 466 | /// 467 | /// let mut graph: Graph = Graph::new(); 468 | /// 469 | /// let v1 = graph.add_vertex(1); 470 | /// let v2 = graph.add_vertex(2); 471 | /// let v3 = graph.add_vertex(3); 472 | /// 473 | /// graph.add_edge(&v1, &v2).unwrap(); 474 | /// 475 | /// assert!(graph.has_edge(&v1, &v2)); 476 | /// assert!(!graph.has_edge(&v2, &v3)); 477 | /// ``` 478 | pub fn has_edge(&self, a: &VertexId, b: &VertexId) -> bool { 479 | match self.outbound_table.get(a) { 480 | Some(outbounds) => outbounds.contains(b), 481 | None => false, 482 | } 483 | } 484 | 485 | /// Returns the total number of edges that are listed 486 | /// in the graph. 487 | /// 488 | /// ## Example 489 | /// ```rust 490 | /// use graphlib::Graph; 491 | /// 492 | /// let mut graph: Graph = Graph::new(); 493 | /// 494 | /// let v1 = graph.add_vertex(0); 495 | /// let v2 = graph.add_vertex(1); 496 | /// let v3 = graph.add_vertex(2); 497 | /// let v4 = graph.add_vertex(3); 498 | /// 499 | /// graph.add_edge(&v1, &v2).unwrap(); 500 | /// graph.add_edge(&v2, &v3).unwrap(); 501 | /// graph.add_edge(&v3, &v4).unwrap(); 502 | /// 503 | /// assert_eq!(graph.edge_count(), 3); 504 | /// ``` 505 | pub fn edge_count(&self) -> usize { 506 | self.edges.len() 507 | } 508 | 509 | /// Returns the number of vertices that are placed in 510 | /// the graph. 511 | /// 512 | /// ## Example 513 | /// ```rust 514 | /// use graphlib::Graph; 515 | /// 516 | /// let mut graph: Graph = Graph::new(); 517 | /// 518 | /// graph.add_vertex(1); 519 | /// graph.add_vertex(2); 520 | /// graph.add_vertex(3); 521 | /// 522 | /// assert_eq!(graph.vertex_count(), 3); 523 | /// ``` 524 | pub fn vertex_count(&self) -> usize { 525 | self.vertices.len() 526 | } 527 | 528 | /// Attempts to fetch a reference to an item placed 529 | /// in the graph using the provided `VertexId`. 530 | /// 531 | /// ## Example 532 | /// ```rust 533 | /// use graphlib::Graph; 534 | /// 535 | /// let mut graph: Graph = Graph::new(); 536 | /// let id = graph.add_vertex(1); 537 | /// 538 | /// assert_eq!(*graph.fetch(&id).unwrap(), 1); 539 | /// ``` 540 | pub fn fetch(&self, id: &VertexId) -> Option<&T> { 541 | let result = self.vertices.get(id); 542 | 543 | match result { 544 | Some((result, _)) => Some(result), 545 | None => None, 546 | } 547 | } 548 | 549 | /// Attempts to fetch a mutable reference to an item placed 550 | /// in the graph using the provided `VertexId`. 551 | /// 552 | /// ## Example 553 | /// ```rust 554 | /// use graphlib::Graph; 555 | /// 556 | /// let mut graph: Graph = Graph::new(); 557 | /// let id = graph.add_vertex(1); 558 | /// 559 | /// assert_eq!(*graph.fetch(&id).unwrap(), 1); 560 | /// 561 | /// // Fetch a mutable reference 562 | /// let v = graph.fetch_mut(&id).unwrap(); 563 | /// 564 | /// // Mutate vertex value 565 | /// *v = 2; 566 | /// 567 | /// assert_eq!(*graph.fetch(&id).unwrap(), 2); 568 | /// ``` 569 | pub fn fetch_mut(&mut self, id: &VertexId) -> Option<&mut T> { 570 | let result = self.vertices.get_mut(id); 571 | 572 | match result { 573 | Some((result, _)) => Some(result), 574 | None => None, 575 | } 576 | } 577 | 578 | /// Removes a vertex that matches the given `VertexId`. 579 | /// 580 | /// ## Example 581 | /// ```rust 582 | /// use graphlib::Graph; 583 | /// 584 | /// let mut graph: Graph = Graph::new(); 585 | /// 586 | /// let v1 = graph.add_vertex(1); 587 | /// let v2 = graph.add_vertex(2); 588 | /// let v3 = graph.add_vertex(3); 589 | /// 590 | /// // The remove operation is idempotent 591 | /// graph.remove(&v2); 592 | /// graph.remove(&v2); 593 | /// graph.remove(&v2); 594 | /// 595 | /// assert_eq!(graph.vertex_count(), 2); 596 | /// ``` 597 | pub fn remove(&mut self, id: &VertexId) { 598 | self.vertices.remove(id); 599 | 600 | // Remove each inbound edge 601 | if let Some(inbounds) = self.inbound_table.remove(id) { 602 | for vertex in inbounds { 603 | self.remove_edge(&vertex, id); 604 | 605 | // Add to tips if inbound vertex doesn't 606 | // have other outbound vertices. 607 | if self.out_neighbors_count(&vertex) == 0 { 608 | self.tips.insert(vertex); 609 | } 610 | } 611 | } 612 | 613 | // Remove each outbound edge 614 | if let Some(outbounds) = self.outbound_table.remove(id) { 615 | for vertex in outbounds { 616 | self.remove_edge(id, &vertex); 617 | 618 | // Add to roots if outbound vertex doesn't 619 | // have other inbound vertices. 620 | if self.in_neighbors_count(&vertex) == 0 { 621 | self.roots.insert(vertex); 622 | } 623 | } 624 | } 625 | 626 | self.roots.remove(&id); 627 | self.tips.remove(&id); 628 | } 629 | 630 | /// Removes the specified edge from the graph. 631 | /// 632 | /// ## Example 633 | /// ```rust 634 | /// use graphlib::Graph; 635 | /// 636 | /// let mut graph: Graph = Graph::new(); 637 | /// 638 | /// let v1 = graph.add_vertex(0); 639 | /// let v2 = graph.add_vertex(1); 640 | /// let v3 = graph.add_vertex(2); 641 | /// let v4 = graph.add_vertex(3); 642 | /// 643 | /// graph.add_edge(&v1, &v2).unwrap(); 644 | /// graph.add_edge(&v2, &v3).unwrap(); 645 | /// graph.add_edge(&v3, &v4).unwrap(); 646 | /// 647 | /// assert_eq!(graph.edge_count(), 3); 648 | /// 649 | /// // The remove edge operation is idempotent 650 | /// graph.remove_edge(&v2, &v3); 651 | /// graph.remove_edge(&v2, &v3); 652 | /// graph.remove_edge(&v2, &v3); 653 | /// 654 | /// assert_eq!(graph.edge_count(), 2); 655 | /// ``` 656 | pub fn remove_edge(&mut self, a: &VertexId, b: &VertexId) { 657 | if let Some(outbounds) = self.outbound_table.get_mut(a) { 658 | outbounds.retain(|v| v != b); 659 | if outbounds.is_empty() { 660 | self.outbound_table.remove(a); 661 | } 662 | } 663 | 664 | if let Some(inbounds) = self.inbound_table.get_mut(b) { 665 | inbounds.retain(|v| v != a); 666 | if inbounds.is_empty() { 667 | self.inbound_table.remove(b); 668 | } 669 | } 670 | 671 | // If outbound vertex doesn't have any more inbounds, 672 | // mark it as root. 673 | if self.in_neighbors_count(&b) == 0 { 674 | self.roots.insert(b.clone()); 675 | } 676 | 677 | // Mark vertex as tip if it doesn't have any more outbounds. 678 | if self.out_neighbors_count(&a) == 0 { 679 | self.tips.insert(a.clone()); 680 | } 681 | 682 | self.edges.remove(&Edge::new(*a, *b)); 683 | } 684 | 685 | /// Iterates through the graph and only keeps 686 | /// vertices that match the given condition. 687 | /// 688 | /// ## Example 689 | /// ```rust 690 | /// use graphlib::Graph; 691 | /// 692 | /// let mut graph: Graph = Graph::new(); 693 | /// 694 | /// graph.add_vertex(1); 695 | /// graph.add_vertex(2); 696 | /// graph.add_vertex(2); 697 | /// graph.add_vertex(2); 698 | /// graph.add_vertex(3); 699 | /// 700 | /// graph.retain(|v| *v != 2); 701 | /// 702 | /// assert_eq!(graph.vertex_count(), 2); 703 | /// ``` 704 | pub fn retain(&mut self, fun: impl Fn(&T) -> bool) { 705 | let vertices: Vec = self 706 | .vertices() 707 | .filter(|v| !fun(self.fetch(v).unwrap())) 708 | .cloned() 709 | .collect(); 710 | 711 | vertices.iter().for_each(|v| self.remove(&v)); 712 | } 713 | 714 | /// Performs a fold over the vertices that are 715 | /// situated in the graph in Depth-First Order. 716 | /// 717 | /// ## Example 718 | /// ```rust 719 | /// use graphlib::Graph; 720 | /// 721 | /// let mut graph: Graph = Graph::new(); 722 | /// 723 | /// graph.add_vertex(1); 724 | /// graph.add_vertex(2); 725 | /// graph.add_vertex(3); 726 | /// 727 | /// let result = graph.fold(0, |v, acc| v + acc); 728 | /// 729 | /// assert_eq!(result, 6); 730 | /// ``` 731 | pub fn fold(&self, initial: A, fun: impl Fn(&T, A) -> A) -> A { 732 | let mut acc = initial; 733 | 734 | for v in self.dfs() { 735 | acc = fun(self.fetch(v).unwrap(), acc) 736 | } 737 | 738 | acc 739 | } 740 | 741 | /// Performs a map over all of the vertices of the graph, 742 | /// applying the given transformation function to each one. 743 | /// 744 | /// Returns a new graph with the same edges but with transformed 745 | /// vertices. 746 | /// ## Example 747 | /// ```rust 748 | /// use graphlib::Graph; 749 | /// 750 | /// let mut graph: Graph = Graph::new(); 751 | /// let id1 = graph.add_vertex(1); 752 | /// let id2 = graph.add_vertex(2); 753 | /// 754 | /// graph.add_edge(&id1, &id2); 755 | /// 756 | /// // Map each vertex 757 | /// let mapped: Graph = graph.map(|v| v + 2); 758 | /// 759 | /// assert!(graph.has_edge(&id1, &id2)); 760 | /// assert!(mapped.has_edge(&id1, &id2)); 761 | /// assert_eq!(graph.fetch(&id1).unwrap(), &1); 762 | /// assert_eq!(graph.fetch(&id2).unwrap(), &2); 763 | /// assert_eq!(mapped.fetch(&id1).unwrap(), &3); 764 | /// assert_eq!(mapped.fetch(&id2).unwrap(), &4); 765 | /// ``` 766 | pub fn map(&self, fun: impl Fn(&T) -> R) -> Graph { 767 | let mut graph: Graph = Graph::new(); 768 | 769 | // Copy edge and vertex information 770 | graph.edges = self.edges.clone(); 771 | graph.roots = self.roots.clone(); 772 | graph.tips = self.tips.clone(); 773 | graph.inbound_table = self.inbound_table.clone(); 774 | graph.outbound_table = self.outbound_table.clone(); 775 | graph.vertices = self 776 | .vertices 777 | .iter() 778 | .map(|(id, (v, i))| (*id, (fun(v), *i))) 779 | .collect(); 780 | 781 | #[cfg(feature = "dot")] 782 | { 783 | graph.vertex_labels = self.vertex_labels.clone(); 784 | graph.edge_labels = self.edge_labels.clone(); 785 | } 786 | 787 | graph 788 | } 789 | 790 | /// Returns true if the graph has cycles. 791 | /// 792 | /// ```rust 793 | /// use graphlib::Graph; 794 | /// 795 | /// let mut graph: Graph = Graph::new(); 796 | /// 797 | /// let v1 = graph.add_vertex(0); 798 | /// let v2 = graph.add_vertex(1); 799 | /// let v3 = graph.add_vertex(2); 800 | /// let v4 = graph.add_vertex(3); 801 | /// 802 | /// graph.add_edge(&v1, &v2).unwrap(); 803 | /// graph.add_edge(&v2, &v3).unwrap(); 804 | /// graph.add_edge(&v3, &v4).unwrap(); 805 | /// 806 | /// assert!(!graph.is_cyclic()); 807 | /// 808 | /// graph.add_edge(&v3, &v1); 809 | /// 810 | /// assert!(graph.is_cyclic()); 811 | /// ``` 812 | pub fn is_cyclic(&self) -> bool { 813 | let mut dfs = self.dfs(); 814 | dfs.is_cyclic() 815 | } 816 | 817 | /// Returns the number of root vertices 818 | /// in the graph. 819 | /// 820 | /// ## Example 821 | /// ```rust 822 | /// use graphlib::Graph; 823 | /// 824 | /// let mut graph: Graph = Graph::new(); 825 | /// 826 | /// let v1 = graph.add_vertex(0); 827 | /// let v2 = graph.add_vertex(1); 828 | /// let v3 = graph.add_vertex(2); 829 | /// let v4 = graph.add_vertex(3); 830 | /// 831 | /// graph.add_edge(&v1, &v2).unwrap(); 832 | /// graph.add_edge(&v3, &v1).unwrap(); 833 | /// graph.add_edge(&v1, &v4).unwrap(); 834 | /// 835 | /// assert_eq!(graph.roots_count(), 1); 836 | /// ``` 837 | pub fn roots_count(&self) -> usize { 838 | self.roots.len() 839 | } 840 | 841 | /// Returns the total count of neighboring vertices 842 | /// of the vertex with the given id. 843 | /// 844 | /// ## Example 845 | /// ```rust 846 | /// use graphlib::Graph; 847 | /// 848 | /// let mut graph: Graph = Graph::new(); 849 | /// 850 | /// let v1 = graph.add_vertex(0); 851 | /// let v2 = graph.add_vertex(1); 852 | /// let v3 = graph.add_vertex(2); 853 | /// let v4 = graph.add_vertex(3); 854 | /// 855 | /// graph.add_edge(&v1, &v2).unwrap(); 856 | /// graph.add_edge(&v3, &v1).unwrap(); 857 | /// graph.add_edge(&v1, &v4).unwrap(); 858 | /// 859 | /// assert_eq!(graph.neighbors_count(&v1), 3); 860 | /// ``` 861 | pub fn neighbors_count(&self, id: &VertexId) -> usize { 862 | self.in_neighbors_count(id) + self.out_neighbors_count(id) 863 | } 864 | 865 | /// Returns the total count of inbound neighboring 866 | /// vertices of the vertex with the given id. 867 | /// 868 | /// ## Example 869 | /// ```rust 870 | /// use graphlib::Graph; 871 | /// 872 | /// let mut graph: Graph = Graph::new(); 873 | /// 874 | /// let v1 = graph.add_vertex(0); 875 | /// let v2 = graph.add_vertex(1); 876 | /// let v3 = graph.add_vertex(2); 877 | /// let v4 = graph.add_vertex(3); 878 | /// 879 | /// graph.add_edge(&v1, &v2).unwrap(); 880 | /// graph.add_edge(&v3, &v1).unwrap(); 881 | /// graph.add_edge(&v1, &v4).unwrap(); 882 | /// 883 | /// assert_eq!(graph.in_neighbors_count(&v1), 1); 884 | /// ``` 885 | pub fn in_neighbors_count(&self, id: &VertexId) -> usize { 886 | match self.inbound_table.get(id) { 887 | Some(ins) => ins.len(), 888 | None => 0, 889 | } 890 | } 891 | 892 | /// Returns the total count of outbound neighboring 893 | /// vertices of the vertex with the given id. 894 | /// 895 | /// ## Example 896 | /// ```rust 897 | /// use graphlib::Graph; 898 | /// 899 | /// let mut graph: Graph = Graph::new(); 900 | /// 901 | /// let v1 = graph.add_vertex(0); 902 | /// let v2 = graph.add_vertex(1); 903 | /// let v3 = graph.add_vertex(2); 904 | /// let v4 = graph.add_vertex(3); 905 | /// let v5 = graph.add_vertex(4); 906 | /// 907 | /// graph.add_edge(&v1, &v2).unwrap(); 908 | /// graph.add_edge(&v3, &v1).unwrap(); 909 | /// graph.add_edge(&v1, &v4).unwrap(); 910 | /// graph.add_edge(&v2, &v5).unwrap(); 911 | /// graph.add_edge(&v2, &v3).unwrap(); 912 | /// 913 | /// assert_eq!(graph.out_neighbors_count(&v1), 2); 914 | /// assert_eq!(graph.out_neighbors_count(&v2), 2); 915 | /// ``` 916 | pub fn out_neighbors_count(&self, id: &VertexId) -> usize { 917 | match self.outbound_table.get(id) { 918 | Some(outs) => outs.len(), 919 | None => 0, 920 | } 921 | } 922 | 923 | /// Returns an iterator over the inbound neighbors 924 | /// of the vertex with the given id. 925 | /// 926 | /// ## Example 927 | /// ```rust 928 | /// use graphlib::Graph; 929 | /// 930 | /// let mut graph: Graph = Graph::new(); 931 | /// let mut neighbors = vec![]; 932 | /// 933 | /// let v1 = graph.add_vertex(0); 934 | /// let v2 = graph.add_vertex(1); 935 | /// let v3 = graph.add_vertex(2); 936 | /// let v4 = graph.add_vertex(3); 937 | /// 938 | /// graph.add_edge(&v1, &v2).unwrap(); 939 | /// graph.add_edge(&v3, &v1).unwrap(); 940 | /// graph.add_edge(&v1, &v4).unwrap(); 941 | /// 942 | /// // Iterate over neighbors 943 | /// for v in graph.in_neighbors(&v1) { 944 | /// neighbors.push(v); 945 | /// } 946 | /// 947 | /// assert_eq!(neighbors.len(), 1); 948 | /// assert_eq!(neighbors[0], &v3); 949 | /// ``` 950 | pub fn in_neighbors(&self, id: &VertexId) -> VertexIter<'_> { 951 | match self.inbound_table.get(id) { 952 | Some(neighbors) => VertexIter(Box::new(neighbors.iter().map(AsRef::as_ref))), 953 | None => VertexIter(Box::new(iter::empty())), 954 | } 955 | } 956 | 957 | /// Returns an iterator over the outbound neighbors 958 | /// of the vertex with the given id. 959 | /// 960 | /// ## Example 961 | /// ```rust 962 | /// #[macro_use] extern crate graphlib; 963 | /// use std::collections::HashSet; 964 | /// use graphlib::Graph; 965 | /// 966 | /// let mut graph: Graph = Graph::new(); 967 | /// 968 | /// let v1 = graph.add_vertex(0); 969 | /// let v2 = graph.add_vertex(1); 970 | /// let v3 = graph.add_vertex(2); 971 | /// let v4 = graph.add_vertex(3); 972 | /// 973 | /// graph.add_edge(&v1, &v2).unwrap(); 974 | /// graph.add_edge(&v3, &v1).unwrap(); 975 | /// graph.add_edge(&v1, &v4).unwrap(); 976 | /// 977 | /// assert!(set![&v2, &v4] == graph.out_neighbors(&v1).collect()); 978 | /// ``` 979 | pub fn out_neighbors(&self, id: &VertexId) -> VertexIter<'_> { 980 | match self.outbound_table.get(id) { 981 | Some(iter) => VertexIter(Box::new(iter.iter().rev().map(AsRef::as_ref))), 982 | None => VertexIter(Box::new(iter::empty())), 983 | } 984 | } 985 | 986 | /// Returns an iterator over the inbound and outbound neighbors 987 | /// of the vertex with the given id. 988 | /// 989 | /// ## Example 990 | /// ```rust 991 | /// #[macro_use] extern crate graphlib; 992 | /// use std::collections::HashSet; 993 | /// use graphlib::Graph; 994 | /// 995 | /// let mut graph: Graph = Graph::new(); 996 | /// 997 | /// let v1 = graph.add_vertex(0); 998 | /// let v2 = graph.add_vertex(1); 999 | /// let v3 = graph.add_vertex(2); 1000 | /// let v4 = graph.add_vertex(3); 1001 | /// 1002 | /// graph.add_edge(&v1, &v2).unwrap(); 1003 | /// graph.add_edge(&v3, &v1).unwrap(); 1004 | /// graph.add_edge(&v1, &v4).unwrap(); 1005 | /// 1006 | /// assert!(set![&v2, &v4, &v3] == graph.neighbors(&v1).collect()); 1007 | /// ``` 1008 | pub fn neighbors(&self, id: &VertexId) -> VertexIter<'_> { 1009 | let mut visited = HashSet::new(); 1010 | let neighbors = self 1011 | .out_neighbors(id) 1012 | .chain(self.in_neighbors(id)) 1013 | //Remove duplicates. 1014 | .filter(move |&&v| visited.insert(v)); 1015 | 1016 | VertexIter(Box::new(neighbors)) 1017 | } 1018 | 1019 | /// Returns an iterator over all edges that are situated 1020 | /// in the graph. 1021 | /// 1022 | /// ## Example 1023 | /// ```rust 1024 | /// use graphlib::Graph; 1025 | /// 1026 | /// let mut graph: Graph = Graph::new(); 1027 | /// let mut edges = vec![]; 1028 | /// 1029 | /// let v1 = graph.add_vertex(0); 1030 | /// let v2 = graph.add_vertex(1); 1031 | /// let v3 = graph.add_vertex(2); 1032 | /// let v4 = graph.add_vertex(3); 1033 | /// 1034 | /// graph.add_edge(&v1, &v2).unwrap(); 1035 | /// graph.add_edge(&v3, &v1).unwrap(); 1036 | /// graph.add_edge(&v1, &v4).unwrap(); 1037 | /// 1038 | /// // Iterate over edges 1039 | /// for v in graph.edges() { 1040 | /// edges.push(v); 1041 | /// } 1042 | /// 1043 | /// assert_eq!(edges.len(), 3); 1044 | /// ``` 1045 | pub fn edges(&self) -> impl Iterator { 1046 | self.edges.iter().map(|(e, _)| (e.inbound(), e.outbound())) 1047 | } 1048 | 1049 | /// Returns an iterator over the root vertices 1050 | /// of the graph. 1051 | /// 1052 | /// ## Example 1053 | /// ```rust 1054 | /// use graphlib::Graph; 1055 | /// 1056 | /// let mut graph: Graph = Graph::new(); 1057 | /// let mut roots = vec![]; 1058 | /// 1059 | /// let v1 = graph.add_vertex(0); 1060 | /// let v2 = graph.add_vertex(1); 1061 | /// let v3 = graph.add_vertex(2); 1062 | /// let v4 = graph.add_vertex(3); 1063 | /// 1064 | /// graph.add_edge(&v1, &v2).unwrap(); 1065 | /// graph.add_edge(&v3, &v1).unwrap(); 1066 | /// graph.add_edge(&v1, &v4).unwrap(); 1067 | /// 1068 | /// // Iterate over roots 1069 | /// for v in graph.roots() { 1070 | /// roots.push(v); 1071 | /// } 1072 | /// 1073 | /// assert_eq!(roots.len(), 1); 1074 | /// assert_eq!(roots[0], &v3); 1075 | /// ``` 1076 | pub fn roots(&self) -> VertexIter<'_> { 1077 | VertexIter(Box::new(self.roots.iter().map(AsRef::as_ref))) 1078 | } 1079 | 1080 | /// Returns an iterator over the tips of the graph. These 1081 | /// are all the vertices that have an inbound edge but no 1082 | /// outbound edge. 1083 | /// 1084 | /// ## Example 1085 | /// ```rust 1086 | /// #[macro_use] extern crate graphlib; 1087 | /// use std::collections::HashSet; 1088 | /// use graphlib::Graph; 1089 | /// 1090 | /// let mut graph: Graph = Graph::new(); 1091 | /// let mut tips = set![]; 1092 | /// 1093 | /// let v1 = graph.add_vertex(0); 1094 | /// let v2 = graph.add_vertex(1); 1095 | /// let v3 = graph.add_vertex(2); 1096 | /// let v4 = graph.add_vertex(3); 1097 | /// 1098 | /// graph.add_edge(&v1, &v2).unwrap(); 1099 | /// graph.add_edge(&v3, &v1).unwrap(); 1100 | /// graph.add_edge(&v1, &v4).unwrap(); 1101 | /// 1102 | /// // Iterate over tips 1103 | /// for v in graph.tips() { 1104 | /// tips.insert(v); 1105 | /// } 1106 | /// 1107 | /// assert_eq!(tips.len(), 2); 1108 | /// assert_eq!(tips, set![&v2, &v4]); 1109 | /// ``` 1110 | pub fn tips(&self) -> VertexIter<'_> { 1111 | VertexIter(Box::new(self.tips.iter().map(AsRef::as_ref))) 1112 | } 1113 | 1114 | /// Returns an iterator over all of the 1115 | /// vertices that are placed in the graph. 1116 | /// 1117 | /// ## Example 1118 | /// ```rust 1119 | /// use graphlib::Graph; 1120 | /// 1121 | /// let mut graph: Graph = Graph::new(); 1122 | /// let mut vertices = vec![]; 1123 | /// 1124 | /// let v1 = graph.add_vertex(0); 1125 | /// let v2 = graph.add_vertex(1); 1126 | /// let v3 = graph.add_vertex(2); 1127 | /// let v4 = graph.add_vertex(3); 1128 | /// 1129 | /// // Iterate over vertices 1130 | /// for v in graph.vertices() { 1131 | /// vertices.push(v); 1132 | /// } 1133 | /// 1134 | /// assert_eq!(vertices.len(), 4); 1135 | /// ``` 1136 | pub fn vertices(&self) -> VertexIter<'_> { 1137 | VertexIter(Box::new(self.vertices.keys().map(AsRef::as_ref))) 1138 | } 1139 | 1140 | /// Returns an iterator over the vertices 1141 | /// of the graph in Depth-First Order. The iterator 1142 | /// will follow vertices with lower weights first. 1143 | /// 1144 | /// ## Example 1145 | /// ```rust 1146 | /// #[macro_use] extern crate graphlib; 1147 | /// use graphlib::Graph; 1148 | /// use std::collections::HashSet; 1149 | /// 1150 | /// let mut graph: Graph = Graph::new(); 1151 | /// 1152 | /// let v1 = graph.add_vertex(0); 1153 | /// let v2 = graph.add_vertex(1); 1154 | /// let v3 = graph.add_vertex(2); 1155 | /// let v4 = graph.add_vertex(3); 1156 | /// 1157 | /// graph.add_edge(&v1, &v2).unwrap(); 1158 | /// graph.add_edge(&v3, &v1).unwrap(); 1159 | /// graph.add_edge(&v1, &v4).unwrap(); 1160 | /// 1161 | /// let mut dfs = graph.dfs(); 1162 | /// 1163 | /// assert_eq!(dfs.next(), Some(&v3)); 1164 | /// assert_eq!(dfs.next(), Some(&v1)); 1165 | /// assert!(set![&v2, &v4] == dfs.collect()); 1166 | /// ``` 1167 | pub fn dfs(&self) -> Dfs<'_, T> { 1168 | Dfs::new(self) 1169 | } 1170 | 1171 | /// Returns an iterator over the vertices 1172 | /// of the graph in Breadth-First Order. The iterator 1173 | /// will follow vertices with lower weights first. 1174 | /// 1175 | /// ## Example 1176 | /// ```rust 1177 | /// use graphlib::Graph; 1178 | /// 1179 | /// let mut graph: Graph = Graph::new(); 1180 | /// let mut vertices = vec![]; 1181 | /// 1182 | /// let v1 = graph.add_vertex(0); 1183 | /// let v2 = graph.add_vertex(1); 1184 | /// let v3 = graph.add_vertex(2); 1185 | /// let v4 = graph.add_vertex(3); 1186 | /// let v5 = graph.add_vertex(4); 1187 | /// let v6 = graph.add_vertex(5); 1188 | /// let v7 = graph.add_vertex(6); 1189 | /// 1190 | /// graph.add_edge(&v1, &v2).unwrap(); 1191 | /// graph.add_edge(&v3, &v1).unwrap(); 1192 | /// graph.add_edge(&v1, &v4).unwrap(); 1193 | /// graph.add_edge(&v1, &v7).unwrap(); 1194 | /// graph.add_edge(&v2, &v5).unwrap(); 1195 | /// graph.add_edge(&v5, &v6).unwrap(); 1196 | /// 1197 | /// // Iterate over vertices 1198 | /// for v in graph.bfs() { 1199 | /// vertices.push(v); 1200 | /// } 1201 | /// 1202 | /// assert_eq!(vertices.len(), 7); 1203 | /// ``` 1204 | pub fn bfs(&self) -> Bfs<'_, T> { 1205 | Bfs::new(self) 1206 | } 1207 | 1208 | /// Returns an iterator over the vertices 1209 | /// of the graph which follows a DFS based 1210 | /// topological order (Kahn's algorithm). 1211 | /// 1212 | /// Topological sorting is not possible for 1213 | /// graphs which contain a cycle. You may 1214 | /// use topo.is_cylic() == false to verify 1215 | /// that your graph is a DAG. 1216 | /// 1217 | /// If you attempt to use a topological 1218 | /// order without confirming that your graph 1219 | /// is a DAG, you may encounter a panic!(). 1220 | /// 1221 | /// The panic!() will be encountered when 1222 | /// the iterator detects that there are no 1223 | /// more vertices to visit, but all vertices 1224 | /// have not been visited. 1225 | /// 1226 | /// ## Example 1227 | /// ```rust 1228 | /// #[macro_use] extern crate graphlib; 1229 | /// use graphlib::Graph; 1230 | /// use std::collections::HashSet; 1231 | /// 1232 | /// let mut graph: Graph = Graph::new(); 1233 | /// 1234 | /// let v1 = graph.add_vertex(1); 1235 | /// let v2 = graph.add_vertex(2); 1236 | /// let v3 = graph.add_vertex(3); 1237 | /// let v4 = graph.add_vertex(4); 1238 | /// 1239 | /// graph.add_edge(&v1, &v2).unwrap(); 1240 | /// graph.add_edge(&v2, &v3).unwrap(); 1241 | /// graph.add_edge(&v3, &v4).unwrap(); 1242 | /// 1243 | /// let mut topo = graph.topo(); 1244 | /// 1245 | /// assert_eq!(topo.next(), Some(&v1)); 1246 | /// assert_eq!(topo.next(), Some(&v2)); 1247 | /// assert!(set![&v3, &v4] == topo.collect()); 1248 | /// ``` 1249 | pub fn topo(&self) -> Topo<'_, T> { 1250 | Topo::new(self) 1251 | } 1252 | 1253 | /// Returns an iterator over the shortest path from the source 1254 | /// vertex to the destination vertex. The iterator will yield 1255 | /// `None` if there is no such path or the provided vertex ids 1256 | /// do not belong to any vertices in the graph. 1257 | /// ## Example 1258 | /// ```rust 1259 | /// #[macro_use] extern crate graphlib; 1260 | /// use graphlib::Graph; 1261 | /// use std::collections::HashSet; 1262 | /// 1263 | /// let mut graph: Graph = Graph::new(); 1264 | /// 1265 | /// let v1 = graph.add_vertex(1); 1266 | /// let v2 = graph.add_vertex(2); 1267 | /// let v3 = graph.add_vertex(3); 1268 | /// let v4 = graph.add_vertex(4); 1269 | /// let v5 = graph.add_vertex(5); 1270 | /// let v6 = graph.add_vertex(6); 1271 | /// 1272 | /// graph.add_edge(&v1, &v2).unwrap(); 1273 | /// graph.add_edge(&v2, &v3).unwrap(); 1274 | /// graph.add_edge(&v3, &v4).unwrap(); 1275 | /// graph.add_edge(&v3, &v5).unwrap(); 1276 | /// graph.add_edge(&v5, &v6).unwrap(); 1277 | /// graph.add_edge(&v6, &v4).unwrap(); 1278 | /// 1279 | /// let mut dijkstra = graph.dijkstra(&v1, &v4); 1280 | /// 1281 | /// assert_eq!(dijkstra.next(), Some(&v1)); 1282 | /// assert_eq!(dijkstra.next(), Some(&v2)); 1283 | /// assert_eq!(dijkstra.next(), Some(&v3)); 1284 | /// assert_eq!(dijkstra.next(), Some(&v4)); 1285 | /// assert_eq!(dijkstra.next(), None); 1286 | /// ``` 1287 | pub fn dijkstra<'a>(&'a self, src: &'a VertexId, dest: &'a VertexId) -> VertexIter<'a> { 1288 | if let Some(dijkstra) = Dijkstra::new(&self, src).ok() { 1289 | if let Some(iter) = dijkstra.get_path_to(dest).ok() { 1290 | iter 1291 | } else { 1292 | VertexIter(Box::new(iter::empty())) 1293 | } 1294 | } else { 1295 | VertexIter(Box::new(iter::empty())) 1296 | } 1297 | } 1298 | 1299 | /// Returns an iterator over the values of the vertices 1300 | /// placed in the graph. 1301 | /// 1302 | /// ## Example 1303 | /// ```rust 1304 | /// #[macro_use] extern crate graphlib; 1305 | /// use graphlib::Graph; 1306 | /// use std::collections::HashSet; 1307 | /// 1308 | /// let mut graph: Graph = Graph::new(); 1309 | /// 1310 | /// let v1 = graph.add_vertex(1); 1311 | /// let v2 = graph.add_vertex(2); 1312 | /// let v3 = graph.add_vertex(3); 1313 | /// 1314 | /// let mut values = graph.values(); 1315 | /// 1316 | /// assert!(set![&1, &2, &3] == values.collect()); 1317 | /// ``` 1318 | pub fn values(&self) -> ValuesIter<'_, T> { 1319 | let iter = self.vertices.values().map(|(v, _)| v); 1320 | 1321 | ValuesIter(Box::new(iter)) 1322 | } 1323 | 1324 | #[cfg(feature = "dot")] 1325 | /// Creates a file with the dot representation of the graph. 1326 | /// This method requires the `dot` crate feature. 1327 | /// 1328 | /// ## Example 1329 | /// ```rust 1330 | /// use graphlib::Graph; 1331 | /// 1332 | /// use std::fs::File; 1333 | /// let mut f = File::create("example1.dot").unwrap(); 1334 | /// 1335 | /// let mut graph: Graph = Graph::new(); 1336 | /// 1337 | /// let v1 = graph.add_vertex("test1".to_string()); 1338 | /// let v2 = graph.add_vertex("test2".to_string()); 1339 | /// let v3 = graph.add_vertex("test3".to_string()); 1340 | /// let v4 = graph.add_vertex("test4".to_string()); 1341 | /// 1342 | /// let v5 = graph.add_vertex("test5".to_string()); 1343 | /// let v6 = graph.add_vertex("test6".to_string()); 1344 | /// 1345 | /// graph.add_edge(&v1, &v2).unwrap(); 1346 | /// graph.add_edge(&v3, &v1).unwrap(); 1347 | /// graph.add_edge(&v1, &v4).unwrap(); 1348 | /// graph.add_edge(&v5, &v6).unwrap(); 1349 | /// 1350 | /// assert!(graph.to_dot("example1", &mut f).is_ok()); 1351 | /// ``` 1352 | pub fn to_dot( 1353 | &self, 1354 | graph_name: &str, 1355 | output: &mut impl ::std::io::Write, 1356 | ) -> Result<(), GraphErr> { 1357 | let graph = crate::dot::DotGraph::new(&self, graph_name)?; 1358 | dot::render(&graph, output).map_err(|_| GraphErr::CouldNotRender) 1359 | } 1360 | 1361 | #[cfg(feature = "dot")] 1362 | /// Labels the vertex with the given id. Returns the old label if successful. 1363 | /// 1364 | /// This method requires the `dot` crate feature. 1365 | /// 1366 | /// ## Example 1367 | /// ```rust 1368 | /// use graphlib::{Graph, VertexId}; 1369 | /// 1370 | /// let mut graph: Graph = Graph::new(); 1371 | /// let random_id = VertexId::random(); 1372 | /// 1373 | /// let v1 = graph.add_vertex(0); 1374 | /// let v2 = graph.add_vertex(1); 1375 | /// let v3 = graph.add_vertex(2); 1376 | /// 1377 | /// assert!(graph.add_vertex_label(&v1, "V1").is_ok()); 1378 | /// assert!(graph.add_vertex_label(&v2, "V2").is_ok()); 1379 | /// assert!(graph.add_vertex_label(&v3, "V3").is_ok()); 1380 | /// assert!(graph.add_vertex_label(&random_id, "will fail").is_err()); 1381 | /// ``` 1382 | pub fn add_vertex_label(&mut self, vertex_id: &VertexId, label: &str) 1383 | -> Result, GraphErr> 1384 | { 1385 | if self.vertices.get(vertex_id).is_none() { 1386 | return Err(GraphErr::NoSuchVertex); 1387 | } 1388 | 1389 | let old_label = self.vertex_labels.insert(vertex_id.clone(), label.to_owned()); 1390 | Ok(old_label) 1391 | } 1392 | 1393 | #[cfg(feature = "dot")] 1394 | /// Labels the edge with between the given vertices. Returns the old label if successful. 1395 | /// 1396 | /// This method requires the `dot` crate feature. 1397 | /// 1398 | /// ## Example 1399 | /// ```rust 1400 | /// use graphlib::{Graph, VertexId}; 1401 | /// 1402 | /// let mut graph: Graph = Graph::new(); 1403 | /// let random_id = VertexId::random(); 1404 | /// 1405 | /// let v1 = graph.add_vertex(0); 1406 | /// let v2 = graph.add_vertex(1); 1407 | /// let v3 = graph.add_vertex(2); 1408 | /// 1409 | /// graph.add_edge(&v1, &v2).unwrap(); 1410 | /// graph.add_edge(&v3, &v1).unwrap(); 1411 | /// 1412 | /// assert!(graph.add_edge_label(&v1, &v2, "V1->V2").is_ok()); 1413 | /// assert!(graph.add_edge_label(&v3, &v1, "V3->V1").is_ok()); 1414 | /// assert!(graph.add_edge_label(&v2, &v3, "V2->V3").is_err()); 1415 | /// assert!(graph.add_edge_label(&v1, &v3, "V1->V3").is_err()); 1416 | /// ``` 1417 | pub fn add_edge_label(&mut self, a: &VertexId, b: &VertexId, label: &str) 1418 | -> Result, GraphErr> 1419 | { 1420 | if !self.has_edge(a, b) { 1421 | return Err(GraphErr::NoSuchEdge); 1422 | } 1423 | 1424 | let edge = Edge::new(a.clone(), b.clone()); 1425 | let old_label = self.edge_labels.insert(edge, label.to_owned()); 1426 | Ok(old_label) 1427 | } 1428 | 1429 | #[cfg(feature = "dot")] 1430 | /// Retrieves the label of the vertex with the given id. 1431 | /// 1432 | /// This method requires the `dot` crate feature. 1433 | /// 1434 | /// Returns `None` if there is no vertex associated with the given id in the graph. 1435 | pub fn vertex_label(&self, vertex_id: &VertexId) -> Option<&str> { 1436 | if !self.vertices.contains_key(vertex_id) { 1437 | return None; 1438 | } 1439 | 1440 | self.vertex_labels.get(vertex_id) 1441 | .map(|x| x.as_str()) 1442 | .or(Some(&DEFAULT_LABEL)) 1443 | } 1444 | 1445 | #[cfg(feature = "dot")] 1446 | /// Retrieves the label of the edge with the given vertices. 1447 | /// 1448 | /// This method requires the `dot` crate feature. 1449 | /// 1450 | /// Returns `None` if there is no edge associated with the given vertices in the graph. 1451 | pub fn edge_label(&self, a: &VertexId, b: &VertexId) -> Option<&str> { 1452 | if !self.has_edge(a, b) { 1453 | return None; 1454 | } 1455 | 1456 | self.edge_labels.get(&Edge::new(*a, *b)) 1457 | .map(|x| x.as_str()) 1458 | .or(Some(&DEFAULT_LABEL)) 1459 | } 1460 | 1461 | #[cfg(feature = "dot")] 1462 | /// Maps each label that is placed on a vertex to a new label. 1463 | /// 1464 | /// This method requires the `dot` crate feature. 1465 | /// 1466 | /// ```rust 1467 | /// use std::collections::HashMap; 1468 | /// use graphlib::{Graph, VertexId}; 1469 | /// 1470 | /// let mut graph: Graph = Graph::new(); 1471 | /// let random_id = VertexId::random(); 1472 | /// let mut vertex_id: usize = 1; 1473 | /// 1474 | /// let v1 = graph.add_vertex(0); 1475 | /// let v2 = graph.add_vertex(1); 1476 | /// let v3 = graph.add_vertex(2); 1477 | /// let v4 = graph.add_vertex(3); 1478 | /// 1479 | /// assert!(graph.add_vertex_label(&v1, &format!("V{}", vertex_id)).is_ok()); 1480 | /// vertex_id += 1; 1481 | /// 1482 | /// assert!(graph.add_vertex_label(&v2, &format!("V{}", vertex_id)).is_ok()); 1483 | /// vertex_id += 1; 1484 | /// 1485 | /// assert!(graph.add_vertex_label(&v3, &format!("V{}", vertex_id)).is_ok()); 1486 | /// 1487 | /// assert_eq!(graph.vertex_label(&v1).unwrap(), "V1"); 1488 | /// assert_eq!(graph.vertex_label(&v2).unwrap(), "V2"); 1489 | /// assert_eq!(graph.vertex_label(&v3).unwrap(), "V3"); 1490 | /// 1491 | /// let new_labels: HashMap = vec![v1.clone(), v2.clone(), v3.clone(), v4.clone()] 1492 | /// .iter() 1493 | /// .map(|id| { 1494 | /// vertex_id += 1; 1495 | /// let label = format!("V{}", vertex_id); 1496 | /// 1497 | /// (id.clone(), label) 1498 | /// }) 1499 | /// .collect(); 1500 | /// 1501 | /// graph.map_vertex_labels(|id, _old_label| new_labels.get(id).unwrap().clone()); 1502 | /// 1503 | /// assert_eq!(graph.vertex_label(&v1).unwrap(), "V4"); 1504 | /// assert_eq!(graph.vertex_label(&v2).unwrap(), "V5"); 1505 | /// assert_eq!(graph.vertex_label(&v3).unwrap(), "V6"); 1506 | /// assert_eq!(graph.vertex_label(&v4).unwrap(), "V7"); 1507 | /// ``` 1508 | pub fn map_vertex_labels(&mut self, mut fun: impl FnMut(&VertexId, Option<&str>) -> String) { 1509 | for (id, _) in self.vertices.iter() { 1510 | self.vertex_labels.entry(*id) 1511 | .and_modify(|e| { *e = fun(id, Some(e)); }) 1512 | .or_insert_with(|| fun(id, None)); 1513 | } 1514 | } 1515 | 1516 | #[cfg(feature = "dot")] 1517 | /// Maps each label that is placed on an edge to a new label. 1518 | /// 1519 | /// This method requires the `dot` crate feature. 1520 | /// 1521 | /// ```rust 1522 | /// use std::collections::HashMap; 1523 | /// use graphlib::{Graph, VertexId}; 1524 | /// 1525 | /// let mut graph: Graph = Graph::new(); 1526 | /// let random_id = VertexId::random(); 1527 | /// let mut vertex_id: usize = 1; 1528 | /// 1529 | /// let v1 = graph.add_vertex(0); 1530 | /// let v2 = graph.add_vertex(1); 1531 | /// let v3 = graph.add_vertex(2); 1532 | /// let v4 = graph.add_vertex(3); 1533 | /// 1534 | /// graph.add_edge(&v1, &v2).unwrap(); 1535 | /// graph.add_edge(&v2, &v3).unwrap(); 1536 | /// graph.add_edge(&v1, &v4).unwrap(); 1537 | /// graph.add_edge(&v4, &v3).unwrap(); 1538 | /// 1539 | /// assert!(graph.add_edge_label(&v1, &v2, &"V1->V2").is_ok()); 1540 | /// assert!(graph.add_edge_label(&v2, &v3, &"V2->V3").is_ok()); 1541 | /// assert!(graph.add_edge_label(&v1, &v4, &"V1->V4").is_ok()); 1542 | /// assert!(graph.add_edge_label(&v4, &v3, &"V4->V3").is_ok()); 1543 | /// assert!(graph.add_edge_label(&v1, &v3, &"V1->V3").is_err()); 1544 | /// 1545 | /// assert_eq!(graph.edge_label(&v1, &v2).unwrap(), "V1->V2"); 1546 | /// assert_eq!(graph.edge_label(&v2, &v3).unwrap(), "V2->V3"); 1547 | /// assert_eq!(graph.edge_label(&v1, &v4).unwrap(), "V1->V4"); 1548 | /// assert_eq!(graph.edge_label(&v4, &v3).unwrap(), "V4->V3"); 1549 | /// 1550 | /// graph.map_edge_labels(|edge, old_label| format!("*{}*", old_label.unwrap())); 1551 | /// 1552 | /// assert_eq!(graph.edge_label(&v1, &v2).unwrap(), "*V1->V2*"); 1553 | /// assert_eq!(graph.edge_label(&v2, &v3).unwrap(), "*V2->V3*"); 1554 | /// assert_eq!(graph.edge_label(&v1, &v4).unwrap(), "*V1->V4*"); 1555 | /// assert_eq!(graph.edge_label(&v4, &v3).unwrap(), "*V4->V3*"); 1556 | /// ``` 1557 | pub fn map_edge_labels(&mut self, mut fun: impl FnMut(&Edge, Option<&str>) -> String) { 1558 | for (edge, _) in self.edges.iter() { 1559 | self.edge_labels.entry(Edge::new(*edge.outbound(), *edge.inbound())) 1560 | .and_modify(|e| { *e = fun(edge, Some(e)); }) 1561 | .or_insert_with(|| fun(edge, None)); 1562 | } 1563 | } 1564 | 1565 | fn do_add_edge( 1566 | &mut self, 1567 | a: &VertexId, 1568 | b: &VertexId, 1569 | weight: f32, 1570 | check_cycle: bool, 1571 | ) -> Result<(), GraphErr> { 1572 | let id_ptr1 = if self.vertices.get(a).is_some() { 1573 | *a 1574 | } else { 1575 | return Err(GraphErr::NoSuchVertex); 1576 | }; 1577 | 1578 | let id_ptr2 = if self.vertices.get(b).is_some() { 1579 | *b 1580 | } else { 1581 | return Err(GraphErr::NoSuchVertex); 1582 | }; 1583 | 1584 | let edge = Edge::new(id_ptr1, id_ptr2); 1585 | 1586 | // Push edge 1587 | self.edges.insert(edge, weight); 1588 | 1589 | // Update outbound table 1590 | match self.outbound_table.get(&id_ptr1) { 1591 | Some(outbounds) => { 1592 | let mut outbounds = outbounds.clone(); 1593 | outbounds.push(id_ptr2.clone()); 1594 | 1595 | self.sort_outbounds(id_ptr1.clone(), &mut outbounds); 1596 | self.outbound_table.insert(id_ptr1.clone(), outbounds); 1597 | } 1598 | None => { 1599 | self.outbound_table.insert(id_ptr1.clone(), vec![id_ptr2]); 1600 | } 1601 | } 1602 | 1603 | // Update inbound table 1604 | match self.inbound_table.get_mut(&id_ptr2) { 1605 | Some(inbounds) => { 1606 | inbounds.push(id_ptr1); 1607 | } 1608 | None => { 1609 | self.inbound_table.insert(id_ptr2, vec![id_ptr1]); 1610 | } 1611 | } 1612 | 1613 | // Remove outbound vertex from roots 1614 | let was_root = self.roots.remove(&b); 1615 | 1616 | // Remove inbound vertex from tips 1617 | let was_tip = self.tips.remove(&a); 1618 | 1619 | let mut is_cyclic = false; 1620 | 1621 | if check_cycle { 1622 | let mut dfs = Dfs::new(&self); 1623 | is_cyclic = dfs.is_cyclic(); 1624 | } 1625 | 1626 | // Roll-back changes if cycle check succeeds 1627 | if is_cyclic { 1628 | // Remove from edge table 1629 | self.remove_edge(a, b); 1630 | 1631 | if was_root { 1632 | self.roots.insert(b.clone()); 1633 | } 1634 | 1635 | if was_tip { 1636 | self.tips.insert(a.clone()); 1637 | } 1638 | 1639 | return Err(GraphErr::CycleError); 1640 | } 1641 | 1642 | Ok(()) 1643 | } 1644 | 1645 | fn sort_outbounds(&self, inbound: VertexId, outbounds: &mut Vec) { 1646 | let outbound_weights: HashMap = outbounds 1647 | .iter() 1648 | .map(|id| (*id, *self.edges.get(&Edge::new(inbound, *id)).unwrap())) 1649 | .collect(); 1650 | 1651 | // Sort outbounds 1652 | outbounds.sort_by(|a, b| { 1653 | let a_weight = outbound_weights.get(a).cloned(); 1654 | let b_weight = outbound_weights.get(b).cloned(); 1655 | 1656 | match (a_weight, b_weight) { 1657 | // Sort normally if both weights are set 1658 | (Some(a_weight), Some(b_weight)) => { 1659 | a_weight.partial_cmp(&b_weight).unwrap_or_else(|| a.cmp(b)) 1660 | } 1661 | (Some(weight), None) => { 1662 | if weight != 0.00 { 1663 | weight.partial_cmp(&0.00).unwrap_or_else(|| a.cmp(b)) 1664 | } else { 1665 | // Fallback to lexicographic sort 1666 | a.cmp(b) 1667 | } 1668 | } 1669 | (None, Some(weight)) => { 1670 | if weight != 0.00 { 1671 | weight.partial_cmp(&0.00).unwrap_or_else(|| a.cmp(b)) 1672 | } else { 1673 | // Fallback to lexicographic sort 1674 | a.cmp(b) 1675 | } 1676 | } 1677 | // Sort lexicographically by ids if no weight is set 1678 | (None, None) => a.cmp(b), 1679 | } 1680 | }); 1681 | } 1682 | 1683 | /// Attempts to fetch a reference to a stored vertex id 1684 | /// which is equal to the given `VertexId`. 1685 | pub(crate) fn fetch_id_ref<'b>(&'b self, id: &VertexId) -> Option<&'b VertexId> { 1686 | match self.vertices.get(id) { 1687 | Some((_, id_ptr)) => Some(id_ptr), 1688 | None => None, 1689 | } 1690 | } 1691 | } 1692 | 1693 | #[cfg(test)] 1694 | mod tests { 1695 | use super::*; 1696 | 1697 | #[test] 1698 | fn is_thread_safe() { 1699 | let mut graph: Graph = Graph::new(); 1700 | graph.add_vertex(0); 1701 | 1702 | std::panic::set_hook(Box::new(move |_| { 1703 | let mut graph = graph.clone(); 1704 | 1705 | graph.add_vertex(1); 1706 | graph.add_vertex(2); 1707 | })); 1708 | } 1709 | 1710 | #[test] 1711 | fn dfs() { 1712 | let mut graph: Graph = Graph::new(); 1713 | 1714 | let v1 = graph.add_vertex(0); 1715 | let v2 = graph.add_vertex(1); 1716 | let v3 = graph.add_vertex(2); 1717 | let v4 = graph.add_vertex(3); 1718 | let v5 = graph.add_vertex(4); 1719 | let v6 = graph.add_vertex(5); 1720 | let v7 = graph.add_vertex(6); 1721 | 1722 | graph.add_edge_with_weight(&v1, &v2, -0.23).unwrap(); 1723 | graph.add_edge(&v3, &v1).unwrap(); 1724 | graph.add_edge_with_weight(&v1, &v4, -0.56).unwrap(); 1725 | graph.add_edge_with_weight(&v1, &v5, 0.44).unwrap(); 1726 | graph.add_edge(&v5, &v6).unwrap(); 1727 | graph.add_edge(&v5, &v7).unwrap(); 1728 | 1729 | graph.set_weight(&v5, &v6, 0.23).unwrap(); 1730 | graph.set_weight(&v5, &v7, 0.33).unwrap(); 1731 | 1732 | let mut dfs = graph.dfs(); 1733 | 1734 | assert_eq!(dfs.next(), Some(&v3)); 1735 | assert_eq!(dfs.next(), Some(&v1)); 1736 | assert_eq!(dfs.next(), Some(&v4)); 1737 | assert_eq!(dfs.next(), Some(&v2)); 1738 | assert_eq!(dfs.next(), Some(&v5)); 1739 | assert_eq!(dfs.next(), Some(&v6)); 1740 | assert_eq!(dfs.next(), Some(&v7)); 1741 | } 1742 | 1743 | #[test] 1744 | fn dfs_mul_roots() { 1745 | let mut graph: Graph = Graph::new(); 1746 | 1747 | let v1 = graph.add_vertex(0); 1748 | let v2 = graph.add_vertex(1); 1749 | let v3 = graph.add_vertex(2); 1750 | let v4 = graph.add_vertex(3); 1751 | 1752 | graph.add_edge(&v1, &v2).unwrap(); 1753 | graph.add_edge(&v3, &v1).unwrap(); 1754 | graph.add_edge(&v1, &v4).unwrap(); 1755 | 1756 | let v5 = graph.add_vertex(4); 1757 | let v6 = graph.add_vertex(5); 1758 | 1759 | graph.add_edge(&v5, &v6).unwrap(); 1760 | 1761 | // Iterate over vertices 1762 | let mut dfs = graph.dfs(); 1763 | 1764 | for _ in 0..2 { 1765 | let v = dfs.next(); 1766 | 1767 | if v == Some(&v3) { 1768 | assert_eq!(dfs.next(), Some(&v1)); 1769 | assert!(set![&v2, &v4] == (&mut dfs).take(2).collect()); 1770 | } else if v == Some(&v5) { 1771 | assert_eq!(dfs.next(), Some(&v6)); 1772 | } else { 1773 | panic!("Not a root node") 1774 | } 1775 | } 1776 | 1777 | assert_eq!(dfs.count(), 0, "There were remaining nodes"); 1778 | } 1779 | 1780 | #[test] 1781 | fn test_remove_edge() { 1782 | let mut graph = Graph::new(); 1783 | 1784 | let v1 = graph.add_vertex(0); 1785 | let v2 = graph.add_vertex(1); 1786 | let v3 = graph.add_vertex(2); 1787 | 1788 | graph.add_edge(&v1, &v2).unwrap(); 1789 | graph.add_edge(&v2, &v3).unwrap(); 1790 | 1791 | let old_inbound = graph.inbound_table.clone(); 1792 | let old_outbound = graph.outbound_table.clone(); 1793 | 1794 | graph.add_edge(&v3, &v1).unwrap(); 1795 | graph.remove_edge(&v3, &v1); 1796 | 1797 | assert_eq!(old_inbound, graph.inbound_table.clone()); 1798 | assert_eq!(old_outbound, graph.outbound_table); 1799 | } 1800 | 1801 | #[test] 1802 | fn test_non_clonable_type() { 1803 | // this simply tests that a Graph that has a non-clonable type can be created 1804 | // this is done easiest by adding dyn Trait object, which can never be cloned 1805 | // 1806 | // It also tests that the dyn object can still be used as expected 1807 | let mut graph = Graph::>::new(); 1808 | 1809 | graph.add_vertex(Box::new(String::from("Hello World"))); 1810 | let mut result = String::new(); 1811 | for vertex_identifier in graph.vertices() { 1812 | if let Some(v) = graph.fetch(vertex_identifier) { 1813 | result = format!("{}", v); 1814 | } 1815 | } 1816 | 1817 | assert_eq!(result, "Hello World"); 1818 | } 1819 | #[test] 1820 | fn test_clonable() { 1821 | let mut graph = Graph::new(); 1822 | graph.add_vertex(String::from("Test")); 1823 | 1824 | let cloned = graph.clone(); 1825 | assert_eq!(graph.vertex_count(), cloned.vertex_count()); 1826 | let mut cloned_iter = cloned.vertices(); 1827 | for vertex_identifier in graph.vertices() { 1828 | if let Some(cloned_identifier) = cloned_iter.next() { 1829 | assert_eq!( 1830 | graph.fetch(vertex_identifier), 1831 | cloned.fetch(cloned_identifier) 1832 | ); 1833 | } else { 1834 | panic!("graph and clone of graph are not equal!"); 1835 | } 1836 | } 1837 | } 1838 | 1839 | #[test] 1840 | fn test_add_edge_cycle_check() { 1841 | let mut graph: Graph = Graph::new(); 1842 | 1843 | // Id of vertex that is not place in the graph 1844 | let id = VertexId::random(); 1845 | 1846 | let v1 = graph.add_vertex(1); 1847 | let v2 = graph.add_vertex(2); 1848 | 1849 | // Adding an edge is idempotent 1850 | graph.add_edge_check_cycle(&v1, &v2).unwrap(); 1851 | graph.add_edge_check_cycle(&v1, &v2).unwrap(); 1852 | graph.add_edge_check_cycle(&v1, &v2).unwrap(); 1853 | 1854 | let mut graph2 = graph.clone(); 1855 | 1856 | // Fails on adding an edge which creates 1857 | // a cycle in the graph. 1858 | assert_eq!( 1859 | graph2.add_edge_check_cycle(&v2, &v1), 1860 | Err(GraphErr::CycleError) 1861 | ); 1862 | 1863 | // Check that the graph state has rolled back 1864 | assert_eq!(graph.edges, graph2.edges); 1865 | assert_eq!(graph.roots, graph2.roots); 1866 | assert_eq!(graph.tips, graph2.tips); 1867 | assert_eq!(graph.inbound_table, graph2.inbound_table); 1868 | assert_eq!(graph.outbound_table, graph2.outbound_table); 1869 | } 1870 | } 1871 | -------------------------------------------------------------------------------- /src/iterators/bfs.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | use crate::graph::Graph; 4 | use crate::vertex_id::VertexId; 5 | 6 | use hashbrown::HashSet; 7 | #[cfg(not(feature = "no_std"))] 8 | use std::collections::VecDeque; 9 | 10 | #[cfg(feature = "no_std")] 11 | extern crate alloc; 12 | #[cfg(feature = "no_std")] 13 | use alloc::collections::vec_deque::VecDeque; 14 | 15 | #[cfg(feature = "no_std")] 16 | use alloc::vec::Vec; 17 | 18 | #[cfg(feature = "no_std")] 19 | use core::fmt::Debug; 20 | 21 | #[cfg(not(feature = "no_std"))] 22 | use std::fmt::Debug; 23 | 24 | #[derive(Debug)] 25 | /// Breadth-First Iterator 26 | pub struct Bfs<'a, T> { 27 | queue: VecDeque, 28 | current_ptr: Option, 29 | visited_set: HashSet, 30 | roots_stack: Vec, 31 | iterable: &'a Graph, 32 | } 33 | 34 | impl<'a, T> Bfs<'a, T> { 35 | pub fn new(graph: &'a Graph) -> Bfs<'_, T> { 36 | let mut roots_stack = Vec::with_capacity(graph.roots_count()); 37 | 38 | for v in graph.roots() { 39 | roots_stack.push(v.clone()); 40 | } 41 | 42 | let current_ptr = roots_stack.pop(); 43 | 44 | Bfs { 45 | queue: VecDeque::with_capacity(graph.vertex_count()), 46 | current_ptr, 47 | visited_set: HashSet::with_capacity(graph.vertex_count()), 48 | roots_stack, 49 | iterable: graph, 50 | } 51 | } 52 | } 53 | 54 | impl<'a, T> Iterator for Bfs<'a, T> { 55 | type Item = &'a VertexId; 56 | 57 | fn next(&mut self) -> Option { 58 | loop { 59 | if let Some(current_ptr) = &self.current_ptr { 60 | // Yield current pointed value if 61 | // it isn't in the visited stack. 62 | if !self.visited_set.contains(current_ptr) { 63 | self.visited_set.insert(current_ptr.clone()); 64 | return self.iterable.fetch_id_ref(current_ptr.as_ref()); 65 | } 66 | 67 | // Iterate through current neighbors 68 | // and check their visited status. 69 | for n in self.iterable.out_neighbors(current_ptr.as_ref()) { 70 | if !self.visited_set.contains(n) { 71 | self.visited_set.insert(n.clone()); 72 | self.queue.push_back(n.clone()); 73 | 74 | return self.iterable.fetch_id_ref(n); 75 | } 76 | } 77 | 78 | // Move to next root if possible and yield it. 79 | if self.queue.is_empty() { 80 | if let Some(next_root) = self.roots_stack.pop() { 81 | self.current_ptr = Some(next_root); 82 | } else { 83 | // Break execution if there are no more roots 84 | return None; 85 | } 86 | } else { 87 | // Pop item from queue and set it 88 | // as the current pointer. 89 | self.current_ptr = self.queue.pop_front(); 90 | } 91 | } else { 92 | return None; 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/iterators/dfs.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | use crate::graph::Graph; 4 | use crate::iterators::VertexIter; 5 | use crate::vertex_id::VertexId; 6 | 7 | #[cfg(feature = "no_std")] 8 | use core::iter::{Chain, Cloned, Peekable}; 9 | use hashbrown::HashSet; 10 | #[cfg(not(feature = "no_std"))] 11 | use std::iter::{Chain, Cloned, Peekable}; 12 | 13 | #[cfg(feature = "no_std")] 14 | extern crate alloc; 15 | #[cfg(feature = "no_std")] 16 | use alloc::vec::Vec; 17 | 18 | #[cfg(feature = "no_std")] 19 | use core::fmt::Debug; 20 | 21 | #[cfg(not(feature = "no_std"))] 22 | use std::fmt::Debug; 23 | 24 | #[derive(Debug)] 25 | /// Depth-First Iterator 26 | pub struct Dfs<'a, T> { 27 | /// All the vertices to be checked with the roots coming first. 28 | unchecked: Peekable, VertexIter<'a>>>>, 29 | /// All black vertices. 30 | black: HashSet, 31 | /// All grey vertices. 32 | grey: HashSet, 33 | /// All vertices pending processing. 34 | pending_stack: Vec<(VertexId, bool)>, 35 | /// The Graph being iterated. 36 | iterable: &'a Graph, 37 | /// A cached answer to the question: does this Graph contain cycles. 38 | cached_cyclic: bool, 39 | } 40 | 41 | impl<'a, T> Dfs<'a, T> { 42 | pub fn new(graph: &'a Graph) -> Dfs<'_, T> { 43 | let unchecked = graph.roots().chain(graph.vertices()).cloned().peekable(); 44 | 45 | Dfs { 46 | unchecked, 47 | iterable: graph, 48 | cached_cyclic: false, 49 | grey: HashSet::new(), 50 | black: HashSet::new(), 51 | pending_stack: Vec::new(), 52 | } 53 | } 54 | 55 | /// Returns true if the iterated graph has a cycle. 56 | /// 57 | /// # Warning 58 | /// 59 | /// It is a logic error to use this iterator after calling this function. 60 | pub fn is_cyclic(&mut self) -> bool { 61 | //Check for a cached answer. 62 | if self.cached_cyclic { 63 | return self.cached_cyclic; 64 | } 65 | 66 | //Search until an answer is found. 67 | while self.process_vertex().is_some() {} 68 | 69 | self.cached_cyclic 70 | } 71 | 72 | /// Processes the next vertex. 73 | /// 74 | /// Will return None if: 75 | /// 76 | /// * No vertices are left. 77 | /// * The next vertex forms a cycle. 78 | fn process_vertex(&mut self) -> Option<&'a VertexId> { 79 | if self.pending_stack.is_empty() { 80 | //Spliting the borrows for the borrow checker. 81 | let unchecked = &mut self.unchecked; 82 | let black = &self.black; 83 | 84 | //Search for an unprocessed vertex. 85 | let next = unchecked.find(move |v| !black.contains(v)); 86 | 87 | //We found a new vertex. 88 | if let Some(v) = next { 89 | self.pending_stack.push((v, false)); 90 | } 91 | } 92 | 93 | // get next vertex 94 | let mut should_return = true; 95 | let n = self 96 | .pending_stack 97 | .pop() 98 | .iter() 99 | //Filter cycles. 100 | .filter_map(|v| { 101 | let (v, already_seen) = v; 102 | 103 | // if we have seen the vertex before, 104 | // we remove it from grey and add it to black 105 | if *already_seen { 106 | self.grey.remove(v); 107 | self.black.insert(*v); 108 | } else { 109 | // otherwise we remember that we have to 110 | // mark it as done (i.e. move it to black) 111 | // the next time we see it 112 | self.grey.insert(*v); 113 | self.pending_stack.push((*v, true)); 114 | 115 | // add all successors that are not already marked 116 | // "under consideration", i.e. in grey 117 | for v in self.iterable.out_neighbors(v) { 118 | if self.grey.contains(v) { 119 | // if we do encounter such an edge, 120 | // there is a cycle 121 | self.cached_cyclic = true; 122 | } else if !self.black.contains(v) { 123 | self.pending_stack.push((*v, false)); 124 | } 125 | } 126 | } 127 | // we don't want to return nodes twice so we only 128 | // return a node when we haven't seen it yet 129 | should_return = !*already_seen; 130 | self.iterable.fetch_id_ref(v) 131 | }) 132 | .next(); 133 | if should_return { 134 | n 135 | } else { 136 | self.process_vertex() 137 | } 138 | } 139 | } 140 | 141 | impl<'a, T> Iterator for Dfs<'a, T> { 142 | type Item = &'a VertexId; 143 | 144 | fn size_hint(&self) -> (usize, Option) { 145 | let remaining = self.iterable.vertex_count() - self.black.len(); 146 | 147 | (0, Some(remaining)) 148 | } 149 | fn next(&mut self) -> Option { 150 | (0..self.size_hint().1.unwrap()) 151 | .filter_map(move |_| self.process_vertex()) 152 | .next() 153 | } 154 | } 155 | 156 | #[cfg(test)] 157 | mod tests { 158 | use super::*; 159 | 160 | #[test] 161 | fn is_cyclic() { 162 | /* 163 | A previous version of the function would fail if the iterator had passed through the last cycle. 164 | 165 | The current version written 2019-03-23 caches if any cycles have been found as it 166 | iterates to resolve this issue. 167 | */ 168 | 169 | for _ in 0..100 { 170 | let mut graph = Graph::new(); 171 | 172 | let v = graph.add_vertex(0); 173 | 174 | assert!(graph.add_edge(&v, &v).is_ok(), "Failed to create cycle"); 175 | 176 | for _ in 0..100 { 177 | graph.add_vertex(0); 178 | } 179 | 180 | let mut dfs = graph.dfs(); 181 | 182 | for _ in 0..99 { 183 | dfs.next(); 184 | } 185 | 186 | assert!(dfs.is_cyclic()); 187 | } 188 | } 189 | #[test] 190 | fn not_cyclic() { 191 | let mut graph = Graph::new(); 192 | 193 | let v1 = graph.add_vertex(()); 194 | let v2 = graph.add_vertex(()); 195 | let v3 = graph.add_vertex(()); 196 | 197 | graph.add_edge(&v1, &v2); 198 | graph.add_edge(&v3, &v2); 199 | 200 | graph.add_vertex(()); 201 | 202 | assert_eq!(graph.is_cyclic(), false); 203 | } 204 | 205 | #[test] 206 | fn not_cyclic_edge_to_successor() { 207 | let mut graph = Graph::new(); 208 | 209 | let v1 = graph.add_vertex(1); 210 | let v2 = graph.add_vertex(2); 211 | let v3 = graph.add_vertex(3); 212 | 213 | graph.add_edge(&v1, &v2).unwrap(); 214 | graph.add_edge(&v2, &v3).unwrap(); 215 | graph.add_edge(&v1, &v3).unwrap(); 216 | 217 | assert_eq!(graph.is_cyclic(), false); 218 | } 219 | 220 | #[test] 221 | fn not_cyclic_edge_split_merge() { 222 | let mut graph = Graph::new(); 223 | 224 | let v1 = graph.add_vertex(1); 225 | let v2 = graph.add_vertex(2); 226 | let v3 = graph.add_vertex(3); 227 | let v4 = graph.add_vertex(4); 228 | let v5 = graph.add_vertex(5); 229 | let v6 = graph.add_vertex(6); 230 | 231 | graph.add_edge(&v1, &v2).unwrap(); 232 | graph.add_edge(&v2, &v3).unwrap(); 233 | graph.add_edge(&v3, &v4).unwrap(); 234 | graph.add_edge(&v3, &v5).unwrap(); 235 | graph.add_edge(&v4, &v6).unwrap(); 236 | graph.add_edge(&v5, &v6).unwrap(); 237 | 238 | assert_eq!(graph.is_cyclic(), false); 239 | } 240 | 241 | #[test] 242 | fn not_cyclic_split_merge_continue() { 243 | // TODO: rename that test 244 | 245 | let mut graph = Graph::new(); 246 | 247 | let v1 = graph.add_vertex(1); 248 | let v2 = graph.add_vertex(2); 249 | let v3 = graph.add_vertex(3); 250 | let v4 = graph.add_vertex(4); 251 | let v5 = graph.add_vertex(5); 252 | let v6 = graph.add_vertex(6); 253 | let v7 = graph.add_vertex(7); 254 | 255 | graph.add_edge(&v1, &v2).unwrap(); 256 | graph.add_edge(&v2, &v3).unwrap(); 257 | graph.add_edge(&v3, &v4).unwrap(); 258 | graph.add_edge(&v3, &v5).unwrap(); 259 | graph.add_edge(&v4, &v6).unwrap(); 260 | graph.add_edge(&v5, &v6).unwrap(); 261 | graph.add_edge(&v1, &v6).unwrap(); 262 | graph.add_edge(&v6, &v7).unwrap(); 263 | 264 | assert_eq!(graph.is_cyclic(), false); 265 | } 266 | 267 | #[test] 268 | fn cycle_self_edge() { 269 | let mut graph = Graph::new(); 270 | 271 | let v1 = graph.add_vertex(1); 272 | 273 | graph.add_edge(&v1, &v1).unwrap(); 274 | 275 | assert!(graph.is_cyclic()); 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /src/iterators/dijkstra.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Chakrapani Gautam 2 | 3 | use crate::graph::{Graph, GraphErr}; 4 | use crate::iterators::owning_iterator::OwningIterator; 5 | use crate::iterators::vertices::VertexIter; 6 | use crate::vertex_id::VertexId; 7 | 8 | use hashbrown::HashMap; 9 | use hashbrown::HashSet; 10 | 11 | #[cfg(not(feature = "no_std"))] 12 | use std::{ 13 | cmp::Ordering, 14 | collections::{BinaryHeap, VecDeque}, 15 | f32, 16 | fmt::Debug, 17 | iter, 18 | }; 19 | 20 | #[cfg(feature = "no_std")] 21 | extern crate alloc; 22 | #[cfg(feature = "no_std")] 23 | use alloc::boxed::Box; 24 | #[cfg(feature = "no_std")] 25 | use alloc::collections::{binary_heap::BinaryHeap, vec_deque::VecDeque}; 26 | 27 | #[cfg(feature = "no_std")] 28 | use core::{cmp::Ordering, f32, fmt::Debug, iter}; 29 | 30 | #[derive(PartialEq, Debug)] 31 | struct VertexMeta { 32 | id: VertexId, 33 | distance: f32, 34 | } 35 | 36 | impl Eq for VertexMeta {} 37 | 38 | impl PartialOrd for VertexMeta { 39 | fn partial_cmp(&self, other: &Self) -> Option { 40 | other.distance.partial_cmp(&self.distance) 41 | } 42 | } 43 | 44 | impl Ord for VertexMeta { 45 | fn cmp(&self, other: &Self) -> Ordering { 46 | self.partial_cmp(other).unwrap() 47 | } 48 | } 49 | 50 | #[derive(Clone, Debug)] 51 | /// Dijkstra Single-source Shortest Path Iterator 52 | pub struct Dijkstra<'a, T> { 53 | source: &'a VertexId, 54 | iterable: &'a Graph, 55 | iterator: VecDeque, 56 | distances: HashMap, 57 | previous: HashMap>, 58 | } 59 | 60 | impl<'a, T> Dijkstra<'a, T> { 61 | pub fn new(graph: &'a Graph, src: &'a VertexId) -> Result, GraphErr> { 62 | if graph.fetch(src).is_none() { 63 | return Err(GraphErr::NoSuchVertex); 64 | } 65 | 66 | for edge in graph.edges() { 67 | if let Some(w) = graph.weight(edge.1, edge.0) { 68 | if w < 0.0 { 69 | return Err(GraphErr::InvalidWeight); 70 | } 71 | } 72 | } 73 | 74 | let mut instance = Dijkstra { 75 | source: src, 76 | iterable: graph, 77 | iterator: VecDeque::with_capacity(graph.vertex_count()), 78 | distances: HashMap::with_capacity(graph.vertex_count()), 79 | previous: HashMap::with_capacity(graph.vertex_count()), 80 | }; 81 | 82 | instance.calc_distances(); 83 | 84 | Ok(instance) 85 | } 86 | 87 | pub fn set_source(&mut self, vert: &'a VertexId) -> Result<(), GraphErr> { 88 | if self.iterable.fetch(vert).is_none() { 89 | return Err(GraphErr::NoSuchVertex); 90 | } 91 | 92 | self.source = vert; 93 | self.distances.clear(); 94 | self.previous.clear(); 95 | self.calc_distances(); 96 | 97 | Ok(()) 98 | } 99 | 100 | pub fn get_path_to(mut self, vert: &'a VertexId) -> Result { 101 | if self.iterable.fetch(vert).is_none() { 102 | return Err(GraphErr::NoSuchVertex); 103 | } 104 | 105 | if self.previous.contains_key(vert) { 106 | let mut cur_vert = Some(vert); 107 | self.iterator.clear(); 108 | 109 | while cur_vert.is_some() { 110 | self.iterator.push_front(*cur_vert.unwrap()); 111 | 112 | match self.previous.get(cur_vert.unwrap()) { 113 | Some(v) => cur_vert = v.as_ref(), 114 | None => cur_vert = None, 115 | } 116 | } 117 | 118 | return Ok(VertexIter(Box::new(OwningIterator::new(self.iterator)))); 119 | } 120 | 121 | Ok(VertexIter(Box::new(iter::empty()))) 122 | } 123 | 124 | pub fn get_distance(&mut self, vert: &'a VertexId) -> Result { 125 | if self.iterable.fetch(vert).is_none() { 126 | return Err(GraphErr::NoSuchVertex); 127 | } 128 | 129 | if self.distances.contains_key(vert) { 130 | return Ok(*self.distances.get(vert).unwrap()); 131 | } 132 | 133 | Ok(f32::MAX) 134 | } 135 | 136 | fn calc_distances(&mut self) { 137 | let mut visited: HashSet = HashSet::with_capacity(self.iterable.vertex_count()); 138 | let mut vertex_pq: BinaryHeap = 139 | BinaryHeap::with_capacity(self.iterable.vertex_count()); 140 | 141 | for vert in self.iterable.vertices() { 142 | self.distances.insert(*vert, f32::MAX); 143 | } 144 | 145 | vertex_pq.push(VertexMeta { 146 | id: *self.source, 147 | distance: 0.0, 148 | }); 149 | 150 | self.distances.insert(*self.source, 0.0); 151 | self.previous.insert(*self.source, None); 152 | 153 | while let Some(vert_meta) = vertex_pq.pop() { 154 | if !visited.insert(vert_meta.id) { 155 | continue; 156 | } 157 | 158 | for neighbor in self.iterable.out_neighbors(&vert_meta.id) { 159 | if !visited.contains(&neighbor) { 160 | let mut alt_dist = *self.distances.get(&vert_meta.id).unwrap(); 161 | 162 | if let Some(w) = self.iterable.weight(&vert_meta.id, &neighbor) { 163 | alt_dist += w; 164 | } 165 | 166 | if alt_dist < *self.distances.get(&neighbor).unwrap() { 167 | self.distances.insert(*neighbor, alt_dist); 168 | self.previous.insert(*neighbor, Some(vert_meta.id)); 169 | 170 | vertex_pq.push(VertexMeta { 171 | id: *neighbor, 172 | distance: alt_dist, 173 | }); 174 | } 175 | } 176 | } 177 | } 178 | } 179 | } 180 | 181 | #[cfg(test)] 182 | mod tests { 183 | use super::*; 184 | 185 | #[test] 186 | fn test_new_with_empty_graph() { 187 | let random_vertex = VertexId::random(); 188 | 189 | let graph: Graph = Graph::new(); 190 | let result = Dijkstra::new(&graph, &random_vertex); 191 | 192 | assert!(result.is_err()); 193 | } 194 | 195 | #[test] 196 | fn test_new_with_invalid_source() { 197 | let random_vertex = VertexId::random(); 198 | 199 | let mut graph: Graph = Graph::new(); 200 | let v1 = graph.add_vertex(1); 201 | let v2 = graph.add_vertex(2); 202 | graph.add_edge_with_weight(&v1, &v2, 0.0); 203 | 204 | let result = Dijkstra::new(&graph, &random_vertex); 205 | 206 | assert!(result.is_err()); 207 | } 208 | 209 | #[test] 210 | fn test_new_with_negative_weight_edge() { 211 | let mut graph: Graph = Graph::new(); 212 | let v1 = graph.add_vertex(1); 213 | let v2 = graph.add_vertex(2); 214 | 215 | graph.add_edge_with_weight(&v1, &v2, -0.1); 216 | graph.add_edge_with_weight(&v2, &v1, 0.1); 217 | 218 | let result = Dijkstra::new(&graph, &v1); 219 | 220 | assert!(result.is_err()); 221 | } 222 | 223 | #[test] 224 | fn test_set_source_with_invalid_vertex() { 225 | let random_vertex = VertexId::random(); 226 | 227 | let mut graph: Graph = Graph::new(); 228 | let v1 = graph.add_vertex(1); 229 | let v2 = graph.add_vertex(2); 230 | graph.add_edge_with_weight(&v1, &v2, 0.0); 231 | 232 | let mut iterator = Dijkstra::new(&graph, &v1).unwrap(); 233 | let result = iterator.set_source(&random_vertex); 234 | 235 | assert!(result.is_err()); 236 | } 237 | 238 | #[test] 239 | fn test_get_path_to_with_invalid_vertex() { 240 | let random_vertex = VertexId::random(); 241 | 242 | let mut graph: Graph = Graph::new(); 243 | let v1 = graph.add_vertex(1); 244 | let v2 = graph.add_vertex(2); 245 | graph.add_edge_with_weight(&v1, &v2, 0.0); 246 | 247 | let mut iterator = Dijkstra::new(&graph, &v1).unwrap(); 248 | let result = iterator.get_path_to(&random_vertex); 249 | 250 | assert!(result.is_err()); 251 | } 252 | 253 | #[test] 254 | fn test_get_distance_with_invalid_vertex() { 255 | let random_vertex = VertexId::random(); 256 | 257 | let mut graph: Graph = Graph::new(); 258 | let v1 = graph.add_vertex(1); 259 | let v2 = graph.add_vertex(2); 260 | graph.add_edge_with_weight(&v1, &v2, 0.0); 261 | 262 | let mut iterator = Dijkstra::new(&graph, &v1).unwrap(); 263 | let result = iterator.get_distance(&random_vertex); 264 | 265 | assert!(result.is_err()); 266 | } 267 | 268 | #[test] 269 | fn test_on_connected_graphs() { 270 | let infinity = f32::MAX; 271 | 272 | let mut graph: Graph = Graph::new(); 273 | 274 | let v_a = graph.add_vertex(1); 275 | let v_b = graph.add_vertex(2); 276 | let v_c = graph.add_vertex(3); 277 | let v_d = graph.add_vertex(4); 278 | let v_e = graph.add_vertex(5); 279 | let v_f = graph.add_vertex(6); 280 | 281 | graph.add_edge_with_weight(&v_a, &v_b, 0.1).unwrap(); 282 | graph.add_edge_with_weight(&v_b, &v_d, 0.2).unwrap(); 283 | graph.add_edge_with_weight(&v_c, &v_b, 0.5).unwrap(); 284 | graph.add_edge_with_weight(&v_c, &v_d, 0.1).unwrap(); 285 | graph.add_edge_with_weight(&v_c, &v_e, 0.5).unwrap(); 286 | graph.add_edge_with_weight(&v_d, &v_f, 0.8).unwrap(); 287 | 288 | { 289 | let mut iterator = Dijkstra::new(&graph, &v_a).unwrap(); 290 | 291 | assert_eq!(iterator.get_distance(&v_a).unwrap(), 0.0); 292 | assert_eq!(iterator.get_distance(&v_b).unwrap(), 0.1); 293 | assert_eq!(iterator.get_distance(&v_c).unwrap(), infinity); 294 | assert_eq!(iterator.get_distance(&v_d).unwrap(), 0.3); 295 | assert_eq!(iterator.get_distance(&v_e).unwrap(), infinity); 296 | assert_eq!(iterator.get_distance(&v_f).unwrap(), 1.1); 297 | } 298 | 299 | graph.add_edge_with_weight(&v_b, &v_a, 0.1).unwrap(); 300 | graph.add_edge_with_weight(&v_d, &v_b, 0.2).unwrap(); 301 | graph.add_edge_with_weight(&v_b, &v_c, 0.5).unwrap(); 302 | graph.add_edge_with_weight(&v_d, &v_c, 0.1).unwrap(); 303 | graph.add_edge_with_weight(&v_e, &v_c, 0.5).unwrap(); 304 | graph.add_edge_with_weight(&v_f, &v_d, 0.8).unwrap(); 305 | 306 | let mut iterator = Dijkstra::new(&graph, &v_a).unwrap(); 307 | 308 | assert_eq!(iterator.get_distance(&v_a).unwrap(), 0.0); 309 | assert_eq!(iterator.get_distance(&v_b).unwrap(), 0.1); 310 | assert_eq!(iterator.get_distance(&v_c).unwrap(), 0.4); 311 | assert_eq!(iterator.get_distance(&v_d).unwrap(), 0.3); 312 | assert_eq!(iterator.get_distance(&v_e).unwrap(), 0.9); 313 | assert_eq!(iterator.get_distance(&v_f).unwrap(), 1.1); 314 | 315 | iterator.set_source(&v_c); 316 | 317 | assert_eq!(iterator.get_distance(&v_a).unwrap(), 0.4); 318 | assert_eq!(iterator.get_distance(&v_b).unwrap(), 0.3); 319 | assert_eq!(iterator.get_distance(&v_c).unwrap(), 0.0); 320 | assert_eq!(iterator.get_distance(&v_d).unwrap(), 0.1); 321 | assert_eq!(iterator.get_distance(&v_e).unwrap(), 0.5); 322 | assert_eq!(iterator.get_distance(&v_f).unwrap(), 0.900_000_04); 323 | // Ugh! I wish there was something like `assert_approx_eq!()`. Too lazy to write on my own. 324 | 325 | assert_eq!(iterator.clone().get_path_to(&v_a).unwrap().count(), 4); 326 | assert_eq!(iterator.clone().get_path_to(&v_b).unwrap().count(), 3); 327 | assert_eq!(iterator.clone().get_path_to(&v_c).unwrap().count(), 1); 328 | assert_eq!(iterator.clone().get_path_to(&v_d).unwrap().count(), 2); 329 | assert_eq!(iterator.clone().get_path_to(&v_e).unwrap().count(), 2); 330 | assert_eq!(iterator.clone().get_path_to(&v_f).unwrap().count(), 3); 331 | 332 | /* 333 | // To run these tests, uncomment and use `-- --nocapture` flag in `cargo test` 334 | 335 | for vert in graph.vertices() { 336 | println!("Current vertex: {:?}", graph.fetch(vert)); 337 | 338 | for arg in iterator.get_path_to(vert).unwrap() { 339 | print!(" {:?}", graph.fetch(arg)); 340 | } 341 | println!(); 342 | } 343 | */ 344 | } 345 | 346 | #[test] 347 | fn test_on_unweighted_graph() { 348 | let infinity = f32::MAX; 349 | 350 | let mut graph: Graph = Graph::new(); 351 | 352 | let v_a = graph.add_vertex(1); 353 | let v_b = graph.add_vertex(2); 354 | let v_c = graph.add_vertex(3); 355 | let v_d = graph.add_vertex(4); 356 | let v_e = graph.add_vertex(5); 357 | let v_f = graph.add_vertex(6); 358 | 359 | graph.add_edge(&v_a, &v_b).unwrap(); 360 | graph.add_edge(&v_b, &v_d).unwrap(); 361 | graph.add_edge(&v_c, &v_b).unwrap(); 362 | graph.add_edge(&v_c, &v_d).unwrap(); 363 | graph.add_edge(&v_c, &v_e).unwrap(); 364 | graph.add_edge(&v_d, &v_f).unwrap(); 365 | 366 | let mut iterator = Dijkstra::new(&graph, &v_a).unwrap(); 367 | 368 | assert_eq!(iterator.get_distance(&v_a).unwrap(), 0.0); 369 | assert_eq!(iterator.get_distance(&v_b).unwrap(), 0.0); 370 | assert_eq!(iterator.get_distance(&v_c).unwrap(), infinity); 371 | assert_eq!(iterator.get_distance(&v_d).unwrap(), 0.0); 372 | assert_eq!(iterator.get_distance(&v_e).unwrap(), infinity); 373 | assert_eq!(iterator.get_distance(&v_f).unwrap(), 0.0); 374 | 375 | assert_eq!(iterator.clone().get_path_to(&v_a).unwrap().count(), 1); 376 | assert_eq!(iterator.clone().get_path_to(&v_b).unwrap().count(), 2); 377 | assert_eq!(iterator.clone().get_path_to(&v_c).unwrap().count(), 0); 378 | assert_eq!(iterator.clone().get_path_to(&v_d).unwrap().count(), 3); 379 | assert_eq!(iterator.clone().get_path_to(&v_e).unwrap().count(), 0); 380 | assert_eq!(iterator.clone().get_path_to(&v_f).unwrap().count(), 4); 381 | 382 | iterator.set_source(&v_c).unwrap(); 383 | 384 | assert_eq!(iterator.get_distance(&v_a).unwrap(), infinity); 385 | assert_eq!(iterator.get_distance(&v_b).unwrap(), 0.0); 386 | assert_eq!(iterator.get_distance(&v_c).unwrap(), 0.0); 387 | assert_eq!(iterator.get_distance(&v_d).unwrap(), 0.0); 388 | assert_eq!(iterator.get_distance(&v_e).unwrap(), 0.0); 389 | assert_eq!(iterator.get_distance(&v_f).unwrap(), 0.0); 390 | 391 | assert_eq!(iterator.clone().get_path_to(&v_a).unwrap().count(), 0); 392 | assert_eq!(iterator.clone().get_path_to(&v_b).unwrap().count(), 2); 393 | assert_eq!(iterator.clone().get_path_to(&v_c).unwrap().count(), 1); 394 | assert_eq!(iterator.clone().get_path_to(&v_d).unwrap().count(), 2); 395 | assert_eq!(iterator.clone().get_path_to(&v_e).unwrap().count(), 2); 396 | assert_eq!(iterator.clone().get_path_to(&v_f).unwrap().count(), 3); 397 | 398 | /* 399 | // To run these tests, uncomment and use `-- --nocapture` flag in `cargo test` 400 | 401 | for vert in graph.vertices() { 402 | println!("Current vertex: {:?}", graph.fetch(vert)); 403 | 404 | for arg in iterator.get_path_to(vert).unwrap() { 405 | print!(" {:?}", graph.fetch(arg)); 406 | } 407 | println!(); 408 | } 409 | */ 410 | } 411 | } 412 | -------------------------------------------------------------------------------- /src/iterators/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | mod bfs; 4 | mod dfs; 5 | mod dijkstra; 6 | mod owning_iterator; 7 | mod topo; 8 | mod values; 9 | mod vertices; 10 | 11 | pub use bfs::*; 12 | pub use dfs::*; 13 | pub use dijkstra::*; 14 | pub use topo::*; 15 | pub use values::*; 16 | pub use vertices::*; 17 | -------------------------------------------------------------------------------- /src/iterators/owning_iterator.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | use crate::vertex_id::VertexId; 4 | 5 | #[cfg(not(feature = "no_std"))] 6 | use std::fmt::Debug; 7 | 8 | #[cfg(not(feature = "no_std"))] 9 | use std::marker::PhantomData; 10 | 11 | #[cfg(feature = "no_std")] 12 | use core::marker::PhantomData; 13 | 14 | #[cfg(feature = "no_std")] 15 | use core::mem; 16 | 17 | #[cfg(not(feature = "no_std"))] 18 | use std::mem; 19 | 20 | #[cfg(not(feature = "no_std"))] 21 | use std::collections::VecDeque; 22 | 23 | #[cfg(feature = "no_std")] 24 | use alloc::collections::VecDeque; 25 | 26 | /// Iterator that owns the data. 27 | #[derive(Debug)] 28 | pub(crate) struct OwningIterator<'a> { 29 | iterable: VecDeque, 30 | cur_idx: usize, // Quite the hack, but it works 31 | phantom: PhantomData<&'a u8>, 32 | } 33 | 34 | impl<'a> OwningIterator<'a> { 35 | pub fn new(iterable: VecDeque) -> Self { 36 | OwningIterator { 37 | iterable, 38 | cur_idx: 0, 39 | phantom: PhantomData, 40 | } 41 | } 42 | } 43 | 44 | impl<'a> Iterator for OwningIterator<'a> { 45 | type Item = &'a VertexId; 46 | 47 | #[inline] 48 | fn next(&mut self) -> Option { 49 | if self.cur_idx == self.iterable.len() { 50 | None 51 | } else { 52 | let last_idx = self.cur_idx; 53 | self.cur_idx += 1; 54 | 55 | // Since we cannot annotate the lifetime 'a to &mut self 56 | // because of the Iterator trait's signature, this seems 57 | // the only way to make the compiler happy. 58 | // 59 | // TODO: If you can make this work with safe Rust, please do. 60 | unsafe { 61 | let ptr = &self.iterable[last_idx] as *const VertexId; 62 | let transmuted = mem::transmute::<*const VertexId, &VertexId>(ptr); 63 | Some(transmuted) 64 | } 65 | } 66 | } 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use super::*; 72 | 73 | #[test] 74 | fn it_yields_correct_vertex_ids() { 75 | let ids: VecDeque = 76 | vec![VertexId::random(), VertexId::random(), VertexId::random()] 77 | .iter() 78 | .cloned() 79 | .collect(); 80 | let mut iter = OwningIterator::new(ids.clone()); 81 | 82 | assert_eq!(iter.next(), Some(&ids[0])); 83 | assert_eq!(iter.next(), Some(&ids[1])); 84 | assert_eq!(iter.next(), Some(&ids[2])); 85 | assert_eq!(iter.next(), None); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/iterators/topo.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Gary Pennington 2 | 3 | use crate::graph::Graph; 4 | use crate::vertex_id::VertexId; 5 | 6 | use hashbrown::HashMap; 7 | 8 | #[cfg(feature = "no_std")] 9 | use alloc::vec::Vec; 10 | 11 | #[cfg(feature = "no_std")] 12 | use core::fmt::Debug; 13 | 14 | #[cfg(not(feature = "no_std"))] 15 | use std::fmt::Debug; 16 | 17 | const PANIC_MSG: &str = "graph contains cycle(s)"; 18 | 19 | #[derive(Debug)] 20 | /// Topological Iterator 21 | pub struct Topo<'a, T> { 22 | /// The Graph being iterated. 23 | iterable: &'a Graph, 24 | /// Processed vertices 25 | vertices: Vec<&'a VertexId>, 26 | /// Working set of vertices 27 | roots: Vec<&'a VertexId>, 28 | /// Working set of vertex edges 29 | vertex_edges: HashMap<&'a VertexId, usize>, 30 | } 31 | 32 | impl<'a, T> Topo<'a, T> { 33 | pub fn new(graph: &'a Graph) -> Topo<'_, T> { 34 | let mut roots = vec![]; 35 | for node in graph.roots() { 36 | roots.push(node); 37 | } 38 | 39 | Topo { 40 | iterable: graph, 41 | vertices: vec![], 42 | roots, 43 | vertex_edges: HashMap::new(), 44 | } 45 | } 46 | 47 | /// Processes the next vertex. 48 | /// 49 | /// Will return None if: 50 | /// 51 | /// * No vertices are left. 52 | fn process_vertex(&mut self, check_cyclic: bool) -> Option<&'a VertexId> { 53 | match self.roots.pop() { 54 | Some(node) => { 55 | self.vertices.push(node); 56 | for out in self.iterable.out_neighbors(node) { 57 | let count = match self.vertex_edges.get_mut(out) { 58 | Some(count) => count, 59 | None => { 60 | self.vertex_edges 61 | .insert(out, self.iterable.in_neighbors_count(out)); 62 | self.vertex_edges.get_mut(out).unwrap() 63 | } 64 | }; 65 | if *count == 1 { 66 | self.roots.push(out); 67 | } else { 68 | *count -= 1; 69 | } 70 | } 71 | Some(node) 72 | } 73 | None => { 74 | if check_cyclic && self.vertices.len() != self.iterable.vertex_count() { 75 | panic!("{}", PANIC_MSG); 76 | } 77 | None 78 | } 79 | } 80 | } 81 | 82 | /// 83 | /// Returns true if the iterated graph has a cycle. 84 | /// 85 | /// # Warning 86 | /// 87 | /// It is a logic error to use this iterator after calling this function. 88 | pub fn is_cyclic(&mut self) -> bool { 89 | //Search until an answer is found. 90 | while self.process_vertex(false).is_some() {} 91 | 92 | self.vertices.len() != self.iterable.vertex_count() 93 | } 94 | } 95 | 96 | impl<'a, T> Iterator for Topo<'a, T> { 97 | type Item = &'a VertexId; 98 | 99 | fn size_hint(&self) -> (usize, Option) { 100 | let remaining = self.iterable.vertex_count() - self.vertices.len(); 101 | 102 | (0, Some(remaining)) 103 | } 104 | fn next(&mut self) -> Option { 105 | (0..self.size_hint().1.unwrap()) 106 | .filter_map(move |_| self.process_vertex(true)) 107 | .next() 108 | } 109 | } 110 | 111 | #[cfg(test)] 112 | mod tests { 113 | use super::*; 114 | 115 | #[test] 116 | fn is_not_cyclic() { 117 | let mut graph: Graph = Graph::new(); 118 | 119 | let v1 = graph.add_vertex(1); 120 | let v2 = graph.add_vertex(2); 121 | let v3 = graph.add_vertex(3); 122 | let v4 = graph.add_vertex(4); 123 | let v5 = graph.add_vertex(5); 124 | let v6 = graph.add_vertex(6); 125 | let v7 = graph.add_vertex(7); 126 | 127 | graph.add_edge(&v1, &v4).unwrap(); 128 | graph.add_edge(&v2, &v4).unwrap(); 129 | graph.add_edge(&v2, &v5).unwrap(); 130 | graph.add_edge(&v3, &v5).unwrap(); 131 | graph.add_edge(&v4, &v6).unwrap(); 132 | graph.add_edge(&v4, &v7).unwrap(); 133 | graph.add_edge(&v5, &v6).unwrap(); 134 | graph.add_edge(&v6, &v7).unwrap(); 135 | 136 | let mut topo = graph.topo(); 137 | 138 | assert!(!topo.is_cyclic()); 139 | } 140 | 141 | #[test] 142 | fn is_cyclic() { 143 | let mut graph: Graph = Graph::new(); 144 | 145 | let v1 = graph.add_vertex(1); 146 | let v2 = graph.add_vertex(2); 147 | let v3 = graph.add_vertex(3); 148 | let v4 = graph.add_vertex(4); 149 | let v5 = graph.add_vertex(5); 150 | let v6 = graph.add_vertex(6); 151 | let v7 = graph.add_vertex(7); 152 | 153 | graph.add_edge(&v1, &v4).unwrap(); 154 | graph.add_edge(&v2, &v4).unwrap(); 155 | graph.add_edge(&v2, &v5).unwrap(); 156 | graph.add_edge(&v3, &v5).unwrap(); 157 | graph.add_edge(&v4, &v6).unwrap(); 158 | graph.add_edge(&v4, &v7).unwrap(); 159 | graph.add_edge(&v5, &v6).unwrap(); 160 | graph.add_edge(&v6, &v7).unwrap(); 161 | graph.add_edge(&v7, &v2).unwrap(); 162 | 163 | let mut topo = graph.topo(); 164 | 165 | assert!(topo.is_cyclic()); 166 | } 167 | 168 | #[test] 169 | #[should_panic(expected = "graph contains cycle(s)")] 170 | fn is_cyclic_and_panic() { 171 | let mut graph: Graph = Graph::new(); 172 | 173 | let v1 = graph.add_vertex(1); 174 | let v2 = graph.add_vertex(2); 175 | let v3 = graph.add_vertex(3); 176 | let v4 = graph.add_vertex(4); 177 | let v5 = graph.add_vertex(5); 178 | let v6 = graph.add_vertex(6); 179 | let v7 = graph.add_vertex(7); 180 | 181 | graph.add_edge(&v1, &v4).unwrap(); 182 | graph.add_edge(&v2, &v4).unwrap(); 183 | graph.add_edge(&v2, &v5).unwrap(); 184 | graph.add_edge(&v3, &v5).unwrap(); 185 | graph.add_edge(&v4, &v6).unwrap(); 186 | graph.add_edge(&v4, &v7).unwrap(); 187 | graph.add_edge(&v5, &v6).unwrap(); 188 | graph.add_edge(&v6, &v7).unwrap(); 189 | graph.add_edge(&v7, &v2).unwrap(); 190 | 191 | let mut topo = graph.topo(); 192 | 193 | topo.next(); 194 | topo.next(); 195 | topo.next(); 196 | topo.next(); 197 | topo.next(); 198 | topo.next(); 199 | topo.next(); 200 | } 201 | 202 | #[test] 203 | fn was_cyclic() { 204 | let mut graph: Graph = Graph::new(); 205 | 206 | let v1 = graph.add_vertex(1); 207 | let v2 = graph.add_vertex(2); 208 | let v3 = graph.add_vertex(3); 209 | 210 | graph.add_edge(&v1, &v2).unwrap(); 211 | graph.add_edge(&v2, &v3).unwrap(); 212 | graph.add_edge(&v3, &v1).unwrap(); 213 | 214 | graph.remove_edge(&v3, &v1); 215 | 216 | let mut topo = graph.topo(); 217 | 218 | assert!(!topo.is_cyclic()); 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/iterators/values.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | #[cfg(feature = "no_std")] 4 | extern crate alloc; 5 | #[cfg(feature = "no_std")] 6 | use alloc::boxed::Box; 7 | 8 | /// Generic values Iterator. 9 | pub struct ValuesIter<'a, T>(pub(crate) Box>); 10 | 11 | impl<'a, T> Iterator for ValuesIter<'a, T> { 12 | type Item = &'a T; 13 | 14 | #[inline] 15 | fn next(&mut self) -> Option { 16 | self.0.next() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/iterators/vertices.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | use crate::vertex_id::VertexId; 4 | #[cfg(feature = "no_std")] 5 | use core::fmt::Debug; 6 | #[cfg(feature = "no_std")] 7 | extern crate alloc; 8 | #[cfg(feature = "no_std")] 9 | use alloc::boxed::Box; 10 | #[cfg(not(feature = "no_std"))] 11 | use std::fmt::Debug; 12 | 13 | pub(crate) trait MergedTrait<'a>: Iterator + Debug {} 14 | 15 | impl<'a, T> MergedTrait<'a> for T where T: Iterator + Debug {} 16 | 17 | /// Generic Vertex Iterator. 18 | #[derive(Debug)] 19 | pub struct VertexIter<'a>(pub(crate) Box>); 20 | 21 | impl<'a> Iterator for VertexIter<'a> { 22 | type Item = &'a VertexId; 23 | 24 | #[inline] 25 | fn next(&mut self) -> Option { 26 | self.0.next() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | #![cfg_attr(feature = "no_std", no_std)] 4 | 5 | //! # Graphlib 6 | //! Graphlib is a simple and powerful Rust graph library. 7 | //! 8 | //! --- 9 | //! 10 | //! This library attempts to provide a generic api for building, mutating and iterating over graphs that is similar to that of other data-structures in rust i.e. `Vec`, `HashMap`, `VecDeque`, etc. 11 | //! 12 | //! ### Usage 13 | //! ```rust 14 | //! use graphlib::Graph; 15 | //! 16 | //! let mut graph: Graph = Graph::new(); 17 | //! 18 | //! // Add two vertices to the graph 19 | //! let id1 = graph.add_vertex(1); 20 | //! let id2 = graph.add_vertex(2); 21 | //! 22 | //! // Add an edge between the two vertices 23 | //! graph.add_edge(&id1, &id2); 24 | //! 25 | //! assert_eq!(*graph.fetch(&id1).unwrap(), 1); 26 | //! assert_eq!(*graph.fetch(&id2).unwrap(), 2); 27 | //! 28 | //! // The graph has 2 vertices and one edge at this point 29 | //! assert_eq!(graph.vertex_count(), 2); 30 | //! assert_eq!(graph.edge_count(), 1); 31 | //! 32 | //! // Remove one of the connected vertices 33 | //! graph.remove(&id1); 34 | //! 35 | //! assert_eq!(graph.vertex_count(), 1); 36 | //! assert_eq!(graph.edge_count(), 0); 37 | //! ``` 38 | 39 | #![allow(mutable_transmutes)] 40 | 41 | mod edge; 42 | #[macro_use] 43 | mod macros; 44 | mod graph; 45 | pub mod iterators; 46 | mod vertex_id; 47 | 48 | // use global variables to create VertexId::random() 49 | use core::sync::atomic::AtomicUsize; 50 | 51 | #[cfg(feature = "dot")] 52 | pub mod dot; 53 | 54 | pub use graph::*; 55 | pub use vertex_id::*; 56 | 57 | static SEED: AtomicUsize = AtomicUsize::new(0); 58 | 59 | use rand; 60 | use rand::Rng; 61 | use rand::SeedableRng; 62 | use rand_core::RngCore; 63 | use rand_isaac::IsaacRng; 64 | 65 | use core::sync::atomic::Ordering; 66 | 67 | pub(crate) fn gen_bytes() -> [u8; 16] { 68 | IsaacRng::gen::<[u8; 16]>(&mut IsaacRng::seed_from_u64(IsaacRng::next_u64( 69 | &mut IsaacRng::seed_from_u64(SEED.fetch_add(1, Ordering::Relaxed) as u64), 70 | ))) 71 | } 72 | 73 | #[cfg(feature = "no_std")] 74 | #[macro_use] 75 | extern crate alloc; 76 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | /// Find the minimum of a set of numbers 2 | #[macro_export] 3 | macro_rules! min { 4 | ($x: expr) => ($x); 5 | ($x: expr, $($z: expr),+) => (::core::cmp::min($x, min!($($z),*))); 6 | } 7 | 8 | /// Returns a HashSet containing the passed values. 9 | #[macro_export] 10 | macro_rules! set { 11 | () => ({ 12 | HashSet::new() 13 | }); 14 | 15 | ($fst:expr $(, $v:expr)*) => ({ 16 | let mut set = HashSet::with_capacity(count!($fst $(, $v)*)); 17 | 18 | set.insert($fst); 19 | $(set.insert($v);)* 20 | 21 | set 22 | }); 23 | } 24 | 25 | /// Counts the number of values passed to it. 26 | #[macro_export] 27 | macro_rules! count { 28 | () => (0); 29 | ($fst:expr) => (1); 30 | ($fst:expr, $snd:expr) => (2); 31 | ($fst:expr, $snd:expr $(, $v:expr)*) => (1 + count!($snd $(, $v)*)); 32 | } 33 | -------------------------------------------------------------------------------- /src/vertex_id.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Octavian Oncescu 2 | 3 | #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] 4 | /// Id of a vertex 5 | pub struct VertexId([u8; 16]); // 128bit 6 | 7 | impl core::fmt::Debug for VertexId { 8 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 9 | let mut buff: [u8; 32] = [0 as u8; 32]; 10 | let _ = hex::encode_to_slice(self.0, &mut buff); 11 | let s = core::str::from_utf8(&buff).unwrap(); 12 | write!(f, "VertexId({})", s) 13 | } 14 | } 15 | 16 | impl core::convert::AsRef for VertexId { 17 | fn as_ref(&self) -> &VertexId { 18 | &self 19 | } 20 | } 21 | 22 | impl VertexId { 23 | pub fn random() -> VertexId { 24 | VertexId(super::gen_bytes()) 25 | } 26 | 27 | pub fn bytes(&self) -> &[u8; 16] { 28 | &self.0 29 | } 30 | } 31 | --------------------------------------------------------------------------------