in core/optaplanner-core-impl/src/main/java/org/optaplanner/core/impl/heuristic/selector/move/generic/list/kopt/KOptListMoveIterator.java [286:357]
KOptDescriptor<Node_> patchCyclesRec(Iterator<Node_> valueIterator,
KOptDescriptor<Node_> originalMove, EntityOrderInfo entityOrderInfo,
Node_[] oldRemovedEdges, int[] addedEdgeToOtherEndpoint, int[] cycle, int currentCycle,
int k, int patchedCycleCount, int cycleCount) {
Node_ s1, s2, s3, s4;
int NewCycle, i;
Integer[] cycleSaved = new Integer[1 + 2 * k];
Node_[] removedEdges = Arrays.copyOf(oldRemovedEdges, oldRemovedEdges.length + 2);
s1 = removedEdges[2 * k + 1];
s2 = removedEdges[i = 2 * (k + patchedCycleCount) - 2];
addedEdgeToOtherEndpoint[addedEdgeToOtherEndpoint[i] = i + 1] = i;
for (i = 1; i <= 2 * k; i++) {
cycleSaved[i] = cycle[i];
}
s3 = valueIterator.next();
int remainingAttempts = cycleCount * 2;
while (s3 == getNodePredecessor(entityOrderInfo, s2) || s3 == getNodeSuccessor(entityOrderInfo, s2)
|| ((NewCycle = findCycleIdentifierForNode(entityOrderInfo, s3, removedEdges,
originalMove.getRemovedEdgeIndexToTourOrder(),
cycle)) == currentCycle)
||
(isEdgeAlreadyDeleted(removedEdges, s3, getNodePredecessor(entityOrderInfo, s3), k)
&& isEdgeAlreadyDeleted(removedEdges, s3, getNodeSuccessor(entityOrderInfo, s3), k))) {
if (remainingAttempts == 0) {
return originalMove;
}
s3 = valueIterator.next();
remainingAttempts--;
}
removedEdges[2 * (k + patchedCycleCount) - 1] = s3;
if (isEdgeAlreadyDeleted(removedEdges, s3, getNodePredecessor(entityOrderInfo, s3), k)) {
s4 = getNodeSuccessor(entityOrderInfo, s3);
} else if (isEdgeAlreadyDeleted(removedEdges, s3, getNodeSuccessor(entityOrderInfo, s3), k)) {
s4 = getNodePredecessor(entityOrderInfo, s3);
} else {
s4 = workingRandom.nextBoolean() ? getNodeSuccessor(entityOrderInfo, s3) : getNodePredecessor(entityOrderInfo, s3);
}
removedEdges[2 * (k + patchedCycleCount)] = s4;
if (cycleCount > 2) {
for (i = 1; i <= 2 * k; i++) {
if (cycle[i] == NewCycle) {
cycle[i] = currentCycle;
}
}
KOptDescriptor<Node_> recursiveCall =
patchCyclesRec(valueIterator, originalMove, entityOrderInfo, removedEdges, addedEdgeToOtherEndpoint, cycle,
currentCycle,
k, patchedCycleCount + 1, cycleCount - 1);
if (recursiveCall.isFeasible()) {
return recursiveCall;
}
for (i = 1; i <= 2 * k; i++) {
cycle[i] = cycleSaved[i];
}
} else if (s4 != s1) {
addedEdgeToOtherEndpoint[addedEdgeToOtherEndpoint[2 * k + 1] = 2 * (k + patchedCycleCount)] =
2 * k + 1;
return new KOptDescriptor<>(removedEdges, addedEdgeToOtherEndpoint,
KOptUtils.getMultiEntitySuccessorFunction(removedEdges,
listVariableDescriptor,
inverseVariableSupply,
indexVariableSupply),
KOptUtils.getMultiEntityBetweenPredicate(removedEdges,
listVariableDescriptor,
inverseVariableSupply,
indexVariableSupply));
}
return originalMove;
}