Example #1
0
        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));
        }
Example #6
0
        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 + ".");
            }
        }
Example #7
0
    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;
    }
Example #8
0
        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());
        }