1
1
/*
2
- * SPDX-FileCopyrightText: 2023 Inria
2
+ * SPDX-FileCopyrightText: 2023-2025 Inria
3
3
* SPDX-FileCopyrightText: 2023 Sebastiano Vigna
4
4
*
5
5
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
8
8
use crate :: prelude:: * ;
9
9
10
10
use lender:: prelude:: * ;
11
- use std:: { collections:: BTreeSet , mem :: MaybeUninit } ;
11
+ use std:: collections:: BTreeMap ;
12
12
13
13
/// A mutable [`LabeledRandomAccessGraph`] implementation based on a vector of
14
14
/// [`BTreeSet`].
@@ -20,12 +20,12 @@ use std::{collections::BTreeSet, mem::MaybeUninit};
20
20
/// By setting the feature `serde`, this struct can be serialized and
21
21
/// deserialized using [serde](https://crates.io/crates/serde).
22
22
#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
23
- #[ derive( Clone , Debug ) ]
23
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
24
24
pub struct LabeledBTreeGraph < L : Clone + ' static = ( ) > {
25
25
/// The number of arcs in the graph.
26
26
number_of_arcs : u64 ,
27
27
/// For each node, its list of successors.
28
- succ : Vec < BTreeSet < Successor < L > > > ,
28
+ succ : Vec < BTreeMap < usize , L > > ,
29
29
}
30
30
31
31
impl < L : Clone + ' static > core:: default:: Default for LabeledBTreeGraph < L > {
@@ -34,38 +34,6 @@ impl<L: Clone + 'static> core::default::Default for LabeledBTreeGraph<L> {
34
34
}
35
35
}
36
36
37
- /// Manual implementation of [`PartialEq`]. This implementation is necessary
38
- /// because the private struct [`Successor`] that we use to store in a
39
- /// [`BTreeSet`] the tuple `(usize, Label)` implements [`PartialEq`] ignoring
40
- /// the label so to enforce the absence of duplicate arcs. This implies that the
41
- /// derived implementation of [`PartialEq`] would not check labels, so the same
42
- /// graph with different labels would be equal, and this is not the intended
43
- /// semantics.
44
- impl < L : Clone + ' static + PartialEq > PartialEq for LabeledBTreeGraph < L > {
45
- fn eq ( & self , other : & Self ) -> bool {
46
- if self . number_of_arcs != other. number_of_arcs {
47
- return false ;
48
- }
49
- if self . succ . len ( ) != other. succ . len ( ) {
50
- return false ;
51
- }
52
- for ( s, o) in self . succ . iter ( ) . zip ( other. succ . iter ( ) ) {
53
- if s. len ( ) != o. len ( ) {
54
- return false ;
55
- }
56
- let s_iter = s. iter ( ) . map ( |x| ( x. 0 , & x. 1 ) ) ;
57
- let o_iter = o. iter ( ) . map ( |x| ( x. 0 , & x. 1 ) ) ;
58
- for ( v1, v2) in s_iter. zip ( o_iter) {
59
- if v1 != v2 {
60
- return false ;
61
- }
62
- }
63
- }
64
- true
65
- }
66
- }
67
- impl < L : Clone + ' static + Eq > Eq for LabeledBTreeGraph < L > { }
68
-
69
37
impl < L : Clone + ' static > LabeledBTreeGraph < L > {
70
38
/// Creates a new empty graph.
71
39
pub fn new ( ) -> Self {
@@ -79,7 +47,7 @@ impl<L: Clone + 'static> LabeledBTreeGraph<L> {
79
47
pub fn empty ( n : usize ) -> Self {
80
48
Self {
81
49
number_of_arcs : 0 ,
82
- succ : Vec :: from_iter ( ( 0 ..n) . map ( |_| BTreeSet :: new ( ) ) ) ,
50
+ succ : Vec :: from_iter ( ( 0 ..n) . map ( |_| BTreeMap :: new ( ) ) ) ,
83
51
}
84
52
}
85
53
@@ -91,7 +59,7 @@ impl<L: Clone + 'static> LabeledBTreeGraph<L> {
91
59
/// than the number of nodes in the graph.
92
60
pub fn add_node ( & mut self , node : usize ) -> bool {
93
61
let len = self . succ . len ( ) ;
94
- self . succ . extend ( ( len..=node) . map ( |_| BTreeSet :: new ( ) ) ) ;
62
+ self . succ . extend ( ( len..=node) . map ( |_| BTreeMap :: new ( ) ) ) ;
95
63
len <= node
96
64
}
97
65
@@ -105,9 +73,9 @@ impl<L: Clone + 'static> LabeledBTreeGraph<L> {
105
73
self . succ. len( ) ,
106
74
) ;
107
75
}
108
- let result = self . succ [ u] . insert ( Successor ( v, l) ) ;
109
- self . number_of_arcs += result as u64 ;
110
- result
76
+ let is_new_arc = self . succ [ u] . insert ( v, l) . is_none ( ) ;
77
+ self . number_of_arcs += is_new_arc as u64 ;
78
+ is_new_arc
111
79
}
112
80
113
81
/// Remove an arc from the graph and return whether it was present or not.
@@ -120,13 +88,9 @@ impl<L: Clone + 'static> LabeledBTreeGraph<L> {
120
88
self . succ. len( ) ,
121
89
) ;
122
90
}
123
- // SAFETY: the label is not used by Eq/Ord.
124
- let result = self . succ [ u] . remove ( & Successor ( v, unsafe {
125
- #[ allow( clippy:: uninit_assumed_init) ]
126
- MaybeUninit :: < L > :: uninit ( ) . assume_init ( )
127
- } ) ) ;
128
- self . number_of_arcs -= result as u64 ;
129
- result
91
+ let arc_existed = self . succ [ u] . remove ( & v) . is_some ( ) ;
92
+ self . number_of_arcs -= arc_existed as u64 ;
93
+ arc_existed
130
94
}
131
95
132
96
/// Add nodes and labeled successors from an [`IntoLender`] yielding a
@@ -375,8 +339,8 @@ impl SequentialGraph for BTreeGraph {}
375
339
376
340
impl RandomAccessLabeling for BTreeGraph {
377
341
type Labels < ' succ > = std:: iter:: Map <
378
- std:: collections:: btree_set :: Iter < ' succ , Successor < ( ) > > ,
379
- fn ( & Successor < ( ) > ) -> usize ,
342
+ std:: collections:: btree_map :: Keys < ' succ , usize , ( ) > ,
343
+ fn ( & usize ) -> usize ,
380
344
> ;
381
345
382
346
#[ inline( always) ]
@@ -391,7 +355,7 @@ impl RandomAccessLabeling for BTreeGraph {
391
355
392
356
#[ inline( always) ]
393
357
fn labels ( & self , node : usize ) -> <Self as RandomAccessLabeling >:: Labels < ' _ > {
394
- self . 0 . succ [ node] . iter ( ) . map ( |x| x . 0 )
358
+ self . 0 . succ [ node] . keys ( ) . map ( |& key| key )
395
359
}
396
360
}
397
361
@@ -403,50 +367,17 @@ impl From<LabeledBTreeGraph<()>> for BTreeGraph {
403
367
}
404
368
}
405
369
406
- #[ doc( hidden) ]
407
- /// A struct containing a successor.
408
- ///
409
- /// By implementing equality and order on the first coordinate only, we
410
- /// can store the successors of a node and their labels as a
411
- /// [`BTreeSet`] of pairs `(usize, L)`.
412
- #[ derive( Clone , Copy , Debug ) ]
413
- #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
414
- pub struct Successor < L : Clone + ' static > ( usize , L ) ;
415
-
416
- impl < L : Clone + ' static > PartialEq for Successor < L > {
417
- #[ inline( always) ]
418
- fn eq ( & self , other : & Self ) -> bool {
419
- self . 0 == other. 0
420
- }
421
- }
422
-
423
- impl < L : Clone + ' static > Eq for Successor < L > { }
424
-
425
- impl < L : Clone + ' static > PartialOrd for Successor < L > {
426
- #[ inline( always) ]
427
- fn partial_cmp ( & self , other : & Self ) -> Option < core:: cmp:: Ordering > {
428
- Some ( self . 0 . cmp ( & other. 0 ) )
429
- }
430
- }
431
-
432
- impl < L : Clone + ' static > Ord for Successor < L > {
433
- #[ inline( always) ]
434
- fn cmp ( & self , other : & Self ) -> core:: cmp:: Ordering {
435
- self . 0 . cmp ( & other. 0 )
436
- }
437
- }
438
-
439
370
#[ doc( hidden) ]
440
371
#[ repr( transparent) ]
441
- pub struct Successors < ' a , L : Clone + ' static > ( std:: collections:: btree_set :: Iter < ' a , Successor < L > > ) ;
372
+ pub struct Successors < ' a , L : Clone + ' static > ( std:: collections:: btree_map :: Iter < ' a , usize , L > ) ;
442
373
443
374
unsafe impl < L : Clone + ' static > SortedIterator for Successors < ' _ , L > { }
444
375
445
376
impl < L : Clone + ' static > Iterator for Successors < ' _ , L > {
446
377
type Item = ( usize , L ) ;
447
378
#[ inline( always) ]
448
379
fn next ( & mut self ) -> Option < Self :: Item > {
449
- self . 0 . next ( ) . cloned ( ) . map ( |x | ( x . 0 , x . 1 ) )
380
+ self . 0 . next ( ) . map ( |( succ , labels ) | ( * succ , labels . clone ( ) ) )
450
381
}
451
382
}
452
383
0 commit comments