/// <summary> /// order-based crossover operator (OX2) /// Precondition: parent1 and parent2 contain the same alleles. /// Postcondition: child contains the same alleles as parent1. /// </summary> /// <param name="parent1"></param> /// <param name="parent2"></param> /// <returns></returns> public Genotype OrderBasedCrossover(Genotype parent1, Genotype parent2) { var count = parent1.Count; if (count <= 1) { return(parent1); } var minNumberOfPositions = (int)Math.Max(1, count * MinimumNumberOfPositionsFactor); var maxNumberOfPositions = (int)Math.Max(1, count * MaximumNumberOfPositionsFactor); var numberOfPositions = random.Next(minNumberOfPositions, maxNumberOfPositions); // select alleles var selectedAllelesP2 = new HashSet <int>(); for (int i = 0; i < numberOfPositions; i++) { if (!selectedAllelesP2.Add(parent2[random.Next(0, count)])) { // already selected, try again i--; } } // copy alleles from parent1 which are not selected var emptyIndices = new List <int>(count - numberOfPositions); var child = new int[count]; for (int i = 0; i < count; i++) { var allele = parent1[i]; if (!selectedAllelesP2.Contains(allele)) { child[i] = allele; } else { emptyIndices.Add(i); } } // add the missing alleles in the order they appear in parent2 var nextPositionParent2 = 0; var missingAlleles = parent2.Intersect(selectedAllelesP2).ToArray(); foreach (var i in emptyIndices) { // find next allele child[i] = missingAlleles[nextPositionParent2]; nextPositionParent2++; } return(new Genotype(child)); }