11package ai .timefold .solver .core .impl .move .director ;
22
3- import java .util .List ;
43import java .util .Objects ;
54import java .util .function .BiFunction ;
65
@@ -64,15 +63,33 @@ public final <Entity_, Value_> void assignValue(PlanningListVariableMetaModel<So
6463 }
6564
6665 @ Override
67- public final <Entity_ , Value_ > void unassignValue (
68- PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel ,
69- Value_ movedValue , Entity_ sourceEntity , int sourceIndex ) {
66+ public <Entity_ , Value_ > void unassignValue (PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel ,
67+ Value_ value ) {
68+ var locationInList = getPositionOf (variableMetaModel , value )
69+ .ensureAssigned (() -> """
70+ The value (%s) is not assigned to a list variable.
71+ This may indicate score corruption or a problem with the move's implementation."""
72+ .formatted (value ));
73+ unassignValue (variableMetaModel , value , locationInList .entity (), locationInList .index ());
74+ }
75+
76+ @ Override
77+ public <Entity_ , Value_ > Value_ unassignValue (PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel ,
78+ Entity_ entity , int index ) {
79+ var value = getValueAtIndex (variableMetaModel , entity , index );
80+ unassignValue (variableMetaModel , value , entity , index );
81+ return value ;
82+ }
83+
84+ private <Entity_ , Value_ > void unassignValue (
85+ PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel , Value_ movedValue , Entity_ entity ,
86+ int index ) {
7087 var variableDescriptor =
7188 ((DefaultPlanningListVariableMetaModel <Solution_ , Entity_ , Value_ >) variableMetaModel ).variableDescriptor ();
7289 externalScoreDirector .beforeListVariableElementUnassigned (variableDescriptor , movedValue );
73- externalScoreDirector .beforeListVariableChanged (variableDescriptor , sourceEntity , sourceIndex , sourceIndex + 1 );
74- variableDescriptor .getValue (sourceEntity ).remove (sourceIndex );
75- externalScoreDirector .afterListVariableChanged (variableDescriptor , sourceEntity , sourceIndex , sourceIndex );
90+ externalScoreDirector .beforeListVariableChanged (variableDescriptor , entity , index , index + 1 );
91+ variableDescriptor .getValue (entity ).remove (index );
92+ externalScoreDirector .afterListVariableChanged (variableDescriptor , entity , index , index );
7693 externalScoreDirector .afterListVariableElementUnassigned (variableDescriptor , movedValue );
7794 }
7895
@@ -92,6 +109,7 @@ public final <Entity_, Value_> void changeVariable(PlanningVariableMetaModel<Sol
92109 return moveValueInList (variableMetaModel , sourceEntity , sourceIndex , destinationIndex );
93110 }
94111 var variableDescriptor = extractVariableDescriptor (variableMetaModel );
112+
95113 externalScoreDirector .beforeListVariableChanged (variableDescriptor , sourceEntity , sourceIndex , sourceIndex + 1 );
96114 var element = (Value_ ) variableDescriptor .removeElement (sourceEntity , sourceIndex );
97115 externalScoreDirector .afterListVariableChanged (variableDescriptor , sourceEntity , sourceIndex , sourceIndex );
@@ -108,21 +126,57 @@ public final <Entity_, Value_> void changeVariable(PlanningVariableMetaModel<Sol
108126 @ SuppressWarnings ("unchecked" )
109127 @ Override
110128 public final <Entity_ , Value_ > @ Nullable Value_ moveValueInList (
111- PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel , Entity_ entity , int sourceIndex ,
129+ PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel , Entity_ sourceEntity , int sourceIndex ,
112130 int destinationIndex ) {
113131 if (sourceIndex == destinationIndex ) {
114132 return null ;
115- } else if (sourceIndex > destinationIndex ) { // Always start from the lower index.
116- return moveValueInList (variableMetaModel , entity , destinationIndex , sourceIndex );
117133 }
118134 var variableDescriptor = extractVariableDescriptor (variableMetaModel );
119- var toIndex = destinationIndex + 1 ;
120- externalScoreDirector .beforeListVariableChanged (variableDescriptor , entity , sourceIndex , toIndex );
121- var variable = (List <Value_ >) variableDescriptor .getValue (entity );
122- var value = variable .remove (sourceIndex );
123- variable .add (destinationIndex , value );
124- externalScoreDirector .afterListVariableChanged (variableDescriptor , entity , sourceIndex , toIndex );
125- return value ;
135+ var fromIndex = Math .min (sourceIndex , destinationIndex );
136+ var toIndex = Math .max (sourceIndex , destinationIndex ) + 1 ;
137+
138+ externalScoreDirector .beforeListVariableChanged (variableDescriptor , sourceEntity , fromIndex , toIndex );
139+ Value_ element = (Value_ ) variableDescriptor .removeElement (sourceEntity , sourceIndex );
140+ variableDescriptor .addElement (sourceEntity , destinationIndex , element );
141+ externalScoreDirector .afterListVariableChanged (variableDescriptor , sourceEntity , fromIndex , toIndex );
142+
143+ return element ;
144+ }
145+
146+ @ Override
147+ public <Entity_ , Value_ > void swapValuesBetweenLists (
148+ PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel , Entity_ leftEntity , int leftIndex ,
149+ Entity_ rightEntity , int rightIndex ) {
150+ if (leftEntity == rightEntity ) {
151+ swapValuesInList (variableMetaModel , leftEntity , leftIndex , rightIndex );
152+ } else {
153+ var variableDescriptor = extractVariableDescriptor (variableMetaModel );
154+ externalScoreDirector .beforeListVariableChanged (variableDescriptor , leftEntity , leftIndex , leftIndex + 1 );
155+ externalScoreDirector .beforeListVariableChanged (variableDescriptor , rightEntity , rightIndex , rightIndex + 1 );
156+ var oldLeftElement = variableDescriptor .setElement (leftEntity , leftIndex ,
157+ variableDescriptor .getElement (rightEntity , rightIndex ));
158+ variableDescriptor .setElement (rightEntity , rightIndex , oldLeftElement );
159+ externalScoreDirector .afterListVariableChanged (variableDescriptor , leftEntity , leftIndex , leftIndex + 1 );
160+ externalScoreDirector .afterListVariableChanged (variableDescriptor , rightEntity , rightIndex , rightIndex + 1 );
161+ }
162+ }
163+
164+ @ Override
165+ public <Entity_ , Value_ > void swapValuesInList (PlanningListVariableMetaModel <Solution_ , Entity_ , Value_ > variableMetaModel ,
166+ Entity_ entity , int leftIndex , int rightIndex ) {
167+ if (leftIndex == rightIndex ) {
168+ return ;
169+ }
170+
171+ var variableDescriptor = extractVariableDescriptor (variableMetaModel );
172+ var fromIndex = Math .min (leftIndex , rightIndex );
173+ var toIndex = Math .max (leftIndex , rightIndex ) + 1 ;
174+
175+ externalScoreDirector .beforeListVariableChanged (variableDescriptor , entity , fromIndex , toIndex );
176+ var oldLeftElement =
177+ variableDescriptor .setElement (entity , leftIndex , variableDescriptor .getElement (entity , rightIndex ));
178+ variableDescriptor .setElement (entity , rightIndex , oldLeftElement );
179+ externalScoreDirector .afterListVariableChanged (variableDescriptor , entity , fromIndex , toIndex );
126180 }
127181
128182 @ Override
0 commit comments