Skip to main content

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