#region License Information /* HeuristicLab * Copyright (C) 2002-2012 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 HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Algorithms.SimulatedAnnealing { [Item("SimulatedAnnealingMainLoop", "An operator which represents the main loop of a simulated annealing algorithm.")] [StorableClass] public sealed class SimulatedAnnealingMainLoop : AlgorithmOperator { #region Strings private const string MoveGeneratorName = "MoveGenerator"; private const string MoveEvaluatorName = "MoveEvaluator"; private const string MoveMakerName = "MoveMaker"; private const string AnnealingOperatorName = "AnnealingOperator"; private const string ReheatingOperatorName = "ReheatingOperator"; private const string MaximumIterationsName = "MaximumIterations"; private const string LowerTemperatureName = "LowerTemperature"; private const string AnalyzerName = "Analyzer"; private const string RandomName = "Random"; private const string EvaluatedMovesName = "EvaluatedMoves"; private const string IterationsName = "Iterations"; private const string TemperatureStartIndexName = "TemperatureStartIndex"; private const string CoolingName = "Cooling"; private const string InitialTemperatureName = "InitialTemperature"; private const string StartTemperatureName = "StartTemperature"; private const string EndTemperatureName = "EndTemperature"; private const string TemperatureName = "Temperature"; private const string ResultsName = "Results"; private const string MaximizationName = "Maximization"; private const string QualityName = "Quality"; private const string BestKnownQualityName = "BestKnownQuality"; private const string MoveQualityName = "MoveQuality"; private const string IsAcceptedName = "IsAccepted"; private const string TerminateName = "Terminate"; private const string AcceptanceMemoryName = "AcceptanceMemory"; private const string ConsecutiveRejectedSolutionsCountName = "ConsecutiveRejectedSolutions"; private const string AverageAcceptanceRatioName = "AverageAcceptanceRatio"; private const string LastQualityName = "LastQuality"; private const string UphillMovesMemoryName = "UphillMovesMemory"; private const string CurrentRandomWalkStepName = "CurrentRandomWalkStep"; private const string LastAcceptedQualityName = "LastAcceptedQuality"; private const string TemperatureInitializerName = "TemperatureInitializer"; private const string TemperatureInitializedName = "TemperatureInitialized"; #endregion #region Parameter properties public IValueLookupParameter RandomParameter { get { return (IValueLookupParameter)Parameters[RandomName]; } } public IValueLookupParameter MaximizationParameter { get { return (IValueLookupParameter)Parameters[MaximizationName]; } } public ILookupParameter QualityParameter { get { return (ILookupParameter)Parameters[QualityName]; } } public IValueLookupParameter BestKnownQualityParameter { get { return (IValueLookupParameter)Parameters[BestKnownQualityName]; } } public IValueLookupParameter LastQualityParameter { get { return (IValueLookupParameter)Parameters[LastQualityName]; } } public ILookupParameter InitialTemperatureParameter { get { return (ILookupParameter)Parameters[InitialTemperatureName]; } } public ILookupParameter MoveQualityParameter { get { return (ILookupParameter)Parameters[MoveQualityName]; } } public ILookupParameter TemperatureParameter { get { return (ILookupParameter)Parameters[TemperatureName]; } } public IValueLookupParameter LowerTemperatureParameter { get { return (IValueLookupParameter)Parameters[LowerTemperatureName]; } } public ILookupParameter IterationsParameter { get { return (ILookupParameter)Parameters[IterationsName]; } } public IValueLookupParameter MaximumIterationsParameter { get { return (IValueLookupParameter)Parameters[MaximumIterationsName]; } } public IValueLookupParameter MoveGeneratorParameter { get { return (IValueLookupParameter)Parameters[MoveGeneratorName]; } } public IValueLookupParameter MoveEvaluatorParameter { get { return (IValueLookupParameter)Parameters[MoveEvaluatorName]; } } public IValueLookupParameter MoveMakerParameter { get { return (IValueLookupParameter)Parameters[MoveMakerName]; } } public IValueLookupParameter AnnealingOperatorParameter { get { return (IValueLookupParameter)Parameters[AnnealingOperatorName]; } } public IValueLookupParameter ReheatingOperatorParameter { get { return (IValueLookupParameter)Parameters[ReheatingOperatorName]; } } public IValueLookupParameter AnalyzerParameter { get { return (IValueLookupParameter)Parameters[AnalyzerName]; } } public IValueLookupParameter ResultsParameter { get { return (IValueLookupParameter)Parameters[ResultsName]; } } public ILookupParameter EvaluatedMovesParameter { get { return (ILookupParameter)Parameters[EvaluatedMovesName]; } } public ILookupParameter StartTemperatureParameter { get { return (ILookupParameter)Parameters[StartTemperatureName]; } } public ILookupParameter EndTemperatureParameter { get { return (ILookupParameter)Parameters[EndTemperatureName]; } } public ILookupParameter TemperatureStartIndexParameter { get { return (ILookupParameter)Parameters[TemperatureStartIndexName]; } } public ILookupParameter CoolingParameter { get { return (ILookupParameter)Parameters[CoolingName]; } } #endregion [StorableConstructor] private SimulatedAnnealingMainLoop(bool deserializing) : base(deserializing) { } private SimulatedAnnealingMainLoop(SimulatedAnnealingMainLoop original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new SimulatedAnnealingMainLoop(this, cloner); } public SimulatedAnnealingMainLoop() : base() { Initialize(); } private void Initialize() { #region Create parameters Parameters.Add(new ValueLookupParameter(RandomName, "A pseudo random number generator.")); Parameters.Add(new ValueLookupParameter(MaximizationName, "True if the problem is a maximization problem, otherwise false.")); Parameters.Add(new LookupParameter(QualityName, "The value which represents the quality of a solution.")); Parameters.Add(new ValueLookupParameter(BestKnownQualityName, "The best known quality value found so far.")); Parameters.Add(new LookupParameter(MoveQualityName, "The value which represents the quality of a move.")); Parameters.Add(new LookupParameter(TemperatureName, "The current temperature.")); Parameters.Add(new ValueLookupParameter(LowerTemperatureName, "The lower bound of the temperature.")); Parameters.Add(new LookupParameter(IterationsName, "The number of iterations.")); Parameters.Add(new ValueLookupParameter(MaximumIterationsName, "The maximum number of iterations which should be processed.")); Parameters.Add(new ValueLookupParameter(MoveGeneratorName, "The operator that generates the moves.")); Parameters.Add(new ValueLookupParameter(MoveEvaluatorName, "The operator that evaluates a move.")); Parameters.Add(new ValueLookupParameter(MoveMakerName, "The operator that performs a move and updates the quality.")); Parameters.Add(new ValueLookupParameter(AnnealingOperatorName, "The operator that cools the temperature.")); Parameters.Add(new ValueLookupParameter(ReheatingOperatorName, "The operator that reheats the temperature if necessary.")); Parameters.Add(new ValueLookupParameter(TemperatureInitializerName, "The operator that initialized the temperature.")); Parameters.Add(new ValueLookupParameter(AnalyzerName, "The operator used to analyze each generation.")); Parameters.Add(new ValueLookupParameter(ResultsName, "The variable collection where results should be stored.")); Parameters.Add(new LookupParameter(EvaluatedMovesName, "The number of evaluated moves.")); Parameters.Add(new LookupParameter(InitialTemperatureName, "The initial temperature.")); Parameters.Add(new LookupParameter(TemperatureStartIndexName, "The index where the annealing or heating was last changed.")); Parameters.Add(new LookupParameter(CoolingName, "True when the temperature should be cooled, false otherwise.")); Parameters.Add(new LookupParameter(StartTemperatureName, "The temperature from which cooling or reheating should occur.")); Parameters.Add(new LookupParameter(EndTemperatureName, "The temperature to which should be cooled or heated.")); #endregion #region Create operators var variableCreator = new VariableCreator(); var ssp1 = new SubScopesProcessor(); var analyzer1 = new Placeholder(); var ssp2 = new SubScopesProcessor(); var resultsCollector = new ResultsCollector(); var mainProcessor = new SubScopesProcessor(); var moveGenerator = new Placeholder(); var moveEvaluationProcessor = new SubScopesProcessor(); var moveEvaluator = new Placeholder(); var evaluatedMovesCounter = new IntCounter(); var qualityComparator = new ProbabilisticQualityComparator(); var acceptsQualityBranch = new ConditionalBranch(); var moveMaker = new Placeholder(); var temperatureController = new TemperatureController(); var subScopesRemover = new SubScopesRemover(); var iterationsCounter = new IntCounter(); var iterationsComparator = new Comparator(); var ssp3 = new SubScopesProcessor(); var analyzer2 = new Placeholder(); var iterationsTermination = new ConditionalBranch(); variableCreator.Name = "Initialize Memory"; variableCreator.CollectedValues.Add(new ValueParameter(TemperatureInitializedName, new BoolValue(false))); variableCreator.CollectedValues.Add(new ValueParameter(AverageAcceptanceRatioName, new DoubleValue(0d))); variableCreator.CollectedValues.Add(new ValueParameter(ConsecutiveRejectedSolutionsCountName, new IntValue(0))); variableCreator.CollectedValues.Add(new ValueParameter>(AcceptanceMemoryName, new ItemList())); variableCreator.CollectedValues.Add(new ValueParameter(LastQualityName, new DoubleValue(-1))); variableCreator.CollectedValues.Add(new ValueParameter>(UphillMovesMemoryName, new ItemList())); variableCreator.CollectedValues.Add(new ValueParameter(CurrentRandomWalkStepName, new IntValue(0))); variableCreator.CollectedValues.Add(new ValueParameter(LastAcceptedQualityName, new DoubleValue(-1))); analyzer1.Name = "Analyzer"; analyzer1.OperatorParameter.ActualName = AnalyzerParameter.Name; moveGenerator.Name = "Move generator"; moveGenerator.OperatorParameter.ActualName = MoveGeneratorParameter.Name; moveEvaluator.Name = "Move evaluator"; moveEvaluator.OperatorParameter.ActualName = MoveEvaluatorParameter.Name; evaluatedMovesCounter.Name = "EvaluatedMoves++"; evaluatedMovesCounter.ValueParameter.ActualName = EvaluatedMovesParameter.Name; evaluatedMovesCounter.Increment = new IntValue(1); qualityComparator.LeftSideParameter.ActualName = MoveQualityParameter.Name; qualityComparator.RightSideParameter.ActualName = QualityParameter.Name; qualityComparator.ResultParameter.ActualName = IsAcceptedName; qualityComparator.DampeningParameter.ActualName = TemperatureParameter.Name; acceptsQualityBranch.ConditionParameter.ActualName = IsAcceptedName; moveMaker.Name = "Move maker"; moveMaker.OperatorParameter.ActualName = MoveMakerParameter.Name; subScopesRemover.RemoveAllSubScopes = true; iterationsCounter.Name = "Iterations++"; iterationsCounter.Increment = new IntValue(1); iterationsCounter.ValueParameter.ActualName = IterationsParameter.Name; iterationsComparator.Name = "Iterations >= MaximumIterations"; iterationsComparator.LeftSideParameter.ActualName = IterationsParameter.Name; iterationsComparator.RightSideParameter.ActualName = MaximumIterationsParameter.Name; iterationsComparator.ResultParameter.ActualName = TerminateName; iterationsComparator.Comparison.Value = ComparisonType.GreaterOrEqual; analyzer2.Name = "Analyzer (placeholder)"; analyzer2.OperatorParameter.ActualName = AnalyzerParameter.Name; iterationsTermination.Name = "Iterations termination condition"; iterationsTermination.ConditionParameter.ActualName = TerminateName; #endregion #region Create operator graph OperatorGraph.InitialOperator = variableCreator; variableCreator.Successor = ssp1; ssp1.Operators.Add(analyzer1); ssp1.Successor = ssp2; analyzer1.Successor = null; ssp2.Operators.Add(resultsCollector); ssp2.Successor = mainProcessor; resultsCollector.Successor = null; mainProcessor.Operators.Add(moveGenerator); mainProcessor.Successor = iterationsCounter; moveGenerator.Successor = moveEvaluationProcessor; moveEvaluationProcessor.Operators.Add(moveEvaluator); moveEvaluationProcessor.Successor = evaluatedMovesCounter; moveEvaluator.Successor = qualityComparator; qualityComparator.Successor = acceptsQualityBranch; acceptsQualityBranch.TrueBranch = moveMaker; acceptsQualityBranch.FalseBranch = null; acceptsQualityBranch.Successor = temperatureController; moveMaker.Successor = null; temperatureController.Successor = null; evaluatedMovesCounter.Successor = subScopesRemover; subScopesRemover.Successor = null; iterationsCounter.Successor = iterationsComparator; iterationsComparator.Successor = ssp3; ssp3.Operators.Add(analyzer2); ssp3.Successor = iterationsTermination; iterationsTermination.TrueBranch = null; iterationsTermination.FalseBranch = mainProcessor; #endregion } public override IOperation Apply() { if (MoveGeneratorParameter.ActualValue == null || MoveEvaluatorParameter.ActualValue == null || MoveMakerParameter.ActualValue == null) return null; return base.Apply(); } } }