Skip to content

Commit

Permalink
mutation: Inline and simplify cross-over helpers
Browse files Browse the repository at this point in the history
Also rename `withChunk` to `onCorrespondingChunks` to make it more clear
that this doesn't apply to the "insert" action (see the parent commit).
  • Loading branch information
fmeum committed Sep 6, 2023
1 parent d6bc0a6 commit f6cf799
Showing 1 changed file with 29 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,47 +39,31 @@ static <T> void insertChunk(List<T> list, List<T> otherList, int maxSize, Pseudo
}

static <T> void overwriteChunk(List<T> list, List<T> otherList, PseudoRandom prng) {
int maxChunkSize = Math.min(list.size(), otherList.size());
withChunkElements(list, otherList, maxChunkSize, prng, list::set);
onCorrespondingChunks(list, otherList, prng, list::set);
}

static <T> void crossOverChunk(
List<T> list, List<T> otherList, SerializingMutator<T> elementMutator, PseudoRandom prng) {
int maxChunkSize = Math.min(list.size(), otherList.size());
withChunkElements(list, otherList, maxChunkSize, prng, (toPos, element) -> {
onCorrespondingChunks(list, otherList, prng, (toPos, element) -> {
list.set(toPos, elementMutator.crossOver(list.get(toPos), element, prng));
});
}

@FunctionalInterface
private interface ChunkListOperation<T> {
void apply(int fromPos, int toPos, List<T> chunk);
}

@FunctionalInterface
private interface ChunkListElementOperation<T> {
void apply(int toPos, T chunk);
}

static private <T> void withChunk(List<T> list, List<T> otherList, int maxChunkSize,
PseudoRandom prng, ChunkListOperation<T> operation) {
if (maxChunkSize == 0) {
return;
}
static private <T> void onCorrespondingChunks(
List<T> list, List<T> otherList, PseudoRandom prng, ChunkListElementOperation<T> operation) {
int maxChunkSize = Math.min(list.size(), otherList.size());
int chunkSize = prng.closedRangeBiasedTowardsSmall(1, maxChunkSize);
int fromPos = prng.closedRange(0, otherList.size() - chunkSize);
int toPos = prng.closedRange(0, list.size() - chunkSize);
List<T> chunk = otherList.subList(fromPos, fromPos + chunkSize);
operation.apply(fromPos, toPos, chunk);
}

static private <T> void withChunkElements(List<T> list, List<T> otherList, int maxChunkSize,
PseudoRandom prng, ChunkListElementOperation<T> operation) {
withChunk(list, otherList, maxChunkSize, prng, (fromPos, toPos, chunk) -> {
for (int i = 0; i < chunk.size(); i++) {
operation.apply(toPos + i, chunk.get(i));
}
});
for (int i = 0; i < chunk.size(); i++) {
operation.apply(toPos + i, chunk.get(i));
}
}

static <K, V> void insertChunk(
Expand All @@ -104,8 +88,7 @@ static <K, V> void insertChunk(
}

static <K, V> void overwriteChunk(Map<K, V> map, Map<K, V> otherMap, PseudoRandom prng) {
int maxChunkSize = Math.min(map.size(), otherMap.size());
withChunk(map, otherMap, maxChunkSize, prng, (fromIterator, toIterator, chunkSize) -> {
onCorrespondingChunks(map, otherMap, prng, (fromIterator, toIterator, chunkSize) -> {
// As keys can not be overwritten, only removed and new ones added, this
// cross over overwrites the values. Removal of keys is handled by the
// removeChunk mutation. Value equality is not checked here.
Expand All @@ -128,8 +111,7 @@ static <K, V> void crossOverChunk(Map<K, V> map, Map<K, V> otherMap,

private static <K, V> void crossOverChunkKeys(
Map<K, V> map, Map<K, V> otherMap, SerializingMutator<K> keyMutator, PseudoRandom prng) {
int maxChunkSize = Math.min(map.size(), otherMap.size());
withChunk(map, otherMap, maxChunkSize, prng, (fromIterator, toIterator, chunkSize) -> {
onCorrespondingChunks(map, otherMap, prng, (fromIterator, toIterator, chunkSize) -> {
Map<K, V> entriesToAdd = new LinkedHashMap<>(chunkSize);
for (int i = 0; i < chunkSize; i++) {
Entry<K, V> to = toIterator.next();
Expand Down Expand Up @@ -161,15 +143,22 @@ private static <K, V> void crossOverChunkKeys(

private static <K, V> void crossOverChunkValues(
Map<K, V> map, Map<K, V> otherMap, SerializingMutator<V> valueMutator, PseudoRandom prng) {
int maxChunkSize = Math.min(map.size(), otherMap.size());
withChunkElements(map, otherMap, maxChunkSize, prng, (fromEntry, toEntry) -> {
// As cross-overs do not guarantee to mutate the given object, no
// checks if a new value is produced are performed.
V newValue = valueMutator.crossOver(toEntry.getValue(), fromEntry.getValue(), prng);

// The cross-over could have already mutated value, but explicitly set it
// through the iterator to be sure.
toEntry.setValue(newValue);
// As cross-overs do not guarantee to mutate the given object, no
// checks if a new value is produced are performed.
// The cross-over could have already mutated value, but explicitly set it
// through the iterator to be sure.
onCorrespondingChunks(map, otherMap, prng, (fromIterator, toIterator, chunkSize) -> {
for (int i = 0; i < chunkSize; i++) {
Entry<K, V> fromEntry = fromIterator.next();
Entry<K, V> toEntry = toIterator.next();
// As cross-overs do not guarantee to mutate the given object, no
// checks if a new value is produced are performed.
V newValue = valueMutator.crossOver(toEntry.getValue(), fromEntry.getValue(), prng);

// The cross-over could have already mutated value, but explicitly set it
// through the iterator to be sure.
toEntry.setValue(newValue);
}
});
}

Expand All @@ -178,13 +167,9 @@ private interface ChunkMapOperation<K, V> {
void apply(Iterator<Entry<K, V>> fromIterator, Iterator<Entry<K, V>> toIterator, int chunkSize);
}

@FunctionalInterface
private interface ChunkMapElementOperation<K, V> {
void apply(Entry<K, V> fromEntry, Entry<K, V> toEntry);
}

static <K, V> void withChunk(Map<K, V> map, Map<K, V> otherMap, int maxChunkSize,
PseudoRandom prng, ChunkMapOperation<K, V> operation) {
static <K, V> void onCorrespondingChunks(
Map<K, V> map, Map<K, V> otherMap, PseudoRandom prng, ChunkMapOperation<K, V> operation) {
int maxChunkSize = Math.min(map.size(), otherMap.size());
int chunkSize = prng.closedRangeBiasedTowardsSmall(1, maxChunkSize);
int fromChunkOffset = prng.closedRange(0, otherMap.size() - chunkSize);
int toChunkOffset = prng.closedRange(0, map.size() - chunkSize);
Expand All @@ -199,15 +184,6 @@ static <K, V> void withChunk(Map<K, V> map, Map<K, V> otherMap, int maxChunkSize
operation.apply(fromIterator, toIterator, chunkSize);
}

static <K, V> void withChunkElements(Map<K, V> map, Map<K, V> otherMap, int maxChunkSize,
PseudoRandom prng, ChunkMapElementOperation<K, V> operation) {
withChunk(map, otherMap, maxChunkSize, prng, (fromIterator, toIterator, chunkSize) -> {
for (int i = 0; i < chunkSize; i++) {
operation.apply(fromIterator.next(), toIterator.next());
}
});
}

public enum CrossOverAction {
INSERT_CHUNK,
OVERWRITE_CHUNK,
Expand Down

0 comments on commit f6cf799

Please sign in to comment.