@@ -129,20 +129,31 @@ public Iterator<Object> iterator(Object entity) {
129
129
@ Override
130
130
public Iterator <Object > iterator () {
131
131
if (randomSelection ) {
132
- return new RandomFilteringValueRangeIterator (replayingValueSelector .iterator (), listVariableStateSupply ,
133
- reachableValues , workingRandom , (int ) getSize (), checkSourceAndDestination , true );
132
+ // If the nonReplayingValueSelector does not have any additional configuration,
133
+ // we can bypass it and only use reachable values,
134
+ // which helps optimize the number of evaluations.
135
+ // However, if the nonReplayingValueSelector includes custom configurations,
136
+ // such as filtering,
137
+ // we will first evaluate its values and then filter out those that are not reachable.
138
+ if (nonReplayingValueSelector instanceof IterableFromEntityPropertyValueSelector <Solution_ >) {
139
+ return new OptimizedRandomFilteringValueRangeIterator (replayingValueSelector .iterator (),
140
+ listVariableStateSupply ,
141
+ reachableValues , workingRandom , (int ) getSize (), checkSourceAndDestination );
142
+ } else {
143
+ return new RandomFilteringValueRangeIterator (replayingValueSelector .iterator (),
144
+ nonReplayingValueSelector .iterator (), listVariableStateSupply , reachableValues , (int ) getSize (),
145
+ checkSourceAndDestination );
146
+ }
134
147
} else {
135
148
return new OriginalFilteringValueRangeIterator (replayingValueSelector .iterator (),
136
- nonReplayingValueSelector .iterator (), listVariableStateSupply , reachableValues , checkSourceAndDestination ,
137
- false );
149
+ nonReplayingValueSelector .iterator (), listVariableStateSupply , reachableValues , checkSourceAndDestination );
138
150
}
139
151
}
140
152
141
153
@ Override
142
154
public Iterator <Object > endingIterator (Object entity ) {
143
155
return new OriginalFilteringValueRangeIterator (replayingValueSelector .iterator (),
144
- nonReplayingValueSelector .iterator (), listVariableStateSupply , reachableValues , checkSourceAndDestination ,
145
- false );
156
+ nonReplayingValueSelector .iterator (), listVariableStateSupply , reachableValues , checkSourceAndDestination );
146
157
}
147
158
148
159
@ Override
@@ -258,7 +269,7 @@ boolean isValueOrEntityReachable(Object destinationValue) {
258
269
private class OriginalFilteringValueRangeIterator extends AbstractFilteringValueRangeIterator {
259
270
// The value iterator that only replays the current selected value
260
271
private final Iterator <Object > replayingValueIterator ;
261
- // The value iterator returns all possible values based on its settings.
272
+ // The value iterator returns all possible values based on the outer selector settings.
262
273
// However,
263
274
// it may include invalid values that need to be filtered out.
264
275
// This iterator must be used to ensure that all positions are included in the CH phase.
@@ -267,8 +278,8 @@ private class OriginalFilteringValueRangeIterator extends AbstractFilteringValue
267
278
268
279
private OriginalFilteringValueRangeIterator (Iterator <Object > replayingValueIterator , Iterator <Object > valueIterator ,
269
280
ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
270
- boolean checkSourceAndDestination , boolean useValueList ) {
271
- super (listVariableStateSupply , reachableValues , checkSourceAndDestination , useValueList );
281
+ boolean checkSourceAndDestination ) {
282
+ super (listVariableStateSupply , reachableValues , checkSourceAndDestination , false );
272
283
this .replayingValueIterator = replayingValueIterator ;
273
284
this .valueIterator = valueIterator ;
274
285
}
@@ -307,15 +318,71 @@ protected Object createUpcomingSelection() {
307
318
}
308
319
309
320
private class RandomFilteringValueRangeIterator extends AbstractFilteringValueRangeIterator {
321
+ // The value iterator that only replays the current selected value
322
+ private final Iterator <Object > replayingValueIterator ;
323
+ // The value iterator returns all possible values based on the outer selector settings.
324
+ private final Iterator <Object > valueIterator ;
325
+ private final int maxBailoutSize ;
326
+
327
+ private RandomFilteringValueRangeIterator (Iterator <Object > replayingValueIterator , Iterator <Object > valueIterator ,
328
+ ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
329
+ int maxBailoutSize , boolean checkSourceAndDestination ) {
330
+ super (listVariableStateSupply , reachableValues , checkSourceAndDestination , false );
331
+ this .replayingValueIterator = replayingValueIterator ;
332
+ this .valueIterator = valueIterator ;
333
+ this .maxBailoutSize = maxBailoutSize ;
334
+ }
335
+
336
+ private void initialize () {
337
+ if (initialized ) {
338
+ return ;
339
+ }
340
+ if (replayingValueIterator .hasNext ()) {
341
+ var upcomingValue = replayingValueIterator .next ();
342
+ if (!valueIterator .hasNext ()) {
343
+ noData ();
344
+ } else {
345
+ loadValues (Objects .requireNonNull (upcomingValue ));
346
+ }
347
+ } else {
348
+ noData ();
349
+ }
350
+ }
351
+
352
+ @ Override
353
+ protected Object createUpcomingSelection () {
354
+ initialize ();
355
+ if (!hasData ) {
356
+ return noUpcomingSelection ();
357
+ }
358
+ Object next ;
359
+ var bailoutSize = maxBailoutSize ;
360
+ do {
361
+ if (bailoutSize <= 0 || !valueIterator .hasNext ()) {
362
+ return noUpcomingSelection ();
363
+ }
364
+ bailoutSize --;
365
+ next = valueIterator .next ();
366
+ } while (!isValueOrEntityReachable (next ));
367
+ return next ;
368
+ }
369
+ }
370
+
371
+ /**
372
+ * The optimized iterator only traverses reachable values from the current selection.
373
+ * Unlike {@link RandomFilteringValueRangeIterator},
374
+ * it does not use an outer iterator to filter out non-reachable values.
375
+ */
376
+ private class OptimizedRandomFilteringValueRangeIterator extends AbstractFilteringValueRangeIterator {
310
377
311
378
private final Iterator <Object > replayingValueIterator ;
312
379
private final Random workingRandom ;
313
380
private final int maxBailoutSize ;
314
381
315
- private RandomFilteringValueRangeIterator (Iterator <Object > replayingValueIterator ,
382
+ private OptimizedRandomFilteringValueRangeIterator (Iterator <Object > replayingValueIterator ,
316
383
ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
317
- Random workingRandom , int maxBailoutSize , boolean checkSourceAndDestination , boolean useValueList ) {
318
- super (listVariableStateSupply , reachableValues , checkSourceAndDestination , useValueList );
384
+ Random workingRandom , int maxBailoutSize , boolean checkSourceAndDestination ) {
385
+ super (listVariableStateSupply , reachableValues , checkSourceAndDestination , true );
319
386
this .replayingValueIterator = replayingValueIterator ;
320
387
this .workingRandom = workingRandom ;
321
388
this .maxBailoutSize = maxBailoutSize ;
0 commit comments