#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 System.Threading; using HEAL.Attic; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Parameters; namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment.Algorithms.LAHC { [Item("pLAHC-s (GQAP)", "Parameterless Late-acceptance hill climber for the GQAP.")] [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)] [StorableType("90A97927-D784-4F73-9215-ADC75A9F6C9D")] public sealed class PLAHCS : StochasticAlgorithm { public override bool SupportsPause { get { return true; } } public override Type ProblemType { get { return typeof(GQAP); } } public new GQAP Problem { get { return (GQAP)base.Problem; } set { base.Problem = value; } } [Storable] private FixedValueParameter maximumExponentParameter; public IFixedValueParameter MaximumExponentParameter { get { return maximumExponentParameter; } } [Storable] private FixedValueParameter minimumSprintIterationsParameter; public IFixedValueParameter MinimumSprintIterationsParameter { get { return minimumSprintIterationsParameter; } } public int MaximumExponent { get { return maximumExponentParameter.Value.Value; } set { maximumExponentParameter.Value.Value = value; } } public int MinimumSprintIterations { get { return minimumSprintIterationsParameter.Value.Value; } set { minimumSprintIterationsParameter.Value.Value = value; } } [StorableConstructor] private PLAHCS(StorableConstructorFlag _) : base(_) { } private PLAHCS(PLAHCS original, Cloner cloner) : base(original, cloner) { maximumExponentParameter = cloner.Clone(original.maximumExponentParameter); minimumSprintIterationsParameter = cloner.Clone(original.minimumSprintIterationsParameter); } public PLAHCS() { Parameters.Add(maximumExponentParameter = new FixedValueParameter("MaximumExponent", "The maximum power to which memory sizes should be tried (2^x). Do not set higher than 31", new IntValue(24))); Parameters.Add(minimumSprintIterationsParameter = new FixedValueParameter("MinimumSprintIterations", "The minimum amount of iterations per sprint.", new IntValue(100000))); Problem = new GQAP(); } public override IDeepCloneable Clone(Cloner cloner) { return new PLAHCS(this, cloner); } protected override void Initialize(CancellationToken token) { base.Initialize(token); Context.Problem = Problem; Context.LastSuccess = 0; var assign = new IntegerVector(Problem.ProblemInstance.Demands.Length, Context.Random, 0, Problem.ProblemInstance.Capacities.Length); var eval = Problem.ProblemInstance.Evaluate(assign); var fit = Problem.ProblemInstance.ToSingleObjective(eval); Context.EvaluatedSolutions++; var candidate = new GQAPSolution(assign, eval); Context.ReplaceIncumbent(Context.ToScope(candidate, fit)); Context.BestQuality = fit; Context.BestSolution = (GQAPSolution)candidate.Clone(); Context.BestList = new ItemList(new[] { new DoubleValue(Context.BestQuality) }); Results.Add(new Result("Sprint Iterations", new IntValue(Context.SprintIterations))); Results.Add(new Result("Iterations", new IntValue(Context.Iterations))); Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions))); Results.Add(new Result("CurrentMemorySize", new IntValue(0))); try { Context.RunOperator(Analyzer, token); } catch (OperationCanceledException) { } } protected override void Run(CancellationToken cancellationToken) { base.Run(cancellationToken); var lastUpdate = ExecutionTime; for (var i = 0; i <= MaximumExponent; i++) { var l = (int)Math.Pow(2, i); var memory = new double[l]; for (var vv = 0; vv < l; vv++) memory[vv] = Context.BestList[Context.BestList.Count - 1 - (vv % Context.BestList.Count)].Value; Array.Sort(memory); Context.Memory = new DoubleArray(memory); if (i > 0) Context.ReplaceIncumbent(Context.ToScope((GQAPSolution)Context.BestSolution.Clone(), Context.BestQuality)); IResult memorySizeResult; if (Results.TryGetValue("CurrentMemorySize", out memorySizeResult)) ((IntValue)memorySizeResult.Value).Value = Context.Memory.Length; else Results.Add(new Result("CurrentMemorySize", new IntValue(Context.Memory.Length))); Context.SprintIterations = 0; while (!StoppingCriterion() && (Context.SprintIterations < MinimumSprintIterations || (Context.SprintIterations - Context.LastSuccess) < Context.SprintIterations * 0.02)) { var move = StochasticNMoveSingleMoveGenerator.GenerateOneMove(Context.Random, Context.Incumbent.Solution.Assignment, Problem.ProblemInstance.Capacities); var moveEval = GQAPNMoveEvaluator.Evaluate(move, Context.Incumbent.Solution.Assignment, Context.Incumbent.Solution.Evaluation, Problem.ProblemInstance); if (Context.SprintIterations % Problem.ProblemInstance.Demands.Length == 0) Context.EvaluatedSolutions++; var nextFit = Problem.ProblemInstance.ToSingleObjective(moveEval); var nextVec = new IntegerVector(Context.Incumbent.Solution.Assignment); NMoveMaker.Apply(nextVec, move); var v = Context.Iterations % Context.Memory.Length; Context.Iterations++; Context.SprintIterations++; var prevFit = Context.Memory[v]; var accept = nextFit <= Context.Incumbent.Fitness || nextFit <= prevFit; if (accept && nextFit < Context.Incumbent.Fitness) Context.LastSuccess = Context.SprintIterations; if (accept) { Context.ReplaceIncumbent(Context.ToScope(new GQAPSolution(nextVec, moveEval), nextFit)); if (nextFit < Context.BestQuality) { Context.BestSolution = (GQAPSolution)Context.Incumbent.Solution.Clone(); Context.BestQuality = nextFit; Context.BestList.Add(new DoubleValue(Context.BestQuality)); } } if (Context.Incumbent.Fitness < prevFit) Context.Memory[v] = Context.Incumbent.Fitness; IResult result; if (ExecutionTime - lastUpdate > TimeSpan.FromSeconds(1)) { if (Results.TryGetValue("Iterations", out result)) ((IntValue)result.Value).Value = Context.Iterations; else Results.Add(new Result("Iterations", new IntValue(Context.Iterations))); if (Results.TryGetValue("Sprint Iterations", out result)) ((IntValue)result.Value).Value = Context.SprintIterations; else Results.Add(new Result("Total Iterations", new IntValue(Context.SprintIterations))); if (Results.TryGetValue("EvaluatedSolutions", out result)) ((IntValue)result.Value).Value = Context.EvaluatedSolutions; else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions))); lastUpdate = ExecutionTime; } if (Results.TryGetValue("BestQuality", out result)) ((DoubleValue)result.Value).Value = Context.BestQuality; else Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality))); if (Results.TryGetValue("BestSolution", out result)) result.Value = Context.BestSolution; else Results.Add(new Result("BestSolution", Context.BestSolution)); try { Context.RunOperator(Analyzer, cancellationToken); } catch (OperationCanceledException) { } if (cancellationToken.IsCancellationRequested) break; } if (StoppingCriterion() || cancellationToken.IsCancellationRequested) break; } IResult result2; if (Results.TryGetValue("Iterations", out result2)) ((IntValue)result2.Value).Value = Context.Iterations; else Results.Add(new Result("Iterations", new IntValue(Context.Iterations))); if (Results.TryGetValue("Sprint Iterations", out result2)) ((IntValue)result2.Value).Value = Context.SprintIterations; else Results.Add(new Result("Sprint Iterations", new IntValue(Context.SprintIterations))); if (Results.TryGetValue("EvaluatedSolutions", out result2)) ((IntValue)result2.Value).Value = Context.EvaluatedSolutions; else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions))); } } }