public static ItemArray <IItem> Apply(IItem initiator, IItem[] guides, DistanceMatrix distances, PercentValue n) { if (!(initiator is Permutation) || guides.Any(x => !(x is Permutation))) { throw new ArgumentException("Cannot relink path because some of the provided solutions have the wrong type."); } if (n.Value <= 0.0) { throw new ArgumentException("RelinkingAccuracy must be greater than 0."); } Permutation v1 = initiator.Clone() as Permutation; Permutation[] targets = new Permutation[guides.Length]; Array.Copy(guides, targets, guides.Length); if (targets.Any(x => x.Length != v1.Length)) { throw new ArgumentException("At least one solution is of different length."); } IList <Permutation> solutions = new List <Permutation>(); for (int i = 0; i < v1.Length; i++) { int currCityIndex = i; int bestCityIndex = (i + 1) % v1.Length; double currDistance = distances[v1[currCityIndex], v1[bestCityIndex]]; // check each guiding solution targets.ToList().ForEach(solution => { // locate current city var node = solution.Select((x, index) => new { Id = x, Index = index }).Single(x => x.Id == v1[currCityIndex]); int pred = solution[(node.Index - 1 + solution.Length) % solution.Length]; int succ = solution[(node.Index + 1) % solution.Length]; // get distances to neighbors var results = new[] { pred, succ }.Select(x => new { Id = x, Distance = distances[x, node.Id] }); var bestCity = results.Where(x => x.Distance < currDistance).OrderBy(x => x.Distance).FirstOrDefault(); if (bestCity != null) { bestCityIndex = v1.Select((x, index) => new { Id = x, Index = index }).Single(x => x.Id == bestCity.Id).Index; currDistance = bestCity.Distance; } }); Invert(v1, currCityIndex + 1, bestCityIndex); solutions.Add(v1.Clone() as Permutation); } IList <IItem> selection = new List <IItem>(); if (solutions.Count > 0) { int noSol = (int)(solutions.Count * n.Value); if (noSol <= 0) { noSol++; } double stepSize = (double)solutions.Count / (double)noSol; for (int i = 0; i < noSol; i++) { selection.Add(solutions.ElementAt((int)((i + 1) * stepSize - stepSize * 0.5))); } } return(new ItemArray <IItem>(selection)); }