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#functions) 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 = "StableGraph")]
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* **serde-1** -
440 Defaults off. Enables serialization for ``Graph, StableGraph, GraphMap`` using
441 [`serde 1.0`](https://crates.io/crates/serde). May require a more recent version
442 of Rust than petgraph alone.
443* **graphmap** -
444 Defaults on. Enables [`GraphMap`](./graphmap/struct.GraphMap.html).
445* **stable_graph** -
446 Defaults on. Enables [`StableGraph`](./stable_graph/struct.StableGraph.html).
447* **matrix_graph** -
448 Defaults on. Enables [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html).
449* **rayon** -
450 Defaults off. Enables parallel versions of iterators and algorithms using
451 [`rayon`](https://docs.rs/rayon/latest/rayon/) crate. Requires the `std` feature.
452* **std** -
453 Defaults on. Enables the Rust Standard Library. Disabling the `std` feature makes it possible to use `petgraph` in `no_std` contexts.
454* **generate** -
455 Defaults off. Enables graph generators.
456* **unstable** -
457 Defaults off. Enables unstable crate features (currently only `generate`).
458* **dot_parser** -
459 Defaults off. 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).
460*/
461#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")]
462#![no_std]
463
464extern crate alloc;
465
466#[cfg(any(feature = "std", test))]
467extern crate std;
468
469extern crate fixedbitset;
470#[cfg(feature = "graphmap")]
471extern crate indexmap;
472
473#[cfg(feature = "serde-1")]
474extern crate serde;
475#[cfg(feature = "serde-1")]
476#[macro_use]
477extern crate serde_derive;
478
479#[cfg(all(feature = "serde-1", test))]
480extern crate itertools;
481
482#[doc(no_inline)]
483pub use crate::graph::Graph;
484
485pub use crate::Direction::{Incoming, Outgoing};
486
487#[macro_use]
488mod macros;
489mod scored;
490
491// these modules define trait-implementing macros
492#[macro_use]
493pub mod visit;
494#[macro_use]
495pub mod data;
496
497pub mod acyclic;
498pub mod adj;
499pub mod algo;
500pub mod csr;
501pub mod dot;
502#[cfg(feature = "generate")]
503pub mod generate;
504pub mod graph6;
505mod graph_impl;
506#[cfg(feature = "graphmap")]
507pub mod graphmap;
508mod iter_format;
509mod iter_utils;
510#[cfg(feature = "matrix_graph")]
511pub mod matrix_graph;
512#[cfg(feature = "quickcheck")]
513mod quickcheck;
514#[cfg(feature = "serde-1")]
515mod serde_utils;
516mod traits_graph;
517pub mod unionfind;
518mod util;
519
520pub mod operator;
521pub mod prelude;
522
523/// `Graph<N, E, Ty, Ix>` is a graph datastructure using an adjacency list representation.
524pub mod graph {
525 pub use crate::graph_impl::{
526 edge_index, node_index, DefaultIx, DiGraph, Edge, EdgeIndex, EdgeIndices, EdgeReference,
527 EdgeReferences, EdgeWeightsMut, Edges, EdgesConnecting, Externals, Frozen, Graph,
528 GraphError, GraphIndex, IndexType, Neighbors, Node, NodeIndex, NodeIndices, NodeReferences,
529 NodeWeightsMut, UnGraph, WalkNeighbors,
530 };
531}
532
533#[cfg(feature = "stable_graph")]
534pub use crate::graph_impl::stable_graph;
535
536// Index into the NodeIndex and EdgeIndex arrays
537/// Edge direction.
538#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
539#[repr(usize)]
540#[cfg_attr(
541 feature = "serde-1",
542 derive(serde_derive::Serialize, serde_derive::Deserialize)
543)]
544pub enum Direction {
545 /// An `Outgoing` edge is an outward edge *from* the current node.
546 Outgoing = 0,
547 /// An `Incoming` edge is an inbound edge *to* the current node.
548 Incoming = 1,
549}
550
551impl Direction {
552 /// Return the opposite `Direction`.
553 #[inline]
554 pub fn opposite(self) -> Direction {
555 match self {
556 Outgoing => Incoming,
557 Incoming => Outgoing,
558 }
559 }
560
561 /// Return `0` for `Outgoing` and `1` for `Incoming`.
562 #[inline]
563 pub fn index(self) -> usize {
564 (self as usize) & 0x1
565 }
566}
567
568#[doc(hidden)]
569pub use crate::Direction as EdgeDirection;
570
571/// Marker type for a directed graph.
572#[derive(Clone, Copy, Debug)]
573#[cfg_attr(
574 feature = "serde-1",
575 derive(serde_derive::Serialize, serde_derive::Deserialize)
576)]
577pub enum Directed {}
578
579/// Marker type for an undirected graph.
580#[derive(Clone, Copy, Debug)]
581#[cfg_attr(
582 feature = "serde-1",
583 derive(serde_derive::Serialize, serde_derive::Deserialize)
584)]
585pub enum Undirected {}
586
587/// A graph's edge type determines whether it has directed edges or not.
588pub trait EdgeType {
589 fn is_directed() -> bool;
590}
591
592impl EdgeType for Directed {
593 #[inline]
594 fn is_directed() -> bool {
595 true
596 }
597}
598
599impl EdgeType for Undirected {
600 #[inline]
601 fn is_directed() -> bool {
602 false
603 }
604}
605
606/// Convert an element like `(i, j)` or `(i, j, w)` into
607/// a triple of source, target, edge weight.
608///
609/// For `Graph::from_edges` and `GraphMap::from_edges`.
610pub trait IntoWeightedEdge<E> {
611 type NodeId;
612 fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
613}
614
615impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
616where
617 E: Default,
618{
619 type NodeId = Ix;
620
621 fn into_weighted_edge(self) -> (Ix, Ix, E) {
622 let (s, t) = self;
623 (s, t, E::default())
624 }
625}
626
627impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E) {
628 type NodeId = Ix;
629 fn into_weighted_edge(self) -> (Ix, Ix, E) {
630 self
631 }
632}
633
634impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &E)
635where
636 E: Clone,
637{
638 type NodeId = Ix;
639 fn into_weighted_edge(self) -> (Ix, Ix, E) {
640 let (a, b, c) = self;
641 (a, b, c.clone())
642 }
643}
644
645impl<Ix, E> IntoWeightedEdge<E> for &(Ix, Ix)
646where
647 Ix: Copy,
648 E: Default,
649{
650 type NodeId = Ix;
651 fn into_weighted_edge(self) -> (Ix, Ix, E) {
652 let (s, t) = *self;
653 (s, t, E::default())
654 }
655}
656
657impl<Ix, E> IntoWeightedEdge<E> for &(Ix, Ix, E)
658where
659 Ix: Copy,
660 E: Clone,
661{
662 type NodeId = Ix;
663 fn into_weighted_edge(self) -> (Ix, Ix, E) {
664 self.clone()
665 }
666}