public static LinearLinkage Apply(IRandom random, LinearLinkage p1, LinearLinkage p2) { var length = p1.Length; var lleeP1 = p1.ToEndLinks(); var lleeP2 = p2.ToEndLinks(); var lleeChild = new int[length]; var isTransfered = new bool[length]; for (var i = p1.Length - 1; i >= 0; i--) { lleeChild[i] = i; // Step 1 var isEndP1 = p1[i] == i; var isEndP2 = p2[i] == i; if (isEndP1 & isEndP2 || (isEndP1 | isEndP2 && random.NextDouble() < 0.5)) { isTransfered[i] = true; continue; } // Step 2 var end1 = lleeP1[i]; var end2 = lleeP2[i]; if (isTransfered[end1] & isTransfered[end2]) { var end = random.NextDouble() < 0.5 ? end1 : end2; lleeChild[i] = end; } else if (isTransfered[end1]) { lleeChild[i] = end1; } else if (isTransfered[end2]) { lleeChild[i] = end2; } else { var next = random.NextDouble() < 0.5 ? p1[i] : p2[i]; var end = lleeChild[next]; lleeChild[i] = end; } } return(LinearLinkage.FromEndLinks(lleeChild)); }