@@ -17,18 +17,18 @@ use std::cmp::Ordering;
1717use std:: convert:: Infallible ;
1818use std:: hash:: Hash ;
1919
20+ type SubgraphResult < K , E > = Result < Vec < SubgraphData < K > > , E > ;
21+ type SubgraphData < K > = (
22+ Graph < usize , K , Undirected > ,
23+ HashMap < usize , NodeIndex > ,
24+ HashMap < usize , EdgeIndex > ,
25+ ) ;
26+
2027fn create_subgraphs_from_components < G , F , K , E > (
2128 graph : G ,
2229 components : Vec < HashSet < G :: NodeId > > ,
2330 mut weight_fn : F ,
24- ) -> Result <
25- Vec < (
26- Graph < usize , K , Undirected > ,
27- HashMap < usize , NodeIndex > ,
28- HashMap < usize , EdgeIndex > ,
29- ) > ,
30- E ,
31- >
31+ ) -> SubgraphResult < K , E >
3232where
3333 G : IntoEdgeReferences
3434 + NodeIndexable
@@ -78,47 +78,118 @@ where
7878 } )
7979 . collect ( )
8080}
81- pub fn minimal_cycle_basis < G , F , K , E > ( graph : G , mut weight_fn : F ) -> Result < Vec < Vec < NodeIndex > > , E >
81+
82+ fn _min_cycle < H , F , K , E > (
83+ subgraph : H ,
84+ orth : HashSet < ( usize , usize ) > ,
85+ mut weight_fn : F ,
86+ ) -> Result < Vec < ( usize , usize ) > , E >
8287where
83- G : EdgeCount
84- + IntoNodeIdentifiers
85- + NodeIndexable
86- + EdgeIndexable
87- + DataMap
88- + GraphProp
89- + IntoNeighborsDirected
90- + Visitable
91- + IntoEdges ,
92- G :: EdgeWeight : Clone ,
93- G :: NodeId : Eq + Hash ,
94- F : FnMut ( G :: EdgeRef ) -> Result < K , E > ,
88+ H : IntoNodeReferences + IntoEdgeReferences + DataMap + NodeIndexable + EdgeIndexable ,
89+ H :: NodeId : Eq + Hash ,
90+ F : FnMut ( H :: EdgeRef ) -> Result < K , E > ,
9591 K : Clone + PartialOrd + Copy + Measure + Default ,
9692{
97- let conn_components = connected_components ( & graph) ;
98- let mut min_cycle_basis = Vec :: new ( ) ;
99- let subgraphs_with_maps =
100- create_subgraphs_from_components ( & graph, conn_components, & mut weight_fn) ?;
101- // Convert weight_fn to a closure that takes a subgraph edge and returns the weight of the original graph edge
102- for ( subgraph, node_subnode_map, edge_subedge_map) in subgraphs_with_maps {
103- // Find the key of edge_subedge_map that corresponds to the value e.id()
104- let mut subgraph_weight_fn = |e : <& Graph < usize , K , Undirected , DefaultIx > as IntoEdgeReferences >:: EdgeRef | -> Result < K , Infallible > {
105- // use the edge_subedge_map to find the key that corresponds to the value e.id()
106- let edge = edge_subedge_map. iter ( ) . find ( |( _key, & value) | value == e. id ( ) ) . unwrap ( ) . 0 ;
107- match weight_fn (
108- graph. edge_references ( ) . nth ( * edge) . unwrap ( ) ,
109- ) {
110- Ok ( weight) => Ok ( weight) ,
111- Err ( _) => {
112- // Handle the error here. Since the error type is Infallible, this branch should never be reached.
113- unreachable ! ( )
93+ let mut gi = Graph :: < _ , _ , petgraph:: Undirected > :: default ( ) ;
94+ let mut subgraph_gi_map = HashMap :: new ( ) ;
95+ let mut gi_subgraph_map = HashMap :: new ( ) ;
96+ for node in subgraph. node_identifiers ( ) {
97+ let gi_node = gi. add_node ( node) ;
98+ let gi_lifted_node = gi. add_node ( node) ;
99+ gi_subgraph_map. insert ( gi_node, node) ;
100+ gi_subgraph_map. insert ( gi_lifted_node, node) ;
101+ subgraph_gi_map. insert ( node, ( gi_node, gi_lifted_node) ) ;
102+ }
103+ // # Add 2 copies of each edge in G to Gi.
104+ // # If edge is in orth, add cross edge; otherwise in-plane edge
105+
106+ for edge in subgraph. edge_references ( ) {
107+ let u_id = edge. source ( ) ;
108+ let v_id = edge. target ( ) ;
109+ let u = NodeIndexable :: to_index ( & subgraph, u_id) ;
110+ let v = NodeIndexable :: to_index ( & subgraph, v_id) ;
111+ let weight = weight_fn ( edge) ?;
112+ // For each pair of (u, v) from the subgraph, there is a corresponding double pair of (u_node, v_node) and (u_lifted_node, v_lifted_node) in the gi
113+ let ( u_node, u_lifted_node) = subgraph_gi_map[ & u_id] ;
114+ let ( v_node, v_lifted_node) = subgraph_gi_map[ & v_id] ;
115+ if orth. contains ( & ( u, v) ) || orth. contains ( & ( v, u) ) {
116+ // Add cross edges with weight
117+ gi. add_edge ( u_node, v_lifted_node, weight) ;
118+ gi. add_edge ( u_lifted_node, v_node, weight) ;
119+ } else {
120+ // Add in-plane edges with weight
121+ gi. add_edge ( u_node, v_node, weight) ;
122+ gi. add_edge ( u_lifted_node, v_lifted_node, weight) ;
123+ }
124+ }
125+ // Instead of finding the shortest path between each node and its lifted node, store the shortest paths in a list to find the shortest paths among them
126+ let mut shortest_path_map: HashMap < H :: NodeId , K > = HashMap :: new ( ) ;
127+ for subnodeid in subgraph. node_identifiers ( ) {
128+ let ( gi_nodeidx, gi_lifted_nodeidx) = subgraph_gi_map[ & subnodeid] ;
129+
130+ let result: Result < DictMap < NodeIndex , K > > = dijkstra (
131+ & gi,
132+ gi_nodeidx,
133+ Some ( gi_lifted_nodeidx) ,
134+ |edge| Ok ( * edge. weight ( ) ) ,
135+ None ,
136+ ) ;
137+ let spl = result. unwrap ( ) [ & gi_lifted_nodeidx] ;
138+ shortest_path_map. insert ( subnodeid, spl) ;
139+ }
140+ let min_start = shortest_path_map
141+ . iter ( )
142+ . min_by ( |a, b| a. 1 . partial_cmp ( b. 1 ) . unwrap_or ( Ordering :: Equal ) )
143+ . unwrap ( )
144+ . 0 ;
145+ let min_start_node = subgraph_gi_map[ min_start] . 0 ;
146+ let min_start_lifted_node = subgraph_gi_map[ min_start] . 1 ;
147+ let result: Result < Option < ( K , Vec < NodeIndex > ) > > = astar (
148+ & gi,
149+ min_start_node,
150+ |finish| Ok ( finish == min_start_lifted_node) ,
151+ |e| Ok ( * e. weight ( ) ) ,
152+ |_| Ok ( K :: default ( ) ) ,
153+ ) ;
154+
155+ let mut min_path: Vec < usize > = Vec :: new ( ) ;
156+ match result {
157+ Ok ( Some ( ( _cost, path) ) ) => {
158+ for node in path {
159+ if let Some ( & subgraph_nodeid) = gi_subgraph_map. get ( & node) {
160+ let subgraph_node = NodeIndexable :: to_index ( & subgraph, subgraph_nodeid) ;
161+ min_path. push ( subgraph_node. index ( ) ) ;
114162 }
115163 }
116- } ;
117- let num_cycles: Result < Vec < Vec < NodeIndex > > , Infallible > =
118- _min_cycle_basis ( & subgraph, & mut subgraph_weight_fn, & node_subnode_map) ;
119- min_cycle_basis. extend ( num_cycles. unwrap ( ) ) ;
164+ }
165+ Ok ( None ) => { }
166+ Err ( _) => { }
120167 }
121- Ok ( min_cycle_basis)
168+ let edgelist = min_path
169+ . windows ( 2 )
170+ . map ( |w| ( w[ 0 ] , w[ 1 ] ) )
171+ . collect :: < Vec < _ > > ( ) ;
172+ let mut edgeset: HashSet < ( usize , usize ) > = HashSet :: new ( ) ;
173+ for e in edgelist. iter ( ) {
174+ if edgeset. contains ( e) {
175+ edgeset. remove ( e) ;
176+ } else if edgeset. contains ( & ( e. 1 , e. 0 ) ) {
177+ edgeset. remove ( & ( e. 1 , e. 0 ) ) ;
178+ } else {
179+ edgeset. insert ( * e) ;
180+ }
181+ }
182+ let mut min_edgelist: Vec < ( usize , usize ) > = Vec :: new ( ) ;
183+ for e in edgelist. iter ( ) {
184+ if edgeset. contains ( e) {
185+ min_edgelist. push ( * e) ;
186+ edgeset. remove ( e) ;
187+ } else if edgeset. contains ( & ( e. 1 , e. 0 ) ) {
188+ min_edgelist. push ( ( e. 1 , e. 0 ) ) ;
189+ edgeset. remove ( & ( e. 1 , e. 0 ) ) ;
190+ }
191+ }
192+ Ok ( min_edgelist)
122193}
123194
124195fn _min_cycle_basis < H , F , K , E > (
@@ -182,7 +253,7 @@ where
182253 }
183254 while let Some ( chord_pop) = set_orth. pop ( ) {
184255 let base = chord_pop;
185- let cycle_edges = _min_cycle ( & subgraph, base. clone ( ) , & mut weight_fn) ?;
256+ let cycle_edges = _min_cycle ( subgraph, base. clone ( ) , & mut weight_fn) ?;
186257 let mut cb_temp: Vec < usize > = Vec :: new ( ) ;
187258 for edge in cycle_edges. iter ( ) {
188259 cb_temp. push ( edge. 1 ) ;
@@ -192,7 +263,7 @@ where
192263 let mut new_orth = HashSet :: new ( ) ;
193264 if cycle_edges
194265 . iter ( )
195- . filter ( |edge| orth. contains ( * edge) || orth. contains ( & ( ( * edge) . 1 , ( * edge) . 0 ) ) )
266+ . filter ( |edge| orth. contains ( * edge) || orth. contains ( & ( edge. 1 , edge. 0 ) ) )
196267 . count ( )
197268 % 2
198269 == 1
@@ -209,7 +280,8 @@ where
209280 }
210281 * orth = new_orth;
211282 } else {
212- * orth = orth. clone ( ) ;
283+ let orth_clone = orth. clone ( ) ;
284+ orth. clone_from ( & orth_clone) ;
213285 }
214286 }
215287 }
@@ -235,118 +307,47 @@ where
235307 Ok ( cb)
236308}
237309
238- fn _min_cycle < H , F , K , E > (
239- subgraph : H ,
240- orth : HashSet < ( usize , usize ) > ,
241- mut weight_fn : F ,
242- ) -> Result < Vec < ( usize , usize ) > , E >
310+ pub fn minimal_cycle_basis < G , F , K , E > ( graph : G , mut weight_fn : F ) -> Result < Vec < Vec < NodeIndex > > , E >
243311where
244- H : IntoNodeReferences + IntoEdgeReferences + DataMap + NodeIndexable + EdgeIndexable ,
245- H :: NodeId : Eq + Hash ,
246- F : FnMut ( H :: EdgeRef ) -> Result < K , E > ,
312+ G : EdgeCount
313+ + IntoNodeIdentifiers
314+ + NodeIndexable
315+ + EdgeIndexable
316+ + DataMap
317+ + GraphProp
318+ + IntoNeighborsDirected
319+ + Visitable
320+ + IntoEdges ,
321+ G :: EdgeWeight : Clone ,
322+ G :: NodeId : Eq + Hash ,
323+ F : FnMut ( G :: EdgeRef ) -> Result < K , E > ,
247324 K : Clone + PartialOrd + Copy + Measure + Default ,
248325{
249- let mut gi = Graph :: < _ , _ , petgraph:: Undirected > :: default ( ) ;
250- let mut subgraph_gi_map = HashMap :: new ( ) ;
251- let mut gi_subgraph_map = HashMap :: new ( ) ;
252- for node in subgraph. node_identifiers ( ) {
253- let gi_node = gi. add_node ( node) ;
254- let gi_lifted_node = gi. add_node ( node) ;
255- gi_subgraph_map. insert ( gi_node, node) ;
256- gi_subgraph_map. insert ( gi_lifted_node, node) ;
257- subgraph_gi_map. insert ( node, ( gi_node, gi_lifted_node) ) ;
258- }
259- // # Add 2 copies of each edge in G to Gi.
260- // # If edge is in orth, add cross edge; otherwise in-plane edge
261-
262- for edge in subgraph. edge_references ( ) {
263- let u_id = edge. source ( ) ;
264- let v_id = edge. target ( ) ;
265- let u = NodeIndexable :: to_index ( & subgraph, u_id) ;
266- let v = NodeIndexable :: to_index ( & subgraph, v_id) ;
267- let edge_cost = Some ( weight_fn ( edge) ?) ;
268- let weight = edge_cost. clone ( ) . unwrap ( ) ;
269- // For each pair of (u, v) from the subgraph, there is a corresponding double pair of (u_node, v_node) and (u_lifted_node, v_lifted_node) in the gi
270- let ( u_node, u_lifted_node) = subgraph_gi_map[ & u_id] ;
271- let ( v_node, v_lifted_node) = subgraph_gi_map[ & v_id] ;
272- if orth. contains ( & ( u, v) ) || orth. contains ( & ( v, u) ) {
273- // Add cross edges with weight
274- gi. add_edge ( u_node, v_lifted_node, weight) ;
275- gi. add_edge ( u_lifted_node, v_node, weight) ;
276- } else {
277- // Add in-plane edges with weight
278- gi. add_edge ( u_node, v_node, weight) ;
279- gi. add_edge ( u_lifted_node, v_lifted_node, weight) ;
280- }
281- }
282- // Instead of finding the shortest path between each node and its lifted node, store the shortest paths in a list to find the shortest paths among them
283- let mut shortest_path_map: HashMap < H :: NodeId , K > = HashMap :: new ( ) ;
284- for subnodeid in subgraph. node_identifiers ( ) {
285- let ( gi_nodeidx, gi_lifted_nodeidx) = subgraph_gi_map[ & subnodeid] ;
286-
287- let result: Result < DictMap < NodeIndex , K > > = dijkstra (
288- & gi,
289- gi_nodeidx,
290- Some ( gi_lifted_nodeidx) ,
291- |edge| Ok ( * edge. weight ( ) ) ,
292- None ,
293- ) ;
294- let spl = result. unwrap ( ) [ & gi_lifted_nodeidx] ;
295- shortest_path_map. insert ( subnodeid, spl) ;
296- }
297- let min_start = shortest_path_map
298- . iter ( )
299- . min_by ( |a, b| a. 1 . partial_cmp ( b. 1 ) . unwrap_or ( Ordering :: Equal ) )
300- . unwrap ( )
301- . 0 ;
302- let min_start_node = subgraph_gi_map[ min_start] . 0 ;
303- let min_start_lifted_node = subgraph_gi_map[ min_start] . 1 ;
304- let result: Result < Option < ( K , Vec < NodeIndex > ) > > = astar (
305- & gi,
306- min_start_node. clone ( ) ,
307- |finish| Ok ( finish == min_start_lifted_node. clone ( ) ) ,
308- |e| Ok ( * e. weight ( ) ) ,
309- |_| Ok ( K :: default ( ) ) ,
310- ) ;
311-
312- let mut min_path: Vec < usize > = Vec :: new ( ) ;
313- match result {
314- Ok ( Some ( ( _cost, path) ) ) => {
315- for node in path {
316- if let Some ( & subgraph_nodeid) = gi_subgraph_map. get ( & node) {
317- let subgraph_node = NodeIndexable :: to_index ( & subgraph, subgraph_nodeid) ;
318- min_path. push ( subgraph_node. index ( ) ) ;
326+ let conn_components = connected_components ( & graph) ;
327+ let mut min_cycle_basis = Vec :: new ( ) ;
328+ let subgraphs_with_maps =
329+ create_subgraphs_from_components ( & graph, conn_components, & mut weight_fn) ?;
330+ // Convert weight_fn to a closure that takes a subgraph edge and returns the weight of the original graph edge
331+ for ( subgraph, node_subnode_map, edge_subedge_map) in subgraphs_with_maps {
332+ // Find the key of edge_subedge_map that corresponds to the value e.id()
333+ let mut subgraph_weight_fn = |e : <& Graph < usize , K , Undirected , DefaultIx > as IntoEdgeReferences >:: EdgeRef | -> Result < K , Infallible > {
334+ // use the edge_subedge_map to find the key that corresponds to the value e.id()
335+ let edge = edge_subedge_map. iter ( ) . find ( |( _key, & value) | value == e. id ( ) ) . unwrap ( ) . 0 ;
336+ match weight_fn (
337+ graph. edge_references ( ) . nth ( * edge) . unwrap ( ) ,
338+ ) {
339+ Ok ( weight) => Ok ( weight) ,
340+ Err ( _) => {
341+ // Handle the error here. Since the error type is Infallible, this branch should never be reached.
342+ unreachable ! ( )
319343 }
320344 }
321- }
322- Ok ( None ) => { }
323- Err ( _) => { }
324- }
325- let edgelist = min_path
326- . windows ( 2 )
327- . map ( |w| ( w[ 0 ] , w[ 1 ] ) )
328- . collect :: < Vec < _ > > ( ) ;
329- let mut edgeset: HashSet < ( usize , usize ) > = HashSet :: new ( ) ;
330- for e in edgelist. iter ( ) {
331- if edgeset. contains ( e) {
332- edgeset. remove ( e) ;
333- } else if edgeset. contains ( & ( e. 1 , e. 0 ) ) {
334- edgeset. remove ( & ( e. 1 , e. 0 ) ) ;
335- } else {
336- edgeset. insert ( * e) ;
337- }
338- }
339- let mut min_edgelist: Vec < ( usize , usize ) > = Vec :: new ( ) ;
340- for e in edgelist. iter ( ) {
341- if edgeset. contains ( e) {
342- min_edgelist. push ( * e) ;
343- edgeset. remove ( e) ;
344- } else if edgeset. contains ( & ( e. 1 , e. 0 ) ) {
345- min_edgelist. push ( ( e. 1 , e. 0 ) ) ;
346- edgeset. remove ( & ( e. 1 , e. 0 ) ) ;
347- }
345+ } ;
346+ let num_cycles: Result < Vec < Vec < NodeIndex > > , Infallible > =
347+ _min_cycle_basis ( & subgraph, & mut subgraph_weight_fn, & node_subnode_map) ;
348+ min_cycle_basis. extend ( num_cycles. unwrap ( ) ) ;
348349 }
349- Ok ( min_edgelist )
350+ Ok ( min_cycle_basis )
350351}
351352
352353#[ cfg( test) ]
0 commit comments