petgraph/
data.rs

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