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); }
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); }
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 Swap2Move[] Apply(Permutation permutation, IRandom random, int sampleSize) { int length = permutation.Length; Swap2Move[] moves = new Swap2Move[sampleSize]; for (int i = 0; i < sampleSize; i++) { moves[i] = StochasticSwap2SingleMoveGenerator.Apply(permutation, random); } return moves; }
public static Swap2Move[] Apply(Permutation permutation) { int length = permutation.Length; int totalMoves = (length) * (length - 1) / 2; Swap2Move[] moves = new Swap2Move[totalMoves]; int count = 0; foreach (Swap2Move move in Generate(permutation)) { moves[count++] = move; } return moves; }
public static Swap2Move[] Apply(Permutation permutation, IRandom random, int sampleSize) { int length = permutation.Length; Swap2Move[] moves = new Swap2Move[sampleSize]; for (int i = 0; i < sampleSize; i++) { moves[i] = StochasticSwap2SingleMoveGenerator.Apply(permutation, random); } return(moves); }
public override IOperation Apply() { Swap2Move move = Swap2MoveParameter.ActualValue; Permutation permutation = PermutationParameter.ActualValue; DoubleValue moveQuality = MoveQualityParameter.ActualValue; DoubleValue quality = QualityParameter.ActualValue; Swap2Manipulator.Apply(permutation, move.Index1, move.Index2); quality.Value = moveQuality.Value; return(base.Apply()); }
public static Swap2Move[] Apply(Permutation permutation) { int length = permutation.Length; int totalMoves = (length) * (length - 1) / 2; Swap2Move[] moves = new Swap2Move[totalMoves]; int count = 0; foreach (Swap2Move move in Generate(permutation)) { moves[count++] = move; } return(moves); }
public override IOperation Apply() { ItemList <IItem> tabuList = TabuListParameter.ActualValue; Swap2Move move = Swap2MoveParameter.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) { isTabu = EvaluateRelativeTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration); } else { isTabu = EvaluateAbsoluteTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration); } MoveTabuParameter.ActualValue = new BoolValue(isTabu); return(base.Apply()); }
/// <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, Swap2Move move, DoubleMatrix weights, DoubleMatrix distances) { if (move.Index1 == move.Index2) return 0; double moveQuality = 0; int fac1 = move.Index1, fac2 = move.Index2; int loc1 = assignment[fac1], loc2 = assignment[fac2]; for (int j = 0; j < assignment.Length; j++) { if (j == fac1) { moveQuality += weights[fac1, fac1] * (distances[loc2, loc2] - distances[loc1, loc1]); moveQuality += weights[fac1, fac2] * (distances[loc2, loc1] - distances[loc1, loc2]); } else if (j == fac2) { moveQuality += weights[fac2, fac2] * (distances[loc1, loc1] - distances[loc2, loc2]); moveQuality += weights[fac2, fac1] * (distances[loc1, loc2] - distances[loc2, loc1]); } else { int locJ = assignment[j]; moveQuality += weights[fac1, j] * (distances[loc2, locJ] - distances[loc1, locJ]); moveQuality += weights[j, fac1] * (distances[locJ, loc2] - distances[locJ, loc1]); moveQuality += weights[fac2, j] * (distances[loc1, locJ] - distances[loc2, locJ]); moveQuality += weights[j, fac2] * (distances[locJ, loc1] - distances[locJ, loc2]); } } return moveQuality; }
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; }
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; }
protected Swap2Move(Swap2Move original, Cloner cloner) : base(original, cloner) { }
/// <summary> /// Is able to compute the move qualities faster O(1) in some cases if it knows the quality of /// performing the move <paramref name="move"/> previously. In other cases it performs a /// standard move quality calculation with runtime complexity O(N). /// </summary> /// <remarks> /// The number of cases that the calculation can be performed faster grows with N^2 /// while the number of cases which require a larger recalculation grows linearly with N. /// Larger problem instances thus benefit from this faster method to a larger degree. /// </remarks> /// <param name="assignment">The current permutation.</param> /// <param name="move">The current move that is to be evaluated.</param> /// <param name="previousQuality">The quality of that move as evaluated for the previous permutation.</param> /// <param name="weights">The weigths matrix.</param> /// <param name="distances">The distances matrix.</param> /// <param name="lastMove">The move that was applied to transform the permutation from the previous to the current one.</param> /// <returns>The relative change in quality if <paramref name="move"/> was applied to <paramref name="assignment"/>.</returns> public static double Apply(Permutation assignment, Swap2Move move, double previousQuality, DoubleMatrix weights, DoubleMatrix distances, Swap2Move lastMove) { bool overlapsLastMove = move.Index1 == lastMove.Index1 || move.Index2 == lastMove.Index1 || move.Index1 == lastMove.Index2 || move.Index2 == lastMove.Index2; if (!overlapsLastMove) { int r = lastMove.Index1, u = move.Index1, s = lastMove.Index2, v = move.Index2; int pR = assignment[lastMove.Index1], pU = assignment[move.Index1], pS = assignment[lastMove.Index2], pV = assignment[move.Index2]; return previousQuality + (weights[r, u] - weights[r, v] + weights[s, v] - weights[s, u]) * (distances[pS, pU] - distances[pS, pV] + distances[pR, pV] - distances[pR, pU]) + (weights[u, r] - weights[v, r] + weights[v, s] - weights[u, s]) * (distances[pU, pS] - distances[pV, pS] + distances[pV, pR] - distances[pU, pR]); } else { return Apply(assignment, move, weights, distances); } }
public void Swap2MoveEvaluatorFastEvaluationTest() { for (int i = 0; i < 500; i++) { Swap2Move lastMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize)); Permutation prevAssignment = (Permutation)assignment.Clone(); Swap2Manipulator.Apply(assignment, lastMove.Index1, lastMove.Index2); Permutation nextAssignment = (Permutation)assignment.Clone(); Swap2Move currentMove = new Swap2Move(random.Next(ProblemSize), random.Next(ProblemSize)); Swap2Manipulator.Apply(nextAssignment, currentMove.Index1, currentMove.Index2); double moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, symmetricWeights, symmetricDistances); double moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove, moveBefore, symmetricWeights, symmetricDistances, lastMove); double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double after = QAPEvaluator.Apply(nextAssignment, symmetricWeights, symmetricDistances); Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on symmetric matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + "."); moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, asymmetricWeights, asymmetricDistances); moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove, moveBefore, asymmetricWeights, asymmetricDistances, lastMove); before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); after = QAPEvaluator.Apply(nextAssignment, asymmetricWeights, asymmetricDistances); Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on asymmetric matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + "."); moveBefore = QAPSwap2MoveEvaluator.Apply(prevAssignment, currentMove, nonZeroDiagonalWeights, nonZeroDiagonalDistances); moveAfter = QAPSwap2MoveEvaluator.Apply(assignment, currentMove, moveBefore, nonZeroDiagonalWeights, nonZeroDiagonalDistances, lastMove); before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); after = QAPEvaluator.Apply(nextAssignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(moveAfter.IsAlmost(after - before), "Failed on non-zero diagonal matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveAfter + "."); } }