Skip to content

Commit

Permalink
chore: improve the new list variable logic (#1248)
Browse files Browse the repository at this point in the history
For some reason, this commit was not merged together with ee760ca and I
only discovered it now.
  • Loading branch information
triceo authored Dec 4, 2024
1 parent 05539ad commit 8dfa1a1
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 108 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,23 @@ public ExternalizedListVariableStateSupply(ListVariableDescriptor<Solution_> sou

@Override
public void externalize(IndexShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
listVariableState.linkDescriptor(shadowVariableDescriptor);
listVariableState.linkShadowVariable(shadowVariableDescriptor);
}

@Override
public void externalize(InverseRelationShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
listVariableState.linkDescriptor(shadowVariableDescriptor);
listVariableState.linkShadowVariable(shadowVariableDescriptor);
}

@Override
public void externalize(PreviousElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
listVariableState.linkDescriptor(shadowVariableDescriptor);
listVariableState.linkShadowVariable(shadowVariableDescriptor);
previousExternalized = true;
}

@Override
public void externalize(NextElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
listVariableState.linkDescriptor(shadowVariableDescriptor);
listVariableState.linkShadowVariable(shadowVariableDescriptor);
nextExternalized = true;
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ai.timefold.solver.core.impl.domain.variable;

import java.util.List;
import java.util.Objects;

import ai.timefold.solver.core.impl.domain.variable.descriptor.ShadowVariableDescriptor;
import ai.timefold.solver.core.impl.domain.variable.nextprev.NextElementShadowVariableDescriptor;
import ai.timefold.solver.core.impl.domain.variable.nextprev.PreviousElementShadowVariableDescriptor;
import ai.timefold.solver.core.impl.score.director.InnerScoreDirector;

final class ExternalizedNextPrevElementVariableProcessor<Solution_> {

public static <Solution_> ExternalizedNextPrevElementVariableProcessor<Solution_>
ofPrevious(PreviousElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
return new ExternalizedNextPrevElementVariableProcessor<>(shadowVariableDescriptor, -1);
}

public static <Solution_> ExternalizedNextPrevElementVariableProcessor<Solution_>
ofNext(NextElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
return new ExternalizedNextPrevElementVariableProcessor<>(shadowVariableDescriptor, 1);
}

private final ShadowVariableDescriptor<Solution_> shadowVariableDescriptor;
private final int modifier;

private ExternalizedNextPrevElementVariableProcessor(ShadowVariableDescriptor<Solution_> shadowVariableDescriptor,
int modifier) {
this.shadowVariableDescriptor = Objects.requireNonNull(shadowVariableDescriptor);
this.modifier = modifier;
}

public void setElement(InnerScoreDirector<Solution_, ?> scoreDirector, List<Object> listVariable, Object element,
int index) {
var target = index + modifier;
if (target < 0 || target >= listVariable.size()) {
setValue(scoreDirector, element, null);
} else {
setValue(scoreDirector, element, listVariable.get(target));
}
}

private void setValue(InnerScoreDirector<Solution_, ?> scoreDirector, Object element, Object value) {
if (getElement(element) != value) {
scoreDirector.beforeVariableChanged(shadowVariableDescriptor, element);
shadowVariableDescriptor.setValue(element, value);
scoreDirector.afterVariableChanged(shadowVariableDescriptor, element);
}
}

public Object getElement(Object element) {
return shadowVariableDescriptor.getValue(element);
}

public void unsetElement(InnerScoreDirector<Solution_, ?> scoreDirector, Object element) {
setValue(scoreDirector, element, null);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ final class ListVariableState<Solution_> {

private ExternalizedIndexVariableProcessor<Solution_> externalizedIndexProcessor = null;
private ExternalizedListInverseVariableProcessor<Solution_> externalizedInverseProcessor = null;
private AbstractExternalizedNextPrevElementVariableProcessor<Solution_> externalizedPreviousElementProcessor = null;
private AbstractExternalizedNextPrevElementVariableProcessor<Solution_> externalizedNextElementProcessor = null;
private ExternalizedNextPrevElementVariableProcessor<Solution_> externalizedPreviousElementProcessor = null;
private ExternalizedNextPrevElementVariableProcessor<Solution_> externalizedNextElementProcessor = null;

private boolean canUseExternalizedLocation = false;
private boolean requiresLocationMap = true;
private InnerScoreDirector<Solution_, ?> scoreDirector;
private int unassignedCount = 0;
Expand All @@ -33,30 +32,29 @@ public ListVariableState(ListVariableDescriptor<Solution_> sourceVariableDescrip
this.sourceVariableDescriptor = sourceVariableDescriptor;
}

public void linkDescriptor(IndexShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
public void linkShadowVariable(IndexShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
this.externalizedIndexProcessor = new ExternalizedIndexVariableProcessor<>(shadowVariableDescriptor);
}

public void linkDescriptor(InverseRelationShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
public void linkShadowVariable(InverseRelationShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
this.externalizedInverseProcessor =
new ExternalizedListInverseVariableProcessor<>(shadowVariableDescriptor, sourceVariableDescriptor);
}

public void linkDescriptor(PreviousElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
public void linkShadowVariable(PreviousElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
this.externalizedPreviousElementProcessor =
new ExternalizedPreviousElementVariableProcessor<>(shadowVariableDescriptor);
ExternalizedNextPrevElementVariableProcessor.ofPrevious(shadowVariableDescriptor);
}

public void linkDescriptor(NextElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
this.externalizedNextElementProcessor = new ExternalizedNextElementVariableProcessor<>(shadowVariableDescriptor);
public void linkShadowVariable(NextElementShadowVariableDescriptor<Solution_> shadowVariableDescriptor) {
this.externalizedNextElementProcessor = ExternalizedNextPrevElementVariableProcessor.ofNext(shadowVariableDescriptor);
}

public void initialize(InnerScoreDirector<Solution_, ?> scoreDirector, int initialUnassignedCount) {
this.scoreDirector = scoreDirector;
this.unassignedCount = initialUnassignedCount;

this.canUseExternalizedLocation = externalizedIndexProcessor != null && externalizedInverseProcessor != null;
this.requiresLocationMap = !canUseExternalizedLocation
this.requiresLocationMap = externalizedIndexProcessor == null || externalizedInverseProcessor == null
|| externalizedPreviousElementProcessor == null || externalizedNextElementProcessor == null;
if (requiresLocationMap) {
if (elementLocationMap == null) {
Expand Down Expand Up @@ -220,14 +218,14 @@ private enum ChangeType {
}

public ElementLocation getLocationInList(Object planningValue) {
if (!canUseExternalizedLocation) {
if (requiresLocationMap) {
return Objects.requireNonNullElse(elementLocationMap.get(planningValue), ElementLocation.unassigned());
} else {
var inverse = getInverseSingleton(planningValue);
} else { // At this point, both inverse and index are externalized.
var inverse = externalizedInverseProcessor.getInverseSingleton(planningValue);
if (inverse == null) {
return ElementLocation.unassigned();
}
return ElementLocation.of(inverse, getIndex(planningValue));
return ElementLocation.of(inverse, externalizedIndexProcessor.getIndex(planningValue));
}
}

Expand Down

0 comments on commit 8dfa1a1

Please sign in to comment.