petgraph/
data.rs

1//! Graph traits for associated data and graph construction.
2
3use crate::graph::IndexType;
4#[cfg(feature = "graphmap")]
5use crate::graphmap::{GraphMap, NodeTrait};
6#[cfg(feature = "stable_graph")]
7use crate::stable_graph::StableGraph;
8use crate::visit::{Data, NodeCount, NodeIndexable, Reversed};
9use crate::EdgeType;
10use crate::Graph;
11
12trait_template! {
13    /// Access node and edge weights (associated data).
14#[allow(clippy::needless_arbitrary_self_type)]
15pub trait DataMap : Data {
16    @section self
17    fn node_weight(self: &Self, id: Self::NodeId) -> Option<&Self::NodeWeight>;
18    fn edge_weight(self: &Self, id: Self::EdgeId) -> Option<&Self::EdgeWeight>;
19}
20}
21
22macro_rules! access0 {
23    ($e:expr) => {
24        $e.0
25    };
26}
27
28DataMap! {delegate_impl []}
29DataMap! {delegate_impl [['a, G], G, &'a mut G, deref_twice]}
30DataMap! {delegate_impl [[G], G, Reversed<G>, access0]}
31
32trait_template! {
33    /// Access node and edge weights mutably.
34#[allow(clippy::needless_arbitrary_self_type)]
35pub trait DataMapMut : DataMap {
36    @section self
37    fn node_weight_mut(self: &mut Self, id: Self::NodeId) -> Option<&mut Self::NodeWeight>;
38    fn edge_weight_mut(self: &mut Self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight>;
39}
40}
41
42DataMapMut! {delegate_impl [['a, G], G, &'a mut G, deref_twice]}
43DataMapMut! {delegate_impl [[G], G, Reversed<G>, access0]}
44
45/// A graph that can be extended with further nodes and edges
46pub trait Build: Data + NodeCount {
47    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId;
48    /// Add a new edge. If parallel edges (duplicate) are not allowed and
49    /// the edge already exists, return `None`.
50    fn add_edge(
51        &mut self,
52        a: Self::NodeId,
53        b: Self::NodeId,
54        weight: Self::EdgeWeight,
55    ) -> Option<Self::EdgeId> {
56        Some(self.update_edge(a, b, weight))
57    }
58    /// Add or update the edge from `a` to `b`. Return the id of the affected
59    /// edge.
60    fn update_edge(
61        &mut self,
62        a: Self::NodeId,
63        b: Self::NodeId,
64        weight: Self::EdgeWeight,
65    ) -> Self::EdgeId;
66}
67
68/// A graph that can be created
69pub trait Create: Build + Default {
70    fn with_capacity(nodes: usize, edges: usize) -> Self;
71}
72
73impl<N, E, Ty, Ix> Data for Graph<N, E, Ty, Ix>
74where
75    Ix: IndexType,
76{
77    type NodeWeight = N;
78    type EdgeWeight = E;
79}
80
81impl<N, E, Ty, Ix> DataMap for Graph<N, E, Ty, Ix>
82where
83    Ty: EdgeType,
84    Ix: IndexType,
85{
86    fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
87        self.node_weight(id)
88    }
89    fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
90        self.edge_weight(id)
91    }
92}
93
94impl<N, E, Ty, Ix> DataMapMut for Graph<N, E, Ty, Ix>
95where
96    Ty: EdgeType,
97    Ix: IndexType,
98{
99    fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
100        self.node_weight_mut(id)
101    }
102    fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
103        self.edge_weight_mut(id)
104    }
105}
106
107#[cfg(feature = "stable_graph")]
108impl<N, E, Ty, Ix> DataMap for StableGraph<N, E, Ty, Ix>
109where
110    Ty: EdgeType,
111    Ix: IndexType,
112{
113    fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
114        self.node_weight(id)
115    }
116    fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
117        self.edge_weight(id)
118    }
119}
120
121#[cfg(feature = "stable_graph")]
122impl<N, E, Ty, Ix> DataMapMut for StableGraph<N, E, Ty, Ix>
123where
124    Ty: EdgeType,
125    Ix: IndexType,
126{
127    fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
128        self.node_weight_mut(id)
129    }
130    fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
131        self.edge_weight_mut(id)
132    }
133}
134
135impl<N, E, Ty, Ix> Build for Graph<N, E, Ty, Ix>
136where
137    Ty: EdgeType,
138    Ix: IndexType,
139{
140    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
141        self.add_node(weight)
142    }
143    fn add_edge(
144        &mut self,
145        a: Self::NodeId,
146        b: Self::NodeId,
147        weight: Self::EdgeWeight,
148    ) -> Option<Self::EdgeId> {
149        Some(self.add_edge(a, b, weight))
150    }
151    fn update_edge(
152        &mut self,
153        a: Self::NodeId,
154        b: Self::NodeId,
155        weight: Self::EdgeWeight,
156    ) -> Self::EdgeId {
157        self.update_edge(a, b, weight)
158    }
159}
160
161#[cfg(feature = "stable_graph")]
162impl<N, E, Ty, Ix> Build for StableGraph<N, E, Ty, Ix>
163where
164    Ty: EdgeType,
165    Ix: IndexType,
166{
167    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
168        self.add_node(weight)
169    }
170    fn add_edge(
171        &mut self,
172        a: Self::NodeId,
173        b: Self::NodeId,
174        weight: Self::EdgeWeight,
175    ) -> Option<Self::EdgeId> {
176        Some(self.add_edge(a, b, weight))
177    }
178    fn update_edge(
179        &mut self,
180        a: Self::NodeId,
181        b: Self::NodeId,
182        weight: Self::EdgeWeight,
183    ) -> Self::EdgeId {
184        self.update_edge(a, b, weight)
185    }
186}
187
188#[cfg(feature = "graphmap")]
189impl<N, E, Ty> Build for GraphMap<N, E, Ty>
190where
191    Ty: EdgeType,
192    N: NodeTrait,
193{
194    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
195        self.add_node(weight)
196    }
197    fn add_edge(
198        &mut self,
199        a: Self::NodeId,
200        b: Self::NodeId,
201        weight: Self::EdgeWeight,
202    ) -> Option<Self::EdgeId> {
203        if self.contains_edge(a, b) {
204            None
205        } else {
206            let r = self.add_edge(a, b, weight);
207            debug_assert!(r.is_none());
208            Some((a, b))
209        }
210    }
211    fn update_edge(
212        &mut self,
213        a: Self::NodeId,
214        b: Self::NodeId,
215        weight: Self::EdgeWeight,
216    ) -> Self::EdgeId {
217        self.add_edge(a, b, weight);
218        (a, b)
219    }
220}
221
222impl<N, E, Ty, Ix> Create for Graph<N, E, Ty, Ix>
223where
224    Ty: EdgeType,
225    Ix: IndexType,
226{
227    fn with_capacity(nodes: usize, edges: usize) -> Self {
228        Self::with_capacity(nodes, edges)
229    }
230}
231
232#[cfg(feature = "stable_graph")]
233impl<N, E, Ty, Ix> Create for StableGraph<N, E, Ty, Ix>
234where
235    Ty: EdgeType,
236    Ix: IndexType,
237{
238    fn with_capacity(nodes: usize, edges: usize) -> Self {
239        Self::with_capacity(nodes, edges)
240    }
241}
242
243#[cfg(feature = "graphmap")]
244impl<N, E, Ty> Create for GraphMap<N, E, Ty>
245where
246    Ty: EdgeType,
247    N: NodeTrait,
248{
249    fn with_capacity(nodes: usize, edges: usize) -> Self {
250        Self::with_capacity(nodes, edges)
251    }
252}
253
254/// A graph element.
255///
256/// A sequence of Elements, for example an iterator, is laid out as follows:
257/// Nodes are implicitly given the index of their appearance in the sequence.
258/// The edges’ source and target fields refer to these indices.
259#[derive(Clone, Debug, PartialEq, Eq)]
260pub enum Element<N, E> {
261    /// A graph node.
262    Node { weight: N },
263    /// A graph edge.
264    Edge {
265        source: usize,
266        target: usize,
267        weight: E,
268    },
269}
270
271/// Create a graph from an iterator of elements.
272pub trait FromElements: Create {
273    fn from_elements<I>(iterable: I) -> Self
274    where
275        Self: Sized,
276        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
277    {
278        let mut gr = Self::with_capacity(0, 0);
279        // usize -> NodeId map
280        let mut map = Vec::new();
281        for element in iterable {
282            match element {
283                Element::Node { weight } => {
284                    map.push(gr.add_node(weight));
285                }
286                Element::Edge {
287                    source,
288                    target,
289                    weight,
290                } => {
291                    gr.add_edge(map[source], map[target], weight);
292                }
293            }
294        }
295        gr
296    }
297}
298
299fn from_elements_indexable<G, I>(iterable: I) -> G
300where
301    G: Create + NodeIndexable,
302    I: IntoIterator<Item = Element<G::NodeWeight, G::EdgeWeight>>,
303{
304    let mut gr = G::with_capacity(0, 0);
305    let map = |gr: &G, i| gr.from_index(i);
306    for element in iterable {
307        match element {
308            Element::Node { weight } => {
309                gr.add_node(weight);
310            }
311            Element::Edge {
312                source,
313                target,
314                weight,
315            } => {
316                let from = map(&gr, source);
317                let to = map(&gr, target);
318                gr.add_edge(from, to, weight);
319            }
320        }
321    }
322    gr
323}
324
325impl<N, E, Ty, Ix> FromElements for Graph<N, E, Ty, Ix>
326where
327    Ty: EdgeType,
328    Ix: IndexType,
329{
330    fn from_elements<I>(iterable: I) -> Self
331    where
332        Self: Sized,
333        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
334    {
335        from_elements_indexable(iterable)
336    }
337}
338
339#[cfg(feature = "stable_graph")]
340impl<N, E, Ty, Ix> FromElements for StableGraph<N, E, Ty, Ix>
341where
342    Ty: EdgeType,
343    Ix: IndexType,
344{
345    fn from_elements<I>(iterable: I) -> Self
346    where
347        Self: Sized,
348        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
349    {
350        from_elements_indexable(iterable)
351    }
352}
353
354#[cfg(feature = "graphmap")]
355impl<N, E, Ty> FromElements for GraphMap<N, E, Ty>
356where
357    Ty: EdgeType,
358    N: NodeTrait,
359{
360    fn from_elements<I>(iterable: I) -> Self
361    where
362        Self: Sized,
363        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
364    {
365        from_elements_indexable(iterable)
366    }
367}
368
369/// Iterator adaptors for iterators of `Element`.
370pub trait ElementIterator<N, E>: Iterator<Item = Element<N, E>> {
371    /// Create an iterator adaptor that filters graph elements.
372    ///
373    /// The function `f` is called with each element and if its return value
374    /// is `true` the element is accepted and if `false` it is removed.
375    /// `f` is called with mutable references to the node and edge weights,
376    /// so that they can be mutated (but the edge endpoints can not).
377    ///
378    /// This filter adapts the edge source and target indices in the
379    /// stream so that they are correct after the removals.
380    fn filter_elements<F>(self, f: F) -> FilterElements<Self, F>
381    where
382        Self: Sized,
383        F: FnMut(Element<&mut N, &mut E>) -> bool,
384    {
385        FilterElements {
386            iter: self,
387            node_index: 0,
388            map: Vec::new(),
389            f,
390        }
391    }
392}
393
394impl<N, E, I: ?Sized> ElementIterator<N, E> for I where I: Iterator<Item = Element<N, E>> {}
395
396/// An iterator that filters graph elements.
397///
398/// See [`.filter_elements()`][1] for more information.
399///
400/// [1]: trait.ElementIterator.html#method.filter_elements
401#[derive(Debug, Clone)]
402pub struct FilterElements<I, F> {
403    iter: I,
404    node_index: usize,
405    map: Vec<usize>,
406    f: F,
407}
408
409impl<I, F, N, E> Iterator for FilterElements<I, F>
410where
411    I: Iterator<Item = Element<N, E>>,
412    F: FnMut(Element<&mut N, &mut E>) -> bool,
413{
414    type Item = Element<N, E>;
415
416    fn next(&mut self) -> Option<Self::Item> {
417        loop {
418            let mut elt = self.iter.next()?;
419            let keep = (self.f)(match elt {
420                Element::Node { ref mut weight } => Element::Node { weight },
421                Element::Edge {
422                    source,
423                    target,
424                    ref mut weight,
425                } => Element::Edge {
426                    source,
427                    target,
428                    weight,
429                },
430            });
431            let is_node = if let Element::Node { .. } = elt {
432                true
433            } else {
434                false
435            };
436            if !keep && is_node {
437                self.map.push(self.node_index);
438            }
439            if is_node {
440                self.node_index += 1;
441            }
442            if !keep {
443                continue;
444            }
445
446            // map edge parts
447            match elt {
448                Element::Edge {
449                    ref mut source,
450                    ref mut target,
451                    ..
452                } => {
453                    // Find the node indices in the map of removed ones.
454                    // If a node was removed, the edge is as well.
455                    // Otherwise the counts are adjusted by the number of nodes
456                    // removed.
457                    // Example: map: [1, 3, 4, 6]
458                    // binary search for 2, result is Err(1). One node has been
459                    // removed before 2.
460                    match self.map.binary_search(source) {
461                        Ok(_) => continue,
462                        Err(i) => *source -= i,
463                    }
464                    match self.map.binary_search(target) {
465                        Ok(_) => continue,
466                        Err(i) => *target -= i,
467                    }
468                }
469                Element::Node { .. } => {}
470            }
471            return Some(elt);
472        }
473    }
474    fn size_hint(&self) -> (usize, Option<usize>) {
475        let (_, upper) = self.iter.size_hint();
476        (0, upper)
477    }
478}