@SuppressWarnings("unchecked") protected KeyedChromosome<Object> performCrossover( KeyedChromosome<Object> parentA, KeyedChromosome<Object> parentB) { KeyedChromosome<Object> child = (KeyedChromosome<Object>) parentA.clone(); Map<Object, Gene> replaced = new HashMap<Object, Gene>(); double originalFitness = parentA.getFitness(); Gene originalGene; Gene replacement; boolean crossedOver; int attempts = 0; for (; attempts < maxAttempts; attempts++) { crossedOver = false; replaced.clear(); for (Object key : child.getGenes().keySet()) { if (coin.flip()) { originalGene = child.getGenes().get(key); replacement = parentB.getGenes().get(key).clone(); if (!replacement.equals(originalGene)) { replaced.put(key, originalGene); child.replaceGene(key, replacement); crossedOver = true; } } } if (crossedOver) { double fitness = fitnessEvaluator.evaluate(child); if (fitness > originalFitness) { child.setFitness(fitness); break; } else { // revert crossover for (Object key : replaced.keySet()) { child.replaceGene(key, replaced.get(key)); } // Make sure it doesn't get re-evaluated child.setFitness(originalFitness); } } } if (attempts >= maxAttempts) { log.debug( "Unable to find guaranteed better fitness via crossover after " + maxAttempts + " attempts. Returning clone of first parent."); } return child; }
@Override public List<KeyedChromosome<Object>> crossover( KeyedChromosome<Object> parentA, KeyedChromosome<Object> parentB) { List<KeyedChromosome<Object>> children = new ArrayList<KeyedChromosome<Object>>(1); KeyedChromosome<Object> child = performCrossover(parentA, parentB); // The Chromosome could be null if it's identical to one of its parents if (child != null) { children.add(child); if (maxGenerations > 0) { child.setAncestry( new Ancestry( parentA.getId(), parentB.getId(), parentA.getAncestry(), parentB.getAncestry(), maxGenerations)); } parentA.increaseNumberOfChildren(); parentB.increaseNumberOfChildren(); } return children; }