@@ -23,7 +23,8 @@ pub struct Memory<P: Package, V: Version> {
23
23
#[ derive( Clone ) ]
24
24
struct PackageAssignments < V : Version > {
25
25
decision : Option < ( V , Term < V > ) > ,
26
- derivations : Vec < Term < V > > ,
26
+ derivations_intersected : Term < V > ,
27
+ derivations_not_intersected_yet : Vec < Term < V > > ,
27
28
}
28
29
29
30
impl < P : Package , V : Version > Memory < P , V > {
@@ -34,12 +35,12 @@ impl<P: Package, V: Version> Memory<P, V> {
34
35
}
35
36
}
36
37
37
- /// Retrieve terms in memory related to package.
38
- pub fn terms_for_package ( & self , package : & P ) -> impl Iterator < Item = & Term < V > > {
39
- self . assignments . get ( package) . into_iter ( ) . flat_map ( |a| {
40
- let decision_iter = a . decision . iter ( ) . map ( | ( _ , term ) | term ) ;
41
- decision_iter . chain ( a . derivations . iter ( ) )
42
- } )
38
+ /// Retrieve intersection of terms in memory related to package.
39
+ pub fn term_intersection_for_package ( & mut self , package : & P ) -> Term < V > {
40
+ match self . assignments . get_mut ( package) {
41
+ None => Term :: any ( ) ,
42
+ Some ( pa ) => pa . assignment_intersection ( ) ,
43
+ }
43
44
}
44
45
45
46
/// Building step of a Memory from a given assignment.
@@ -72,7 +73,7 @@ impl<P: Package, V: Version> Memory<P, V> {
72
73
. assignments
73
74
. entry ( package)
74
75
. or_insert ( PackageAssignments :: new ( ) ) ;
75
- pa. derivations . push ( term) ;
76
+ pa. derivations_not_intersected_yet . push ( term) ;
76
77
}
77
78
78
79
/// Extract all packages that may potentially be picked next
@@ -81,26 +82,10 @@ impl<P: Package, V: Version> Memory<P, V> {
81
82
/// selected version (no "decision")
82
83
/// and if it contains at least one positive derivation term
83
84
/// in the partial solution.
84
- pub fn potential_packages ( & self ) -> impl Iterator < Item = ( & P , & [ Term < V > ] ) > {
85
+ pub fn potential_packages ( & mut self ) -> impl Iterator < Item = ( & P , & Term < V > ) > {
85
86
self . assignments
86
- . iter ( )
87
- . filter_map ( |( p, pa) | Self :: potential_package_filter ( p, pa) )
88
- }
89
-
90
- fn potential_package_filter < ' a , ' b > (
91
- package : & ' a P ,
92
- package_assignments : & ' b PackageAssignments < V > ,
93
- ) -> Option < ( & ' a P , & ' b [ Term < V > ] ) > {
94
- if & package_assignments. decision == & None
95
- && package_assignments
96
- . derivations
97
- . iter ( )
98
- . any ( |t| t. is_positive ( ) )
99
- {
100
- Some ( ( package, package_assignments. derivations . as_slice ( ) ) )
101
- } else {
102
- None
103
- }
87
+ . iter_mut ( )
88
+ . filter_map ( |( p, pa) | pa. potential_package_filter ( p) )
104
89
}
105
90
106
91
/// If a partial solution has, for every positive derivation,
@@ -125,7 +110,8 @@ impl<V: Version> PackageAssignments<V> {
125
110
fn new ( ) -> Self {
126
111
Self {
127
112
decision : None ,
128
- derivations : Vec :: new ( ) ,
113
+ derivations_intersected : Term :: any ( ) ,
114
+ derivations_not_intersected_yet : Vec :: new ( ) ,
129
115
}
130
116
}
131
117
@@ -134,8 +120,55 @@ impl<V: Version> PackageAssignments<V> {
134
120
/// it's a total solution and version solving has succeeded.
135
121
fn is_valid ( & self ) -> bool {
136
122
match self . decision {
137
- None => self . derivations . iter ( ) . all ( |t| t. is_negative ( ) ) ,
123
+ None => {
124
+ self . derivations_intersected . is_negative ( )
125
+ && self
126
+ . derivations_not_intersected_yet
127
+ . iter ( )
128
+ . all ( |t| t. is_negative ( ) )
129
+ }
138
130
Some ( _) => true ,
139
131
}
140
132
}
133
+
134
+ /// Returns intersection of all assignments (decision included).
135
+ /// Mutates itself to store the intersection result.
136
+ fn assignment_intersection ( & mut self ) -> Term < V > {
137
+ self . derivation_intersection ( ) ;
138
+ match & self . decision {
139
+ None => self . derivations_intersected . clone ( ) ,
140
+ Some ( ( _, decision_term) ) => decision_term. intersection ( & self . derivations_intersected ) ,
141
+ }
142
+ }
143
+
144
+ /// Returns intersection of all derivation terms.
145
+ /// Mutates itself to store the intersection result.
146
+ fn derivation_intersection ( & mut self ) -> & Term < V > {
147
+ for derivation in self . derivations_not_intersected_yet . iter ( ) {
148
+ self . derivations_intersected = self . derivations_intersected . intersection ( derivation) ;
149
+ }
150
+ self . derivations_not_intersected_yet . clear ( ) ;
151
+ & self . derivations_intersected
152
+ }
153
+
154
+ /// A package is a potential pick if there isn't an already
155
+ /// selected version (no "decision")
156
+ /// and if it contains at least one positive derivation term
157
+ /// in the partial solution.
158
+ fn potential_package_filter < ' a , ' b , P : Package > (
159
+ & ' a mut self ,
160
+ package : & ' b P ,
161
+ ) -> Option < ( & ' b P , & ' a Term < V > ) > {
162
+ if self . decision == None
163
+ && ( self . derivations_intersected . is_positive ( )
164
+ || self
165
+ . derivations_not_intersected_yet
166
+ . iter ( )
167
+ . any ( |t| t. is_positive ( ) ) )
168
+ {
169
+ Some ( ( package, self . derivation_intersection ( ) ) )
170
+ } else {
171
+ None
172
+ }
173
+ }
141
174
}
0 commit comments