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;
    }
        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> deleted             = new List <Edge>();

            deleted.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index1], bidirectional));
            deleted.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index1 + 1), bidirectional));
            deleted.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index2], bidirectional));
            deleted.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index2 + 1), bidirectional));
            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.AddedEdges.Count; i++)
                    {
                        isTabu = eq.Equals(relAttrib.AddedEdges[i], deleted[0]) ||
                                 eq.Equals(relAttrib.AddedEdges[i], deleted[1]) ||
                                 eq.Equals(relAttrib.AddedEdges[i], deleted[2]) ||
                                 eq.Equals(relAttrib.AddedEdges[i], deleted[3]);
                        if (isTabu)
                        {
                            break;
                        }
                    }
                    if (isTabu)
                    {
                        break;
                    }
                    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);
        }
Ejemplo n.º 3
0
        protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality)
        {
            Swap2Move   move        = Swap2MoveParameter.ActualValue;
            Permutation permutation = PermutationParameter.ActualValue;
            double      baseQuality = moveQuality;

            if (maximization && quality > moveQuality || !maximization && quality < moveQuality)
            {
                baseQuality = quality;                                                                            // we make an uphill move, the lower bound is the solution quality
            }
            if (permutation.PermutationType == PermutationTypes.Absolute)
            {
                return(new Swap2MoveAbsoluteAttribute(move.Index1, permutation[move.Index1], move.Index2, permutation[move.Index2], baseQuality));
            }
            else
            {
                Swap2MoveRelativeAttribute attrib = new Swap2MoveRelativeAttribute(baseQuality);
                bool bidirectional = permutation.PermutationType == PermutationTypes.RelativeUndirected;
                attrib.DeletedEdges.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index1], bidirectional));
                attrib.DeletedEdges.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index1 + 1), bidirectional));
                attrib.DeletedEdges.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index2], bidirectional));
                attrib.DeletedEdges.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index2 + 1), bidirectional));
                attrib.AddedEdges.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index2], bidirectional));
                attrib.AddedEdges.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index1 + 1), bidirectional));
                attrib.AddedEdges.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index1], bidirectional));
                attrib.AddedEdges.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index2 + 1), bidirectional));
                return(attrib);
            }
        }
 public static double EvaluateByDistanceMatrix(Permutation permutation, InversionMove move, DistanceMatrix distanceMatrix) {
   int edge1source = permutation.GetCircular(move.Index1 - 1);
   int edge1target = permutation[move.Index1];
   int edge2source = permutation[move.Index2];
   int edge2target = permutation.GetCircular(move.Index2 + 1);
   if (move.Index2 - move.Index1 >= permutation.Length - 2) return 0;
   double moveQuality = 0;
   // remove two edges
   moveQuality -= distanceMatrix[edge1source, edge1target];
   moveQuality -= distanceMatrix[edge2source, edge2target];
   // add two edges
   moveQuality += distanceMatrix[edge1source, edge2source];
   moveQuality += distanceMatrix[edge1target, edge2target];
   return moveQuality;
 }
 public static double EvaluateByCoordinates(Permutation permutation, InversionMove move, DoubleMatrix coordinates, TSPInversionMovePathEvaluator evaluator) {
   int edge1source = permutation.GetCircular(move.Index1 - 1);
   int edge1target = permutation[move.Index1];
   int edge2source = permutation[move.Index2];
   int edge2target = permutation.GetCircular(move.Index2 + 1);
   if (move.Index2 - move.Index1 >= permutation.Length - 2) return 0;
   double moveQuality = 0;
   // remove two 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]);
   // add two edges
   moveQuality += evaluator.CalculateDistance(coordinates[edge1source, 0], coordinates[edge1source, 1],
     coordinates[edge2source, 0], coordinates[edge2source, 1]);
   moveQuality += evaluator.CalculateDistance(coordinates[edge1target, 0], coordinates[edge1target, 1],
     coordinates[edge2target, 0], coordinates[edge2target, 1]);
   return moveQuality;
 }
        protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality)
        {
            InversionMove move        = InversionMoveParameter.ActualValue;
            Permutation   permutation = PermutationParameter.ActualValue;
            double        baseQuality = moveQuality;

            if (maximization && quality > moveQuality || !maximization && quality < moveQuality)
            {
                baseQuality = quality;                                                                            // we make an uphill move, the lower bound is the solution quality
            }
            if (permutation.PermutationType == PermutationTypes.Absolute)
            {
                return(new InversionMoveAbsoluteAttribute(move.Index1, permutation[move.Index1], move.Index2, permutation[move.Index2], baseQuality));
            }
            else
            {
                return(new InversionMoveRelativeAttribute(permutation.GetCircular(move.Index1 - 1),
                                                          permutation[move.Index1],
                                                          permutation[move.Index2],
                                                          permutation.GetCircular(move.Index2 + 1),
                                                          baseQuality));
            }
        }
        protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality)
        {
            TranslocationMove move        = TranslocationMoveParameter.ActualValue;
            Permutation       permutation = PermutationParameter.ActualValue;
            double            baseQuality = moveQuality;

            if (maximization && quality > moveQuality || !maximization && quality < moveQuality)
            {
                baseQuality = quality;                                                                            // we make an uphill move, the lower bound is the solution quality
            }
            if (permutation.PermutationType == PermutationTypes.Absolute)
            {
                int[] numbers = new int[move.Index2 - move.Index1 + 1];
                for (int i = 0; i < numbers.Length; i++)
                {
                    numbers[i] = permutation[i + move.Index1];
                }
                return(new TranslocationMoveAbsoluteAttribute(numbers, move.Index1, move.Index3, baseQuality));;
            }
            else
            {
                if (move.Index3 > move.Index1)
                {
                    return(new TranslocationMoveRelativeAttribute(permutation.GetCircular(move.Index1 - 1),
                                                                  permutation[move.Index1],
                                                                  permutation[move.Index2],
                                                                  permutation.GetCircular(move.Index2 + 1),
                                                                  permutation.GetCircular(move.Index3 + move.Index2 - move.Index1),
                                                                  permutation.GetCircular(move.Index3 + move.Index2 - move.Index1 + 1),
                                                                  baseQuality));
                }
                else
                {
                    return(new TranslocationMoveRelativeAttribute(permutation.GetCircular(move.Index1 - 1),
                                                                  permutation[move.Index1],
                                                                  permutation[move.Index2],
                                                                  permutation.GetCircular(move.Index2 + 1),
                                                                  permutation.GetCircular(move.Index3 - 1),
                                                                  permutation.GetCircular(move.Index3),
                                                                  baseQuality));
                }
            }
        }
 public static double EvaluateMove(Permutation tour, InversionMove move, Func<int, int, double> distance, ItemList<BoolArray> realizations) {
   double moveQuality = 0;
   var edges = new int[4];
   var indices = new int[4];
   edges[0] = tour.GetCircular(move.Index1 - 1);
   indices[0] = move.Index1 - 1;
   if (indices[0] == -1) indices[0] = tour.Length - 1;
   edges[1] = tour[move.Index1];
   indices[1] = move.Index1;
   edges[2] = tour[move.Index2];
   indices[2] = move.Index2;
   edges[3] = tour.GetCircular(move.Index2 + 1);
   indices[3] = move.Index2 + 1;
   if (indices[3] == tour.Length + 1) indices[3] = 0;
   var aPosteriori = new int[4];
   foreach (var realization in realizations) {
     for (var i = 0; i < edges.Length; i++) {
       if (realization[edges[i]]) {
         aPosteriori[i] = edges[i];
       } else {
         var j = 1;
         if (i % 2 == 0) {
           // find nearest predecessor in realization if source edge
           while (!realization[tour.GetCircular(indices[i] - j)]) {
             j++;
           }
           aPosteriori[i] = tour.GetCircular(indices[i] - j);
         } else {
           // find nearest successor in realization if target edge
           while (!realization[tour.GetCircular(indices[i] + j)]) {
             j++;
           }
           aPosteriori[i] = tour.GetCircular(indices[i] + j);
         }
       }
     }
     // compute cost difference between the two a posteriori solutions
     if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3])) {
       moveQuality = moveQuality + distance(aPosteriori[0], aPosteriori[2]) + distance(aPosteriori[1], aPosteriori[3])
         - distance(aPosteriori[0], aPosteriori[1]) - distance(aPosteriori[2], aPosteriori[3]);
     }
     Array.Clear(aPosteriori, 0, aPosteriori.Length);
   }
   // return average of cost differences
   return moveQuality / realizations.Count;
 }
Ejemplo n.º 9
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])
                                    {
                                        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 (permutation.PermutationType == PermutationTypes.RelativeUndirected)
                            {
                                if (// if previously added Edge3Source-Edge1Target is deleted
                                    attribute.Edge3Source == E1S && attribute.Edge1Target == E1T || attribute.Edge3Source == E1T && attribute.Edge1Target == E1S ||
                                    attribute.Edge3Source == E2S && attribute.Edge1Target == E2T || attribute.Edge3Source == E2T && attribute.Edge1Target == E2S ||
                                    attribute.Edge3Source == E3S && attribute.Edge1Target == E3T || attribute.Edge3Source == E3T && attribute.Edge1Target == E3S
                                    // if previously added Edge2Source-Edge3Target is deleted
                                    || attribute.Edge2Source == E1S && attribute.Edge3Target == E1T || attribute.Edge2Source == E1T && attribute.Edge3Target == E1S ||
                                    attribute.Edge2Source == E2S && attribute.Edge3Target == E2T || attribute.Edge2Source == E2T && attribute.Edge3Target == E2S ||
                                    attribute.Edge2Source == E3S && attribute.Edge3Target == E3T || attribute.Edge2Source == E3T && attribute.Edge3Target == E3S
                                    // if previously added Edge1Source-Edge2Target is deleted
                                    || attribute.Edge1Source == E1S && attribute.Edge2Target == E1T || attribute.Edge1Source == E1T && attribute.Edge2Target == E1S ||
                                    attribute.Edge1Source == E2S && attribute.Edge2Target == E2T || attribute.Edge1Source == E2T && attribute.Edge2Target == E2S ||
                                    attribute.Edge1Source == E3S && attribute.Edge2Target == E3T || attribute.Edge1Source == E3T && attribute.Edge2Target == E3S)
                                {
                                    isTabu = true;
                                    break;
                                }
                            }
                            else
                            {
                                if (// if previously added Edge3Source-Edge1Target is deleted
                                    attribute.Edge3Source == E1S && attribute.Edge1Target == E1T ||
                                    attribute.Edge3Source == E2S && attribute.Edge1Target == E2T ||
                                    attribute.Edge3Source == E3S && attribute.Edge1Target == E3T
                                    // if previously added Edge2Source-Edge3Target is deleted
                                    || attribute.Edge2Source == E1S && attribute.Edge3Target == E1T ||
                                    attribute.Edge2Source == E2S && attribute.Edge3Target == E2T ||
                                    attribute.Edge2Source == E3S && attribute.Edge3Target == E3T
                                    // if previously added Edge1Source-Edge2Target is deleted
                                    || attribute.Edge1Source == E1S && attribute.Edge2Target == E1T ||
                                    attribute.Edge1Source == E2S && attribute.Edge2Target == E2T ||
                                    attribute.Edge1Source == E3S && attribute.Edge2Target == E3T)
                                {
                                    isTabu = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            MoveTabuParameter.ActualValue = new BoolValue(isTabu);
            return(base.Apply());
        }
    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;
    }
    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 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());
        }
    public static double EvaluateMove(Permutation tour, TranslocationMove move, Func<int, int, double> distance, ItemList<BoolArray> realizations) {
      var afterMove = (Permutation)tour.Clone();
      TranslocationManipulator.Apply(afterMove, move.Index1, move.Index1, move.Index3);
      double moveQuality = 0;
      var edges = new int[12];
      var indices = new int[12];
      edges[0] = tour.GetCircular(move.Index1 - 1);
      indices[0] = DecreaseCircularIndex(tour.Length, move.Index1);
      edges[1] = tour[move.Index1];
      indices[1] = move.Index1;
      edges[2] = tour[move.Index1];
      indices[2] = move.Index1;
      edges[3] = tour.GetCircular(move.Index1 + 1);
      indices[3] = IncreaseCircularIndex(tour.Length, move.Index1);

      edges[6] = afterMove.GetCircular(move.Index3 - 1);
      indices[6] = DecreaseCircularIndex(afterMove.Length, move.Index3);
      edges[7] = afterMove[move.Index3];
      indices[7] = move.Index3;
      edges[8] = afterMove[move.Index3];
      indices[8] = move.Index3;
      edges[9] = afterMove.GetCircular(move.Index3 + 1);
      indices[9] = IncreaseCircularIndex(afterMove.Length, move.Index3);

      if (move.Index3 > move.Index1) {
        edges[4] = tour[move.Index3];
        indices[4] = move.Index3;
        edges[5] = tour.GetCircular(move.Index3 + 1);
        indices[5] = indices[9];
        edges[10] = afterMove.GetCircular(move.Index1 - 1);
        indices[10] = indices[0];
        edges[11] = afterMove[move.Index1];
        indices[11] = move.Index1;
      } else {
        edges[4] = tour.GetCircular(move.Index3 - 1);
        indices[4] = indices[6];
        edges[5] = tour[move.Index3];
        indices[5] = move.Index3;
        edges[10] = afterMove[move.Index1];
        indices[10] = move.Index1;
        edges[11] = afterMove.GetCircular(move.Index1 + 1);
        indices[11] = indices[3];
      }
      int[] aPosteriori = new int[12];
      foreach (var realization in realizations) {
        for (int i = 0; i < edges.Length; i++) {
          Permutation tempPermutation;
          if (i < 6) {
            tempPermutation = tour;
          } else {
            tempPermutation = afterMove;
          }
          if (realization[edges[i]]) {
            aPosteriori[i] = edges[i];
          } else {
            int j = 1;
            if (i % 2 == 0) {
              // find nearest predecessor in realization if source edge
              while (!realization[tempPermutation.GetCircular(indices[i] - j)]) {
                j++;
              }
              aPosteriori[i] = tempPermutation.GetCircular(indices[i] - j);
            } else {
              // find nearest successor in realization if target edge
              while (!realization[tempPermutation.GetCircular(indices[i] + j)]) {
                j++;
              }
              aPosteriori[i] = tempPermutation.GetCircular(indices[i] + j);
            }
          }
        }
        if (!(aPosteriori[0] == aPosteriori[2] && aPosteriori[1] == aPosteriori[3]) &&
          !(aPosteriori[0] == aPosteriori[4] && aPosteriori[1] == aPosteriori[5]) &&
          !(aPosteriori[2] == aPosteriori[4] && aPosteriori[3] == aPosteriori[5])) {
          // compute cost difference between the two a posteriori solutions
          moveQuality = moveQuality + distance(aPosteriori[6], aPosteriori[7]) + distance(aPosteriori[8], aPosteriori[9]) + distance(aPosteriori[10], aPosteriori[11]);
          moveQuality = moveQuality - distance(aPosteriori[0], aPosteriori[1]) - distance(aPosteriori[2], aPosteriori[3]) - distance(aPosteriori[4], aPosteriori[5]);
        }
        Array.Clear(aPosteriori, 0, aPosteriori.Length);
      }
      // return average of cost differences
      return moveQuality / realizations.Count;
    }