@@ -76,7 +76,7 @@ public void phaseStarted(AbstractPhaseScope<Solution_> phaseScope) {
76
76
this .nonReplayingValueSelector .phaseStarted (phaseScope );
77
77
this .replayingValueSelector .phaseStarted (phaseScope );
78
78
this .reachableValues = phaseScope .getScoreDirector ().getValueRangeManager ()
79
- .getReachableValeMatrix (listVariableStateSupply .getSourceVariableDescriptor ());
79
+ .getReachableValues (listVariableStateSupply .getSourceVariableDescriptor ());
80
80
valuesSize = reachableValues .getSize ();
81
81
}
82
82
@@ -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
@@ -255,25 +266,21 @@ boolean isValueOrEntityReachable(Object destinationValue) {
255
266
}
256
267
}
257
268
258
- private class OriginalFilteringValueRangeIterator extends AbstractFilteringValueRangeIterator {
269
+ private abstract class AbstractUpcomingValueRangeIterator extends AbstractFilteringValueRangeIterator {
259
270
// The value iterator that only replays the current selected value
260
- private final Iterator <Object > replayingValueIterator ;
261
- // The value iterator returns all possible values based on its settings.
262
- // However,
263
- // it may include invalid values that need to be filtered out.
264
- // This iterator must be used to ensure that all positions are included in the CH phase.
265
- // This does not apply to the LS phase.
266
- private final Iterator <Object > valueIterator ;
271
+ final Iterator <Object > replayingValueIterator ;
272
+ // The value iterator returns all possible values based on the outer selector settings.
273
+ final Iterator <Object > valueIterator ;
267
274
268
- private OriginalFilteringValueRangeIterator (Iterator <Object > replayingValueIterator , Iterator <Object > valueIterator ,
275
+ private AbstractUpcomingValueRangeIterator (Iterator <Object > replayingValueIterator , Iterator <Object > valueIterator ,
269
276
ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
270
277
boolean checkSourceAndDestination , boolean useValueList ) {
271
278
super (listVariableStateSupply , reachableValues , checkSourceAndDestination , useValueList );
272
279
this .replayingValueIterator = replayingValueIterator ;
273
280
this .valueIterator = valueIterator ;
274
281
}
275
282
276
- private void initialize () {
283
+ void initialize () {
277
284
if (initialized ) {
278
285
return ;
279
286
}
@@ -288,6 +295,16 @@ private void initialize() {
288
295
noData ();
289
296
}
290
297
}
298
+ }
299
+
300
+ private class OriginalFilteringValueRangeIterator extends AbstractUpcomingValueRangeIterator {
301
+
302
+ private OriginalFilteringValueRangeIterator (Iterator <Object > replayingValueIterator , Iterator <Object > valueIterator ,
303
+ ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
304
+ boolean checkSourceAndDestination ) {
305
+ super (replayingValueIterator , valueIterator , listVariableStateSupply , reachableValues , checkSourceAndDestination ,
306
+ false );
307
+ }
291
308
292
309
@ Override
293
310
protected Object createUpcomingSelection () {
@@ -306,16 +323,51 @@ protected Object createUpcomingSelection() {
306
323
}
307
324
}
308
325
309
- private class RandomFilteringValueRangeIterator extends AbstractFilteringValueRangeIterator {
326
+ private class RandomFilteringValueRangeIterator extends AbstractUpcomingValueRangeIterator {
327
+ private final int maxBailoutSize ;
328
+
329
+ private RandomFilteringValueRangeIterator (Iterator <Object > replayingValueIterator , Iterator <Object > valueIterator ,
330
+ ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
331
+ int maxBailoutSize , boolean checkSourceAndDestination ) {
332
+ super (replayingValueIterator , valueIterator , listVariableStateSupply , reachableValues , checkSourceAndDestination ,
333
+ false );
334
+ this .maxBailoutSize = maxBailoutSize ;
335
+ }
336
+
337
+ @ Override
338
+ protected Object createUpcomingSelection () {
339
+ initialize ();
340
+ if (!hasData ) {
341
+ return noUpcomingSelection ();
342
+ }
343
+ Object next ;
344
+ var bailoutSize = maxBailoutSize ;
345
+ do {
346
+ if (bailoutSize <= 0 || !valueIterator .hasNext ()) {
347
+ return noUpcomingSelection ();
348
+ }
349
+ bailoutSize --;
350
+ next = valueIterator .next ();
351
+ } while (!isValueOrEntityReachable (next ));
352
+ return next ;
353
+ }
354
+ }
355
+
356
+ /**
357
+ * The optimized iterator only traverses reachable values from the current selection.
358
+ * Unlike {@link RandomFilteringValueRangeIterator},
359
+ * it does not use an outer iterator to filter out non-reachable values.
360
+ */
361
+ private class OptimizedRandomFilteringValueRangeIterator extends AbstractFilteringValueRangeIterator {
310
362
311
363
private final Iterator <Object > replayingValueIterator ;
312
364
private final Random workingRandom ;
313
365
private final int maxBailoutSize ;
314
366
315
- private RandomFilteringValueRangeIterator (Iterator <Object > replayingValueIterator ,
367
+ private OptimizedRandomFilteringValueRangeIterator (Iterator <Object > replayingValueIterator ,
316
368
ListVariableStateSupply <Solution_ > listVariableStateSupply , ReachableValues reachableValues ,
317
- Random workingRandom , int maxBailoutSize , boolean checkSourceAndDestination , boolean useValueList ) {
318
- super (listVariableStateSupply , reachableValues , checkSourceAndDestination , useValueList );
369
+ Random workingRandom , int maxBailoutSize , boolean checkSourceAndDestination ) {
370
+ super (listVariableStateSupply , reachableValues , checkSourceAndDestination , true );
319
371
this .replayingValueIterator = replayingValueIterator ;
320
372
this .workingRandom = workingRandom ;
321
373
this .maxBailoutSize = maxBailoutSize ;
0 commit comments