diff --git a/core/src/main/java/aima/core/search/basic/local/GeneticAlgorithm.java b/core/src/main/java/aima/core/search/basic/local/GeneticAlgorithm.java
index b989889b9a..ba53241b12 100644
--- a/core/src/main/java/aima/core/search/basic/local/GeneticAlgorithm.java
+++ b/core/src/main/java/aima/core/search/basic/local/GeneticAlgorithm.java
@@ -60,7 +60,7 @@ public class GeneticAlgorithm {
*
* @param population
* a set of individuals
- * @param fitnessFn
+ * @param fitnessFN
* a function that measures the fitness of an individual
* @return the best individual in the specified population, according to the
* specified FITNESS-FN.
@@ -73,18 +73,8 @@ public Individual geneticAlgorithm(Set> population, ToDoubleFun
Set> new_population = new HashSet>(population.size());
// repeat
do {
- // x <- RANDOM-SELECTION(population, FITNESS-FN)
- Individual x = randomSelection(population, fitnessFN);
- // y <- RANDOM-SELECTION(population, FITNESS-FN)
- Individual y = randomSelection(population, fitnessFN);
- // child <- REPRODUCE(x, y)
- Individual child = reproduce(x, y);
- // if (small random probability) then child <- MUTATE(child)
- if (isSmallRandomProbabilityOfMutation()) {
- child = mutate(child);
- }
- // add child to new_population
- new_population.add(child);
+ // population <- [MUTATE(RECOMBINE(SELECT(2, population, FITNESS-FN)))]
+ new_population.add(mutate(recombine(select(2, population, fitnessFN ))));
} // until SIZE(new_population) = SIZE(population)
while (new_population.size() != population.size());
population = new_population;
@@ -94,13 +84,36 @@ public Individual geneticAlgorithm(Set> population, ToDoubleFun
return bestIndividual;
}
- // function REPRODUCE(x, y) returns an individual
- public Individual reproduce(Individual x, Individual y) {
- // n <- LENGTH(x);
+
+ public Set> select(int p, Set> population, ToDoubleFunction> fitnessFN){
+ Set> selection = new HashSet>(2*p);
+ // selection <- a uniform random sample of 2*p individuals from population
+ do{
+ selection.add(randomSelection(population,fitnessFN));
+ }
+ while (selection.size() != 2*p);
+
+ // return the top p individuals in selection, ranked by FITNESS-FN
+ Set> fittestIndividuals = new HashSet>(p);
+ do{
+ Individual best = selectBestIndividual(selection,fitnessFN);
+ fittestIndividuals.add(best);
+ selection.remove(best);
+ }
+ while(fittestIndividuals.size() != p);
+
+ return fittestIndividuals;
+ }
+
+ public Individual recombine(Set> parentIndividuals){
+ Iterator> parentIt = parentIndividuals.iterator();
+ Individual x = parentIt.next();
+ Individual y = parentIt.next();
+ // n <- LENGTH(X)
int n = x.length();
- // c <- random number from 1 to n
+ // c <- random number from 0 to n
int c = random.nextInt(n);
- // return APPEND(SUBSTRING(x, 1, c), SUBSTRING(y, c+1, n))
+ // return APPEND(x[0:c], y[c:n])
return new Individual(x.substring(0, c), y.substring(c, n));
}
@@ -154,34 +167,41 @@ public boolean isSmallRandomProbabilityOfMutation() {
}
public Individual mutate(Individual child) {
- // We will mutate the child in place.
- child.getRepresentation().set(random.nextInt(child.length()), alphabet.get(random.nextInt(alphabet.size())));
+ // if (small random probability) then child <- MUTATE(child)
+ if(isSmallRandomProbabilityOfMutation()){
+ // We will mutate the child in place.
+ child.getRepresentation().set(random.nextInt(child.length()), alphabet.get(random.nextInt(alphabet.size())));
+ }
return child;
}
public Individual selectBestIndividualIfReady(Set> population,
ToDoubleFunction> fitnessFN) {
- Individual best = null;
-
// until some individual is fit enough, or enough time has elapsed
if (!executionController.isExecuting() || population.stream().anyMatch(fitEnoughPredicate)) {
- double bestValue = 0;
- Iterator> popIt = population.iterator();
- while (popIt.hasNext()) {
- Individual current = popIt.next();
- double currentValue = fitnessFN.applyAsDouble(current);
- if (best == null || currentValue > bestValue) {
+ return selectBestIndividual(population,fitnessFN);
+ }
+ return null;
+ }
+
+ public Individual selectBestIndividual(Set> population,
+ ToDoubleFunction> fitnessFN) {
+ Individual best = null;
+ double bestValue = 0;
+ Iterator> popIt = population.iterator();
+ while (popIt.hasNext()) {
+ Individual current = popIt.next();
+ double currentValue = fitnessFN.applyAsDouble(current);
+ if (best == null || currentValue > bestValue) {
+ best = current;
+ bestValue = currentValue;
+ } else if (currentValue == bestValue) {
+ // Randomly break ties
+ if (random.nextBoolean()) {
best = current;
- bestValue = currentValue;
- } else if (currentValue == bestValue) {
- // Randomly break ties
- if (random.nextBoolean()) {
- best = current;
- }
}
}
}
-
return best;
}
}