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); }
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; }
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; }