1
1
use super :: * ;
2
+ use as_slice:: AsSlice ;
2
3
use :: io;
3
4
use std:: io:: Result ;
4
5
use std:: path:: Path ;
5
6
6
7
#[ derive( Debug , Clone ) ]
7
- pub struct FirstOutGraph {
8
+ pub struct FirstOutGraph < FirstOutContainer , HeadContainer , WeightContainer > where
9
+ FirstOutContainer : AsSlice < u32 > ,
10
+ HeadContainer : AsSlice < NodeId > ,
11
+ WeightContainer : AsSlice < Weight > ,
12
+ {
8
13
// index of first edge of each node +1 entry in the end
9
- first_out : Vec < u32 > ,
14
+ first_out : FirstOutContainer ,
10
15
// the node ids to which each edge points
11
- head : Vec < NodeId > ,
16
+ head : HeadContainer ,
12
17
// the weight of each edge
13
- weight : Vec < Weight >
18
+ weight : WeightContainer ,
14
19
}
15
20
16
- impl FirstOutGraph {
17
- pub fn new ( first_out : Vec < u32 > , head : Vec < NodeId > , weight : Vec < Weight > ) -> FirstOutGraph {
18
- assert_eq ! ( * first_out. first( ) . unwrap( ) , 0 ) ;
19
- assert_eq ! ( * first_out. last( ) . unwrap( ) as usize , head. len( ) ) ;
20
- assert_eq ! ( weight. len( ) , head. len( ) ) ;
21
+ pub type OwnedGraph = FirstOutGraph < Vec < u32 > , Vec < NodeId > , Vec < Weight > > ;
21
22
22
- FirstOutGraph {
23
- first_out, head, weight
24
- }
23
+ impl < FirstOutContainer , HeadContainer , WeightContainer > FirstOutGraph < FirstOutContainer , HeadContainer , WeightContainer > where
24
+ FirstOutContainer : AsSlice < u32 > ,
25
+ HeadContainer : AsSlice < NodeId > ,
26
+ WeightContainer : AsSlice < Weight > ,
27
+ {
28
+ fn first_out ( & self ) -> & [ u32 ] { self . first_out . as_slice ( ) }
29
+ fn head ( & self ) -> & [ u32 ] { self . head . as_slice ( ) }
30
+ fn weight ( & self ) -> & [ u32 ] { self . weight . as_slice ( ) }
31
+
32
+ pub fn new ( first_out : FirstOutContainer , head : HeadContainer , weight : WeightContainer ) -> FirstOutGraph < FirstOutContainer , HeadContainer , WeightContainer > {
33
+ assert_eq ! ( * first_out. as_slice( ) . first( ) . unwrap( ) , 0 ) ;
34
+ assert_eq ! ( * first_out. as_slice( ) . last( ) . unwrap( ) as usize , head. as_slice( ) . len( ) ) ;
35
+ assert_eq ! ( weight. as_slice( ) . len( ) , head. as_slice( ) . len( ) ) ;
36
+
37
+ FirstOutGraph { first_out, head, weight }
38
+ }
39
+
40
+ pub fn write_to_dir ( & self , dir : & str ) -> Result < ( ) > {
41
+ let path = Path :: new ( dir) ;
42
+ let res1 = io:: write_vector_to_file ( path. join ( "first_out" ) . to_str ( ) . unwrap ( ) , self . first_out ( ) ) ;
43
+ let res2 = io:: write_vector_to_file ( path. join ( "head" ) . to_str ( ) . unwrap ( ) , self . head ( ) ) ;
44
+ let res3 = io:: write_vector_to_file ( path. join ( "weights" ) . to_str ( ) . unwrap ( ) , self . weight ( ) ) ;
45
+ res1. and ( res2) . and ( res3)
25
46
}
26
47
27
- pub fn from_adjancecy_lists ( adjancecy_lists : Vec < Vec < Link > > ) -> FirstOutGraph {
48
+ pub fn decompose ( self ) -> ( FirstOutContainer , HeadContainer , WeightContainer ) {
49
+ ( self . first_out , self . head , self . weight )
50
+ }
51
+ }
52
+
53
+ impl OwnedGraph {
54
+ pub fn from_adjancecy_lists ( adjancecy_lists : Vec < Vec < Link > > ) -> OwnedGraph {
28
55
// create first_out array for reversed by doing a prefix sum over the adjancecy list sizes
29
56
let first_out = std:: iter:: once ( 0 ) . chain ( adjancecy_lists. iter ( ) . scan ( 0 , |state, incoming_links| {
30
57
* state = * state + incoming_links. len ( ) as u32 ;
@@ -37,70 +64,43 @@ impl FirstOutGraph {
37
64
. flat_map ( |neighbors| neighbors. into_iter ( ) . map ( |Link { node, weight } | ( node, weight) ) )
38
65
. unzip ( ) ;
39
66
40
- FirstOutGraph :: new ( first_out, head, weight)
41
- }
42
-
43
- pub fn neighbor_iter ( & self , node : NodeId ) -> std:: iter:: Map < std:: iter:: Zip < std:: slice:: Iter < NodeId > , std:: slice:: Iter < Weight > > , fn ( ( & NodeId , & Weight ) ) ->Link > {
44
- let range = ( self . first_out [ node as usize ] as usize ) ..( self . first_out [ ( node + 1 ) as usize ] as usize ) ;
45
- self . head [ range. clone ( ) ] . iter ( )
46
- . zip ( self . weight [ range] . iter ( ) )
47
- . map ( |( & neighbor, & weight) | Link { node : neighbor, weight : weight } )
48
- }
49
-
50
- pub fn edge_index ( & self , from : NodeId , to : NodeId ) -> Option < usize > {
51
- let first_out = self . first_out [ from as usize ] as usize ;
52
- self . neighbor_iter ( from) . enumerate ( ) . find ( |& ( _, Link { node, .. } ) | node == to) . map ( |( i, _) | first_out + i )
53
- }
54
-
55
- pub fn reverse ( & self ) -> FirstOutGraph {
56
- // vector of adjacency lists for the reverse graph
57
- let mut reversed: Vec < Vec < Link > > = ( 0 ..self . num_nodes ( ) ) . map ( |_| Vec :: < Link > :: new ( ) ) . collect ( ) ;
58
-
59
- // iterate over all edges and insert them in the reversed structure
60
- for node in 0 ..( self . num_nodes ( ) as NodeId ) {
61
- for Link { node : neighbor, weight } in self . neighbor_iter ( node) {
62
- reversed[ neighbor as usize ] . push ( Link { node, weight } ) ;
63
- }
64
- }
65
- FirstOutGraph :: from_adjancecy_lists ( reversed)
66
- }
67
-
68
- pub fn ch_split ( self , node_ranks : & Vec < u32 > ) -> ( FirstOutGraph , FirstOutGraph ) {
69
- let mut up: Vec < Vec < Link > > = ( 0 ..self . num_nodes ( ) ) . map ( |_| Vec :: < Link > :: new ( ) ) . collect ( ) ;
70
- let mut down: Vec < Vec < Link > > = ( 0 ..self . num_nodes ( ) ) . map ( |_| Vec :: < Link > :: new ( ) ) . collect ( ) ;
71
-
72
- // iterate over all edges and insert them in the reversed structure
73
- for node in 0 ..( self . num_nodes ( ) as NodeId ) {
74
- for Link { node : neighbor, weight } in self . neighbor_iter ( node) {
75
- if node_ranks[ node as usize ] < node_ranks[ neighbor as usize ] {
76
- up[ node as usize ] . push ( Link { node : neighbor, weight } ) ;
77
- } else {
78
- down[ neighbor as usize ] . push ( Link { node, weight } ) ;
79
- }
80
- }
81
- }
82
-
83
- ( FirstOutGraph :: from_adjancecy_lists ( up) , FirstOutGraph :: from_adjancecy_lists ( down) )
67
+ OwnedGraph :: new ( first_out, head, weight)
84
68
}
69
+ }
85
70
86
- pub fn write_to_dir ( & self , dir : & str ) -> Result < ( ) > {
87
- let path = Path :: new ( dir) ;
88
- let res1 = io:: write_vector_to_file ( path. join ( "first_out" ) . to_str ( ) . unwrap ( ) , & self . first_out ) ;
89
- let res2 = io:: write_vector_to_file ( path. join ( "head" ) . to_str ( ) . unwrap ( ) , & self . head ) ;
90
- let res3 = io:: write_vector_to_file ( path. join ( "weights" ) . to_str ( ) . unwrap ( ) , & self . weight ) ;
91
- res1. and ( res2) . and ( res3)
71
+ impl < FirstOutContainer , HeadContainer , WeightContainer > Graph for FirstOutGraph < FirstOutContainer , HeadContainer , WeightContainer > where
72
+ FirstOutContainer : AsSlice < u32 > ,
73
+ HeadContainer : AsSlice < NodeId > ,
74
+ WeightContainer : AsSlice < Weight > ,
75
+ {
76
+ fn num_nodes ( & self ) -> usize {
77
+ self . first_out ( ) . len ( ) - 1
92
78
}
93
79
}
94
80
95
- impl DijkstrableGraph for FirstOutGraph {
96
- fn num_nodes ( & self ) -> usize {
97
- self . first_out . len ( ) - 1
81
+ impl < ' a , FirstOutContainer , HeadContainer , WeightContainer > LinkIterGraph < ' a > for FirstOutGraph < FirstOutContainer , HeadContainer , WeightContainer > where
82
+ FirstOutContainer : AsSlice < u32 > ,
83
+ HeadContainer : AsSlice < NodeId > ,
84
+ WeightContainer : AsSlice < Weight > ,
85
+ {
86
+ type Iter = std:: iter:: Map < std:: iter:: Zip < std:: slice:: Iter < ' a , NodeId > , std:: slice:: Iter < ' a , Weight > > , fn ( ( & NodeId , & Weight ) ) ->Link > ;
87
+
88
+ fn neighbor_iter ( & ' a self , node : NodeId ) -> Self :: Iter {
89
+ let range = ( self . first_out ( ) [ node as usize ] as usize ) ..( self . first_out ( ) [ ( node + 1 ) as usize ] as usize ) ;
90
+ self . head ( ) [ range. clone ( ) ] . iter ( )
91
+ . zip ( self . weight ( ) [ range] . iter ( ) )
92
+ . map ( |( & neighbor, & weight) | Link { node : neighbor, weight : weight } )
98
93
}
94
+ }
99
95
100
- fn for_each_neighbor ( & self , node : NodeId , f : & mut FnMut ( Link ) ) {
101
- for link in self . neighbor_iter ( node) {
102
- f ( link) ;
103
- }
96
+ impl < FirstOutContainer , HeadContainer , WeightContainer > RandomLinkAccessGraph for FirstOutGraph < FirstOutContainer , HeadContainer , WeightContainer > where
97
+ FirstOutContainer : AsSlice < u32 > ,
98
+ HeadContainer : AsSlice < NodeId > ,
99
+ WeightContainer : AsSlice < Weight > ,
100
+ {
101
+ fn edge_index ( & self , from : NodeId , to : NodeId ) -> Option < usize > {
102
+ let first_out = self . first_out ( ) [ from as usize ] as usize ;
103
+ self . neighbor_iter ( from) . enumerate ( ) . find ( |& ( _, Link { node, .. } ) | node == to) . map ( |( i, _) | first_out + i )
104
104
}
105
105
}
106
106
0 commit comments