@@ -41,9 +41,6 @@ use std::collections::VecDeque;
41
41
#[ cfg( feature = "copious-debugging" ) ]
42
42
use std:: fmt:: Display ;
43
43
44
- use itertools:: izip;
45
- use itertools:: Itertools ;
46
-
47
44
use crate :: arena:: Arena ;
48
45
use crate :: arena:: Handle ;
49
46
use crate :: arena:: HandleSet ;
@@ -763,17 +760,13 @@ impl<'a> Display for DisplaySymbolStackKey<'a> {
763
760
pub struct ForwardPartialPathStitcher < H > {
764
761
candidates : Vec < H > ,
765
762
extensions : Vec < ( PartialPath , AppendingCycleDetector < H > ) > ,
766
- queue : VecDeque < ( PartialPath , AppendingCycleDetector < H > , bool ) > ,
763
+ queue : VecDeque < ( PartialPath , PathStitchingState < H > ) > ,
767
764
// tracks the number of initial paths in the queue because we do not want call
768
765
// extend_until on those
769
766
initial_paths : usize ,
770
767
// next_iteration is a tuple of queues instead of an queue of tuples so that the path queue
771
768
// can be cheaply exposed through the C API as a continuous memory block
772
- next_iteration : (
773
- VecDeque < PartialPath > ,
774
- VecDeque < AppendingCycleDetector < H > > ,
775
- VecDeque < bool > ,
776
- ) ,
769
+ next_iteration : ( VecDeque < PartialPath > , VecDeque < PathStitchingState < H > > ) ,
777
770
appended_paths : Appendables < H > ,
778
771
similar_path_detector : Option < SimilarPathDetector < PartialPath > > ,
779
772
check_only_join_nodes : bool ,
@@ -782,40 +775,83 @@ pub struct ForwardPartialPathStitcher<H> {
782
775
phase_number : usize ,
783
776
}
784
777
778
+ struct PathStitchingState < H > {
779
+ cycle_detector : AppendingCycleDetector < H > ,
780
+ has_split : bool ,
781
+ }
782
+
783
+ impl < H > Default for ForwardPartialPathStitcher < H > {
784
+ fn default ( ) -> Self {
785
+ Self {
786
+ candidates : Vec :: new ( ) ,
787
+ extensions : Vec :: new ( ) ,
788
+ queue : VecDeque :: new ( ) ,
789
+ initial_paths : 0 ,
790
+ next_iteration : ( VecDeque :: new ( ) , VecDeque :: new ( ) ) ,
791
+ appended_paths : Appendables :: new ( ) ,
792
+ similar_path_detector : Some ( SimilarPathDetector :: new ( ) ) ,
793
+ // By default, all nodes are checked for cycles and (if enabled) similarity
794
+ check_only_join_nodes : false ,
795
+ // By default, there's no artificial bound on the amount of work done per phase
796
+ max_work_per_phase : usize:: MAX ,
797
+ #[ cfg( feature = "copious-debugging" ) ]
798
+ phase_number : 1 ,
799
+ }
800
+ }
801
+ }
802
+
785
803
impl < H > ForwardPartialPathStitcher < H > {
786
804
/// Creates a new forward partial path stitcher that is "seeded" with a set of initial partial
787
805
/// paths. If the sticher is used to find complete paths, it is the responsibility of the caller
788
806
/// to ensure precondition variables are eliminated by calling [`PartialPath::eliminate_precondition_stack_variables`][].
789
807
pub fn from_partial_paths < I > (
790
- _graph : & StackGraph ,
791
- _partials : & mut PartialPaths ,
808
+ graph : & StackGraph ,
809
+ partials : & mut PartialPaths ,
792
810
initial_partial_paths : I ,
793
811
) -> Self
794
812
where
795
813
I : IntoIterator < Item = PartialPath > ,
796
814
{
797
- let mut appended_paths = Appendables :: new ( ) ;
798
- let next_iteration: ( VecDeque < _ > , VecDeque < _ > , VecDeque < _ > ) = initial_partial_paths
815
+ let mut result = Self :: default ( ) ;
816
+ result. reset ( graph, partials, initial_partial_paths) ;
817
+ result
818
+ }
819
+
820
+ pub fn reset < I > (
821
+ & mut self ,
822
+ _graph : & StackGraph ,
823
+ _partials : & mut PartialPaths ,
824
+ initial_partial_paths : I ,
825
+ ) where
826
+ I : IntoIterator < Item = PartialPath > ,
827
+ {
828
+ self . appended_paths . clear ( ) ;
829
+ self . next_iteration = initial_partial_paths
799
830
. into_iter ( )
800
831
. map ( |p| {
801
- let c = AppendingCycleDetector :: from ( & mut appended_paths, p. clone ( ) . into ( ) ) ;
802
- ( p, c, false )
832
+ let cycle_detector =
833
+ AppendingCycleDetector :: from ( & mut self . appended_paths , p. clone ( ) . into ( ) ) ;
834
+ (
835
+ p,
836
+ PathStitchingState {
837
+ cycle_detector,
838
+ has_split : false ,
839
+ } ,
840
+ )
803
841
} )
804
- . multiunzip ( ) ;
805
- Self {
806
- candidates : Vec :: new ( ) ,
807
- extensions : Vec :: new ( ) ,
808
- queue : VecDeque :: new ( ) ,
809
- initial_paths : next_iteration. 0 . len ( ) ,
810
- next_iteration,
811
- appended_paths,
812
- similar_path_detector : Some ( SimilarPathDetector :: new ( ) ) ,
813
- // By default, all nodes are checked for cycles and (if enabled) similarity
814
- check_only_join_nodes : false ,
815
- // By default, there's no artificial bound on the amount of work done per phase
816
- max_work_per_phase : usize:: MAX ,
817
- #[ cfg( feature = "copious-debugging" ) ]
818
- phase_number : 1 ,
842
+ . unzip ( ) ;
843
+ self . initial_paths = self . next_iteration . 0 . len ( ) ;
844
+ self . candidates . clear ( ) ;
845
+ self . extensions . clear ( ) ;
846
+ self . queue . clear ( ) ;
847
+ if let Some ( similar_path_detector) = & mut self . similar_path_detector {
848
+ similar_path_detector. clear ( ) ;
849
+ }
850
+ // keep self.check_only_join_nodes
851
+ // keep self.max_work_per_phase
852
+ #[ cfg( feature = "copious-debugging" ) ]
853
+ {
854
+ self . phase_number = 1 ;
819
855
}
820
856
}
821
857
}
@@ -952,7 +988,6 @@ impl<H: Clone> ForwardPartialPathStitcher<H> {
952
988
let new_has_split = has_split || self . extensions . len ( ) > 1 ;
953
989
self . next_iteration . 0 . reserve ( extension_count) ;
954
990
self . next_iteration . 1 . reserve ( extension_count) ;
955
- self . next_iteration . 2 . reserve ( extension_count) ;
956
991
for ( new_partial_path, new_cycle_detector) in self . extensions . drain ( ..) {
957
992
let check_similar_path = new_has_split
958
993
&& ( !self . check_only_join_nodes
@@ -990,8 +1025,10 @@ impl<H: Clone> ForwardPartialPathStitcher<H> {
990
1025
}
991
1026
992
1027
self . next_iteration . 0 . push ( new_partial_path) ;
993
- self . next_iteration . 1 . push ( new_cycle_detector) ;
994
- self . next_iteration . 2 . push ( new_has_split) ;
1028
+ self . next_iteration . 1 . push ( PathStitchingState {
1029
+ cycle_detector : new_cycle_detector,
1030
+ has_split : new_has_split,
1031
+ } ) ;
995
1032
}
996
1033
997
1034
candidate_count
@@ -1022,13 +1059,21 @@ impl<H: Clone> ForwardPartialPathStitcher<H> {
1022
1059
E : Fn ( & StackGraph , & mut PartialPaths , & PartialPath ) -> bool ,
1023
1060
{
1024
1061
copious_debugging ! ( "==> Start phase {}" , self . phase_number) ;
1025
- self . queue . extend ( izip ! (
1026
- self . next_iteration. 0 . drain( ..) ,
1027
- self . next_iteration. 1 . drain( ..) ,
1028
- self . next_iteration. 2 . drain( ..) ,
1029
- ) ) ;
1062
+ self . queue . extend (
1063
+ self . next_iteration
1064
+ . 0
1065
+ . drain ( ..)
1066
+ . zip ( self . next_iteration . 1 . drain ( ..) ) ,
1067
+ ) ;
1030
1068
let mut work_performed = 0 ;
1031
- while let Some ( ( partial_path, cycle_detector, has_split) ) = self . queue . pop_front ( ) {
1069
+ while let Some ( (
1070
+ partial_path,
1071
+ PathStitchingState {
1072
+ cycle_detector,
1073
+ has_split,
1074
+ } ,
1075
+ ) ) = self . queue . pop_front ( )
1076
+ {
1032
1077
let ( graph, partials, _) = candidates. get_graph_partials_and_db ( ) ;
1033
1078
copious_debugging ! (
1034
1079
"--> Candidate partial path {}" ,
@@ -1101,18 +1146,22 @@ impl ForwardPartialPathStitcher<Edge> {
1101
1146
. filter ( |node| graph[ * node] . is_endpoint ( ) )
1102
1147
. map ( |node| PartialPath :: from_node ( graph, partials, node) )
1103
1148
. collect :: < Vec < _ > > ( ) ;
1104
- let mut stitcher =
1105
- ForwardPartialPathStitcher :: from_partial_paths ( graph , partials , initial_paths ) ;
1149
+
1150
+ let mut stitcher = ForwardPartialPathStitcher :: default ( ) ;
1106
1151
stitcher. set_check_only_join_nodes ( true ) ;
1107
- while !stitcher. is_complete ( ) {
1108
- cancellation_flag. check ( "finding complete partial paths" ) ?;
1109
- stitcher. process_next_phase (
1110
- & mut GraphEdgeCandidates :: new ( graph, partials, Some ( file) ) ,
1111
- |g, _ps, p| !as_complete_as_necessary ( g, p) ,
1112
- ) ;
1113
- for path in stitcher. previous_phase_partial_paths ( ) {
1114
- if as_complete_as_necessary ( graph, path) {
1115
- visit ( graph, partials, path) ;
1152
+
1153
+ for initial_path in initial_paths {
1154
+ stitcher. reset ( graph, partials, std:: iter:: once ( initial_path) ) ;
1155
+ while !stitcher. is_complete ( ) {
1156
+ cancellation_flag. check ( "finding complete partial paths" ) ?;
1157
+ stitcher. process_next_phase (
1158
+ & mut GraphEdgeCandidates :: new ( graph, partials, Some ( file) ) ,
1159
+ |g, _ps, p| !as_complete_as_necessary ( g, p) ,
1160
+ ) ;
1161
+ for path in stitcher. previous_phase_partial_paths ( ) {
1162
+ if as_complete_as_necessary ( graph, path) {
1163
+ visit ( graph, partials, path) ;
1164
+ }
1116
1165
}
1117
1166
}
1118
1167
}
@@ -1146,33 +1195,38 @@ impl<H: Clone> ForwardPartialPathStitcher<H> {
1146
1195
F : FnMut ( & StackGraph , & mut PartialPaths , & PartialPath ) ,
1147
1196
Err : std:: convert:: From < CancellationError > ,
1148
1197
{
1149
- let mut stitcher = {
1150
- let ( graph, partials, _) = candidates. get_graph_partials_and_db ( ) ;
1151
- let initial_paths = starting_nodes
1152
- . into_iter ( )
1153
- . filter ( |n| graph[ * n] . is_reference ( ) )
1154
- . map ( |n| {
1155
- let mut p = PartialPath :: from_node ( graph, partials, n) ;
1156
- p. eliminate_precondition_stack_variables ( partials) ;
1157
- p
1158
- } )
1159
- . collect :: < Vec < _ > > ( ) ;
1160
- ForwardPartialPathStitcher :: from_partial_paths ( graph, partials, initial_paths)
1161
- } ;
1198
+ let ( graph, partials, _) = candidates. get_graph_partials_and_db ( ) ;
1199
+ let initial_paths = starting_nodes
1200
+ . into_iter ( )
1201
+ . filter ( |n| graph[ * n] . is_reference ( ) )
1202
+ . map ( |n| {
1203
+ let mut p = PartialPath :: from_node ( graph, partials, n) ;
1204
+ p. eliminate_precondition_stack_variables ( partials) ;
1205
+ p
1206
+ } )
1207
+ . collect :: < Vec < _ > > ( ) ;
1208
+
1209
+ let mut stitcher = ForwardPartialPathStitcher :: default ( ) ;
1162
1210
stitcher. set_check_only_join_nodes ( true ) ;
1163
- while !stitcher. is_complete ( ) {
1164
- cancellation_flag. check ( "finding complete partial paths" ) ?;
1165
- for path in stitcher. previous_phase_partial_paths ( ) {
1166
- candidates. load_forward_candidates ( path, cancellation_flag) ?;
1167
- }
1168
- stitcher. process_next_phase ( candidates, |_, _, _| true ) ;
1211
+
1212
+ for initial_path in initial_paths {
1169
1213
let ( graph, partials, _) = candidates. get_graph_partials_and_db ( ) ;
1170
- for path in stitcher. previous_phase_partial_paths ( ) {
1171
- if path. is_complete ( graph) {
1172
- visit ( graph, partials, path) ;
1214
+ stitcher. reset ( graph, partials, std:: iter:: once ( initial_path) ) ;
1215
+ while !stitcher. is_complete ( ) {
1216
+ cancellation_flag. check ( "finding complete partial paths" ) ?;
1217
+ for path in stitcher. previous_phase_partial_paths ( ) {
1218
+ candidates. load_forward_candidates ( path, cancellation_flag) ?;
1219
+ }
1220
+ stitcher. process_next_phase ( candidates, |_, _, _| true ) ;
1221
+ let ( graph, partials, _) = candidates. get_graph_partials_and_db ( ) ;
1222
+ for path in stitcher. previous_phase_partial_paths ( ) {
1223
+ if path. is_complete ( graph) {
1224
+ visit ( graph, partials, path) ;
1225
+ }
1173
1226
}
1174
1227
}
1175
1228
}
1229
+
1176
1230
Ok ( ( ) )
1177
1231
}
1178
1232
}
0 commit comments