@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; }