11package ai .timefold .solver .core .impl .bavet .common ;
22
3+ import ai .timefold .solver .core .impl .bavet .common .index .IndexedSet ;
34import ai .timefold .solver .core .impl .bavet .common .tuple .AbstractTuple ;
45import ai .timefold .solver .core .impl .bavet .common .tuple .TupleLifecycle ;
56import ai .timefold .solver .core .impl .bavet .common .tuple .TupleState ;
7+ import ai .timefold .solver .core .impl .bavet .common .tuple .TupleStorePositionTracker ;
68import ai .timefold .solver .core .impl .bavet .common .tuple .UniTuple ;
7- import ai .timefold .solver .core .impl .util .ElementAwareList ;
8- import ai .timefold .solver .core .impl .util .ElementAwareListEntry ;
99
1010/**
1111 * This class has two direct children: {@link AbstractIndexedIfExistsNode} and {@link AbstractUnindexedIfExistsNode}.
@@ -20,20 +20,17 @@ public abstract class AbstractIfExistsNode<LeftTuple_ extends AbstractTuple, Rig
2020 extends AbstractTwoInputNode <LeftTuple_ , UniTuple <Right_ >> {
2121
2222 protected final boolean shouldExist ;
23-
24- protected final int inputStoreIndexLeftTrackerList ; // -1 if !isFiltering
25- protected final int inputStoreIndexRightTrackerList ; // -1 if !isFiltering
26-
23+ protected final int inputStoreIndexLeftTrackerSet ; // -1 if !isFiltering
24+ protected final int inputStoreIndexRightTrackerSet ; // -1 if !isFiltering
2725 protected final boolean isFiltering ;
2826 private final DynamicPropagationQueue <LeftTuple_ , ExistsCounter <LeftTuple_ >> propagationQueue ;
2927
30- protected AbstractIfExistsNode (boolean shouldExist ,
31- int inputStoreIndexLeftTrackerList , int inputStoreIndexRightTrackerList ,
32- TupleLifecycle <LeftTuple_ > nextNodesTupleLifecycle ,
28+ protected AbstractIfExistsNode (boolean shouldExist , TupleStorePositionTracker leftTupleStorePositionTracker ,
29+ TupleStorePositionTracker rightTupleStorePositionTracker , TupleLifecycle <LeftTuple_ > nextNodesTupleLifecycle ,
3330 boolean isFiltering ) {
3431 this .shouldExist = shouldExist ;
35- this .inputStoreIndexLeftTrackerList = inputStoreIndexLeftTrackerList ;
36- this .inputStoreIndexRightTrackerList = inputStoreIndexRightTrackerList ;
32+ this .inputStoreIndexLeftTrackerSet = isFiltering ? leftTupleStorePositionTracker . reserveNextAvailablePosition () : - 1 ;
33+ this .inputStoreIndexRightTrackerSet = isFiltering ? rightTupleStorePositionTracker . reserveNextAvailablePosition () : - 1 ;
3734 this .isFiltering = isFiltering ;
3835 this .propagationQueue = new DynamicPropagationQueue <>(nextNodesTupleLifecycle );
3936 }
@@ -66,8 +63,9 @@ protected void updateCounterLeft(ExistsCounter<LeftTuple_> counter) {
6663 }
6764 case OK , DYING -> propagationQueue .update (counter );
6865 case DEAD , ABORTING -> propagationQueue .insert (counter );
69- default -> throw new IllegalStateException ("Impossible state: the counter (" + counter
70- + ") has an impossible insert state (" + state + ")." );
66+ default ->
67+ throw new IllegalStateException ("Impossible state: the counter (%s) has an impossible insert state (%s)."
68+ .formatted (counter , state ));
7169 }
7270 } else {
7371 // Retract or remain dead
@@ -80,8 +78,9 @@ protected void updateCounterLeft(ExistsCounter<LeftTuple_> counter) {
8078 propagationQueue .retract (counter , TupleState .ABORTING );
8179 case OK , UPDATING -> // Kill the original propagation.
8280 propagationQueue .retract (counter , TupleState .DYING );
83- default -> throw new IllegalStateException ("Impossible state: The counter (" + counter
84- + ") has an impossible retract state (" + state + ")." );
81+ default ->
82+ throw new IllegalStateException ("Impossible state: The counter (%s) has an impossible retract state (%s)."
83+ .formatted (counter , state ));
8584
8685 }
8786 }
@@ -115,27 +114,26 @@ protected void decrementCounterRight(ExistsCounter<LeftTuple_> counter) {
115114 } // Else do not even propagate an update
116115 }
117116
118- protected ElementAwareList < FilteringTracker <LeftTuple_ >> updateRightTrackerList (UniTuple <Right_ > rightTuple ) {
119- ElementAwareList < FilteringTracker <LeftTuple_ >> rightTrackerList = rightTuple .getStore (inputStoreIndexRightTrackerList );
120- for ( FilteringTracker < LeftTuple_ > tuple : rightTrackerList ) {
117+ IndexedSet < ExistsCounterHandle <LeftTuple_ >> updateRightTrackerSet (UniTuple <Right_ > rightTuple ) {
118+ IndexedSet < ExistsCounterHandle <LeftTuple_ >> rightTrackerSet = rightTuple .getStore (inputStoreIndexRightTrackerSet );
119+ rightTrackerSet . forEach ( tuple -> {
121120 decrementCounterRight (tuple .counter );
122121 tuple .remove ();
123- }
124- return rightTrackerList ;
122+ });
123+ return rightTrackerSet ;
125124 }
126125
127- protected void updateCounterFromLeft (LeftTuple_ leftTuple , UniTuple <Right_ > rightTuple , ExistsCounter <LeftTuple_ > counter ,
128- ElementAwareList < FilteringTracker <LeftTuple_ >> leftTrackerList ) {
126+ void updateCounterFromLeft (LeftTuple_ leftTuple , UniTuple <Right_ > rightTuple , ExistsCounter <LeftTuple_ > counter ,
127+ IndexedSet < ExistsCounterHandle <LeftTuple_ >> leftTrackerSet ) {
129128 if (testFiltering (leftTuple , rightTuple )) {
130129 counter .countRight ++;
131- ElementAwareList <FilteringTracker <LeftTuple_ >> rightTrackerList =
132- rightTuple .getStore (inputStoreIndexRightTrackerList );
133- new FilteringTracker <>(counter , leftTrackerList , rightTrackerList );
130+ IndexedSet <ExistsCounterHandle <LeftTuple_ >> rightTrackerSet = rightTuple .getStore (inputStoreIndexRightTrackerSet );
131+ new ExistsCounterHandle <>(counter , leftTrackerSet , rightTrackerSet );
134132 }
135133 }
136134
137- protected void updateCounterFromRight (UniTuple <Right_ > rightTuple , ExistsCounter <LeftTuple_ > counter ,
138- ElementAwareList < FilteringTracker <LeftTuple_ >> rightTrackerList ) {
135+ void updateCounterFromRight (UniTuple <Right_ > rightTuple , ExistsCounter <LeftTuple_ > counter ,
136+ IndexedSet < ExistsCounterHandle <LeftTuple_ >> rightTrackerSet ) {
139137 var leftTuple = counter .leftTuple ;
140138 if (!leftTuple .state .isActive ()) {
141139 // Assume the following scenario:
@@ -156,18 +154,18 @@ protected void updateCounterFromRight(UniTuple<Right_> rightTuple, ExistsCounter
156154 }
157155 if (testFiltering (counter .leftTuple , rightTuple )) {
158156 incrementCounterRight (counter );
159- ElementAwareList < FilteringTracker <LeftTuple_ >> leftTrackerList =
160- counter .leftTuple .getStore (inputStoreIndexLeftTrackerList );
161- new FilteringTracker <>(counter , leftTrackerList , rightTrackerList );
157+ IndexedSet < ExistsCounterHandle <LeftTuple_ >> leftTrackerSet =
158+ counter .leftTuple .getStore (inputStoreIndexLeftTrackerSet );
159+ new ExistsCounterHandle <>(counter , leftTrackerSet , rightTrackerSet );
162160 }
163161 }
164162
165163 private void doInsertCounter (ExistsCounter <LeftTuple_ > counter ) {
166164 switch (counter .state ) {
167165 case DYING -> propagationQueue .update (counter );
168166 case DEAD , ABORTING -> propagationQueue .insert (counter );
169- default -> throw new IllegalStateException ("Impossible state: the counter (" + counter
170- + ") has an impossible insert state (" + counter .state + ")." );
167+ default -> throw new IllegalStateException ("Impossible state: the counter (%s) has an impossible insert state (%s)."
168+ . formatted ( counter , counter .state ) );
171169 }
172170 }
173171
@@ -177,8 +175,9 @@ private void doRetractCounter(ExistsCounter<LeftTuple_> counter) {
177175 propagationQueue .retract (counter , TupleState .ABORTING );
178176 case OK , UPDATING -> // Kill the original propagation.
179177 propagationQueue .retract (counter , TupleState .DYING );
180- default -> throw new IllegalStateException ("Impossible state: The counter (" + counter
181- + ") has an impossible retract state (" + counter .state + ")." );
178+ default ->
179+ throw new IllegalStateException ("Impossible state: The counter (%s) has an impossible retract state (%s)."
180+ .formatted (counter , counter .state ));
182181 }
183182 }
184183
@@ -187,23 +186,4 @@ public Propagator getPropagator() {
187186 return propagationQueue ;
188187 }
189188
190- protected static final class FilteringTracker <LeftTuple_ extends AbstractTuple > {
191- final ExistsCounter <LeftTuple_ > counter ;
192- private final ElementAwareListEntry <FilteringTracker <LeftTuple_ >> leftTrackerEntry ;
193- private final ElementAwareListEntry <FilteringTracker <LeftTuple_ >> rightTrackerEntry ;
194-
195- FilteringTracker (ExistsCounter <LeftTuple_ > counter , ElementAwareList <FilteringTracker <LeftTuple_ >> leftTrackerList ,
196- ElementAwareList <FilteringTracker <LeftTuple_ >> rightTrackerList ) {
197- this .counter = counter ;
198- leftTrackerEntry = leftTrackerList .add (this );
199- rightTrackerEntry = rightTrackerList .add (this );
200- }
201-
202- public void remove () {
203- leftTrackerEntry .remove ();
204- rightTrackerEntry .remove ();
205- }
206-
207- }
208-
209189}
0 commit comments