/** {@inheritDoc} */ @Override public <E extends Entity> List<E> crossover(List<E> parentCollection) { checkState( parentCollection.size() >= 3, "There must be a minimum of three parents to perform UNDX crossover."); checkState( numberOfOffspring > 0, "At least one offspring must be generated. Check 'numberOfOffspring'."); List<Vector> solutions = Entities.<Vector>getCandidateSolutions(parentCollection); List<E> offspring = Lists.newArrayListWithCapacity(numberOfOffspring); UniformDistribution randomParent = new UniformDistribution(); final int k = solutions.size(); final int n = solutions.get(0).size(); for (int os = 0; os < numberOfOffspring; os++) { // get index of main parent and put its solution at the end of the list int parent = (int) randomParent.getRandomNumber(0.0, k); Collections.swap(solutions, parent, k - 1); List<Vector> e_zeta = new ArrayList<Vector>(); // calculate mean of parents except main parent Vector g = Vectors.mean(solutions.subList(0, k - 1)); // basis vectors defined by parents for (int i = 0; i < k - 1; i++) { Vector d = solutions.get(i).subtract(g); if (!d.isZero()) { double dbar = d.length(); Vector e = d.orthogonalize(e_zeta); if (!e.isZero()) { e_zeta.add(e.normalize().multiply(dbar)); } } } final double D = solutions.get(k - 1).subtract(g).length(); // create the remaining basis vectors List<Vector> e_eta = Lists.newArrayList(); e_eta.add(solutions.get(k - 1).subtract(g)); for (int i = 0; i < n - e_zeta.size() - 1; i++) { Vector d = Vector.newBuilder().copyOf(g).buildRandom(); e_eta.add(d); } e_eta = Vectors.orthonormalize(e_eta); // construct the offspring Vector variables = Vector.copyOf(g); if (!useIndividualProviders) { for (int i = 0; i < e_zeta.size(); i++) { variables = variables.plus( e_zeta.get(i).multiply(random.getRandomNumber(0.0, sigma1.getParameter()))); } for (int i = 0; i < e_eta.size(); i++) { variables = variables.plus( e_eta .get(i) .multiply( D * random.getRandomNumber(0.0, sigma2.getParameter() / Math.sqrt(n)))); } } else { for (int i = 0; i < e_zeta.size(); i++) { variables = variables.plus( e_zeta .get(i) .multiply( new Supplier<Number>() { @Override public Number get() { return random.getRandomNumber(0.0, sigma1.getParameter()); } })); } for (int i = 0; i < e_eta.size(); i++) { variables = variables.plus( e_eta .get(i) .multiply( new Supplier<Number>() { @Override public Number get() { return D * random.getRandomNumber( 0.0, sigma2.getParameter() / Math.sqrt(n)); } })); } } E child = (E) parentCollection.get(parent).getClone(); child.setCandidateSolution(variables); offspring.add(child); } return offspring; }