@@ -189,14 +189,14 @@ private record GroupVariableUpdaterInfo<Solution_>(
189
189
List <DeclarativeShadowVariableDescriptor <Solution_ >> sortedDeclarativeVariableDescriptors ,
190
190
List <VariableUpdaterInfo <Solution_ >> allUpdaters ,
191
191
List <VariableUpdaterInfo <Solution_ >> groupedUpdaters ,
192
- Map <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , VariableUpdaterInfo <Solution_ >>> variableToEntityToGroupUpdater ) {
192
+ Map <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , List < VariableUpdaterInfo <Solution_ > >>> variableToEntityToGroupUpdater ) {
193
193
194
194
public List <VariableUpdaterInfo <Solution_ >> getUpdatersForEntityVariable (Object entity ,
195
195
DeclarativeShadowVariableDescriptor <Solution_ > declarativeShadowVariableDescriptor ) {
196
196
if (variableToEntityToGroupUpdater .containsKey (declarativeShadowVariableDescriptor )) {
197
- var updater = variableToEntityToGroupUpdater .get (declarativeShadowVariableDescriptor ).get (entity );
198
- if (updater != null ) {
199
- return List . of ( updater ) ;
197
+ var updaters = variableToEntityToGroupUpdater .get (declarativeShadowVariableDescriptor ).get (entity );
198
+ if (updaters != null ) {
199
+ return updaters ;
200
200
}
201
201
}
202
202
for (var shadowVariableDescriptor : sortedDeclarativeVariableDescriptors ) {
@@ -225,24 +225,7 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
225
225
var groupVariables = new ArrayList <DeclarativeShadowVariableDescriptor <Solution_ >>();
226
226
groupIndexToVariables .put (0 , groupVariables );
227
227
for (var declarativeShadowVariableDescriptor : sortedDeclarativeVariableDescriptors ) {
228
- // If a @ShadowSources has a group source (i.e. "visitGroup[].arrivalTimes"),
229
- // create a new group since it must wait until all members of that group are processed
230
- var hasGroupSources = Arrays .stream (declarativeShadowVariableDescriptor .getSources ())
231
- .anyMatch (rootVariableSource -> rootVariableSource .parentVariableType () == ParentVariableType .GROUP );
232
-
233
- // If a @ShadowSources has an alignment key,
234
- // create a new group since multiple entities must be updated for this node
235
- var hasAlignmentKey = declarativeShadowVariableDescriptor .getAlignmentKeyMap () != null ;
236
-
237
- // If the previous @ShadowSources has an alignment key,
238
- // create a new group since we are updating a single entity again
239
- // NOTE: Can potentially be optimized/share a node if VariableUpdaterInfo
240
- // update each group member independently after the alignmentKey
241
- var previousHasAlignmentKey = !groupVariables .isEmpty () && groupVariables .get (0 ).getAlignmentKeyMap () != null ;
242
-
243
- if (!groupVariables .isEmpty () && (hasGroupSources
244
- || hasAlignmentKey
245
- || previousHasAlignmentKey )) {
228
+ if (shouldCreateNewGroupForVariable (declarativeShadowVariableDescriptor , groupVariables )) {
246
229
groupVariables = new ArrayList <>();
247
230
groupIndexToVariables .put (groupIndexToVariables .size (), groupVariables );
248
231
}
@@ -252,11 +235,12 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
252
235
var out = new HashMap <VariableMetaModel <Solution_ , ?, ?>, GroupVariableUpdaterInfo <Solution_ >>();
253
236
var allUpdaters = new ArrayList <VariableUpdaterInfo <Solution_ >>();
254
237
var groupedUpdaters =
255
- new HashMap <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , VariableUpdaterInfo <Solution_ >>>();
238
+ new HashMap <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , List < VariableUpdaterInfo <Solution_ > >>>();
256
239
var updaterKey = 0 ;
257
240
for (var entryKey = 0 ; entryKey < groupIndexToVariables .size (); entryKey ++) {
258
241
var entryGroupVariables = groupIndexToVariables .get (entryKey );
259
242
var updaters = new ArrayList <VariableUpdaterInfo <Solution_ >>();
243
+ var alignmentKeyToGroupIndex = new HashMap <Object , Integer >();
260
244
for (var declarativeShadowVariableDescriptor : entryGroupVariables ) {
261
245
var updater = new VariableUpdaterInfo <>(
262
246
declarativeShadowVariableDescriptor .getVariableMetaModel (),
@@ -265,31 +249,11 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
265
249
declarativeShadowVariableDescriptor .getEntityDescriptor ().getShadowVariableLoopedDescriptor (),
266
250
declarativeShadowVariableDescriptor .getMemberAccessor (),
267
251
declarativeShadowVariableDescriptor .getCalculator ()::executeGetter );
268
- if (declarativeShadowVariableDescriptor .getAlignmentKeyMap () != null ) {
269
- var alignmentKeyFunction = declarativeShadowVariableDescriptor .getAlignmentKeyMap ();
270
- var alignmentKeyToAlignedEntitiesMap = new HashMap <Object , List <Object >>();
271
- for (var entity : entities ) {
272
- if (declarativeShadowVariableDescriptor .getEntityDescriptor ().getEntityClass ().isInstance (entity )) {
273
- var alignmentKey = alignmentKeyFunction .apply (entity );
274
- alignmentKeyToAlignedEntitiesMap .computeIfAbsent (alignmentKey , k -> new ArrayList <>()).add (entity );
275
- }
276
- }
277
- for (var alignmentGroup : alignmentKeyToAlignedEntitiesMap .entrySet ()) {
278
- var updaterCopy = updater .withGroupId (updaterKey );
279
- if (alignmentGroup .getKey () == null ) {
280
- updaters .add (updaterCopy );
281
- allUpdaters .add (updaterCopy );
282
- } else {
283
- updaterCopy = updaterCopy .withGroupEntities (alignmentGroup .getValue ().toArray (new Object [0 ]));
284
- var variableUpdaterMap = groupedUpdaters .computeIfAbsent (declarativeShadowVariableDescriptor ,
285
- ignored -> new IdentityHashMap <>());
286
- for (var entity : alignmentGroup .getValue ()) {
287
- variableUpdaterMap .put (entity , updaterCopy );
288
- }
289
- }
290
- updaterKey ++;
291
- }
292
- updaterKey --; // it will be incremented again at end of the loop
252
+ if (entryGroupVariables .get (0 ).getAlignmentKeyMap () != null ) {
253
+ updaterKey = processAlignmentGroupVariableAndGetNextUpdaterKey (entities ,
254
+ declarativeShadowVariableDescriptor , entryGroupVariables , updater ,
255
+ updaterKey , updaters ,
256
+ allUpdaters , alignmentKeyToGroupIndex , groupedUpdaters );
293
257
} else {
294
258
updaters .add (updater );
295
259
allUpdaters .add (updater );
@@ -301,12 +265,72 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
301
265
for (var declarativeShadowVariableDescriptor : entryGroupVariables ) {
302
266
out .put (declarativeShadowVariableDescriptor .getVariableMetaModel (), groupVariableUpdaterInfo );
303
267
}
304
- updaterKey ++;
268
+ if (entryGroupVariables .get (0 ).getAlignmentKeyMap () == null ) {
269
+ updaterKey ++;
270
+ }
305
271
}
306
272
allUpdaters .replaceAll (updater -> updater .withGroupId (groupIndexToVariables .size ()));
307
273
return out ;
308
274
}
309
275
276
+ private static <Solution_ > boolean shouldCreateNewGroupForVariable (
277
+ DeclarativeShadowVariableDescriptor <Solution_ > declarativeShadowVariableDescriptor ,
278
+ List <DeclarativeShadowVariableDescriptor <Solution_ >> groupVariables ) {
279
+ // If a @ShadowSources has a group source (i.e. "visitGroup[].arrivalTimes"),
280
+ // create a new group since it must wait until all members of that group are processed
281
+ var hasGroupSources = Arrays .stream (declarativeShadowVariableDescriptor .getSources ())
282
+ .anyMatch (rootVariableSource -> rootVariableSource .parentVariableType () == ParentVariableType .GROUP );
283
+
284
+ // If a @ShadowSources has an alignment key,
285
+ // create a new group since multiple entities must be updated for this node
286
+ var alignmentKey = declarativeShadowVariableDescriptor .getAlignmentKeyName ();
287
+ var previousAlignmentKey = groupVariables .isEmpty () ? null : groupVariables .get (0 ).getAlignmentKeyName ();
288
+
289
+ return !groupVariables .isEmpty () && (hasGroupSources
290
+ || (alignmentKey != null && !Objects .equals (alignmentKey , previousAlignmentKey )));
291
+ }
292
+
293
+ private static <Solution_ > int processAlignmentGroupVariableAndGetNextUpdaterKey (Object [] entities ,
294
+ DeclarativeShadowVariableDescriptor <Solution_ > declarativeShadowVariableDescriptor ,
295
+ List <DeclarativeShadowVariableDescriptor <Solution_ >> entryGroupVariables , VariableUpdaterInfo <Solution_ > updater ,
296
+ int updaterKey , List <VariableUpdaterInfo <Solution_ >> updaters ,
297
+ List <VariableUpdaterInfo <Solution_ >> allUpdaters , HashMap <Object , Integer > alignmentKeyToGroupIndex ,
298
+ Map <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , List <VariableUpdaterInfo <Solution_ >>>> groupedUpdaters ) {
299
+ var alignmentKeyFunction = entryGroupVariables .get (0 ).getAlignmentKeyMap ();
300
+ var alignmentKeyToAlignedEntitiesMap = new HashMap <Object , List <Object >>();
301
+ for (var entity : entities ) {
302
+ if (declarativeShadowVariableDescriptor .getEntityDescriptor ().getEntityClass ().isInstance (entity )) {
303
+ var alignmentKey = alignmentKeyFunction .apply (entity );
304
+ alignmentKeyToAlignedEntitiesMap .computeIfAbsent (alignmentKey , k -> new ArrayList <>()).add (entity );
305
+ }
306
+ }
307
+ for (var alignmentGroup : alignmentKeyToAlignedEntitiesMap .entrySet ()) {
308
+ if (alignmentGroup .getKey () == null ) {
309
+ var updaterCopy = updater .withGroupId (updaterKey );
310
+ updaters .add (updaterCopy );
311
+ allUpdaters .add (updaterCopy );
312
+ updaterKey ++;
313
+ } else {
314
+ final var newAlignmentUpdaterKey = updaterKey ;
315
+ final var alignmentUpdaterKey = (int ) alignmentKeyToGroupIndex .computeIfAbsent (alignmentGroup .getKey (),
316
+ ignored -> newAlignmentUpdaterKey );
317
+ if (alignmentUpdaterKey == newAlignmentUpdaterKey ) {
318
+ updaterKey ++;
319
+ }
320
+ var updaterCopy = updater .withGroupId (alignmentUpdaterKey );
321
+ updaterCopy = updaterCopy .withGroupEntities (alignmentGroup .getValue ().toArray (new Object [0 ]),
322
+ declarativeShadowVariableDescriptor .getAlignmentKeyName () != null );
323
+ var variableUpdaterMap = groupedUpdaters .computeIfAbsent (declarativeShadowVariableDescriptor ,
324
+ ignored -> groupedUpdaters .getOrDefault (entryGroupVariables .get (0 ),
325
+ new IdentityHashMap <>()));
326
+ for (var entity : alignmentGroup .getValue ()) {
327
+ variableUpdaterMap .computeIfAbsent (entity , ignored -> new ArrayList <>()).add (updaterCopy );
328
+ }
329
+ }
330
+ }
331
+ return updaterKey ;
332
+ }
333
+
310
334
private static <Solution_ > VariableReferenceGraph buildArbitrarySingleEntityGraph (
311
335
SolutionDescriptor <Solution_ > solutionDescriptor ,
312
336
VariableReferenceGraphBuilder <Solution_ > variableReferenceGraphBuilder , Object [] entities ,
0 commit comments