#region License Information /* HeuristicLab * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Problems.GeneralizedQuadraticAssignment; using HeuristicLab.Random; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace UnitTests { /// ///This is a test class for GQAPNMoveEvaluatorTest and is intended ///to contain all GQAPNMoveEvaluatorTest Unit Tests /// [TestClass()] public class GQAPNMoveEvaluatorTest { private const int Equipments = 10, Locations = 5; private static GQAPInstance symmetricInstance, asymmetricInstance, nonZeroDiagonalInstance; private static IntegerVector assignment; private static MersenneTwister random; private TestContext testContextInstance; /// ///Gets or sets the test context which provides ///information about and functionality for the current test run. /// public TestContext TestContext { get { return testContextInstance; } set { testContextInstance = value; } } #region Additional test attributes [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { random = new MersenneTwister(); var symmetricDistances = new DoubleMatrix(Locations, Locations); var symmetricWeights = new DoubleMatrix(Equipments, Equipments); var asymmetricDistances = new DoubleMatrix(Locations, Locations); var asymmetricWeights = new DoubleMatrix(Equipments, Equipments); var nonZeroDiagonalDistances = new DoubleMatrix(Locations, Locations); var nonZeroDiagonalWeights = new DoubleMatrix(Equipments, Equipments); for (int i = 0; i < Equipments - 1; i++) { for (int j = i + 1; j < Equipments; j++) { symmetricWeights[i, j] = random.Next(Equipments * 100); symmetricWeights[j, i] = symmetricWeights[i, j]; asymmetricWeights[i, j] = random.Next(Equipments * 100); asymmetricWeights[j, i] = random.Next(Equipments * 100); nonZeroDiagonalWeights[i, j] = random.Next(Equipments * 100); nonZeroDiagonalWeights[j, i] = random.Next(Equipments * 100); } nonZeroDiagonalWeights[i, i] = random.Next(Equipments * 100); } for (int i = 0; i < Locations - 1; i++) { for (int j = i + 1; j < Locations; j++) { symmetricDistances[i, j] = random.Next(Locations * 100); symmetricDistances[j, i] = symmetricDistances[i, j]; asymmetricDistances[i, j] = random.Next(Locations * 100); asymmetricDistances[j, i] = random.Next(Locations * 100); nonZeroDiagonalDistances[i, j] = random.Next(Locations * 100); nonZeroDiagonalDistances[j, i] = random.Next(Locations * 100); } nonZeroDiagonalDistances[i, i] = random.Next(Locations * 100); } var installationCosts = new DoubleMatrix(Equipments, Locations); for (int i = 0; i < Equipments; i++) { for (int j = 0; j < Locations; j++) { installationCosts[i, j] = random.Next(0, 10); } } var demands = new DoubleArray(Equipments); for (int i = 0; i < Equipments; i++) { demands[i] = random.Next(1, 10); } var capacities = new DoubleArray(Locations); for (int j = 0; j < Locations; j++) { capacities[j] = random.Next(1, 10) * ((double)Equipments / (double)Locations) * 1.5; } int index = random.Next(Locations); if (nonZeroDiagonalDistances[index, index] == 0) nonZeroDiagonalDistances[index, index] = random.Next(1, Equipments * 100); index = random.Next(Equipments); if (nonZeroDiagonalWeights[index, index] == 0) nonZeroDiagonalWeights[index, index] = random.Next(1, Equipments * 100); var transportationCosts = random.NextDouble() * 10; var overbookedCapacityPenalty = 1000 * random.NextDouble() + 100; assignment = new IntegerVector(Equipments, random, 0, Locations); symmetricInstance = new GQAPInstance() { Capacities = capacities, Demands = demands, InstallationCosts = installationCosts, PenaltyLevel = overbookedCapacityPenalty, TransportationCosts = transportationCosts, Weights = symmetricWeights, Distances = symmetricDistances }; asymmetricInstance = new GQAPInstance() { Capacities = capacities, Demands = demands, InstallationCosts = installationCosts, PenaltyLevel = overbookedCapacityPenalty, TransportationCosts = transportationCosts, Weights = asymmetricWeights, Distances = asymmetricDistances }; nonZeroDiagonalInstance = new GQAPInstance() { Capacities = capacities, Demands = demands, InstallationCosts = installationCosts, PenaltyLevel = overbookedCapacityPenalty, TransportationCosts = transportationCosts, Weights = nonZeroDiagonalWeights, Distances = nonZeroDiagonalDistances }; } #endregion /// ///A test for Evaluate /// [TestMethod()] public void EvaluateTest() { for (int i = 0; i < 500; i++) { NMove currentMove = StochasticNMoveSingleMoveGenerator.GenerateUpToN(random, assignment, 3, symmetricInstance.Capacities); IntegerVector prevAssignment = (IntegerVector)assignment.Clone(); NMoveMaker.Apply(assignment, currentMove); var beforeEval = symmetricInstance.Evaluate(prevAssignment); double before = symmetricInstance.ToSingleObjective(beforeEval); double after = Evaluate(symmetricInstance, assignment); double moveDiff = symmetricInstance.ToSingleObjective( GQAPNMoveEvaluator.Evaluate(currentMove, prevAssignment, beforeEval, symmetricInstance) ) - symmetricInstance.ToSingleObjective(beforeEval); Assert.IsTrue(Math.Abs(moveDiff - (after - before)) < 1e-07, "Failed on symmetric matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveDiff + "."); beforeEval = asymmetricInstance.Evaluate(prevAssignment); before = asymmetricInstance.ToSingleObjective(beforeEval); after = Evaluate(asymmetricInstance, assignment); moveDiff = asymmetricInstance.ToSingleObjective( GQAPNMoveEvaluator.Evaluate(currentMove, prevAssignment, beforeEval, asymmetricInstance) ) - asymmetricInstance.ToSingleObjective(beforeEval); Assert.IsTrue(Math.Abs(moveDiff - (after - before)) < 1e-07, "Failed on asymmetric matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveDiff + "."); beforeEval = nonZeroDiagonalInstance.Evaluate(prevAssignment); before = nonZeroDiagonalInstance.ToSingleObjective(beforeEval); after = Evaluate(nonZeroDiagonalInstance, assignment); moveDiff = nonZeroDiagonalInstance.ToSingleObjective( GQAPNMoveEvaluator.Evaluate(currentMove, prevAssignment, beforeEval, nonZeroDiagonalInstance) ) - nonZeroDiagonalInstance.ToSingleObjective(beforeEval); Assert.IsTrue(Math.Abs(moveDiff - (after - before)) < 1e-07, "Failed on non-zero diagonal matrices: " + Environment.NewLine + "Quality changed from " + before + " to " + after + " (" + (after - before).ToString() + "), but move quality change was " + moveDiff + "."); } } private double Evaluate(GQAPInstance instance, IntegerVector assignment) { return instance.ToSingleObjective(instance.Evaluate(assignment)); } } }