@@ -17,178 +17,182 @@ use petgraph::visit::{Data, NodeIndexable};
1717
1818use super :: InvalidInputError ;
1919
20- mod utils {
21- use super :: * ;
20+ pub struct HexagonalLatticeBuilder {
21+ rowlen : usize , // Number of nodes in each vertical chain
22+ collen : usize , // Number of vertical chains
23+ num_nodes : usize , // Total number of nodes
24+ num_edges : usize , // Total number of edges
25+ bidirectional : bool ,
26+ periodic : bool ,
27+ }
2228
23- pub struct HexagonalLatticeBuilder {
24- rowlen : usize , // Number of nodes in each vertical chain
25- collen : usize , // Number of vertical chains
26- num_nodes : usize , // Total number of nodes
29+ impl HexagonalLatticeBuilder {
30+ pub fn new (
31+ rows : usize ,
32+ cols : usize ,
2733 bidirectional : bool ,
2834 periodic : bool ,
29- }
35+ ) -> Result < HexagonalLatticeBuilder , InvalidInputError > {
36+ if periodic && ( cols % 2 == 1 || rows < 2 || cols < 2 ) {
37+ return Err ( InvalidInputError { } ) ;
38+ }
3039
31- impl HexagonalLatticeBuilder {
32- pub fn new (
33- rows : usize ,
34- cols : usize ,
35- bidirectional : bool ,
36- periodic : bool ,
37- ) -> Result < HexagonalLatticeBuilder , InvalidInputError > {
38- if periodic && ( cols % 2 == 1 || rows < 2 || cols < 2 ) {
39- return Err ( InvalidInputError { } ) ;
40- }
40+ let num_edges_factor = if bidirectional { 2 } else { 1 } ;
41+
42+ let ( rowlen, collen, num_nodes, num_edges) = if periodic {
43+ let r_len = 2 * rows;
44+ (
45+ r_len,
46+ cols,
47+ r_len * cols,
48+ num_edges_factor * 3 * rows * cols,
49+ )
50+ } else {
51+ let r_len = 2 * rows + 2 ;
52+ (
53+ r_len,
54+ cols + 1 ,
55+ r_len * ( cols + 1 ) - 2 ,
56+ num_edges_factor * ( 3 * rows * cols + 2 * ( rows + cols) - 1 ) ,
57+ )
58+ } ;
4159
42- let ( rowlen, collen, num_nodes) = if periodic {
43- let r_len = 2 * rows;
44- ( r_len, cols, r_len * cols)
45- } else {
46- let r_len = 2 * rows + 2 ;
47- ( r_len, cols + 1 , r_len * ( cols + 1 ) - 2 )
48- } ;
49-
50- Ok ( HexagonalLatticeBuilder {
51- rowlen,
52- collen,
53- num_nodes,
54- bidirectional,
55- periodic,
56- } )
57- }
60+ Ok ( HexagonalLatticeBuilder {
61+ rowlen,
62+ collen,
63+ num_nodes,
64+ num_edges,
65+ bidirectional,
66+ periodic,
67+ } )
68+ }
5869
59- pub fn build_with_default_node_weight < G , T , F , H , M > (
60- self ,
61- mut default_node_weight : F ,
62- default_edge_weight : H ,
63- ) -> G
64- where
65- G : Build + Create + Data < NodeWeight = T , EdgeWeight = M > + NodeIndexable ,
66- F : FnMut ( ) -> T ,
67- H : FnMut ( ) -> M ,
68- G :: NodeId : Eq + Hash ,
69- {
70- // ToDo: be more precise about the number of edges
71- let mut graph = G :: with_capacity ( self . num_nodes , self . num_nodes ) ;
72- let nodes: Vec < G :: NodeId > = ( 0 ..self . num_nodes )
73- . map ( |_| graph. add_node ( default_node_weight ( ) ) )
74- . collect ( ) ;
75- self . add_edges ( & mut graph, nodes, default_edge_weight) ;
76-
77- graph
78- }
70+ pub fn build_with_default_node_weight < G , T , F , H , M > (
71+ self ,
72+ mut default_node_weight : F ,
73+ default_edge_weight : H ,
74+ ) -> G
75+ where
76+ G : Build + Create + Data < NodeWeight = T , EdgeWeight = M > + NodeIndexable ,
77+ F : FnMut ( ) -> T ,
78+ H : FnMut ( ) -> M ,
79+ G :: NodeId : Eq + Hash ,
80+ {
81+ let mut graph = G :: with_capacity ( self . num_nodes , self . num_edges ) ;
82+ let nodes: Vec < G :: NodeId > = ( 0 ..self . num_nodes )
83+ . map ( |_| graph. add_node ( default_node_weight ( ) ) )
84+ . collect ( ) ;
85+ self . add_edges ( & mut graph, nodes, default_edge_weight) ;
7986
80- pub fn build_with_position_dependent_node_weight < G , T , F , H , M > (
81- self ,
82- mut node_weight : F ,
83- default_edge_weight : H ,
84- ) -> G
85- where
86- G : Build + Create + Data < NodeWeight = T , EdgeWeight = M > + NodeIndexable ,
87- F : FnMut ( usize , usize ) -> T ,
88- H : FnMut ( ) -> M ,
89- G :: NodeId : Eq + Hash ,
90- {
91- // ToDo: be more precise about the number of edges
92- let mut graph = G :: with_capacity ( self . num_nodes , self . num_nodes ) ;
93-
94- let lattice_position = |n| -> ( usize , usize ) {
95- if self . periodic {
96- ( n / self . rowlen , n % self . rowlen )
87+ graph
88+ }
89+
90+ pub fn build_with_position_dependent_node_weight < G , T , F , H , M > (
91+ self ,
92+ mut node_weight : F ,
93+ default_edge_weight : H ,
94+ ) -> G
95+ where
96+ G : Build + Create + Data < NodeWeight = T , EdgeWeight = M > + NodeIndexable ,
97+ F : FnMut ( usize , usize ) -> T ,
98+ H : FnMut ( ) -> M ,
99+ G :: NodeId : Eq + Hash ,
100+ {
101+ let mut graph = G :: with_capacity ( self . num_nodes , self . num_edges ) ;
102+
103+ let lattice_position = |n| -> ( usize , usize ) {
104+ if self . periodic {
105+ ( n / self . rowlen , n % self . rowlen )
106+ } else {
107+ // In the non-periodic case the first and last vertical
108+ // chains have rowlen - 1 = 2 * rows + 1 nodes. All others
109+ // have rowlen = 2 * rows + 2 nodes.
110+ if n < self . rowlen - 1 {
111+ ( 0 , n)
97112 } else {
98- // In the non-periodic case the first and last vertical
99- // chains have rowlen - 1 = 2 * rows + 1 nodes. All others
100- // have rowlen = 2 * rows + 2 nodes.
101- if n < self . rowlen - 1 {
102- ( 0 , n )
113+ let k = n - ( self . rowlen - 1 ) ;
114+ let u = k / self . rowlen + 1 ;
115+ let v = k % self . rowlen ;
116+ if u == self . collen - 1 && u % 2 == 0 {
117+ ( u , v + 1 )
103118 } else {
104- let k = n - ( self . rowlen - 1 ) ;
105- let u = k / self . rowlen + 1 ;
106- let v = k % self . rowlen ;
107- if u == self . collen - 1 {
108- ( u, v + 1 )
109- } else {
110- ( u, v)
111- }
119+ ( u, v)
112120 }
113121 }
114- } ;
122+ }
123+ } ;
115124
116- let nodes: Vec < G :: NodeId > = ( 0 ..self . num_nodes )
117- . map ( lattice_position)
118- . map ( |( u, v) | graph. add_node ( node_weight ( u, v) ) )
119- . collect ( ) ;
120- self . add_edges ( & mut graph, nodes, default_edge_weight) ;
125+ let nodes: Vec < G :: NodeId > = ( 0 ..self . num_nodes )
126+ . map ( lattice_position)
127+ . map ( |( u, v) | graph. add_node ( node_weight ( u, v) ) )
128+ . collect ( ) ;
129+ self . add_edges ( & mut graph, nodes, default_edge_weight) ;
121130
122- graph
123- }
131+ graph
132+ }
124133
125- fn add_edges < G , H , M > (
126- & self ,
127- graph : & mut G ,
128- nodes : Vec < G :: NodeId > ,
129- mut default_edge_weight : H ,
130- ) where
131- G : Build + NodeIndexable + Data < EdgeWeight = M > ,
132- H : FnMut ( ) -> M ,
133- {
134- let mut add_edge = |u, v| {
135- graph. add_edge ( nodes[ u] , nodes[ v] , default_edge_weight ( ) ) ;
136- if self . bidirectional {
137- graph. add_edge ( nodes[ v] , nodes[ u] , default_edge_weight ( ) ) ;
138- }
139- } ;
134+ fn add_edges < G , H , M > ( & self , graph : & mut G , nodes : Vec < G :: NodeId > , mut default_edge_weight : H )
135+ where
136+ G : Build + NodeIndexable + Data < EdgeWeight = M > ,
137+ H : FnMut ( ) -> M ,
138+ {
139+ let mut add_edge = |u, v| {
140+ graph. add_edge ( nodes[ u] , nodes[ v] , default_edge_weight ( ) ) ;
141+ if self . bidirectional {
142+ graph. add_edge ( nodes[ v] , nodes[ u] , default_edge_weight ( ) ) ;
143+ }
144+ } ;
140145
141- if self . periodic {
142- // Add column edges
143- for i in 0 ..self . collen {
144- let col_start = i * self . rowlen ;
145- for j in col_start..( col_start + self . rowlen - 1 ) {
146- add_edge ( j, j + 1 ) ;
147- }
148- add_edge ( col_start + self . rowlen - 1 , col_start) ;
149- }
150- // Add row edges
151- for i in 0 ..self . collen {
152- let col_start = i * self . rowlen + i % 2 ;
153- for j in ( col_start..( col_start + self . rowlen ) ) . step_by ( 2 ) {
154- add_edge ( j, ( j + self . rowlen ) % self . num_nodes ) ;
155- }
156- }
157- } else {
158- // Add column edges
159- for j in 0 ..( self . rowlen - 2 ) {
146+ if self . periodic {
147+ // Add column edges
148+ for i in 0 ..self . collen {
149+ let col_start = i * self . rowlen ;
150+ for j in col_start..( col_start + self . rowlen - 1 ) {
160151 add_edge ( j, j + 1 ) ;
161152 }
162- for i in 1 ..( self . collen - 1 ) {
163- for j in 0 ..( self . rowlen - 1 ) {
164- add_edge ( i * self . rowlen + j - 1 , i * self . rowlen + j) ;
165- }
153+ add_edge ( col_start + self . rowlen - 1 , col_start) ;
154+ }
155+ // Add row edges
156+ for i in 0 ..self . collen {
157+ let col_start = i * self . rowlen + i % 2 ;
158+ for j in ( col_start..( col_start + self . rowlen ) ) . step_by ( 2 ) {
159+ add_edge ( j, ( j + self . rowlen ) % self . num_nodes ) ;
166160 }
167- for j in 0 ..( self . rowlen - 2 ) {
168- add_edge (
169- ( self . collen - 1 ) * self . rowlen + j - 1 ,
170- ( self . collen - 1 ) * self . rowlen + j,
171- ) ;
161+ }
162+ } else {
163+ // Add column edges
164+ for j in 0 ..( self . rowlen - 2 ) {
165+ add_edge ( j, j + 1 ) ;
166+ }
167+ for i in 1 ..( self . collen - 1 ) {
168+ for j in 0 ..( self . rowlen - 1 ) {
169+ add_edge ( i * self . rowlen + j - 1 , i * self . rowlen + j) ;
172170 }
171+ }
172+ for j in 0 ..( self . rowlen - 2 ) {
173+ add_edge (
174+ ( self . collen - 1 ) * self . rowlen + j - 1 ,
175+ ( self . collen - 1 ) * self . rowlen + j,
176+ ) ;
177+ }
173178
174- // Add row edges
175- for j in ( 0 ..( self . rowlen - 1 ) ) . step_by ( 2 ) {
176- add_edge ( j, j + self . rowlen - 1 ) ;
177- }
178- for i in 1 ..( self . collen - 2 ) {
179- for j in 0 ..self . rowlen {
180- if i % 2 == j % 2 {
181- add_edge ( i * self . rowlen + j - 1 , ( i + 1 ) * self . rowlen + j - 1 ) ;
182- }
179+ // Add row edges
180+ for j in ( 0 ..( self . rowlen - 1 ) ) . step_by ( 2 ) {
181+ add_edge ( j, j + self . rowlen - 1 ) ;
182+ }
183+ for i in 1 ..( self . collen - 2 ) {
184+ for j in 0 ..self . rowlen {
185+ if i % 2 == j % 2 {
186+ add_edge ( i * self . rowlen + j - 1 , ( i + 1 ) * self . rowlen + j - 1 ) ;
183187 }
184188 }
185- if self . collen > 2 {
186- for j in ( ( self . collen % 2 ) .. self . rowlen ) . step_by ( 2 ) {
187- add_edge (
188- ( self . collen - 2 ) * self . rowlen + j - 1 ,
189- ( self . collen - 1 ) * self . rowlen + j - 1 - ( self . collen % 2 ) ,
190- ) ;
191- }
189+ }
190+ if self . collen > 2 {
191+ for j in ( ( self . collen % 2 ) .. self . rowlen ) . step_by ( 2 ) {
192+ add_edge (
193+ ( self . collen - 2 ) * self . rowlen + j - 1 ,
194+ ( self . collen - 1 ) * self . rowlen + j - 1 - ( self . collen % 2 ) ,
195+ ) ;
192196 }
193197 }
194198 }
@@ -272,7 +276,7 @@ where
272276 return Ok ( G :: with_capacity ( 0 , 0 ) ) ;
273277 }
274278
275- let builder = utils :: HexagonalLatticeBuilder :: new ( rows, cols, bidirectional, periodic) ?;
279+ let builder = HexagonalLatticeBuilder :: new ( rows, cols, bidirectional, periodic) ?;
276280
277281 let graph = builder
278282 . build_with_default_node_weight :: < G , T , F , H , M > ( default_node_weight, default_edge_weight) ;
@@ -357,7 +361,7 @@ where
357361 return Ok ( G :: with_capacity ( 0 , 0 ) ) ;
358362 }
359363
360- let builder = utils :: HexagonalLatticeBuilder :: new ( rows, cols, bidirectional, periodic) ?;
364+ let builder = HexagonalLatticeBuilder :: new ( rows, cols, bidirectional, periodic) ?;
361365
362366 let graph = builder. build_with_position_dependent_node_weight :: < G , T , F , H , M > (
363367 node_weight,
@@ -596,7 +600,10 @@ mod tests {
596600 hexagonal_lattice_graph_weighted ( 2 , 2 , |u, v| ( u, v) , || ( ) , false , true ) . unwrap ( ) ;
597601 assert_eq ! ( g_weighted. node_count( ) , 8 ) ;
598602 check_expected_edges_directed ( & g_weighted, & expected_edges) ;
603+ }
599604
605+ #[ test]
606+ fn test_hexagonal_lattice_graph_node_weights ( ) {
600607 let g: petgraph:: graph:: UnGraph < ( usize , usize ) , ( ) > =
601608 hexagonal_lattice_graph_weighted ( 2 , 2 , |u, v| ( u, v) , || ( ) , false , false ) . unwrap ( ) ;
602609 let expected_node_weights = vec ! [
0 commit comments