@@ -9,7 +9,6 @@ use std::{
99} ;
1010
1111use cause:: ModelUpdateCause ;
12- use itertools:: Itertools ;
1312
1413use crate :: {
1514 backtrack:: { Backtrack , DecLvl , ObsTrailCursor } ,
@@ -39,8 +38,8 @@ pub struct AltEqTheory {
3938 enabled_graph : DirectedEqualityGraph ,
4039 /// A cursor that lets us track new events since last propagation
4140 model_events : ObsTrailCursor < ModelEvent > ,
42- /// A temporary vec of newly created, unpropagated constraints
43- new_constraints : VecDeque < ActivationEvent > ,
41+ /// A temporary vec of unpropagated constraints
42+ activation_events : VecDeque < ActivationEvent > ,
4443 identity : Identity < ModelUpdateCause > ,
4544 stats : RefCell < Stats > ,
4645}
@@ -51,7 +50,7 @@ impl AltEqTheory {
5150 constraint_store : Default :: default ( ) ,
5251 enabled_graph : DirectedEqualityGraph :: new ( ) ,
5352 model_events : Default :: default ( ) ,
54- new_constraints : Default :: default ( ) ,
53+ activation_events : Default :: default ( ) ,
5554 identity : Identity :: new ( ReasonerId :: Eq ( 0 ) ) ,
5655 stats : Default :: default ( ) ,
5756 }
@@ -100,7 +99,7 @@ impl AltEqTheory {
10099 if model. entails ( prop. enabler . valid ) && model. entails ( prop. enabler . active ) {
101100 // Propagator always active and valid, only need to propagate once
102101 // So don't add watches
103- self . new_constraints . push_back ( ActivationEvent :: new ( id) ) ;
102+ self . activation_events . push_back ( ActivationEvent :: new ( id) ) ;
104103 }
105104 }
106105 }
@@ -118,7 +117,7 @@ impl Default for AltEqTheory {
118117
119118impl Backtrack for AltEqTheory {
120119 fn save_state ( & mut self ) -> DecLvl {
121- assert ! ( self . new_constraints . is_empty( ) ) ;
120+ assert ! ( self . activation_events . is_empty( ) ) ;
122121 self . enabled_graph . save_state ( )
123122 }
124123
@@ -127,6 +126,7 @@ impl Backtrack for AltEqTheory {
127126 }
128127
129128 fn restore_last ( & mut self ) {
129+ self . activation_events . clear ( ) ;
130130 self . enabled_graph . restore_last ( ) ;
131131 }
132132}
@@ -137,11 +137,6 @@ impl Theory for AltEqTheory {
137137 }
138138
139139 fn propagate ( & mut self , model : & mut Domains ) -> Result < ( ) , Contradiction > {
140- // Propagate newly created constraints
141- while let Some ( event) = self . new_constraints . pop_front ( ) {
142- self . propagate_edge ( model, event. prop_id ) ?;
143- }
144-
145140 while let Some ( & event) = self . model_events . pop ( model. trail ( ) ) {
146141 // Optimisation: If we deactivated an edge with literal l due to a neq cycle, the propagator with literal !l (from reification) is redundant
147142 if let Some ( cause) = event. cause . as_external_inference ( ) {
@@ -152,13 +147,22 @@ impl Theory for AltEqTheory {
152147 }
153148
154149 // For each constraint which might be enabled by this event
155- for ( enabler, prop_id ) in self . constraint_store . enabled_by ( event. new_literal ( ) ) . collect_vec ( ) {
150+ for ( enabler, constraint_id ) in self . constraint_store . enabled_by ( event. new_literal ( ) ) {
156151 // Skip if not enabled
157152 if !model. entails ( enabler. active ) || !model. entails ( enabler. valid ) {
158153 continue ;
159154 }
160- self . stats ( ) . propagations += 1 ;
161- self . propagate_edge ( model, prop_id) ?;
155+ self . activation_events . push_back ( ActivationEvent :: new ( constraint_id) ) ;
156+ }
157+ }
158+
159+ // Propagate all new constraints
160+ while let Some ( event) = self . activation_events . pop_front ( ) {
161+ self . stats ( ) . propagations += 1 ;
162+ let prop_res = self . propagate_edge ( model, event. constraint_id ) ;
163+ if prop_res. is_err ( ) {
164+ self . activation_events . clear ( ) ;
165+ return prop_res;
162166 }
163167 }
164168 Ok ( ( ) )
@@ -229,7 +233,7 @@ mod tests {
229233 F : FnMut ( & mut AltEqTheory , & mut Domains ) -> T ,
230234 {
231235 assert ! (
232- eq. new_constraints . is_empty( ) ,
236+ eq. activation_events . is_empty( ) ,
233237 "Cannot test backtrack when activations pending"
234238 ) ;
235239 eq. save_state ( ) ;
0 commit comments