#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.Linq;
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("LAHC (GQAP)", "Late-acceptance hill climber for the GQAP.")]
[Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms)]
[StorableType("41FABEE1-506A-45FE-A6D3-57932036AEC8")]
public sealed class LAHC : 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 memorySizeParameter;
public IFixedValueParameter MemorySizeParameter {
get { return memorySizeParameter; }
}
public int MemorySize {
get { return memorySizeParameter.Value.Value; }
set { memorySizeParameter.Value.Value = value; }
}
[StorableConstructor]
private LAHC(StorableConstructorFlag _) : base(_) { }
private LAHC(LAHC original, Cloner cloner)
: base(original, cloner) {
memorySizeParameter = cloner.Clone(original.memorySizeParameter);
}
public LAHC() {
Parameters.Add(memorySizeParameter = new FixedValueParameter("MemorySize", "The size of the memory, the shorter the more greedy LAHC performs.", new IntValue(100)));
Problem = new GQAP();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new LAHC(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.Memory = new DoubleArray(Enumerable.Repeat(Context.BestQuality, MemorySize).ToArray());
Results.Add(new Result("Iterations", new IntValue(Context.Iterations)));
Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
Results.Add(new Result("BestQuality", new DoubleValue(Context.BestQuality)));
Results.Add(new Result("BestSolution", Context.BestSolution));
try {
Context.RunOperator(Analyzer, token);
} catch (OperationCanceledException) { }
}
protected override void Run(CancellationToken cancellationToken) {
base.Run(cancellationToken);
var lastUpdate = ExecutionTime;
while (!StoppingCriterion()) {
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.Iterations % 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++;
var prevFit = Context.Memory[v];
var accept = nextFit <= Context.Incumbent.Fitness
|| nextFit <= prevFit;
if (accept && nextFit < Context.Incumbent.Fitness)
Context.LastSuccess = Context.Iterations;
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;
}
}
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("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;
}
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("EvaluatedSolutions", out result2))
((IntValue)result2.Value).Value = Context.EvaluatedSolutions;
else Results.Add(new Result("EvaluatedSolutions", new IntValue(Context.EvaluatedSolutions)));
}
}
}