private PathTSPTour(PathTSPTour original, Cloner cloner) : base(original, cloner) { this.coordinates = cloner.Clone(original.coordinates); this.permutation = cloner.Clone(original.permutation); this.quality = cloner.Clone(original.quality); Initialize(); }
public void SolveTest() { double[,] costs = new double[,] { { 5, 9, 3, 6 }, { 8, 7, 8, 2 }, { 6, 10, 12, 7 }, { 3, 10, 8, 6 }}; double quality; Permutation p; p = new Permutation(PermutationTypes.Absolute, LinearAssignmentProblemSolver.Solve(new DoubleMatrix(costs), out quality)); Assert.AreEqual(18, quality); Assert.IsTrue(p.Validate()); costs = new double[,] { { 11, 7, 10, 17, 10 }, { 13, 21, 7, 11, 13 }, { 13, 13, 15, 13, 14 }, { 18, 10, 13, 16, 14 }, { 12, 8, 16, 19, 10 }}; p = new Permutation(PermutationTypes.Absolute, LinearAssignmentProblemSolver.Solve(new DoubleMatrix(costs), out quality)); Assert.AreEqual(51, quality); Assert.IsTrue(p.Validate()); costs = new double[,] { { 3, 1, 1, 4 }, { 4, 2, 2, 5 }, { 5, 3, 4, 8 }, { 4, 2, 5, 9 }}; p = new Permutation(PermutationTypes.Absolute, LinearAssignmentProblemSolver.Solve(new DoubleMatrix(costs), out quality)); Assert.AreEqual(13, quality); Assert.IsTrue(p.Validate()); }
public ThreeIndexMove(int index1, int index2, int index3, Permutation permutation) : base() { Index1 = index1; Index2 = index2; Index3 = index3; Permutation = permutation; }
private QAPAssignment(QAPAssignment original, Cloner cloner) : base(original, cloner) { distances = cloner.Clone(original.distances); weights = cloner.Clone(original.weights); assignment = cloner.Clone(original.assignment); quality = cloner.Clone(original.quality); }
private static double CalculateAbsolute(Permutation left, Permutation right) { double similarity = 0.0; for (int i = 0; i < left.Length; i++) if (left[i] == right[i]) similarity++; return similarity / left.Length; }
public static void MyClassInitialize(TestContext testContext) { random = new MersenneTwister(); symmetricDistances = new DoubleMatrix(ProblemSize, ProblemSize); symmetricWeights = new DoubleMatrix(ProblemSize, ProblemSize); asymmetricDistances = new DoubleMatrix(ProblemSize, ProblemSize); asymmetricWeights = new DoubleMatrix(ProblemSize, ProblemSize); nonZeroDiagonalDistances = new DoubleMatrix(ProblemSize, ProblemSize); nonZeroDiagonalWeights = new DoubleMatrix(ProblemSize, ProblemSize); for (int i = 0; i < ProblemSize - 1; i++) { for (int j = i + 1; j < ProblemSize; j++) { symmetricDistances[i, j] = random.Next(ProblemSize * 100); symmetricDistances[j, i] = symmetricDistances[i, j]; symmetricWeights[i, j] = random.Next(ProblemSize * 100); symmetricWeights[j, i] = symmetricWeights[i, j]; asymmetricDistances[i, j] = random.Next(ProblemSize * 100); asymmetricDistances[j, i] = random.Next(ProblemSize * 100); asymmetricWeights[i, j] = random.Next(ProblemSize * 100); asymmetricWeights[j, i] = random.Next(ProblemSize * 100); nonZeroDiagonalDistances[i, j] = random.Next(ProblemSize * 100); nonZeroDiagonalDistances[j, i] = random.Next(ProblemSize * 100); nonZeroDiagonalWeights[i, j] = random.Next(ProblemSize * 100); nonZeroDiagonalWeights[j, i] = random.Next(ProblemSize * 100); } nonZeroDiagonalDistances[i, i] = random.Next(ProblemSize * 100); nonZeroDiagonalWeights[i, i] = random.Next(ProblemSize * 100); } int index = random.Next(ProblemSize); if (nonZeroDiagonalDistances[index, index] == 0) nonZeroDiagonalDistances[index, index] = random.Next(1, ProblemSize * 100); index = random.Next(ProblemSize); if (nonZeroDiagonalWeights[index, index] == 0) nonZeroDiagonalWeights[index, index] = random.Next(1, ProblemSize * 100); assignment = new Permutation(PermutationTypes.Absolute, ProblemSize, random); }
/// <summary> /// Moves an randomly chosen element in the specified <paramref name="permutation"/> array /// to another randomly generated position. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="permutation">The permutation to manipulate.</param> public static void Apply(IRandom random, Permutation permutation) { Permutation original = (Permutation)permutation.Clone(); int cutIndex, insertIndex, number; cutIndex = random.Next(original.Length); insertIndex = random.Next(original.Length); number = original[cutIndex]; int i = 0; // index in new permutation int j = 0; // index in old permutation while (i < original.Length) { if (j == cutIndex) { j++; } if (i == insertIndex) { permutation[i] = number; i++; } if ((i < original.Length) && (j < original.Length)) { permutation[i] = original[j]; i++; j++; } } }
/// <summary> /// Performs a cross over permutation of <paramref name="parent1"/> and <paramref name="parent2"/> /// based on randomly chosen positions to define which position to take from where. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <param name="random">The random number generator.</param> /// <param name="parent1">First parent</param> /// <param name="parent2">Second Parent</param> /// <returns>Child</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("PositionBasedCrossover: The parent permutations are of unequal length."); int length = parent1.Length; int[] result = new int[length]; bool[] randomPosition = new bool[length]; bool[] numberCopied = new bool[length]; int randomPosNumber = random.Next(length); for (int i = 0; i < randomPosNumber; i++) { // generate random bit mask randomPosition[random.Next(length)] = true; } for (int i = 0; i < length; i++) { // copy numbers masked as true from second permutation if (randomPosition[i]) { result[i] = parent2[i]; numberCopied[parent2[i]] = true; } } int index = 0; for (int i = 0; i < length; i++) { // copy numbers masked as false from first permutation if (!numberCopied[parent1[i]]) { if (randomPosition[index]) { while (randomPosition[index]) { index++; } } result[index] = parent1[i]; index++; } } return new Permutation(parent1.PermutationType, result); }
public static double EvaluateByDistanceMatrix(Permutation permutation, TranslocationMove move, DistanceMatrix distanceMatrix) { if (move.Index1 == move.Index3 || move.Index2 == permutation.Length - 1 && move.Index3 == 0 || move.Index1 == 0 && move.Index3 == permutation.Length - 1 - move.Index2) return 0; int edge1source = permutation.GetCircular(move.Index1 - 1); int edge1target = permutation[move.Index1]; int edge2source = permutation[move.Index2]; int edge2target = permutation.GetCircular(move.Index2 + 1); int edge3source, edge3target; if (move.Index3 > move.Index1) { edge3source = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1); edge3target = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1); } else { edge3source = permutation.GetCircular(move.Index3 - 1); edge3target = permutation[move.Index3]; } double moveQuality = 0; // remove three edges moveQuality -= distanceMatrix[edge1source, edge1target]; moveQuality -= distanceMatrix[edge2source, edge2target]; moveQuality -= distanceMatrix[edge3source, edge3target]; // add three edges moveQuality += distanceMatrix[edge3source, edge1target]; moveQuality += distanceMatrix[edge2source, edge3target]; moveQuality += distanceMatrix[edge1source, edge2target]; return moveQuality; }
public static void Apply(Permutation permutation, int breakPoint1, int breakPoint2) { for (int i = 0; i <= (breakPoint2 - breakPoint1) / 2; i++) { // invert permutation between breakpoints int temp = permutation[breakPoint1 + i]; permutation[breakPoint1 + i] = permutation[breakPoint2 - i]; permutation[breakPoint2 - i] = temp; } }
public static ScrambleMove GenerateRandomMove(Permutation permutation, IRandom random) { int breakPoint1, breakPoint2; int[] scrambledIndices; breakPoint1 = random.Next(permutation.Length); do { breakPoint2 = random.Next(permutation.Length); } while (Math.Abs(breakPoint2 - breakPoint1) <= 1); if (breakPoint2 < breakPoint1) { int h = breakPoint1; breakPoint1 = breakPoint2; breakPoint2 = h; } scrambledIndices = new int[breakPoint2 - breakPoint1 + 1]; for (int i = 0; i < scrambledIndices.Length; i++) scrambledIndices[i] = i; bool[] moved = new bool[scrambledIndices.Length]; bool changed = false; do { for (int i = scrambledIndices.Length - 1; i > 0; i--) { int j = random.Next(i + 1); int t = scrambledIndices[j]; scrambledIndices[j] = scrambledIndices[i]; scrambledIndices[i] = t; if (scrambledIndices[j] == j) moved[j] = false; else moved[j] = true; if (scrambledIndices[i] == i) moved[i] = false; else moved[i] = true; } changed = moved.Any(x => x); } while (!changed); return new ScrambleMove(breakPoint1, scrambledIndices); }
public static double EvaluateByCoordinates(Permutation permutation, TranslocationMove move, DoubleMatrix coordinates, TSPTranslocationMovePathEvaluator evaluator) { if (move.Index1 == move.Index3 || move.Index2 == permutation.Length - 1 && move.Index3 == 0 || move.Index1 == 0 && move.Index3 == permutation.Length - 1 - move.Index2) return 0; int edge1source = permutation.GetCircular(move.Index1 - 1); int edge1target = permutation[move.Index1]; int edge2source = permutation[move.Index2]; int edge2target = permutation.GetCircular(move.Index2 + 1); int edge3source, edge3target; if (move.Index3 > move.Index1) { edge3source = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1); edge3target = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1); } else { edge3source = permutation.GetCircular(move.Index3 - 1); edge3target = permutation[move.Index3]; } double moveQuality = 0; // remove three edges moveQuality -= evaluator.CalculateDistance(coordinates[edge1source, 0], coordinates[edge1source, 1], coordinates[edge1target, 0], coordinates[edge1target, 1]); moveQuality -= evaluator.CalculateDistance(coordinates[edge2source, 0], coordinates[edge2source, 1], coordinates[edge2target, 0], coordinates[edge2target, 1]); moveQuality -= evaluator.CalculateDistance(coordinates[edge3source, 0], coordinates[edge3source, 1], coordinates[edge3target, 0], coordinates[edge3target, 1]); // add three edges moveQuality += evaluator.CalculateDistance(coordinates[edge3source, 0], coordinates[edge3source, 1], coordinates[edge1target, 0], coordinates[edge1target, 1]); moveQuality += evaluator.CalculateDistance(coordinates[edge2source, 0], coordinates[edge2source, 1], coordinates[edge3target, 0], coordinates[edge3target, 1]); moveQuality += evaluator.CalculateDistance(coordinates[edge1source, 0], coordinates[edge1source, 1], coordinates[edge2target, 0], coordinates[edge2target, 1]); return moveQuality; }
/// <summary> /// Calculates the quality of the move <paramref name="move"/> by evaluating the changes. /// The runtime complexity of this method is O(N) with N being the size of the permutation. /// </summary> /// <param name="assignment">The current permutation.</param> /// <param name="move">The move that is to be evaluated if it was applied to the current permutation.</param> /// <param name="weights">The weights matrix.</param> /// <param name="distances">The distances matrix.</param> /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns> public static double Apply(Permutation assignment, ScrambleMove move, DoubleMatrix weights, DoubleMatrix distances) { double moveQuality = 0; int min = move.StartIndex; int max = min + move.ScrambledIndices.Length - 1; for (int i = min; i <= max; i++) { int locI = assignment[i]; int newlocI = assignment[min + move.ScrambledIndices[i - min]]; if (locI == newlocI) continue; for (int j = 0; j < assignment.Length; j++) { int locJ = assignment[j]; if (j >= min && j <= max) { int newlocJ = assignment[min + move.ScrambledIndices[j - min]]; moveQuality += weights[i, j] * (distances[newlocI, newlocJ] - distances[locI, locJ]); if (locJ == newlocJ) moveQuality += weights[j, i] * (distances[newlocJ, newlocI] - distances[locJ, locI]); } else { moveQuality += weights[i, j] * (distances[newlocI, locJ] - distances[locI, locJ]); moveQuality += weights[j, i] * (distances[locJ, newlocI] - distances[locJ, locI]); } } } return moveQuality; }
/// <summary> /// Performs the order crossover of two permutations. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <exception cref="InvalidOperationException">Thrown if the numbers in the permutation elements are not in the range [0,N) with N = length of the permutation.</exception> /// <remarks> /// Crosses two permutations by copying a randomly chosen interval from the first permutation, preserving /// the positions. Then, starting from the end of the copied interval, copies the missing values from the second permutation /// in the order they occur. /// </remarks> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent permutation to cross.</param> /// <param name="parent2">The second parent permutation to cross.</param> /// <returns>The new permutation resulting from the crossover.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("OrderCrossover: The parent permutations are of unequal length."); int length = parent1.Length; int[] result = new int[length]; bool[] copied = new bool[length]; int breakPoint1 = random.Next(length - 1); int breakPoint2 = random.Next(breakPoint1 + 1, length); try { for (int j = breakPoint1; j <= breakPoint2; j++) { // copy part of first permutation result[j] = parent1[j]; copied[parent1[j]] = true; } int index = ((breakPoint2 + 1 >= length) ? (0) : (breakPoint2 + 1)); int i = index; // for moving in parent2 while (index != breakPoint1) { if (!copied[parent2[i]]) { result[index] = parent2[i]; index++; if (index >= length) index = 0; } i++; if (i >= length) i = 0; } } catch (IndexOutOfRangeException) { throw new InvalidOperationException("OrderCrossover: The permutation must consist of numbers in the interval [0;N) with N = length of the permutation."); } return new Permutation(parent1.PermutationType, result); }
public static double Evaluate(Permutation tour, Func<int, int, double> distance, DoubleArray probabilities) { // Analytical evaluation var firstSum = 0.0; for (var i = 0; i < tour.Length - 1; i++) { for (var j = i + 1; j < tour.Length; j++) { var prod1 = distance(tour[i], tour[j]) * probabilities[tour[i]] * probabilities[tour[j]]; for (var k = i + 1; k < j; k++) { prod1 = prod1 * (1 - probabilities[tour[k]]); } firstSum += prod1; } } var secondSum = 0.0; for (var j = 0; j < tour.Length; j++) { for (var i = 0; i < j; i++) { var prod2 = distance(tour[j], tour[i]) * probabilities[tour[i]] * probabilities[tour[j]]; for (var k = j + 1; k < tour.Length; k++) { prod2 = prod2 * (1 - probabilities[tour[k]]); } for (var k = 0; k < i; k++) { prod2 = prod2 * (1 - probabilities[tour[k]]); } secondSum += prod2; } } return firstSum + secondSum; }
public static double Apply(Permutation assignment, TranslocationMove move, DoubleMatrix weights, DoubleMatrix distances) { double moveQuality = 0; int min = Math.Min(move.Index1, move.Index3); int max = Math.Max(move.Index2, move.Index3 + (move.Index2 - move.Index1)); int iOffset, changeOffset; if (move.Index1 < move.Index3) { iOffset = move.Index2 - move.Index1 + 1; changeOffset = min + max - move.Index2; } else { iOffset = move.Index1 - move.Index3; changeOffset = min + move.Index2 - move.Index1 + 1; } for (int i = min; i <= max; i++) { if (i == changeOffset) iOffset -= (max - min + 1); int jOffset = ((move.Index1 < move.Index3) ? (move.Index2 - move.Index1 + 1) : (move.Index1 - move.Index3)); for (int j = 0; j < assignment.Length; j++) { moveQuality -= weights[i, j] * distances[assignment[i], assignment[j]]; if (j < min || j > max) { moveQuality -= weights[j, i] * distances[assignment[j], assignment[i]]; moveQuality += weights[i, j] * distances[assignment[i + iOffset], assignment[j]]; moveQuality += weights[j, i] * distances[assignment[j], assignment[i + iOffset]]; } else { if (j == changeOffset) jOffset -= (max - min + 1); moveQuality += weights[i, j] * distances[assignment[i + iOffset], assignment[j + jOffset]]; } } } return moveQuality; }
protected TwoIndexMove(TwoIndexMove original, Cloner cloner) : base(original, cloner) { this.Index1 = original.Index1; this.Index2 = original.Index2; if (original.Permutation != null) this.Permutation = cloner.Clone(original.Permutation); }
/// <summary> /// Mixes the elements of the given <paramref name="permutation"/> randomly /// in a randomly chosen interval. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="permutation">The permutation to manipulate.</param> public static void Apply(IRandom random, Permutation permutation) { int breakPoint1, breakPoint2; int[] scrambledIndices, remainingIndices, temp; int selectedIndex, index; breakPoint1 = random.Next(permutation.Length - 1); breakPoint2 = random.Next(breakPoint1 + 1, permutation.Length); scrambledIndices = new int[breakPoint2 - breakPoint1 + 1]; remainingIndices = new int[breakPoint2 - breakPoint1 + 1]; for (int i = 0; i < remainingIndices.Length; i++) { // initialise indices remainingIndices[i] = i; } for (int i = 0; i < scrambledIndices.Length; i++) { // generate permutation of indices selectedIndex = random.Next(remainingIndices.Length); scrambledIndices[i] = remainingIndices[selectedIndex]; temp = remainingIndices; remainingIndices = new int[temp.Length - 1]; index = 0; for (int j = 0; j < remainingIndices.Length; j++) { if (index == selectedIndex) { index++; } remainingIndices[j] = temp[index]; index++; } } Apply(permutation, breakPoint1, scrambledIndices); }
public static double CalculatePhenotypeDistance(Permutation a, Permutation b, DoubleMatrix weights, DoubleMatrix distances) { Dictionary<double, Dictionary<double, int>> alleles = new Dictionary<double, Dictionary<double, int>>(); int distance = 0, len = a.Length; for (int x = 0; x < len; x++) { for (int y = 0; y < len; y++) { // there's a limited universe of double values as they're all drawn from the same matrix double dA = distances[a[x], a[y]], dB = distances[b[x], b[y]]; if (dA == dB) continue; Dictionary<double, int> dAlleles; if (!alleles.ContainsKey(weights[x, y])) { dAlleles = new Dictionary<double, int>(); alleles.Add(weights[x, y], dAlleles); } else dAlleles = alleles[weights[x, y]]; int countA = 1, countB = -1; if (dAlleles.ContainsKey(dA)) countA += dAlleles[dA]; if (dAlleles.ContainsKey(dB)) countB += dAlleles[dB]; if (countA <= 0) distance--; // we've found in A an allele that was present in B else distance++; // we've found in A a new allele dAlleles[dA] = countA; if (countB >= 0) distance--; // we've found in B an allele that was present in A else distance++; // we've found in B a new allele dAlleles[dB] = countB; } } return distance / (double)(2 * len * len); }
public static TwoPointFiveMove[] Apply(Permutation permutation, IRandom random, int sampleSize) { var moves = new TwoPointFiveMove[sampleSize]; for (var i = 0; i < sampleSize; i++) { moves[i] = StochasticTwoPointFiveSingleMoveGenerator.Apply(permutation, random); } return moves; }
public TwoPointFiveMove(int index1, int index2, Permutation permutation, bool isinvert) : base() { Index1 = index1; Index2 = index2; IsInvert = isinvert; Permutation = permutation; }
/// <summary> /// Moves a randomly chosen interval of elements to another (randomly chosen) position in the given /// <paramref name="permutation"/> array and reverses it. /// </summary> /// <param name="random">The random number generator.</param> /// <param name="permutation">The permutation array to manipulate.</param> public static void Apply(IRandom random, Permutation permutation) { Permutation original = (Permutation)permutation.Clone(); int breakPoint1, breakPoint2, insertPoint, insertPointLimit; breakPoint1 = random.Next(original.Length - 1); breakPoint2 = random.Next(breakPoint1 + 1, original.Length); insertPointLimit = original.Length - breakPoint2 + breakPoint1 - 1; // get insertion point in remaining part if (insertPointLimit > 0) insertPoint = random.Next(insertPointLimit); else insertPoint = 0; int i = 0; // index in new permutation int j = 0; // index in old permutation while (i < original.Length) { if (i == insertPoint) { // copy translocated area for (int k = breakPoint2; k >= breakPoint1; k--) { permutation[i] = original[k]; i++; } } if (j == breakPoint1) { // skip area between breakpoints j = breakPoint2 + 1; } if ((i < original.Length) && (j < original.Length)) { permutation[i] = original[j]; i++; j++; } } }
/// <summary> /// Performs the partially matched crossover on <paramref name="parent1"/> and <paramref name="parent2"/>. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length or when the permutations are shorter than 4 elements.</exception> /// <exception cref="InvalidOperationException">Thrown if the numbers in the permutation elements are not in the range [0,N) with N = length of the permutation.</exception> /// <remarks> /// Initially the new offspring is a clone of <paramref name="parent2"/>. /// Then a segment is extracted from <paramref name="parent1"/> and copied to the offspring position by position. /// Whenever a position is copied, the number at that position currently in the offspring is transfered to the position where the copied number has been. /// E.g.: Position 15 is selected to be copied from <paramref name="parent1"/> to <paramref name="parent2"/>. At position 15 there is a '3' in <paramref name="parent1"/> and a '5' in the new offspring. /// The '5' in the offspring is then moved to replace the '3' in the offspring and '3' is written at position 15. /// </remarks> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent permutation to cross.</param> /// <param name="parent2">The second parent permutation to cross.</param> /// <returns>The new permutation resulting from the crossover.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("PartiallyMatchedCrossover: The parent permutations are of unequal length."); if (parent1.Length < 4) throw new ArgumentException("PartiallyMatchedCrossover: The parent permutation must be at least of size 4."); int length = parent1.Length; int[] result = new int[length]; int[] invResult = new int[length]; int breakPoint1, breakPoint2; do { breakPoint1 = random.Next(length - 1); breakPoint2 = random.Next(breakPoint1 + 1, length); } while (breakPoint2 - breakPoint1 >= length - 2); // prevent the case [0,length-1) -> clone of parent1 // clone parent2 and calculate inverse permutation (number -> index) try { for (int j = 0; j < length; j++) { result[j] = parent2[j]; invResult[result[j]] = j; } } catch (IndexOutOfRangeException) { throw new InvalidOperationException("PartiallyMatchedCrossover: The permutation must consist of consecutive numbers from 0 to N-1 with N = length of the permutation."); } for (int j = breakPoint1; j <= breakPoint2; j++) { int orig = result[j]; // save the former value result[j] = parent1[j]; // overwrite the former value with the new value int index = invResult[result[j]]; // look where the new value is in the offspring result[index] = orig; // write the former value to this position invResult[orig] = index; // update the inverse mapping // it's not necessary to do 'invResult[result[j]] = j' as this will not be needed again } return new Permutation(parent1.PermutationType, result); }
/// <summary> /// Performs a variant of the cyclic crossover on <paramref name="parent1"/> and <paramref name="parent2"/>. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <exception cref="InvalidOperationException">Thrown if the numbers in the permutation elements are not in the range [0;N) with N = length of the permutation.</exception> /// <remarks> /// Start at a randomly chosen position x in parent1 and transfer it to the child at the same position. /// Now this position x is no longer available for the node on position x in parent2, so /// the value of the node at position x in parent2 is searched in parent1 and is then transferred /// to the child preserving the position. Now this new position y is no longer available for the node in parent2 and so on.<br/> /// This procedure is repeated until it is again at position x, then the cycle is over.<br/> /// All further positions are copied from the second permutation. /// </remarks> /// <exception cref="ArgumentException">Thrown if the two parents are not of equal length.</exception> /// <param name="random">The random number generator.</param> /// <param name="parent1">The parent scope 1 to cross over.</param> /// <param name="parent2">The parent scope 2 to cross over.</param> /// <returns>The created cross over permutation as int array.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("CyclicCrossover2: The parent permutations are of unequal length."); int length = parent1.Length; int[] result = new int[length]; bool[] indexCopied = new bool[length]; int j, number; j = random.Next(length); // get number to start cycle while (!indexCopied[j]) { // copy whole cycle to new permutation result[j] = parent1[j]; number = parent2[j]; indexCopied[j] = true; j = 0; while ((j < length) && (parent1[j] != number)) { // search copied number in second permutation j++; } } for (int i = 0; i < length; i++) { // copy rest of secound permutation to new permutation if (!indexCopied[i]) { result[i] = parent2[i]; } } return new Permutation(parent1.PermutationType, result); }
private static int[] GetSubSequenceAtPosition(Permutation p1, int index, int subSequenceLength) { var result = new int[subSequenceLength]; for (int i = 0; i < subSequenceLength; i++) result[i] = p1[i + index]; return result; }
public static IEnumerable<TwoPointFiveMove> Generate(Permutation permutation) { int length = permutation.Length; if (length == 1) throw new ArgumentException("Exhaustive 2.5-MoveGenerator: There cannot be a 2.5 move given a permutation of length 1.", "permutation"); int totalMoves = (length) * (length - 1) / 2; if (permutation.PermutationType == PermutationTypes.RelativeUndirected) { if (totalMoves - 3 > 0) { for (int i = 0; i < length - 1; i++) { for (int j = i + 1; j < length; j++) { // doesn't make sense to inverse the whole permutation or the whole but one in case of relative undirected permutations if (j - i >= length - 2) continue; yield return new TwoPointFiveMove(i, j, true); yield return new TwoPointFiveMove(i, j, false); } } } else { // when length is 3 or less, there's actually no difference, but for the sake of not crashing the algorithm create a dummy move yield return new TwoPointFiveMove(0, 1, true); } } else { for (int i = 0; i < length - 1; i++) for (int j = i + 1; j < length; j++) { yield return new TwoPointFiveMove(i, j, true); yield return new TwoPointFiveMove(i, j, false); } } }
public static void Apply(Permutation permutation, TwoPointFiveMove move) { if (move.IsInvert) { InversionManipulator.Apply(permutation, move.Index1, move.Index2); } else { TranslocationManipulator.Apply(permutation, move.Index1, move.Index1, move.Index2); } }
private static void ExchangeSubsequences(Permutation p1, int index1, Permutation p2, int index2, int subSequenceLength) { var aux = (Permutation)p1.Clone(); for (int i = 0; i < subSequenceLength; i++) { p1[i + index1] = p2[i + index2]; p2[i + index2] = aux[i + index1]; } }
public static double CalculateGenotypeSimilarity(Permutation a, Permutation b) { int similar = 0; for (int i = 0; i < a.Length; i++) { if (a[i] == b[i]) similar++; } return similar / (double)a.Length; }
/// <summary> /// Performs a slight variation of the order crossover of two permutations. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <remarks> /// Crosses two permutations by copying a randomly chosen interval from the first permutation, preserving /// the positions. Then, from the beginning of the permutation, copies the missing values from the second permutation /// in the order they occur. /// </remarks> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent permutation to cross.</param> /// <param name="parent2">The second parent permutation to cross.</param> /// <returns>The new permutation resulting from the crossover.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) throw new ArgumentException("OrderCrossover2: The parent permutations are of unequal length."); int[] result = new int[parent1.Length]; bool[] copied = new bool[result.Length]; int breakPoint1 = random.Next(result.Length - 1); int breakPoint2 = random.Next(breakPoint1 + 1, result.Length); for (int i = breakPoint1; i <= breakPoint2; i++) { // copy part of first permutation result[i] = parent1[i]; copied[parent1[i]] = true; } int index = 0; for (int i = 0; i < parent2.Length; i++) { // copy remaining part of second permutation if (index == breakPoint1) { // skip already copied part index = breakPoint2 + 1; } if (!copied[parent2[i]]) { result[index] = parent2[i]; index++; } } return new Permutation(parent1.PermutationType, result); }
public TranslocationMove(int index1, int index2, int index3, Permutation permutation) : base(index1, index2, index3, permutation) { }
protected abstract Swap2Move[] GenerateMoves(Permutation permutation);
/// <summary> /// Performs the maximal preservative crossover on <paramref name="parent1"/> and <paramref name="parent2"/> /// by preserving a large number of edges in both parents. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length or when the permutations are shorter than 4 elements.</exception> /// <exception cref="InvalidOperationException">Thrown if the numbers in the permutation elements are not in the range [0;N) with N = length of the permutation.</exception> /// <remarks> /// First one segment is copied from the first parent to the offspring in the same position. /// Then the tour is completed by adding the next number from the second parent if such an edge exists, /// or from the first parent, or from the next number of the second parent. /// The last case results in an unwanted mutation. /// </remarks> /// <param name="random">A random number generator.</param> /// <param name="parent1">The first parent permutation to cross.</param> /// <param name="parent2">The second parent permutation to cross.</param> /// <returns>The new permutation resulting from the crossover.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) { throw new ArgumentException("MaximalPreservativeCrossover: The parent permutations are of unequal length."); } if (parent1.Length < 4) { throw new ArgumentException("MaximalPreservativeCrossover: The parent permutation must be at least of size 4."); } int length = parent1.Length; int[] result = new int[length]; bool[] numberCopied = new bool[length]; int breakPoint1, breakPoint2, subsegmentLength, index; subsegmentLength = random.Next(3, Math.Max(length / 3, 4)); // as mentioned in Pohlheim, H. Evolutionäre Algorithmen: Verfahren, Operatoren und Hinweise für die Praxis, 1999, p.44, Springer. breakPoint1 = random.Next(length); breakPoint2 = breakPoint1 + subsegmentLength; if (breakPoint2 >= length) { breakPoint2 -= length; } // copy string between position [breakPoint1, breakPoint2) from parent1 to the offspring index = breakPoint1; do { result[index] = parent1[index]; numberCopied[result[index]] = true; index++; if (index >= length) { index -= length; } } while (index != breakPoint2); // calculate inverse permutation (number -> index) to help finding the follower of a given number int[] invParent1 = new int[length]; int[] invParent2 = new int[length]; try { for (int i = 0; i < length; i++) { invParent1[parent1[i]] = i; invParent2[parent2[i]] = i; } } catch (IndexOutOfRangeException) { throw new InvalidOperationException("MaximalPreservativeCrossover: The permutation must consist of numbers in the interval [0;N) with N = length of the permutation."); } int prevIndex = ((index > 0) ? (index - 1) : (length - 1)); do { // look for the follower of the last number in parent2 int p2Follower = GetFollower(parent2, invParent2[result[prevIndex]]); if (!numberCopied[p2Follower]) { result[index] = p2Follower; } else { // if that follower has already been added, look for the follower of the last number in parent1 int p1Follower = GetFollower(parent1, invParent1[result[prevIndex]]); if (!numberCopied[p1Follower]) { result[index] = p1Follower; } else { // if that has also been added, look for the next not already added number in parent2 int tempIndex = index; for (int i = 0; i < parent2.Length; i++) { if (!numberCopied[parent2[tempIndex]]) { result[index] = parent2[tempIndex]; break; } tempIndex++; if (tempIndex >= parent2.Length) { tempIndex = 0; } } } } numberCopied[result[index]] = true; prevIndex = index; index++; if (index >= length) { index -= length; } } while (index != breakPoint1); return(new Permutation(parent1.PermutationType, result)); }
protected override Swap2Move[] GenerateMoves(Permutation permutation) { return(Apply(permutation)); }
protected override Swap2Move[] GenerateMoves(Permutation permutation) { IRandom random = RandomParameter.ActualValue; return(Apply(permutation, random, SampleSizeParameter.ActualValue.Value)); }
/// <summary> /// Inverts a randomly chosen part of a permutation. /// </summary> /// <param name="random">A random number generator.</param> /// <param name="permutation">The permutation to manipulate.</param> protected override void Manipulate(IRandom random, Permutation permutation) { Apply(random, permutation); }
protected abstract InversionMove[] GenerateMoves(Permutation permutation);
protected override TranslocationMove[] GenerateMoves(Permutation permutation) { return(Apply(permutation)); }
public static TranslocationMove[] Apply(Permutation permutation) { return(Generate(permutation).ToArray()); }
protected abstract TranslocationMove[] GenerateMoves(Permutation permutation);
protected override Swap2Move[] GenerateMoves(Permutation permutation) { IRandom random = RandomParameter.ActualValue; return(new Swap2Move[] { Apply(permutation, random) }); }
private bool EvaluateAbsoluteTabuState(ItemList <IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) { bool isTabu = false; foreach (IItem tabuMove in tabuList) { Swap2MoveAbsoluteAttribute attrib = (tabuMove as Swap2MoveAbsoluteAttribute); if (attrib != null && (!useAspiration || maximization && moveQuality <= attrib.MoveQuality || !maximization && moveQuality >= attrib.MoveQuality)) { int i1 = move.Index1; int n1 = permutation[move.Index1]; int i2 = move.Index2; int n2 = permutation[move.Index2]; if ((attrib.Index1 == i1 || attrib.Index1 == i2) && (attrib.Number1 == n1 || attrib.Number1 == n2) || (attrib.Index2 == i2 || attrib.Index2 == i1) && (attrib.Number2 == n2 || attrib.Number2 == n1)) { isTabu = true; } } if (isTabu) { break; } } return(isTabu); }
public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) { throw new ArgumentException("parent1 and parent2 are of different length."); } int length = parent1.Length; int[] child = new int[length]; bool[] numberCopied = new bool[length]; List <int> unoccupied = new List <int>(); for (int i = 0; i < length; i++) { bool copied = true; if (parent1[i] == parent2[i]) { child[i] = parent1[i]; } else if (!numberCopied[parent1[i]] && !numberCopied[parent2[i]]) { child[i] = (random.NextDouble() < 0.5) ? parent1[i] : parent2[i]; } else if (!numberCopied[parent1[i]]) { child[i] = parent1[i]; } else if (!numberCopied[parent2[i]]) { child[i] = parent2[i]; } else { copied = false; unoccupied.Add(i); } if (copied) { numberCopied[child[i]] = true; } } if (unoccupied.Count > 0) { for (int i = 0; i < length; i++) { if (!numberCopied[i]) { int r = random.Next(unoccupied.Count); child[unoccupied[r]] = i; unoccupied.RemoveAt(r); } if (unoccupied.Count == 0) { break; } } } return(new Permutation(parent1.PermutationType, child)); }
public override IOperation Apply() { ItemList <IItem> tabuList = TabuListParameter.ActualValue; TranslocationMove move = TranslocationMoveParameter.ActualValue; Permutation permutation = PermutationParameter.ActualValue; int length = permutation.Length; double moveQuality = MoveQualityParameter.ActualValue.Value; bool maximization = MaximizationParameter.ActualValue.Value; bool useAspiration = UseAspirationCriterion.Value; bool isTabu = false; if (permutation.PermutationType == PermutationTypes.Absolute) { int count = move.Index2 - move.Index1 + 1; int[] numbers = new int[count]; for (int i = move.Index1; i <= move.Index2; i++) { numbers[i - move.Index1] = permutation[i]; } foreach (IItem tabuMove in tabuList) { TranslocationMoveAbsoluteAttribute attribute = (tabuMove as TranslocationMoveAbsoluteAttribute); if (attribute != null) { if (!useAspiration || maximization && moveQuality <= attribute.MoveQuality || !maximization && moveQuality >= attribute.MoveQuality) // if the move quality is improving beyond what was recorded when the move in the tabu list was recorded the move is regarded as okay { for (int i = 0; i < count; i++) { for (int j = 0; j < attribute.Number.Length; j++) { if (attribute.Number[j] == numbers[i] && attribute.OldPosition + j == move.Index3 + i) { isTabu = true; break; } } if (isTabu) { break; } } } } if (isTabu) { break; } } } else { int E1S = permutation.GetCircular(move.Index1 - 1); int E1T = permutation[move.Index1]; int E2S = permutation[move.Index2]; int E2T = permutation.GetCircular(move.Index2 + 1); int E3S, E3T; if (move.Index3 > move.Index1) { E3S = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1); E3T = permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1); } else { E3S = permutation.GetCircular(move.Index3 - 1); E3T = permutation[move.Index3]; } foreach (IItem tabuMove in tabuList) { TranslocationMoveRelativeAttribute attribute = (tabuMove as TranslocationMoveRelativeAttribute); if (attribute != null) { if (!useAspiration || maximization && moveQuality <= attribute.MoveQuality || !maximization && moveQuality >= attribute.MoveQuality) { // if previously deleted Edge1Source-Target is readded if (permutation.PermutationType == PermutationTypes.RelativeUndirected) { if (attribute.Edge1Source == E3S && attribute.Edge1Target == E1T || attribute.Edge1Source == E1T && attribute.Edge1Target == E3S || attribute.Edge1Source == E2S && attribute.Edge1Target == E3T || attribute.Edge1Source == E3T && attribute.Edge1Target == E2S // if previously deleted Edge2Source-Target is readded || attribute.Edge2Source == E3S && attribute.Edge2Target == E1T || attribute.Edge2Source == E1T && attribute.Edge2Target == E3S || attribute.Edge2Source == E2S && attribute.Edge2Target == E3T || attribute.Edge2Source == E3T && attribute.Edge2Target == E2S // if previously deleted Edge3Source-Target is readded || attribute.Edge3Source == E3S && attribute.Edge3Target == E1T || attribute.Edge3Source == E1T && attribute.Edge3Target == E3S || attribute.Edge3Source == E2S && attribute.Edge3Target == E3T || attribute.Edge3Source == E3T && attribute.Edge3Target == E2S) { isTabu = true; break; } } else { if (attribute.Edge1Source == E3S && attribute.Edge1Target == E1T || attribute.Edge1Source == E2S && attribute.Edge1Target == E3T // if previously deleted Edge2Source-Target is readded || attribute.Edge2Source == E3S && attribute.Edge2Target == E1T || attribute.Edge2Source == E2S && attribute.Edge2Target == E3T // if previously deleted Edge3Source-Target is readded || attribute.Edge3Source == E3S && attribute.Edge3Target == E1T || attribute.Edge3Source == E2S && attribute.Edge3Target == E3T) { isTabu = true; break; } } } } } } MoveTabuParameter.ActualValue = new BoolValue(isTabu); return(base.Apply()); }
private static bool EvaluateRelativeTabuState(ItemList <IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) { bool isTabu = false; StandardEdgeEqualityComparer eq = new StandardEdgeEqualityComparer(); bool bidirectional = permutation.PermutationType == PermutationTypes.RelativeUndirected; List <Edge> added = new List <Edge>(); added.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index2], bidirectional)); added.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index1 + 1), bidirectional)); added.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index1], bidirectional)); added.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index2 + 1), bidirectional)); foreach (IItem tabuMove in tabuList) { Swap2MoveRelativeAttribute relAttrib = (tabuMove as Swap2MoveRelativeAttribute); if (relAttrib != null && (!useAspiration || maximization && moveQuality <= relAttrib.MoveQuality || !maximization && moveQuality >= relAttrib.MoveQuality)) { for (int i = 0; i < relAttrib.DeletedEdges.Count; i++) { isTabu = eq.Equals(relAttrib.DeletedEdges[i], added[0]) || eq.Equals(relAttrib.DeletedEdges[i], added[1]) || eq.Equals(relAttrib.DeletedEdges[i], added[2]) || eq.Equals(relAttrib.DeletedEdges[i], added[3]); if (isTabu) { break; } } } if (isTabu) { break; } } return(isTabu); }
public InversionMove(int index1, int index2, Permutation permutation) : base(index1, index2, permutation) { }
public Swap2Move(int index1, int index2, Permutation permutation) : base(index1, index2, permutation) { }
public static void Apply(Permutation permutation, int startIndex, int[] scrambleArray) { permutation.Replace(startIndex, scrambleArray.Select(x => permutation[startIndex + x]).ToArray()); }
protected Permutation(Permutation original, Cloner cloner) : base(original, cloner) { this.permutationType = original.permutationType; }
public static InversionMove[] Apply(Permutation permutation) { return(Generate(permutation).ToArray()); }
/// <summary> /// Performs a cross over permutation of <paramref name="parent1"/> and <paramref name="2"/> /// by calculating the edges of each element. Starts at a randomly chosen position, /// the next element is a neighbour with the least /// number of neighbours, the next again a neighbour and so on. /// </summary> /// <exception cref="ArgumentException">Thrown when <paramref name="parent1"/> and <paramref name="parent2"/> are not of equal length.</exception> /// <exception cref="InvalidOperationException">Thrown when the permutation lacks a number. /// </exception> /// <param name="random">The random number generator.</param> /// <param name="parent1">The parent scope 1 to cross over.</param> /// <param name="parent2">The parent scope 2 to cross over.</param> /// <returns>The created cross over permutation as int array.</returns> public static Permutation Apply(IRandom random, Permutation parent1, Permutation parent2) { if (parent1.Length != parent2.Length) { throw new ArgumentException("EdgeRecombinationCrossover: The parent permutations are of unequal length."); } int length = parent1.Length; int[] result = new int[length]; int[,] edgeList = new int[length, 4]; bool[] remainingNumbers = new bool[length]; int index, currentEdge, currentNumber, nextNumber, currentEdgeCount, minEdgeCount; for (int i = 0; i < length; i++) // generate edge list for every number { remainingNumbers[i] = true; index = 0; while ((index < length) && (parent1[index] != i)) // search edges in parent1 { index++; } if (index == length) { throw (new InvalidOperationException("Permutation doesn't contain number " + i + ".")); } else { edgeList[i, 0] = parent1[(index - 1 + length) % length]; edgeList[i, 1] = parent1[(index + 1) % length]; } index = 0; while ((index < length) && (parent2[index] != i)) // search edges in parent2 { index++; } if (index == length) { throw (new InvalidOperationException("Permutation doesn't contain number " + i + ".")); } else { currentEdge = parent2[(index - 1 + length) % length]; if ((edgeList[i, 0] != currentEdge) && (edgeList[i, 1] != currentEdge)) // new edge found ? { edgeList[i, 2] = currentEdge; } else { edgeList[i, 2] = -1; } currentEdge = parent2[(index + 1) % length]; if ((edgeList[i, 0] != currentEdge) && (edgeList[i, 1] != currentEdge)) // new edge found ? { edgeList[i, 3] = currentEdge; } else { edgeList[i, 3] = -1; } } } currentNumber = random.Next(length); // get number to start for (int i = 0; i < length; i++) { result[i] = currentNumber; remainingNumbers[currentNumber] = false; for (int j = 0; j < 4; j++) // remove all edges to / from currentNumber { if (edgeList[currentNumber, j] != -1) { for (int k = 0; k < 4; k++) { if (edgeList[edgeList[currentNumber, j], k] == currentNumber) { edgeList[edgeList[currentNumber, j], k] = -1; } } } } minEdgeCount = 5; // every number hasn't more than 4 edges nextNumber = -1; for (int j = 0; j < 4; j++) // find next number with least edges { if (edgeList[currentNumber, j] != -1) // next number found { currentEdgeCount = 0; for (int k = 0; k < 4; k++) // count edges of next number { if (edgeList[edgeList[currentNumber, j], k] != -1) { currentEdgeCount++; } } if ((currentEdgeCount < minEdgeCount) || ((currentEdgeCount == minEdgeCount) && (random.NextDouble() < 0.5))) { nextNumber = edgeList[currentNumber, j]; minEdgeCount = currentEdgeCount; } } } currentNumber = nextNumber; if (currentNumber == -1) // current number has no more edge { index = 0; while ((index < length) && (!remainingNumbers[index])) // choose next remaining number { index++; } if (index < length) { currentNumber = index; } } } return(new Permutation(parent1.PermutationType, result)); }
public override IOperation Apply() { ItemList <IItem> tabuList = TabuListParameter.ActualValue; InversionMove move = InversionMoveParameter.ActualValue; Permutation permutation = PermutationParameter.ActualValue; int length = permutation.Length; double moveQuality = MoveQualityParameter.ActualValue.Value; bool maximization = MaximizationParameter.ActualValue.Value; bool useAspiration = UseAspirationCriterion.Value; bool isTabu = false; foreach (IItem tabuMove in tabuList) { PermutationMoveAttribute attrib = (tabuMove as PermutationMoveAttribute); if (!useAspiration || maximization && moveQuality <= attrib.MoveQuality || !maximization && moveQuality >= attrib.MoveQuality) { switch (permutation.PermutationType) { case PermutationTypes.RelativeUndirected: { int E1S = permutation.GetCircular(move.Index1 - 1); int E1T = permutation[move.Index1]; int E2S = permutation[move.Index2]; int E2T = permutation.GetCircular(move.Index2 + 1); InversionMoveRelativeAttribute relAttrib = (attrib as InversionMoveRelativeAttribute); if (relAttrib != null) { if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T || relAttrib.Edge1Source == E1T && relAttrib.Edge2Source == E1S || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge2Source == E2S // if previously added Edge1Target-Edge2Target is deleted || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T || relAttrib.Edge1Target == E2T && relAttrib.Edge2Target == E2S || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T || relAttrib.Edge1Target == E1T && relAttrib.Edge2Target == E1S) { isTabu = true; } } } break; case PermutationTypes.RelativeDirected: { int E1S = permutation.GetCircular(move.Index1 - 1); int E1T = permutation[move.Index1]; int E2S = permutation[move.Index2]; int E2T = permutation.GetCircular(move.Index2 + 1); InversionMoveRelativeAttribute relAttrib = (attrib as InversionMoveRelativeAttribute); if (relAttrib != null) { if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T // if previously added Edge1Target-Edge2Target is deleted || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T) { isTabu = true; } } } break; case PermutationTypes.Absolute: { int i1 = move.Index1; int n1 = permutation[move.Index1]; int i2 = move.Index2; int n2 = permutation[move.Index2]; InversionMoveAbsoluteAttribute absAttrib = (attrib as InversionMoveAbsoluteAttribute); if (absAttrib != null) { if (absAttrib.Number1 == n1 || absAttrib.Number1 == n2 || absAttrib.Number2 == n2 || absAttrib.Number2 == n1) { isTabu = true; } } } break; default: { throw new InvalidOperationException(Name + ": Unknown permutation type."); } } } if (isTabu) { break; } } MoveTabuParameter.ActualValue = new BoolValue(isTabu); return(base.Apply()); }
protected abstract void Manipulate(IRandom random, Permutation permutation);
protected abstract ScrambleMove[] GenerateMoves(Permutation permutation);
public static TranslocationMove[] Apply(Permutation permutation, IRandom random, int sampleSize) { int length = permutation.Length; if (length == 1) { throw new ArgumentException("ExhaustiveSingleInsertionMoveGenerator: There cannot be an insertion move given a permutation of length 1.", "permutation"); } TranslocationMove[] moves = new TranslocationMove[sampleSize]; int count = 0; HashSet <int> usedIndices = new HashSet <int>(); while (count < sampleSize) { int index = random.Next(length); if (usedIndices.Count != length) { while (usedIndices.Contains(index)) { index = random.Next(length); } } usedIndices.Add(index); if (permutation.PermutationType == PermutationTypes.Absolute) { for (int j = 1; j <= length - 1; j++) { moves[count++] = new TranslocationMove(index, index, (index + j) % length); if (count == sampleSize) { break; } } } else { if (length > 2) { for (int j = 1; j < length - 1; j++) { int insertPoint = (index + j) % length; if (index + j >= length) { insertPoint++; } moves[count++] = new TranslocationMove(index, index, insertPoint); if (count == sampleSize) { break; } } } else // doesn't make sense, but just create a dummy move to not crash the algorithms { moves = new TranslocationMove[1]; moves[0] = new TranslocationMove(0, 0, 1); count = sampleSize; } } } return(moves); }