petgraph/
data.rs

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