示例#1
1
 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());
    }
示例#3
0
 public ThreeIndexMove(int index1, int index2, int index3, Permutation permutation)
   : base() {
   Index1 = index1;
   Index2 = index2;
   Index3 = index3;
   Permutation = permutation;
 }
示例#4
0
 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;
    }
示例#14
0
    /// <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);
    }
示例#15
0
 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;
 }
示例#17
0
 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;
 }
示例#21
0
 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);
    }
示例#24
0
    /// <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);
    }
示例#25
0
    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);
          }
      }
    }
示例#27
0
 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);
   }
 }
示例#28
0
 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;
 }
示例#30
0
    /// <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);
    }
示例#31
0
 public TranslocationMove(int index1, int index2, int index3, Permutation permutation) : base(index1, index2, index3, permutation)
 {
 }
示例#32
0
 protected abstract Swap2Move[] GenerateMoves(Permutation permutation);
示例#33
0
        /// <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());
 }
示例#40
0
 protected abstract TranslocationMove[] GenerateMoves(Permutation permutation);
示例#41
0
        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));
        }
示例#44
0
        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);
        }
示例#46
0
 public InversionMove(int index1, int index2, Permutation permutation) : base(index1, index2, permutation)
 {
 }
示例#47
0
 public Swap2Move(int index1, int index2, Permutation permutation) : base(index1, index2, permutation)
 {
 }
示例#48
0
 public static void Apply(Permutation permutation, int startIndex, int[] scrambleArray)
 {
     permutation.Replace(startIndex, scrambleArray.Select(x => permutation[startIndex + x]).ToArray());
 }
示例#49
0
 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);
示例#54
0
 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);
        }