public void ScrambleMoveEvaluatorTest() { for (int i = 0; i < 500; i++) { ScrambleMove scramble = StochasticScrambleMultiMoveGenerator.GenerateRandomMove(assignment, random); // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPScrambleMoveEvaluator.Apply(assignment, scramble, symmetricWeights, symmetricDistances); ScrambleManipulator.Apply(assignment, scramble.StartIndex, scramble.ScrambledIndices); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on symmetric matrices"); // ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPScrambleMoveEvaluator.Apply(assignment, scramble, asymmetricWeights, asymmetricDistances); ScrambleManipulator.Apply(assignment, scramble.StartIndex, scramble.ScrambledIndices); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPScrambleMoveEvaluator.Apply(assignment, scramble, nonZeroDiagonalWeights, nonZeroDiagonalDistances); ScrambleManipulator.Apply(assignment, scramble.StartIndex, scramble.ScrambledIndices); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }
public void InversionMoveEvaluatorTest() { for (int i = 0; i < 500; i++) { int index1 = random.Next(ProblemSize); int index2 = random.Next(ProblemSize); if (index1 > index2) { int h = index1; index1 = index2; index2 = h; } // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); InversionManipulator.Apply(assignment, Math.Min(index1, index2), Math.Max(index1, index2)); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPInversionMoveEvaluator.Apply(assignment, new InversionMove(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(); InversionManipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPInversionMoveEvaluator.Apply(clone, new InversionMove(index1, index2), asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); clone = (Permutation)assignment.Clone(); InversionManipulator.Apply(assignment, index1, index2); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPInversionMoveEvaluator.Apply(clone, new InversionMove(index1, index2), nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }
public void TranslocationMoveEvaluatorTest() { for (int i = 0; i < 500; i++) { int index1 = random.Next(assignment.Length - 1); int index2 = random.Next(index1 + 1, assignment.Length); int insertPointLimit = assignment.Length - index2 + index1 - 1; // get insertion point in remaining part int insertPoint; if (insertPointLimit > 0) { insertPoint = random.Next(insertPointLimit); } else { insertPoint = 0; } // SYMMETRIC MATRICES double before = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); Permutation clone = new Cloner().Clone(assignment); TranslocationManipulator.Apply(assignment, index1, index2, insertPoint); double after = QAPEvaluator.Apply(assignment, symmetricWeights, symmetricDistances); double move = QAPTranslocationMoveEvaluator.Apply(clone, new TranslocationMove(index1, index2, insertPoint, assignment), symmetricWeights, symmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on symmetric matrices"); // ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); clone = new Cloner().Clone(assignment); TranslocationManipulator.Apply(assignment, index1, index2, insertPoint); after = QAPEvaluator.Apply(assignment, asymmetricWeights, asymmetricDistances); move = QAPTranslocationMoveEvaluator.Apply(clone, new TranslocationMove(index1, index2, insertPoint, assignment), asymmetricWeights, asymmetricDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on asymmetric matrices"); // NON-ZERO DIAGONAL ASYMMETRIC MATRICES before = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); clone = new Cloner().Clone(assignment); TranslocationManipulator.Apply(assignment, index1, index2, insertPoint); after = QAPEvaluator.Apply(assignment, nonZeroDiagonalWeights, nonZeroDiagonalDistances); move = QAPTranslocationMoveEvaluator.Apply(clone, new TranslocationMove(index1, index2, insertPoint, assignment), nonZeroDiagonalWeights, nonZeroDiagonalDistances); Assert.IsTrue(move.IsAlmost(after - before), "Failed on non-zero diagonal matrices"); } }
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; }