petgraph/lib.rs
1/*!
2`petgraph` is a graph data structure library.
3
4Graphs are collections of nodes, and edges between nodes. `petgraph`
5provides several [graph types](index.html#graph-types) (each differing in the
6tradeoffs taken in their internal representation),
7[algorithms](./algo/index.html) on those graphs, and functionality to
8[output graphs](./dot/struct.Dot.html) in
9[`Graphviz`](https://www.graphviz.org/) format. Both nodes and edges
10can have arbitrary associated data, and edges may be either directed or undirected.
11
12# Overview
13
14Here is a simple example showing off some features of `petgraph`:
15```
16use petgraph::graph::UnGraph;
17use petgraph::algo::{dijkstra, min_spanning_tree};
18use petgraph::data::FromElements;
19use petgraph::dot::{Dot, Config};
20use petgraph::visit::NodeIndexable;
21
22// Create an undirected graph with associated data
23// of type `i32` for the nodes and `()` for the edges.
24let g = UnGraph::<i32, ()>::from_edges(&[
25 (0, 1), (1, 2), (2, 3), (0, 3)
26]);
27
28// The graph looks like this:
29// 0 -- 1
30// | |
31// 3 -- 2
32
33// Find the shortest path from `0` to `2` using `1` as the cost for every edge.
34let node_map = dijkstra(&g, 0.into(), Some(2.into()), |_| 1);
35assert_eq!(&2i32, node_map.get(&g.from_index(2)).unwrap());
36
37// Get the minimum spanning tree of the graph as a new graph, and check that
38// one edge was trimmed.
39let mst = UnGraph::<_, _>::from_elements(min_spanning_tree(&g));
40assert_eq!(g.raw_edges().len() - 1, mst.raw_edges().len());
41
42// Output the tree to `graphviz` `DOT` format
43println!("{:?}", Dot::with_config(&mst, &[Config::EdgeNoLabel]));
44// graph {
45// 0 [ label = "0" ]
46// 1 [ label = "0" ]
47// 2 [ label = "0" ]
48// 3 [ label = "0" ]
49// 0 -- 1 [ ]
50// 2 -- 3 [ ]
51// 1 -- 2 [ ]
52// }
53```
54
55`petgraph` provides several concrete graph types — [`Graph`](./graph/struct.Graph.html),
56[`StableGraph`](./stable_graph/struct.StableGraph.html), [`GraphMap`](./graphmap/struct.GraphMap.html),
57[`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html), and [`Csr`](./csr/struct.Csr.html)
58— each optimized for different trade-offs in memory layout, index stability, and lookup speed.
59Some types (e.g., [`Graph`](./graph/struct.Graph.html)) expose the fullest set of methods
60and algorithm support, while others (like [`StableGraph`](./stable_graph/struct.StableGraph.html)
61or [`Csr`](./csr/struct.Csr.html)) are more recent and may not yet implement the full feature set,
62see [Graph Types](#graph-types) for more details.
63
64With these types as building blocks, you can insert or remove nodes and edges, attach arbitrary data to them,
65explore neighbors, and apply standard graph algorithms. The [`algo`] module implements routines such as
66shortest‐path searches and minimum spanning trees for any compatible graph, and the [`dot`] module exports
67functionality to convert graphs to DOT format so you can visualize or analyze them with
68[`Graphviz`](https://www.graphviz.org/).
69
70The remainder of this documentation is organized as follows:
71
72* [Usage](#usage) shows how to add `petgraph` to your project.
73
74* [Graph types](#graph-types) explains each implementation’s internal structure and feature set.
75
76 * [Generic parameters](#generic-parameters) clarifies what N, E, Ty, and Ix signify and any trait bounds they impose.
77
78 * [Shorthand types](#shorthand-types) lists commonly used aliases (for example, [`DiGraph<_, _>`](./graph/type.DiGraph.html) for [`Graph<_, _, Directed>`](./graph/struct.Graph.html).
79
80* [Examples](#examples) walks through common tasks such as basic graph construction, index behavior, running algorithms, weight transformations, and DOT export.
81
82* [Crate features](#crate-features) covers (optional) Cargo flags (e.g. serde or rayon support).
83
84* Finally, each submodule page (e.g., [`algo`], [`graph`], [`graphmap`], etc.) provides detailed API documentation and design notes.
85
86# Usage
87
88`petgraph` is available on [crates.io](https://crates.io/crates/petgraph) and can be added to your
89project by adding `petgraph` to your `Cargo.toml`. Or more simply, by running `cargo add petgraph`.
90
91Here is an example that creates a new Rust project, adds a dependency on `petgraph`, and runs
92a simple program that creates an undirected graph.
93
94First, create a new Rust project in a new directory:
95```bash
96cargo new petgraph_example
97cd petgraph_example
98```
99
100Second, add a dependency on `petgraph`:
101```bash
102cargo add petgraph
103```
104
105Third, replace the contents of your main function in `src/main.rs` with the following code:
106```text
107use petgraph::graph::UnGraph;
108
109fn main() {
110 let g = UnGraph::<(), ()>::from_edges(&[(0, 1), (1, 2), (2, 3), (0, 3)]);
111
112 println!("Graph: {:?}", g);
113}
114```
115
116Finally, run the program with `cargo run`:
117```bash
118Graph { Ty: "Undirected", node_count: 4, edge_count: 4, edges: (0, 1), (1, 2), (2, 3), (0, 3) }
119```
120
121# Graph types
122
123* [`Graph`](./graph/struct.Graph.html) -
124 An adjacency list graph with arbitrary associated data.
125* [`StableGraph`](./stable_graph/struct.StableGraph.html) -
126 Similar to `Graph`, but it keeps indices stable across removals.
127* [`GraphMap`](./graphmap/struct.GraphMap.html) -
128 An adjacency list graph backed by a hash table. The node identifiers are the keys
129 into the table.
130* [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html) -
131 An adjacency matrix graph.
132* [`CSR`](./csr/struct.Csr.html) -
133 A sparse adjacency matrix graph with arbitrary associated data.
134
135### Generic parameters
136
137Each graph type is generic over a handful of parameters. All graphs share 3 common
138parameters, `N`, `E`, and `Ty`. This is a broad overview of what those are. Each
139graph type's documentation will have finer detail on these parameters.
140
141`N` & `E` are called *weights* in this implementation, and are associated with
142nodes and edges respectively. They can generally be of arbitrary type, and don't have to
143be what you might conventionally consider weight-like. For example, using `&str` for `N`
144will work. Many algorithms that require costs let you provide a cost function that
145translates your `N` and `E` weights into costs appropriate to the algorithm. Some graph
146types and choices do impose bounds on `N` or `E`.
147[`min_spanning_tree`](./algo/fn.min_spanning_tree.html) for example requires edge weights that
148implement [`PartialOrd`](https://doc.rust-lang.org/stable/core/cmp/trait.PartialOrd.html).
149[`GraphMap`](./graphmap/struct.GraphMap.html) requires node weights that can serve as hash
150map keys, since that graph type does not create standalone node indices.
151
152`Ty` controls whether edges are [`Directed`](./enum.Directed.html) or
153[`Undirected`](./enum.Undirected.html).
154
155`Ix` appears on graph types that use indices. It is exposed so you can control
156the size of node and edge indices, and therefore the memory footprint of your graphs.
157Allowed values are `u8`, `u16`, `u32`, and `usize`, with `u32` being the default.
158
159### Shorthand types
160
161Each graph type vends a few shorthand type definitions that name some specific
162generic choices. For example, [`DiGraph<_, _>`](./graph/type.DiGraph.html) is shorthand
163for [`Graph<_, _, Directed>`](graph/struct.Graph.html).
164[`UnMatrix<_, _>`](./matrix_graph/type.UnMatrix.html) is shorthand for
165[`MatrixGraph<_, _, Undirected>`](./matrix_graph/struct.MatrixGraph.html). Each graph type's
166module documentation lists the available shorthand types.
167
168# Examples
169
170* [Creating an undirected graph and manipulating nodes and edges](#creating-an-undirected-graph-and-manipulating-nodes-and-edges)
171* [Differences of stable and non-stable graphs in index management](#differences-of-stable-and-non-stable-graphs-in-index-management)
172* [Using algorithms on graphs](#using-algorithms-on-graphs)
173* [Associating data with nodes and edges and transmuting the type of the data](#associating-data-with-nodes-and-edges-and-transmuting-the-type-of-the-data)
174* [Exporting graphs to DOT format](#exporting-graphs-to-dot-format)
175
176### Creating an undirected graph and manipulating nodes and edges
177
178```
179use petgraph::graph::UnGraph;
180use petgraph::visit::NodeIndexable;
181
182// Create an undirected graph with associated data of type `i32` for nodes and `()` for edges.
183let mut g = UnGraph::<i32, ()>::from_edges(&[(0, 1), (1, 2), (2, 3), (0, 3)]);
184
185// The graph looks like this:
186// 0 -- 1
187// | |
188// 3 -- 2
189
190// Add two more edges between nodes 0 and 2, and 1 and 3
191g.extend_with_edges(&[(0, 2), (1, 3)]);
192
193// Add another node with a weight of 5
194let node = g.add_node(5);
195
196// Connect the new node to node 2.
197// We can access the recently added node via the returned `NodeIndex`.
198g.add_edge(node, 2.into(), ());
199
200// The graph now looks like this:
201// 0 -- 1
202// | \/ |
203// | /\ |
204// 3 -- 2
205// \
206// 4
207
208// We can also access existing nodes by creating a `NodeIndex` using the from_index
209// method on g. Indexes are zero-based, so the first node is at index 0.
210let node_0 = g.from_index(0);
211
212// And then change the weight of node 0 to 10.
213let node_0_weight = g.node_weight_mut(node_0).unwrap();
214*node_0_weight = 10;
215assert_eq!(g.node_weight(node_0), Some(&10));
216```
217
218Note that when creating the graph, we only specified the edges, and the nodes were created
219automatically. Since we did not specify the node weights, they default to `i32::default()`, which
220is `0`.
221
222### Differences of stable and non-stable graphs in index management
223
224This example shows how to remove a node from a graph and how this might change node indices.
225Removing a node also automatically takes care of removing all edges connected to the removed node.
226
227When removing a node from a non-stable graph, the node indices might change depending on two cases.
228If the node had the highest index, the other nodes' indices don't change. If the removed
229node did not have the highest index, the node with the highest index will take the index of the
230removed node and all other indices stay the same.
231
232[Stable graphs](./stable_graph/struct.StableGraph.html) address this by keeping the indices of nodes
233and edges stable, even after removals. Currently, this comes at the cost of possible additional memory
234usage and lack of some features that other graph types provide. For all the graph types, and their
235internal structure and feature set, please refer to [Graph Types](#graph-types).
236
237```
238#[cfg(feature = "stable_graph")]
239{
240use petgraph::graph::UnGraph;
241use petgraph::stable_graph::StableUnGraph;
242use petgraph::visit::IntoNodeIdentifiers;
243
244// Create an stable and non-stable undirected graph.
245let mut g_non_stable = UnGraph::<i32, ()>::from_edges(&[(0, 1), (1, 2), (2, 3), (0, 3)]);
246let mut g_stable = StableUnGraph::<i32, ()>::from_edges(&[(0, 1), (1, 2), (2, 3), (0, 3)]);
247
248// The graphs look like this:
249// 0 -- 1
250// | |
251// 3 -- 2
252
253// Remove node 1 and see how the node indexes change.
254g_non_stable.remove_node(1.into());
255g_stable.remove_node(1.into());
256
257println!("Node Indices (Non-Stable): {:?}", g_non_stable.node_identifiers().collect::<Vec<_>>());
258// Output: Node Indices (Non-Stable): [NodeIndex(0), NodeIndex(1), NodeIndex(2)]
259println!("Node Indices (Stable): {:?}", g_stable.node_identifiers().collect::<Vec<_>>());
260// Output: Node Indices (Stable): [NodeIndex(0), NodeIndex(1), NodeIndex(3)]
261
262// The non-stable graph now looks like this:
263// 0
264// |
265// 1 -- 2
266// The node which previously had index 1 has been removed, and the node which previously had
267// index 2 has now taken index 1. The other nodes' indices remain unchanged.
268
269// The stable graph now looks like this:
270// 0
271// |
272// 2 -- 3
273// The node indices have remained stable and the node with index 1 has been removed.
274}
275```
276
277### Using algorithms on graphs
278
279Petgraph provides not only data structures for modeling graphs, but also a wide range of algorithms
280that can be applied to them. For example, given a graph, one can compute shortest paths,
281minimum spanning trees, or even compute the maximal cliques of a graph.
282
283Generally, algorithms are found in the [`algo`] module, except for algorithms like
284depth-/breadth-first-search, which can be found in the [`visit`] module. All of them should include
285an example of how to use them. For example, to compute the minimum spanning tree of a graph, one can use the
286[`min_spanning_tree`](algo/min_spanning_tree/fn.min_spanning_tree.html) function.
287
288```
289use petgraph::algo::min_spanning_tree;
290use petgraph::data::FromElements;
291use petgraph::graph::UnGraph;
292
293// Create a graph to compute the minimum spanning tree of.
294let g = UnGraph::<i32, ()>::from_edges(&[(0, 1), (1, 2), (2, 3), (0, 3)]);
295
296// The graphs look like this:
297// 0 -- 1
298// | |
299// 3 -- 2
300
301// Compute a minimum spanning tree of the graph and collect it into a new graph.
302let mst = UnGraph::<_, _>::from_elements(min_spanning_tree(&g));
303
304// Check that the minimum spanning tree has one edge less than the original graph.
305assert_eq!(g.raw_edges().len() - 1, mst.raw_edges().len());
306```
307
308### Associating data with nodes and edges and transmuting the type of the data
309
310In many cases, it is useful to associate data with nodes and/or edges in a graph.
311For example, associating an integer with each edge to represent its usage cost in a network.
312
313Petgraph allows you to associate arbitrary data with both nodes and edges in a graph.
314Not only that, but it also exposes functionality to easily work with your associated
315data and transform it into a different type using the `map` methods.
316
317Associated data might also be referred to as *weights* in the documentation.
318
319```
320use petgraph::graph::UnGraph;
321
322// Create an undirected graph with city names as node data and their distances as edge data.
323let mut g = UnGraph::<String, u32>::new_undirected();
324
325let ber = g.add_node("Berlin".to_owned());
326let del = g.add_node("New Delhi".to_owned());
327let mex = g.add_node("Mexico City".to_owned());
328let syd = g.add_node("Sydney".to_owned());
329
330// Add distances in kilometers as edge data.
331g.extend_with_edges(&[
332 (ber, del, 6_000),
333 (ber, mex, 10_000),
334 (ber, syd, 16_000),
335 (del, mex, 14_000),
336 (del, syd, 12_000),
337 (mex, syd, 15_000),
338]);
339
340// We might now want to change up the distances to be in miles instead and to be strings.
341// We can do this using the `map` method, which takes two closures for the node and edge data,
342// respectively, and returns a new graph with the transformed data.
343let g_miles: UnGraph<String, String> = g.map(
344 |_, city| city.to_owned(),
345 |_, distance| format!("{} miles", (*distance as f64 * 0.621371).round() as i32),
346);
347```
348
349### Exporting graphs to DOT format
350
351Petgraph provides functionality to export graphs to the [DOT](https://www.graphviz.org/doc/info/lang.html)
352format, which can be used with the [Graphviz](https://www.graphviz.org/) suite of tools for
353visualization and analysis of graphs. The [`dot`] module provides the necessary functionality to
354convert graphs into DOT format.
355
356Let's try exporting the graph we created in the previous example to DOT format.
357
358```
359use petgraph::dot::{Config, Dot};
360use petgraph::graph::UnGraph;
361use petgraph::visit::EdgeRef;
362
363// Create an undirected graph with city names as node data and their distances as edge data.
364let mut g = UnGraph::<String, u32>::new_undirected();
365
366let ber = g.add_node("Berlin".to_owned());
367let del = g.add_node("New Delhi".to_owned());
368let mex = g.add_node("Mexico City".to_owned());
369let syd = g.add_node("Sydney".to_owned());
370
371// Add distances in kilometers as edge data.
372g.extend_with_edges(&[
373 (ber, del, 6_000),
374 (ber, mex, 10_000),
375 (ber, syd, 16_000),
376 (del, mex, 14_000),
377 (del, syd, 12_000),
378 (mex, syd, 15_000),
379]);
380
381// Basic DOT export with automatic labels
382let basic_dot = Dot::new(&g);
383println!("Basic DOT format:\n{:?}\n", basic_dot);
384// Output:
385// Basic DOT format:
386// graph {
387// 0 [ label = "\"Berlin\"" ]
388// 1 [ label = "\"New Delhi\"" ]
389// 2 [ label = "\"Mexico City\"" ]
390// 3 [ label = "\"Sydney\"" ]
391// 0 -- 1 [ label = "6000" ]
392// 0 -- 2 [ label = "10000" ]
393// 0 -- 3 [ label = "16000" ]
394// 1 -- 2 [ label = "14000" ]
395// 1 -- 3 [ label = "12000" ]
396// 2 -- 3 [ label = "15000" ]
397// }
398
399// Enhanced DOT export with custom attributes
400let fancy_dot = Dot::with_attr_getters(
401 &g,
402 // Global graph attributes
403 &[],
404 // Edge attribute getter
405 &|graph_reference, edge_reference| {
406 // Style edges depending on distance
407 if graph_reference.edge_weight(edge_reference.id()).unwrap() > &12_500 {
408 "style=dashed, penwidth=3".to_owned()
409 } else {
410 "style=solid".to_owned()
411 }
412 },
413 // Node attribute getter; We don't change any node attributes
414 &|_, (_, _)| String::new(),
415);
416
417println!("Enhanced DOT format:\n{:?}", fancy_dot);
418// Output:
419// Enhanced DOT format:
420// graph {
421// 0 [ label = "\"Berlin\"" ]
422// 1 [ label = "\"New Delhi\"" ]
423// 2 [ label = "\"Mexico City\"" ]
424// 3 [ label = "\"Sydney\"" ]
425// 0 -- 1 [ label = "6000" style=solid]
426// 0 -- 2 [ label = "10000" style=solid]
427// 0 -- 3 [ label = "16000" style=dashed, penwidth=3]
428// 1 -- 2 [ label = "14000" style=dashed, penwidth=3]
429// 1 -- 3 [ label = "12000" style=solid]
430// 2 -- 3 [ label = "15000" style=dashed, penwidth=3]
431// }
432
433// This would typically be written to a file:
434// std::fs::write("flight_network.dot", format!("{:?}", fancy_dot)).unwrap();
435```
436
437# Crate features
438
439`petgraph` is built with these features enabled by default:
440
441* **graphmap** -
442 Enables [`GraphMap`](./graphmap/struct.GraphMap.html).
443* **stable_graph** -
444 Enables [`StableGraph`](./stable_graph/struct.StableGraph.html).
445* **matrix_graph** -
446 Enables [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html).
447* **std** -
448 Enables the Rust Standard Library. Disabling the `std` feature makes it possible to use `petgraph` in `no_std` contexts.
449
450Optionally, the following features can be enabled:
451
452* **serde-1** -
453 Enables serialization for ``Graph, StableGraph, GraphMap`` using
454 [`serde 1.0`](https://crates.io/crates/serde). May require a more recent version
455 of Rust than petgraph alone.
456* **rayon** -
457 Enables parallel versions of iterators and algorithms using
458 [`rayon`](https://docs.rs/rayon/latest/rayon/) crate. Requires the `std` feature.
459* **dot_parser** -
460 Enables building [`Graph`](./graph/struct.Graph.html) and [`StableGraph`](./stable_graph/struct.StableGraph.html) from [DOT/Graphviz](https://www.graphviz.org/doc/info/lang.html) descriptions. Imports can be made statically or dynamically (i.e. at compile time or at runtime).
461* **unstable** -
462 Enables unstable crate features (currently only `generate`).
463* **generate** -
464 Enables graph generators. The API of functionality behind this flag is subject to change at any time.
465*/
466#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")]
467#![no_std]
468
469extern crate alloc;
470
471#[cfg(any(feature = "std", test))]
472extern crate std;
473
474extern crate fixedbitset;
475#[cfg(feature = "graphmap")]
476extern crate indexmap;
477
478#[cfg(feature = "serde-1")]
479extern crate serde;
480#[cfg(feature = "serde-1")]
481#[macro_use]
482extern crate serde_derive;
483
484#[cfg(all(feature = "serde-1", test))]
485extern crate itertools;
486
487#[doc(no_inline)]
488pub use crate::graph::Graph;
489
490pub use crate::Direction::{Incoming, Outgoing};
491
492#[macro_use]
493mod macros;
494mod scored;
495
496// these modules define trait-implementing macros
497#[macro_use]
498pub mod visit;
499#[macro_use]
500pub mod data;
501
502pub mod acyclic;
503pub mod adj;
504pub mod algo;
505pub mod csr;
506pub mod dot;
507#[cfg(feature = "generate")]
508pub mod generate;
509pub mod graph6;
510mod graph_impl;
511#[cfg(feature = "graphmap")]
512pub mod graphmap;
513mod iter_format;
514mod iter_utils;
515#[cfg(feature = "matrix_graph")]
516pub mod matrix_graph;
517#[cfg(feature = "quickcheck")]
518mod quickcheck;
519#[cfg(feature = "serde-1")]
520mod serde_utils;
521mod traits_graph;
522pub mod unionfind;
523
524pub mod operator;
525pub mod prelude;
526
527/// `Graph<N, E, Ty, Ix>` is a graph datastructure using an adjacency list representation.
528pub mod graph {
529 pub use crate::graph_impl::{
530 edge_index, node_index, DefaultIx, DiGraph, Edge, EdgeIndex, EdgeIndices, EdgeReference,
531 EdgeReferences, EdgeWeightsMut, Edges, EdgesConnecting, Externals, Frozen, Graph,
532 GraphError, GraphIndex, IndexType, Neighbors, Node, NodeIndex, NodeIndices, NodeReferences,
533 NodeWeightsMut, UnGraph, WalkNeighbors,
534 };
535}
536
537#[cfg(feature = "stable_graph")]
538pub use crate::graph_impl::stable_graph;
539
540// Index into the NodeIndex and EdgeIndex arrays
541/// Edge direction.
542#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
543#[repr(usize)]
544#[cfg_attr(
545 feature = "serde-1",
546 derive(serde_derive::Serialize, serde_derive::Deserialize)
547)]
548pub enum Direction {
549 /// An `Outgoing` edge is an outward edge *from* the current node.
550 Outgoing = 0,
551 /// An `Incoming` edge is an inbound edge *to* the current node.
552 Incoming = 1,
553}
554
555impl Direction {
556 /// Return the opposite `Direction`.
557 #[inline]
558 pub fn opposite(self) -> Direction {
559 match self {
560 Outgoing => Incoming,
561 Incoming => Outgoing,
562 }
563 }
564
565 /// Return `0` for `Outgoing` and `1` for `Incoming`.
566 #[inline]
567 pub fn index(self) -> usize {
568 (self as usize) & 0x1
569 }
570}
571
572#[doc(hidden)]
573pub use crate::Direction as EdgeDirection;
574
575/// Marker type for a directed graph.
576#[derive(Clone, Copy, Debug)]
577#[cfg_attr(
578 feature = "serde-1",
579 derive(serde_derive::Serialize, serde_derive::Deserialize)
580)]
581pub enum Directed {}
582
583/// Marker type for an undirected graph.
584#[derive(Clone, Copy, Debug)]
585#[cfg_attr(
586 feature = "serde-1",
587 derive(serde_derive::Serialize, serde_derive::Deserialize)
588)]
589pub enum Undirected {}
590
591/// A graph's edge type determines whether it has directed edges or not.
592pub trait EdgeType {
593 fn is_directed() -> bool;
594}
595
596impl EdgeType for Directed {
597 #[inline]
598 fn is_directed() -> bool {
599 true
600 }
601}
602
603impl EdgeType for Undirected {
604 #[inline]
605 fn is_directed() -> bool {
606 false
607 }
608}
609
610/// Convert an element like `(i, j)` or `(i, j, w)` into
611/// a triple of source, target, edge weight.
612///
613/// For `Graph::from_edges` and `GraphMap::from_edges`.
614pub trait IntoWeightedEdge<E> {
615 type NodeId;
616 fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
617}
618
619impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
620where
621 E: Default,
622{
623 type NodeId = Ix;
624
625 fn into_weighted_edge(self) -> (Ix, Ix, E) {
626 let (s, t) = self;
627 (s, t, E::default())
628 }
629}
630
631impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E) {
632 type NodeId = Ix;
633 fn into_weighted_edge(self) -> (Ix, Ix, E) {
634 self
635 }
636}
637
638impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &E)
639where
640 E: Clone,
641{
642 type NodeId = Ix;
643 fn into_weighted_edge(self) -> (Ix, Ix, E) {
644 let (a, b, c) = self;
645 (a, b, c.clone())
646 }
647}
648
649impl<Ix, E> IntoWeightedEdge<E> for &(Ix, Ix)
650where
651 Ix: Copy,
652 E: Default,
653{
654 type NodeId = Ix;
655 fn into_weighted_edge(self) -> (Ix, Ix, E) {
656 let (s, t) = *self;
657 (s, t, E::default())
658 }
659}
660
661impl<Ix, E> IntoWeightedEdge<E> for &(Ix, Ix, E)
662where
663 Ix: Copy,
664 E: Clone,
665{
666 type NodeId = Ix;
667 fn into_weighted_edge(self) -> (Ix, Ix, E) {
668 self.clone()
669 }
670}