avian2d/data_structures/
stable_graph.rs

1//! A stripped down and modified version of petgraph's `StableUnGraph`.
2//!
3//! - Index types always use `u32`.
4//! - Instead of free lists, [`IdPool`]s are used to allocate and free nodes and edges.
5//! - Vacant nodes and edges are occupied in the order of lowest index first.
6//! - Edge iteration order after serialization/deserialization is preserved.
7//! - Fewer iterators and helpers, and a few new ones.
8
9use super::graph::{Edge, EdgeDirection, EdgeIndex, Node, NodeIndex, Pair, UnGraph, index_twice};
10use super::id_pool::IdPool;
11
12/// A graph with undirected edges and stable indices.
13///
14/// Unlike [`UnGraph`], this graph *does not* invalidate any unrelated
15/// node or edge indices when items are removed. Removed nodes and edges
16/// are replaced with vacant slots, which can be reused later in order
17/// of lowest index first.
18#[derive(Clone, Debug)]
19#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
20pub struct StableUnGraph<N, E> {
21    graph: UnGraph<Option<N>, Option<E>>,
22    node_ids: IdPool,
23    edge_ids: IdPool,
24}
25
26impl<N, E> Default for StableUnGraph<N, E> {
27    fn default() -> Self {
28        StableUnGraph {
29            graph: UnGraph::default(),
30            node_ids: IdPool::new(),
31            edge_ids: IdPool::new(),
32        }
33    }
34}
35
36impl<N, E> StableUnGraph<N, E> {
37    /// Creates a new [`StableUnGraph`] with estimated capacity.
38    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
39        StableUnGraph {
40            graph: UnGraph::with_capacity(nodes, edges),
41            node_ids: IdPool::with_capacity(nodes),
42            edge_ids: IdPool::with_capacity(edges),
43        }
44    }
45
46    /// Returns the number of nodes in the graph.
47    ///
48    /// Computes in **O(1)** time.
49    pub fn node_count(&self) -> usize {
50        self.node_ids.len()
51    }
52
53    /// Returns the number of edges in the graph.
54    ///
55    /// Computes in **O(1)** time.
56    pub fn edge_count(&self) -> usize {
57        self.edge_ids.len()
58    }
59
60    /// Adds a node (also called vertex) with associated data `weight` to the graph.
61    ///
62    /// Computes in **O(1)** time.
63    ///
64    /// Returns the index of the new node.
65    ///
66    /// # Panics
67    ///
68    /// Panics if the graph is at the maximum number of nodes.
69    pub fn add_node(&mut self, weight: N) -> NodeIndex {
70        // Allocate a node ID.
71        let node_idx = NodeIndex(self.node_ids.alloc());
72
73        if node_idx.index() != self.graph.nodes.len() {
74            // Reuse a free node.
75            self.occupy_vacant_node(node_idx, weight);
76            node_idx
77        } else {
78            // Create a new node.
79            self.graph.add_node(Some(weight))
80        }
81    }
82
83    /// Creates a new node using a vacant position.
84    fn occupy_vacant_node(&mut self, node_idx: NodeIndex, weight: N) {
85        let node_slot = &mut self.graph.nodes[node_idx.index()];
86
87        let _old = node_slot.weight.replace(weight);
88        debug_assert!(_old.is_none());
89
90        let previous_node = node_slot.next[1];
91        let next_node = node_slot.next[0];
92        node_slot.next = [EdgeIndex::END, EdgeIndex::END];
93
94        if previous_node != EdgeIndex::END {
95            self.graph.nodes[previous_node.index()].next[0] = next_node;
96        }
97        if next_node != EdgeIndex::END {
98            self.graph.nodes[next_node.index()].next[1] = previous_node;
99        }
100    }
101
102    /// Returns the node at index `a` if it is not vacant.
103    fn get_node(&self, a: NodeIndex) -> Option<&Node<Option<N>>> {
104        self.graph
105            .nodes
106            .get(a.index())
107            .and_then(|node| node.weight.as_ref().map(|_| node))
108    }
109
110    /// Accesses the weight for node `a`.
111    ///
112    /// Also available with indexing syntax: `&graph[a]`.
113    pub fn node_weight(&self, a: NodeIndex) -> Option<&N> {
114        let node = self.graph.nodes.get(a.index())?;
115        node.weight.as_ref()
116    }
117
118    /// Adds an edge from `a` to `b` to the graph, with its associated
119    /// data `weight`.
120    ///
121    /// Returns the index of the new edge.
122    ///
123    /// Computes in **O(1)** time.
124    ///
125    /// **Note:** `UnGraph` allows adding parallel (“duplicate”) edges. If you want
126    /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead.
127    ///
128    /// # Panics
129    ///
130    /// Panics if any of the nodes don't exist or the graph is at the maximum number of edges.
131    pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex {
132        let edge_idx;
133        let mut new_edge = None::<Edge<Option<E>>>;
134        {
135            let edge: &mut Edge<Option<E>>;
136
137            // Allocate an edge ID.
138            edge_idx = EdgeIndex(self.edge_ids.alloc());
139
140            if edge_idx.index() != self.graph.edges.len() {
141                // Reuse a free edge.
142                edge = &mut self.graph.edges[edge_idx.index()];
143
144                let _old = edge.weight.replace(weight);
145                debug_assert!(_old.is_none());
146
147                edge.node = [a, b];
148            } else {
149                // Create a new edge.
150                assert!(edge_idx != EdgeIndex::END);
151                new_edge = Some(Edge {
152                    weight: Some(weight),
153                    node: [a, b],
154                    next: [EdgeIndex::END; 2],
155                });
156                edge = new_edge.as_mut().unwrap();
157            }
158
159            let wrong_index = match index_twice(&mut self.graph.nodes, a.index(), b.index()) {
160                Pair::None => Some(core::cmp::max(a.index(), b.index())),
161                Pair::One(an) => {
162                    if an.weight.is_none() {
163                        Some(a.index())
164                    } else {
165                        edge.next = an.next;
166                        an.next[0] = edge_idx;
167                        an.next[1] = edge_idx;
168                        None
169                    }
170                }
171                Pair::Both(an, bn) => {
172                    // `a` and `b` are different indices.
173                    if an.weight.is_none() {
174                        Some(a.index())
175                    } else if bn.weight.is_none() {
176                        Some(b.index())
177                    } else {
178                        edge.next = [an.next[0], bn.next[1]];
179                        an.next[0] = edge_idx;
180                        bn.next[1] = edge_idx;
181                        None
182                    }
183                }
184            };
185
186            assert!(
187                wrong_index.is_none(),
188                "Tried adding an edge to a non-existent node."
189            );
190        }
191
192        if let Some(edge) = new_edge {
193            self.graph.edges.push(edge);
194        }
195
196        edge_idx
197    }
198
199    /// Adds or updates an edge from `a` to `b`.
200    /// If the edge already exists, its weight is updated.
201    ///
202    /// Returns the index of the affected edge.
203    ///
204    /// Computes in **O(e')** time, where **e'** is the number of edges
205    /// connected to `a` (and `b`, if the graph edges are undirected).
206    ///
207    /// # Panics
208    ///
209    /// Panics if any of the nodes doesn't exist or the graph is at the maximum number of edges.
210    pub fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex {
211        if let Some(ix) = self.find_edge(a, b) {
212            *self.edge_weight_mut(ix).unwrap() = weight;
213            return ix;
214        }
215        self.add_edge(a, b, weight)
216    }
217
218    /// Accesses the weight for edge `e`.
219    ///
220    /// Also available with indexing syntax: `&graph[e]`.
221    pub fn edge_weight(&self, e: EdgeIndex) -> Option<&E> {
222        let edge = self.graph.edges.get(e.index())?;
223        edge.weight.as_ref()
224    }
225
226    /// Accesses the weight for edge `e` mutably.
227    ///
228    /// Also available with indexing syntax: `&mut graph[e]`.
229    pub fn edge_weight_mut(&mut self, e: EdgeIndex) -> Option<&mut E> {
230        let edge = self.graph.edges.get_mut(e.index())?;
231        edge.weight.as_mut()
232    }
233
234    /// Accesses the source and target nodes for `e`.
235    pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> {
236        let edge = self.graph.edges.get(e.index())?;
237        Some((edge.source(), edge.target()))
238    }
239
240    /// Removes `a` from the graph if it exists, calling `edge_callback` for each of its edges
241    /// right before removal, and returns its weight. If it doesn't exist in the graph, returns `None`.
242    ///
243    /// Invalidates the node index `a`, but not any other indices.
244    /// Edge indices are invalidated as they would be following
245    /// the removal of each edge with an endpoint in `a`.
246    ///
247    /// Computes in **O(e')** time, where **e'** is the number of affected
248    /// edges, including *n* calls to [`remove_edge`](Self::remove_edge),
249    /// where *n* is the number of edges with an endpoint in `a`,
250    /// and including the edges with an endpoint in the displaced node.
251    pub fn remove_node_with<F>(&mut self, a: NodeIndex, mut edge_callback: F) -> Option<N>
252    where
253        F: FnMut(&mut Self, EdgeIndex),
254    {
255        let node_weight = self.graph.nodes.get_mut(a.index())?.weight.take()?;
256
257        for d in EdgeDirection::ALL {
258            let k = d as usize;
259
260            // Remove all edges from and to this node.
261            loop {
262                let next = self.graph.nodes[a.index()].next[k];
263                if next == EdgeIndex::END {
264                    break;
265                }
266                edge_callback(self, next);
267                self.remove_edge(next).expect("edge not found for removal");
268            }
269        }
270
271        // Clear the node and free its ID.
272        let node_slot = &mut self.graph.nodes[a.index()];
273        node_slot.next = [EdgeIndex::END; 2];
274
275        self.node_ids.free(a.0);
276
277        Some(node_weight)
278    }
279
280    /// Removes an edge and returns its edge weight, or `None` if it didn't exist.
281    ///
282    /// Invalidates the edge index `e`, but not any other indices.
283    ///
284    /// Computes in **O(e')** time, where **e'** is the size of four particular edge lists, for
285    /// the vertices of `e` and the vertices of another affected edge.
286    pub fn remove_edge(&mut self, e: EdgeIndex) -> Option<E> {
287        // Every edge is part of two lists, outgoing and incoming edges.
288        // Remove it from both.
289        let (is_edge, edge_node, edge_next) = match self.graph.edges.get(e.index()) {
290            None => return None,
291            Some(x) => (x.weight.is_some(), x.node, x.next),
292        };
293
294        if !is_edge {
295            return None;
296        }
297
298        // Remove the edge from its in and out lists by replacing it with
299        // a link to the next in the list.
300        self.graph.change_edge_links(edge_node, e, edge_next);
301
302        // Clear the edge and free its ID.
303        let edge_slot = &mut self.graph.edges[e.index()];
304        edge_slot.next = [EdgeIndex::END; 2];
305        edge_slot.node = [NodeIndex::END; 2];
306
307        self.edge_ids.free(e.0);
308
309        edge_slot.weight.take()
310    }
311
312    /// Returns an iterator of all nodes with an edge connected to `a`.
313    ///
314    /// Produces an empty iterator if the node doesn't exist.
315    ///
316    /// The iterator element type is `NodeIndex`.
317    pub fn neighbors(&self, a: NodeIndex) -> Neighbors<'_, E> {
318        Neighbors {
319            skip_start: a,
320            edges: &self.graph.edges,
321            next: match self.get_node(a) {
322                None => [EdgeIndex::END, EdgeIndex::END],
323                Some(n) => n.next,
324            },
325        }
326    }
327
328    /// Returns an iterator of all edges connected to `a`.
329    ///
330    /// Produces an empty iterator if the node doesn't exist.
331    ///
332    /// The iterator element type is `EdgeReference<E>`.
333    pub fn edges(&self, a: NodeIndex) -> Edges<'_, E> {
334        Edges {
335            skip_start: a,
336            edges: &self.graph.edges,
337            direction: EdgeDirection::Outgoing,
338            next: match self.get_node(a) {
339                None => [EdgeIndex::END, EdgeIndex::END],
340                Some(n) => n.next,
341            },
342        }
343    }
344
345    /// Returns an iterator over all edges between `a` and `b`.
346    ///
347    /// The iterator element type is `EdgeReference<E>`.
348    pub fn edges_between(&self, a: NodeIndex, b: NodeIndex) -> EdgesBetween<'_, E> {
349        EdgesBetween {
350            target_node: b,
351            edges: self.edges(a),
352        }
353    }
354
355    /// Looks up if there is an edge from `a` to `b`.
356    ///
357    /// Computes in **O(e')** time, where **e'** is the number of edges
358    /// connected to `a` (and `b`, if the graph edges are undirected).
359    pub fn contains_edge(&self, a: NodeIndex, b: NodeIndex) -> bool {
360        self.find_edge(a, b).is_some()
361    }
362
363    /// Looks up an edge from `a` to `b`.
364    ///
365    /// Computes in **O(e')** time, where **e'** is the number of edges
366    /// connected to `a` (and `b`, if the graph edges are undirected).
367    pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option<EdgeIndex> {
368        self.graph.find_edge_from_node(self.get_node(a)?, b)
369    }
370
371    /// Returns an iterator yielding immutable access to edge weights for edges from or to `a`.
372    pub fn edge_weights(&self, a: NodeIndex) -> EdgeWeights<'_, E> {
373        EdgeWeights {
374            skip_start: a,
375            edges: &self.graph.edges,
376            direction: EdgeDirection::Outgoing,
377            next: match self.get_node(a) {
378                None => [EdgeIndex::END, EdgeIndex::END],
379                Some(n) => n.next,
380            },
381        }
382    }
383
384    /// Returns an iterator yielding mutable access to edge weights for edges from or to `a`.
385    pub fn edge_weights_mut(&mut self, a: NodeIndex) -> EdgeWeightsMut<'_, N, E>
386    where
387        N: Copy,
388    {
389        self.graph
390            .edge_weights_mut(a)
391            .filter_map(|edge| edge.as_mut())
392    }
393
394    /// Returns an iterator yielding immutable access to all edge weights.
395    ///
396    /// The order in which weights are yielded matches the order of their
397    /// edge indices.
398    pub fn all_edge_weights(&self) -> impl Iterator<Item = &E> {
399        self.graph
400            .edges
401            .iter()
402            .filter_map(|edge| edge.weight.as_ref())
403    }
404
405    /// Returns an iterator yielding mutable access to all edge weights.
406    ///
407    /// The order in which weights are yielded matches the order of their
408    /// edge indices.
409    pub fn all_edge_weights_mut(&mut self) -> impl Iterator<Item = &mut E> {
410        self.graph
411            .edges
412            .iter_mut()
413            .filter_map(|edge| edge.weight.as_mut())
414    }
415
416    /// Accesses the internal edge array.
417    ///
418    /// Note that this also includes vacant edges.
419    pub fn raw_edges(&self) -> &[Edge<Option<E>>] {
420        &self.graph.edges
421    }
422
423    /// Accesses the internal edge array mutably.
424    ///
425    /// Note that this also includes vacant edges.
426    pub fn raw_edges_mut(&mut self) -> &mut [Edge<Option<E>>] {
427        &mut self.graph.edges
428    }
429
430    /// Removes all nodes and edges.
431    pub fn clear(&mut self) {
432        self.graph.clear();
433        self.node_ids.clear();
434        self.edge_ids.clear();
435    }
436
437    /// Removes all edges.
438    pub fn clear_edges(&mut self) {
439        self.graph.edges.clear();
440        self.edge_ids.clear();
441
442        // Clear edge links for all nodes.
443        for node in &mut self.graph.nodes {
444            if node.weight.is_some() {
445                node.next = [EdgeIndex::END, EdgeIndex::END];
446            }
447        }
448    }
449
450    /// Returns the current node capacity of the graph.
451    pub fn nodes_capacity(&self) -> usize {
452        self.graph.nodes_capacity()
453    }
454
455    /// Returns the current edge capacity of the graph.
456    pub fn edges_capacity(&self) -> usize {
457        self.graph.edges_capacity()
458    }
459}
460
461/// An iterator over the neighbors of a node.
462///
463/// The iterator element type is `NodeIndex`.
464#[derive(Debug)]
465pub struct Neighbors<'a, E: 'a> {
466    /// The starting node to skip over.
467    skip_start: NodeIndex,
468
469    /// The edges to iterate over.
470    edges: &'a [Edge<Option<E>>],
471
472    /// The next edge to visit.
473    next: [EdgeIndex; 2],
474}
475
476impl<E> Iterator for Neighbors<'_, E> {
477    type Item = NodeIndex;
478
479    fn next(&mut self) -> Option<NodeIndex> {
480        // First any outgoing edges.
481        match self.edges.get(self.next[0].index()) {
482            None => {}
483            Some(edge) => {
484                debug_assert!(edge.weight.is_some());
485                self.next[0] = edge.next[0];
486                return Some(edge.node[1]);
487            }
488        }
489
490        // Then incoming edges.
491        // For an "undirected" iterator, make sure we don't double
492        // count self-loops by skipping them in the incoming list.
493        while let Some(edge) = self.edges.get(self.next[1].index()) {
494            debug_assert!(edge.weight.is_some());
495            self.next[1] = edge.next[1];
496            if edge.node[0] != self.skip_start {
497                return Some(edge.node[0]);
498            }
499        }
500        None
501    }
502}
503
504impl<E> Clone for Neighbors<'_, E> {
505    fn clone(&self) -> Self {
506        Neighbors {
507            skip_start: self.skip_start,
508            edges: self.edges,
509            next: self.next,
510        }
511    }
512}
513
514/// An iterator over edges from or to a node.
515pub struct Edges<'a, E: 'a> {
516    /// The starting node to skip over.
517    skip_start: NodeIndex,
518
519    /// The edges to iterate over.
520    edges: &'a [Edge<Option<E>>],
521
522    /// The next edge to visit.
523    next: [EdgeIndex; 2],
524
525    /// The direction of edges.
526    direction: EdgeDirection,
527}
528
529impl<'a, E> Iterator for Edges<'a, E> {
530    type Item = EdgeReference<'a, E>;
531
532    fn next(&mut self) -> Option<Self::Item> {
533        // Outgoing
534        let i = self.next[0].index();
535        if let Some(Edge {
536            node,
537            weight: Some(weight),
538            next,
539            ..
540        }) = self.edges.get(i)
541        {
542            self.next[0] = next[0];
543            return Some(EdgeReference {
544                index: EdgeIndex(i as u32),
545                node: if self.direction == EdgeDirection::Incoming {
546                    swap_pair(*node)
547                } else {
548                    *node
549                },
550                weight,
551            });
552        }
553
554        // Incoming
555        while let Some(Edge {
556            node,
557            weight: Some(weight),
558            next,
559        }) = self.edges.get(self.next[1].index())
560        {
561            let edge_index = self.next[1];
562            self.next[1] = next[1];
563
564            // In any of the "both" situations, self-loops would be iterated over twice.
565            // Skip them here.
566            if node[0] == self.skip_start {
567                continue;
568            }
569
570            return Some(EdgeReference {
571                index: edge_index,
572                node: if self.direction == EdgeDirection::Outgoing {
573                    swap_pair(*node)
574                } else {
575                    *node
576                },
577                weight,
578            });
579        }
580
581        None
582    }
583}
584
585impl<E> Clone for Edges<'_, E> {
586    fn clone(&self) -> Self {
587        Edges {
588            skip_start: self.skip_start,
589            edges: self.edges,
590            next: self.next,
591            direction: self.direction,
592        }
593    }
594}
595
596/// Iterator over the edges between a source node and a target node.
597#[derive(Clone)]
598pub struct EdgesBetween<'a, E: 'a> {
599    target_node: NodeIndex,
600    edges: Edges<'a, E>,
601}
602
603impl<'a, E> Iterator for EdgesBetween<'a, E> {
604    type Item = EdgeReference<'a, E>;
605
606    fn next(&mut self) -> Option<EdgeReference<'a, E>> {
607        let target_node = self.target_node;
608        self.edges
609            .by_ref()
610            .find(|&edge| edge.target() == target_node)
611    }
612
613    fn size_hint(&self) -> (usize, Option<usize>) {
614        let (_, upper) = self.edges.size_hint();
615        (0, upper)
616    }
617}
618
619fn swap_pair<T>(mut x: [T; 2]) -> [T; 2] {
620    x.swap(0, 1);
621    x
622}
623
624// TODO: Reduce duplication between `Edges` variants.
625/// An iterator over edge weights for edges from or to a node.
626pub struct EdgeWeights<'a, E: 'a> {
627    /// The starting node to skip over.
628    skip_start: NodeIndex,
629
630    /// The edges to iterate over.
631    edges: &'a [Edge<Option<E>>],
632
633    /// The next edge to visit.
634    next: [EdgeIndex; 2],
635
636    /// The direction of edges.
637    direction: EdgeDirection,
638}
639
640impl<'a, E> Iterator for EdgeWeights<'a, E> {
641    type Item = &'a E;
642
643    fn next(&mut self) -> Option<Self::Item> {
644        let i = self.next[0].index();
645        if let Some(Edge {
646            weight: Some(weight),
647            next,
648            ..
649        }) = self.edges.get(i)
650        {
651            self.next[0] = next[0];
652            return Some(weight);
653        }
654
655        while let Some(Edge {
656            node,
657            weight: Some(weight),
658            next,
659        }) = self.edges.get(self.next[1].index())
660        {
661            self.next[1] = next[1];
662
663            // In any of the "both" situations, self-loops would be iterated over twice.
664            // Skip them here.
665            if node[0] == self.skip_start {
666                continue;
667            }
668
669            return Some(weight);
670        }
671
672        None
673    }
674}
675
676impl<E> Clone for EdgeWeights<'_, E> {
677    fn clone(&self) -> Self {
678        EdgeWeights {
679            skip_start: self.skip_start,
680            edges: self.edges,
681            next: self.next,
682            direction: self.direction,
683        }
684    }
685}
686
687/// An iterator over mutable references to all edge weights from or to a node.
688type EdgeWeightsMut<'a, N, E> = core::iter::FilterMap<
689    super::graph::EdgeWeightsMut<'a, Option<N>, Option<E>>,
690    fn(&mut Option<E>) -> Option<&mut E>,
691>;
692
693/// A reference to a graph edge.
694#[derive(Debug)]
695pub struct EdgeReference<'a, E: 'a> {
696    index: EdgeIndex,
697    node: [NodeIndex; 2],
698    weight: &'a E,
699}
700
701impl<'a, E: 'a> EdgeReference<'a, E> {
702    /// Returns the index of the edge.
703    #[inline]
704    pub fn index(&self) -> EdgeIndex {
705        self.index
706    }
707
708    /// Returns the source node index.
709    #[inline]
710    pub fn source(&self) -> NodeIndex {
711        self.node[0]
712    }
713
714    /// Returns the target node index.
715    #[inline]
716    pub fn target(&self) -> NodeIndex {
717        self.node[1]
718    }
719
720    /// Returns the weight of the edge.
721    #[inline]
722    pub fn weight(&self) -> &'a E {
723        self.weight
724    }
725}
726
727impl<E> Clone for EdgeReference<'_, E> {
728    fn clone(&self) -> Self {
729        *self
730    }
731}
732
733impl<E> Copy for EdgeReference<'_, E> {}
734
735impl<E> PartialEq for EdgeReference<'_, E>
736where
737    E: PartialEq,
738{
739    fn eq(&self, rhs: &Self) -> bool {
740        self.index == rhs.index && self.weight == rhs.weight
741    }
742}
743
744/// A mutable reference to a graph edge.
745#[derive(Debug)]
746pub struct EdgeMut<'a, E: 'a> {
747    index: EdgeIndex,
748    weight: &'a mut E,
749}
750
751impl<E> EdgeMut<'_, E> {
752    /// Returns the index of the edge.
753    #[inline]
754    pub fn index(&self) -> EdgeIndex {
755        self.index
756    }
757
758    /// Returns the weight of the edge.
759    #[inline]
760    pub fn weight(&self) -> &E {
761        self.weight
762    }
763
764    /// Returns the weight of the edge mutably.
765    #[inline]
766    pub fn weight_mut(&mut self) -> &mut E {
767        self.weight
768    }
769}
770
771impl<E> PartialEq for EdgeMut<'_, E>
772where
773    E: PartialEq,
774{
775    fn eq(&self, rhs: &Self) -> bool {
776        self.index == rhs.index && self.weight == rhs.weight
777    }
778}