@@ -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 , List < VariableUpdaterInfo <Solution_ > >>> variableToEntityToGroupUpdater ) {
192
+ Map <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , 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 updaters = variableToEntityToGroupUpdater .get (declarativeShadowVariableDescriptor ).get (entity );
198
- if (updaters != null ) {
199
- return updaters ;
197
+ var updater = variableToEntityToGroupUpdater .get (declarativeShadowVariableDescriptor ).get (entity );
198
+ if (updater != null ) {
199
+ return List . of ( updater ) ;
200
200
}
201
201
}
202
202
for (var shadowVariableDescriptor : sortedDeclarativeVariableDescriptors ) {
@@ -225,7 +225,24 @@ 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 (shouldCreateNewGroupForVariable (declarativeShadowVariableDescriptor , groupVariables )) {
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 )) {
229
246
groupVariables = new ArrayList <>();
230
247
groupIndexToVariables .put (groupIndexToVariables .size (), groupVariables );
231
248
}
@@ -235,12 +252,11 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
235
252
var out = new HashMap <VariableMetaModel <Solution_ , ?, ?>, GroupVariableUpdaterInfo <Solution_ >>();
236
253
var allUpdaters = new ArrayList <VariableUpdaterInfo <Solution_ >>();
237
254
var groupedUpdaters =
238
- new HashMap <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , List < VariableUpdaterInfo <Solution_ > >>>();
255
+ new HashMap <DeclarativeShadowVariableDescriptor <Solution_ >, Map <Object , VariableUpdaterInfo <Solution_ >>>();
239
256
var updaterKey = 0 ;
240
257
for (var entryKey = 0 ; entryKey < groupIndexToVariables .size (); entryKey ++) {
241
258
var entryGroupVariables = groupIndexToVariables .get (entryKey );
242
259
var updaters = new ArrayList <VariableUpdaterInfo <Solution_ >>();
243
- var alignmentKeyToGroupIndex = new HashMap <Object , Integer >();
244
260
for (var declarativeShadowVariableDescriptor : entryGroupVariables ) {
245
261
var updater = new VariableUpdaterInfo <>(
246
262
declarativeShadowVariableDescriptor .getVariableMetaModel (),
@@ -249,11 +265,31 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
249
265
declarativeShadowVariableDescriptor .getEntityDescriptor ().getShadowVariableLoopedDescriptor (),
250
266
declarativeShadowVariableDescriptor .getMemberAccessor (),
251
267
declarativeShadowVariableDescriptor .getCalculator ()::executeGetter );
252
- if (entryGroupVariables .get (0 ).getAlignmentKeyMap () != null ) {
253
- updaterKey = processAlignmentGroupVariableAndGetNextUpdaterKey (entities ,
254
- declarativeShadowVariableDescriptor , entryGroupVariables , updater ,
255
- updaterKey , updaters ,
256
- allUpdaters , alignmentKeyToGroupIndex , groupedUpdaters );
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
257
293
} else {
258
294
updaters .add (updater );
259
295
allUpdaters .add (updater );
@@ -265,72 +301,12 @@ public List<VariableUpdaterInfo<Solution_>> getUpdatersForEntityVariable(Object
265
301
for (var declarativeShadowVariableDescriptor : entryGroupVariables ) {
266
302
out .put (declarativeShadowVariableDescriptor .getVariableMetaModel (), groupVariableUpdaterInfo );
267
303
}
268
- if (entryGroupVariables .get (0 ).getAlignmentKeyMap () == null ) {
269
- updaterKey ++;
270
- }
304
+ updaterKey ++;
271
305
}
272
306
allUpdaters .replaceAll (updater -> updater .withGroupId (groupIndexToVariables .size ()));
273
307
return out ;
274
308
}
275
309
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
-
334
310
private static <Solution_ > VariableReferenceGraph buildArbitrarySingleEntityGraph (
335
311
SolutionDescriptor <Solution_ > solutionDescriptor ,
336
312
VariableReferenceGraphBuilder <Solution_ > variableReferenceGraphBuilder , Object [] entities ,
0 commit comments