MATH-1618: Replace class "OnePointCrossover" with "NPointCrossover".
The former is a particular case of the latter.
This commit is contained in:
parent
3c30a6d520
commit
f0fe9ab8eb
|
@ -129,7 +129,7 @@ public final class MathFunctionOptimizer2 {
|
|||
// Offspring generators.
|
||||
final Map<GeneticOperator<Chromosome>, ApplicationRate> operators = new HashMap<>();
|
||||
operators.put(Operators.mutation(mutation), RateGenerators.constant(1));
|
||||
operators.put(Operators.onePointCrossover(), RateGenerators.constant(crossover));
|
||||
operators.put(Operators.nPointCrossover(1), RateGenerators.constant(crossover));
|
||||
|
||||
final Callable<Population<Chromosome, Coordinates>> ga =
|
||||
GeneticAlgorithmFactory.<Chromosome, Coordinates>create(numGenes,
|
||||
|
@ -145,14 +145,12 @@ public final class MathFunctionOptimizer2 {
|
|||
new GenerationLogger());
|
||||
|
||||
try {
|
||||
// Run the GA and retrieve contents of the last generation.
|
||||
final List<Map.Entry<Chromosome, Double>> lastGen = ga.call().contents(true);
|
||||
final Map.Entry<Chromosome, Double> top = lastGen.get(0);
|
||||
final Coordinates best = decoder.apply(top.getKey());
|
||||
final double bestValue = fitnessFunction.applyAsDouble(best);
|
||||
// Run the GA and retrieve the best individual from the last generation.
|
||||
final Map.Entry<Chromosome, Double> best = ga.call().contents(true).get(0);
|
||||
|
||||
// CHECKSTYLE: stop all
|
||||
System.out.println("fitness=" + bestValue + " for " + best.toString());
|
||||
System.out.println("fitness=" + best.getValue() +
|
||||
" for " + decoder.apply(best.getKey()).toString());
|
||||
// CHECKSTYLE: resume all
|
||||
} catch (Exception e) {
|
||||
// Rethrow.
|
||||
|
|
|
@ -27,7 +27,21 @@ import org.apache.commons.math4.ga2.AbstractCrossover;
|
|||
* Genetic operator.
|
||||
* Class is immutable.
|
||||
*/
|
||||
/* package-private */ class OnePointCrossover extends AbstractCrossover<Chromosome> {
|
||||
/* package-private */ class NPointCrossover extends AbstractCrossover<Chromosome> {
|
||||
/** Number of crossover points. */
|
||||
private final int numberOfPoints;
|
||||
|
||||
/**
|
||||
* @param n Number of crossover points.
|
||||
*/
|
||||
NPointCrossover(int n) {
|
||||
if (n <= 0) {
|
||||
throw new IllegalArgumentException("Not strictly positive: " + n);
|
||||
}
|
||||
|
||||
numberOfPoints = n;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected List<Chromosome> apply(Chromosome parent1,
|
||||
|
@ -40,36 +54,57 @@ import org.apache.commons.math4.ga2.AbstractCrossover;
|
|||
parent2.size());
|
||||
}
|
||||
|
||||
// Index of crossover point.
|
||||
final int xIndex = 1 + rng.nextInt(size - 1);
|
||||
final BitSet p1 = parent1.asBitSet();
|
||||
final BitSet p2 = parent2.asBitSet();
|
||||
final BitSet c1;
|
||||
final BitSet c2;
|
||||
final BitSet c1 = parent1.asBitSet();
|
||||
final BitSet c2 = parent2.asBitSet();
|
||||
|
||||
final int midIndex = size / 2;
|
||||
if (xIndex > midIndex) {
|
||||
c1 = parent1.asBitSet();
|
||||
c2 = parent2.asBitSet();
|
||||
// Number or remaining crossover points.
|
||||
int remainingPoints = numberOfPoints;
|
||||
// Index of crossover end point.
|
||||
int xEnd = 0;
|
||||
while (remainingPoints > 0) {
|
||||
// Index of crossover start point.
|
||||
final int xStart = xEnd + 1 + rng.nextInt(size - xEnd - remainingPoints);
|
||||
|
||||
for (int i = xIndex; i < size; i++) {
|
||||
c1.set(i, p2.get(i));
|
||||
c2.set(i, p1.get(i));
|
||||
}
|
||||
if (--remainingPoints > 0) {
|
||||
xEnd = xStart + 1 + rng.nextInt(size - xStart - remainingPoints);
|
||||
|
||||
swap(c1, c2, xStart, xEnd);
|
||||
|
||||
--remainingPoints;
|
||||
} else {
|
||||
c1 = parent2.asBitSet();
|
||||
c2 = parent1.asBitSet();
|
||||
|
||||
for (int i = 0; i < xIndex; i++) {
|
||||
c1.set(i, p1.get(i));
|
||||
c2.set(i, p2.get(i));
|
||||
xEnd = xStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfPoints % 2 != 0) {
|
||||
swap(c1, c2, xEnd, size);
|
||||
}
|
||||
|
||||
final List<Chromosome> offsprings = new ArrayList<>(2);
|
||||
offsprings.add(Chromosome.from(c1, size));
|
||||
offsprings.add(Chromosome.from(c2, size));
|
||||
|
||||
return offsprings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps contents (in-place) within the given range.
|
||||
*
|
||||
* @param a Chromosome.
|
||||
* @param b Chromosome.
|
||||
* @param start Index from which contents should be swapped.
|
||||
* @param end Index at which swapping should stop.
|
||||
*/
|
||||
private void swap(BitSet a,
|
||||
BitSet b,
|
||||
int start,
|
||||
int end) {
|
||||
for (int i = start; i < end; i++) {
|
||||
final boolean aV = a.get(i);
|
||||
final boolean bV = b.get(i);
|
||||
a.set(i, bV);
|
||||
b.set(i, aV);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,9 +35,10 @@ public final class Operators {
|
|||
return new Mutation(probability);
|
||||
}
|
||||
/**
|
||||
* @return a one-point crossover operator.
|
||||
* @param n Number of crossover points.
|
||||
* @return an n-point crossover operator.
|
||||
*/
|
||||
public static GeneticOperator<Chromosome> onePointCrossover() {
|
||||
return new OnePointCrossover();
|
||||
public static GeneticOperator<Chromosome> nPointCrossover(int n) {
|
||||
return new NPointCrossover(n);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue