public void Swap2MoveEvaluatorTest() { for (int i = 0; i < 500; i++) { int index1 = random.Next(ProblemSize); int index2 = random.Next(ProblemSize); // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); Swap2Manipulator.Apply(assignment, index1, index2); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPSwap2MoveEvaluator.Apply(assignment, new Swap2Move(index1, index2, assignment), symmetricWeights, symmetricDistances); Assert.IsTrue(move.IsAlmost(before - after), "Failed on symmetric matrices"); // ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); Permutation clone = (Permutation)assignment.Clone(); Swap2Manipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPSwap2MoveEvaluator.Apply(clone, new Swap2Move(index1, index2), asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASSYMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); clone = (Permutation)assignment.Clone(); Swap2Manipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPSwap2MoveEvaluator.Apply(clone, new Swap2Move(index1, index2), nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }
public static void Improve(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) { double evalSolPerMove = 4.0 / assignment.Length; for (int i = localIterations.Value; i < maxIterations; i++) { Swap2Move bestMove = null; double bestQuality = 0; // we have to make an improvement, so 0 is the baseline double evaluations = 0.0; foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment)) { double moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances); evaluations += evalSolPerMove; if (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality) { bestQuality = moveQuality; bestMove = move; } } evaluatedSolutions.Value += (int)Math.Ceiling(evaluations); if (bestMove == null) { break; } Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2); quality.Value += bestQuality; localIterations.Value++; cancellation.ThrowIfCancellationRequested(); } }
public override double EvaluateMove(Permutation permutation, Swap2Move move, PackingShape binShape, ReadOnlyItemList <PackingItem> items, bool useStackingConstraints) { // uses full evaluation Swap2Manipulator.Apply(permutation, move.Index1, move.Index2); var solution = DecoderParameter.ActualValue.Decode(permutation, binShape, items, useStackingConstraints); return(SolutionEvaluatorParameter.ActualValue.Evaluate(solution)); }
public static void ImproveFast(Permutation assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleValue quality, IntValue localIterations, IntValue evaluatedSolutions, bool maximization, int maxIterations, CancellationToken cancellation) { Swap2Move bestMove = null; double evaluations = 0.0; var lastQuality = new double[assignment.Length, assignment.Length]; for (int i = localIterations.Value; i < maxIterations; i++) { double bestQuality = 0; // we have to make an improvement, so 0 is the baseline var lastMove = bestMove; bestMove = null; foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(assignment)) { double moveQuality; if (lastMove == null) { moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, weights, distances); evaluations += 4.0 / assignment.Length; } else { moveQuality = QAPSwap2MoveEvaluator.Apply(assignment, move, lastQuality[move.Index1, move.Index2], weights, distances, lastMove); if (move.Index1 == lastMove.Index1 || move.Index2 == lastMove.Index1 || move.Index1 == lastMove.Index2 || move.Index2 == lastMove.Index2) { evaluations += 4.0 / assignment.Length; } else { evaluations += 2.0 / (assignment.Length * assignment.Length); } } lastQuality[move.Index1, move.Index2] = moveQuality; if (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality) { bestQuality = moveQuality; bestMove = move; } } if (bestMove == null) { break; } Swap2Manipulator.Apply(assignment, bestMove.Index1, bestMove.Index2); quality.Value += bestQuality; localIterations.Value++; if (cancellation.IsCancellationRequested) { evaluatedSolutions.Value += (int)Math.Round(evaluations); throw new OperationCanceledException(); } } evaluatedSolutions.Value += (int)Math.Round(evaluations); }
public void Swap2ManipulatorApplyTest() { TestRandom random = new TestRandom(); Permutation parent, expected; // The following test is based on an example from Eiben, A.E. and Smith, J.E. 2003. Introduction to Evolutionary Computation. Natural Computing Series, Springer-Verlag Berlin Heidelberg, p. 45 random.Reset(); random.IntNumbers = new int[] { 1, 4 }; parent = new Permutation(PermutationTypes.RelativeUndirected, new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }); Assert.IsTrue(parent.Validate()); expected = new Permutation(PermutationTypes.RelativeUndirected, new int[] { 0, 4, 2, 3, 1, 5, 6, 7, 8 }); Assert.IsTrue(expected.Validate()); Swap2Manipulator.Apply(random, parent); Assert.IsTrue(parent.Validate()); Assert.IsTrue(Auxiliary.PermutationIsEqualByPosition(expected, parent)); }
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 + "."); } }
public override void Main() { DateTime start = DateTime.UtcNow; QuadraticAssignmentProblem qap; if (vars.Contains("qap")) { qap = vars.qap; } else { var provider = new DreznerQAPInstanceProvider(); var instance = provider.GetDataDescriptors().Single(x => x.Name == "dre56"); var data = provider.LoadData(instance); qap = new QuadraticAssignmentProblem(); qap.Load(data); vars.qap = qap; } const uint seed = 0; const int popSize = 100; const int generations = 1000; const double mutationRate = 0.05; var random = new MersenneTwister(seed); var population = new Permutation[popSize]; var qualities = new double[popSize]; var nextGen = new Permutation[popSize]; var nextQual = new double[popSize]; var qualityChart = new DataTable("Quality Chart"); var qualityRow = new DataRow("Best Quality"); qualityChart.Rows.Add(qualityRow); vars.qualityChart = qualityChart; for (int i = 0; i < popSize; i++) { population[i] = new Permutation(PermutationTypes.Absolute, qap.Weights.Rows, random); qualities[i] = QAPEvaluator.Apply(population[i], qap.Weights, qap.Distances); } var bestQuality = qualities.Min(); var bestQualityGeneration = 0; for (int g = 0; g < generations; g++) { var parents = population.SampleProportional(random, 2 * popSize, qualities, windowing: true, inverseProportional: true).ToArray(); for (int i = 0; i < popSize; i++) { nextGen[i] = PartiallyMatchedCrossover.Apply(random, parents[i * 2], parents[i * 2 + 1]); if (random.NextDouble() < mutationRate) { Swap2Manipulator.Apply(random, nextGen[i]); } nextQual[i] = QAPEvaluator.Apply(nextGen[i], qap.Weights, qap.Distances); if (nextQual[i] < bestQuality) { bestQuality = nextQual[i]; bestQualityGeneration = g; } } qualityRow.Values.Add(bestQuality); Array.Copy(nextGen, population, popSize); Array.Copy(nextQual, qualities, popSize); } vars.elapsed = new TimeSpanValue(DateTime.UtcNow - start); vars.bestQuality = bestQuality; vars.bestQualityFoundAt = bestQualityGeneration; }
public override IOperation Apply() { IRandom random = RandomParameter.ActualValue; int iteration = IterationsParameter.ActualValue.Value; IntMatrix shortTermMemory = ShortTermMemoryParameter.ActualValue; DoubleMatrix weights = WeightsParameter.ActualValue; DoubleMatrix distances = DistancesParameter.ActualValue; DoubleMatrix moveQualityMatrix = MoveQualityMatrixParameter.ActualValue; DoubleValue quality = QualityParameter.ActualValue; DoubleValue bestQuality = BestQualityParameter.ActualValue; if (bestQuality == null) { BestQualityParameter.ActualValue = (DoubleValue)quality.Clone(); bestQuality = BestQualityParameter.ActualValue; } bool allMovesTabu = false; if (AllMovesTabuParameter.ActualValue == null) { AllMovesTabuParameter.ActualValue = new BoolValue(false); } else { allMovesTabu = AllMovesTabuParameter.ActualValue.Value; } int minTenure = MinimumTabuTenureParameter.ActualValue.Value; int maxTenure = MaximumTabuTenureParameter.ActualValue.Value; int alternativeAspirationTenure = AlternativeAspirationTenureParameter.ActualValue.Value; bool useAlternativeAspiration = UseAlternativeAspirationParameter.ActualValue.Value; Permutation solution = PermutationParameter.ActualValue; Swap2Move lastMove = LastMoveParameter.ActualValue; double bestMoveQuality = double.MaxValue; Swap2Move bestMove = null; bool already_aspired = false; double evaluations = EvaluatedSolutionEquivalentsParameter.ActualValue.Value; foreach (Swap2Move move in ExhaustiveSwap2MoveGenerator.Generate(solution)) { double moveQuality; if (lastMove == null) { moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, weights, distances); evaluations += 4.0 / solution.Length; } else if (allMovesTabu) { moveQuality = moveQualityMatrix[move.Index1, move.Index2]; } else { moveQuality = QAPSwap2MoveEvaluator.Apply(solution, move, moveQualityMatrix[move.Index1, move.Index2], weights, distances, lastMove); if (move.Index1 == lastMove.Index1 || move.Index2 == lastMove.Index1 || move.Index1 == lastMove.Index2 || move.Index2 == lastMove.Index2) { evaluations += 4.0 / solution.Length; } else { evaluations += 2.0 / (solution.Length * solution.Length); } } moveQualityMatrix[move.Index1, move.Index2] = moveQuality; moveQualityMatrix[move.Index2, move.Index1] = moveQuality; bool autorized = shortTermMemory[move.Index1, solution[move.Index2]] < iteration || shortTermMemory[move.Index2, solution[move.Index1]] < iteration; bool aspired = (shortTermMemory[move.Index1, solution[move.Index2]] < iteration - alternativeAspirationTenure && shortTermMemory[move.Index2, solution[move.Index1]] < iteration - alternativeAspirationTenure) || quality.Value + moveQuality < bestQuality.Value; if ((aspired && !already_aspired) || // the first alternative move is aspired (aspired && already_aspired && moveQuality < bestMoveQuality) || // an alternative move was already aspired, but this is better (autorized && !aspired && !already_aspired && moveQuality < bestMoveQuality)) // a regular better move is found { bestMove = move; bestMoveQuality = moveQuality; if (aspired) { already_aspired = true; } } } ResultCollection results = ResultsParameter.ActualValue; if (results != null) { IntValue aspiredMoves = null; if (!results.ContainsKey("AspiredMoves")) { aspiredMoves = new IntValue(already_aspired ? 1 : 0); results.Add(new Result("AspiredMoves", "Counts the number of moves that were selected because of the aspiration criteria.", aspiredMoves)); } else if (already_aspired) { aspiredMoves = (IntValue)results["AspiredMoves"].Value; aspiredMoves.Value++; } } EvaluatedSolutionEquivalentsParameter.ActualValue.Value = evaluations; EvaluatedSolutionsParameter.ActualValue.Value = (int)Math.Ceiling(evaluations); allMovesTabu = bestMove == null; if (!allMovesTabu) { LastMoveParameter.ActualValue = bestMove; } AllMovesTabuParameter.ActualValue.Value = allMovesTabu; if (allMovesTabu) { return(base.Apply()); } bool useNewAdaptionScheme = UseNewTabuTenureAdaptionSchemeParameter.ActualValue.Value; if (useNewAdaptionScheme) { double r = random.NextDouble(); if (r == 0) { r = 1; // transform to (0;1] } shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = (int)(iteration + r * r * r * maxTenure); r = random.NextDouble(); if (r == 0) { r = 1; // transform to (0;1] } shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = (int)(iteration + r * r * r * maxTenure); } else { shortTermMemory[bestMove.Index1, solution[bestMove.Index1]] = iteration + random.Next(minTenure, maxTenure); shortTermMemory[bestMove.Index2, solution[bestMove.Index2]] = iteration + random.Next(minTenure, maxTenure); } Swap2Manipulator.Apply(solution, bestMove.Index1, bestMove.Index2); quality.Value += bestMoveQuality; if (quality.Value < bestQuality.Value) { bestQuality.Value = quality.Value; } return(base.Apply()); }