Free cookie consent management tool by TermsFeed Policy Generator

source: branches/jschiess/HeuristicLab.Algorithms.SimulatedAnnealing/3.4/AcceptanceRatioReheatingOperator.cs @ 15428

Last change on this file since 15428 was 15333, checked in by jschiess, 7 years ago

#1836 SA reheating strategies
+ added an adaptive temperature control strategy
+ some refactorings

File size: 13.3 KB
RevLine 
[14555]1using HeuristicLab.Operators;
2using System;
3using System.Collections.Generic;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7using HeuristicLab.Common;
8using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
9using HeuristicLab.Core;
10using HeuristicLab.Data;
11using HeuristicLab.Parameters;
12using HeuristicLab.Optimization;
13using HeuristicLab.PluginInfrastructure;
14using HeuristicLab.Analysis;
15
16namespace HeuristicLab.Algorithms.SimulatedAnnealing
17{
[15315]18    [Item("AcceptanceRatioReheatingOperator", "Reheats the temperature if the acceptance is below a threshold until it is above another one.")]
[14555]19    [StorableClass]
20    public class AcceptanceRatioReheatingOperator : SingleSuccessorOperator, IReheatingOperator
21    {
22        #region Strings
23        private const string AnnealingOperatorName = "AnnealingOperator";
24        private const string LowerTemperatureName = "LowerTemperature";
25        private const string IterationsName = "Iterations";
26        private const string TemperatureStartIndexName = "TemperatureStartIndex";
27        private const string StartTemperatureName = "StartTemperature";
28        private const string EndTemperatureName = "EndTemperature";
29        private const string TemperatureName = "Temperature";
30        private const string MaximumIterationsName = "MaximumIterations";
31
32        private const string UpperTemperatureName = "UpperTemperature";
33        private const string ReheatingOperatorName = "ReheatingOperator";
34        private const string ThresholdName = "Threshold";
35        private const string MemorySizeName = "MemorySize";
36        private const string CoolingName = "Cooling";
37        private const string IsAcceptedName = "IsAccepted";
38        private const string AcceptanceMemoryName = "AcceptanceMemory";
[15001]39        private const string AverageAcceptanceRatioName = "AverageAcceptanceRatio";
[15315]40        private const string ReheatWindowSizeName = "ReheatWindowSize";
[15333]41        private const string LastAcceptedQualityName = "LastAcceptedQuality";
42        private const string MoveQualityName = "MoveQuality";
[14555]43
44
45        #endregion
46        #region Parameters
47        public ILookupParameter<DoubleValue> TemperatureParameter
48        {
49            get { return (ILookupParameter<DoubleValue>)Parameters[TemperatureName]; }
50        }
51        public ILookupParameter<DoubleValue> LowerTemperatureParameter
52        {
53            get { return (ILookupParameter<DoubleValue>)Parameters[LowerTemperatureName]; }
54        }
55        public ILookupParameter<DoubleValue> StartTemperatureParameter
56        {
57            get { return (ILookupParameter<DoubleValue>)Parameters[StartTemperatureName]; }
58        }
59        public ILookupParameter<DoubleValue> EndTemperatureParameter
60        {
61            get { return (ILookupParameter<DoubleValue>)Parameters[EndTemperatureName]; }
62        }
63        public ILookupParameter<IntValue> TemperatureStartIndexParameter
64        {
65            get { return (ILookupParameter<IntValue>)Parameters[TemperatureStartIndexName]; }
66        }
67        public ILookupParameter<IntValue> IterationsParameter
68        {
69            get { return (ILookupParameter<IntValue>)Parameters[IterationsName]; }
70        }
[15333]71        public ILookupParameter<IDiscreteDoubleValueModifier> AnnealingOperatorParameter
[14555]72        {
[15333]73            get { return (ILookupParameter<IDiscreteDoubleValueModifier>)Parameters[AnnealingOperatorName]; }
[14555]74        }
75        public ILookupParameter<IntValue> MaximumIterationsParameter
76        {
77            get { return (ILookupParameter<IntValue>)Parameters[MaximumIterationsName]; }
78        }
[15001]79        private ValueLookupParameter<DoubleValue> UpperTemperatureParameter
[14555]80        {
[15001]81            get { return (ValueLookupParameter<DoubleValue>)Parameters[UpperTemperatureName]; }
[14555]82        }
83        private IConstrainedValueParameter<IDiscreteDoubleValueModifier> ReheatingOperatorParameter
84        {
85            get { return (IConstrainedValueParameter<IDiscreteDoubleValueModifier>)Parameters[ReheatingOperatorName]; }
86        }
87        private ValueParameter<DoubleRange> ThresholdParameter
88        {
89            get { return (ValueParameter<DoubleRange>)Parameters[ThresholdName]; }
90        }
91        private ValueParameter<IntValue> MemorySizeParameter
92        {
93            get { return (ValueParameter<IntValue>)Parameters[MemorySizeName]; }
94        }
95        public ILookupParameter<BoolValue> CoolingParameter
96        {
97            get { return (ILookupParameter<BoolValue>)Parameters[CoolingName]; }
98        }
99        public ILookupParameter<BoolValue> IsAcceptedParameter
100        {
101            get { return (ILookupParameter<BoolValue>)Parameters[IsAcceptedName]; }
102        }
103        public ILookupParameter<ItemList<BoolValue>> AcceptanceMemoryParameter
104        {
105            get { return (ILookupParameter<ItemList<BoolValue>>)Parameters[AcceptanceMemoryName]; }
106        }
[15001]107        public ILookupParameter<DoubleValue> AverageAcceptanceRatioParameter
108        {
109            get { return (ILookupParameter<DoubleValue>)Parameters[AverageAcceptanceRatioName]; }
110        }
[15315]111        public IValueParameter<IntValue> ReheatWindowSizeParameter
112        {
113            get { return (IValueParameter<IntValue>)Parameters[ReheatWindowSizeName]; }
114        }
[15333]115        public ILookupParameter<DoubleValue> MoveQualityParameter
116        {
117            get { return (ILookupParameter<DoubleValue>)Parameters[MoveQualityName]; }
118        }
119        public ILookupParameter<DoubleValue> LastAcceptedQualityParameter
120        {
121            get { return (ILookupParameter<DoubleValue>)Parameters[LastAcceptedQualityName]; }
122        }
[14555]123
124        #endregion
125
126        public AcceptanceRatioReheatingOperator() : base()
127        {
128            #region Create parameters
129            Parameters.Add(new LookupParameter<DoubleValue>(TemperatureName, "The current temperature."));
130            Parameters.Add(new LookupParameter<DoubleValue>(LowerTemperatureName, "The lower bound of the temperature."));
131            Parameters.Add(new LookupParameter<IntValue>(IterationsName, "The number of iterations."));
[15333]132            Parameters.Add(new LookupParameter<IDiscreteDoubleValueModifier>(AnnealingOperatorName, "The operator that cools the temperature."));
[14555]133            Parameters.Add(new LookupParameter<IntValue>(TemperatureStartIndexName, "The index where the annealing or heating was last changed."));
134            Parameters.Add(new LookupParameter<DoubleValue>(StartTemperatureName, "The temperature from which cooling or reheating should occur."));
135            Parameters.Add(new LookupParameter<DoubleValue>(EndTemperatureName, "The temperature to which should be cooled or heated."));
136            Parameters.Add(new LookupParameter<IntValue>(MaximumIterationsName, "The maximum number of iterations which should be processed."));
137            Parameters.Add(new LookupParameter<BoolValue>(IsAcceptedName, "Whether the move was accepted or not."));
138            Parameters.Add(new LookupParameter<ItemList<BoolValue>>(AcceptanceMemoryName, "Memorizes the last N acceptance decisions."));
139            Parameters.Add(new LookupParameter<BoolValue>(CoolingName, "True when the temperature should be cooled, false otherwise."));
[15001]140            Parameters.Add(new ValueLookupParameter<DoubleValue>(UpperTemperatureName, "The upper bound of the temperature.", "InitialTemperature"));
[14555]141            Parameters.Add(new ConstrainedValueParameter<IDiscreteDoubleValueModifier>(ReheatingOperatorName, "The operator that reheats the temperature."));
[15001]142            Parameters.Add(new ValueParameter<DoubleRange>(ThresholdName, "The threshold controls the temperature. If the average ratio of accepted moves goes below the start of the range the temperature is heated. If the the average ratio of accepted moves goes beyond the end of the range the temperature is cooled again.", new DoubleRange(0.01, 0.1)));
[14555]143            Parameters.Add(new ValueParameter<IntValue>(MemorySizeName, "The maximum size of the acceptance memory.", new IntValue(100)));
[15001]144            Parameters.Add(new LookupParameter<DoubleValue>(AverageAcceptanceRatioName, "Average acceptance over full acceptance memory."));
[15315]145            Parameters.Add(new ValueParameter<IntValue>(ReheatWindowSizeName, "The amount of iterations each reheat needs to heat the current temperature to upper temperature.", new IntValue(10000)));
[15333]146            Parameters.Add(new LookupParameter<DoubleValue>(LastAcceptedQualityName, "Quality of last accepted solution."));
147            Parameters.Add(new LookupParameter<DoubleValue>(MoveQualityName, "The value which represents the quality of a move."));
[14555]148            #endregion
149
150            foreach (var op in ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>().OrderBy(x => x.Name))
151            {
152                ReheatingOperatorParameter.ValidValues.Add((IDiscreteDoubleValueModifier) op);
153            }
154            Parameterize();
155        }
156
157        [StorableConstructor]
158        protected AcceptanceRatioReheatingOperator(bool deserializing) : base(deserializing) { }
159        protected AcceptanceRatioReheatingOperator(AcceptanceRatioReheatingOperator original, Cloner cloner) : base(original, cloner) { }
160
161
162        public override IDeepCloneable Clone(Cloner cloner)
163        {
164            return new AcceptanceRatioReheatingOperator(this, cloner);
165        }
166
167        public void Parameterize()
168        {
169            foreach (var op in ReheatingOperatorParameter.ValidValues)
170            {
171                op.IndexParameter.ActualName = IterationsName;
172                op.IndexParameter.Hidden = true;
173                op.StartIndexParameter.Value = null;
174                op.StartIndexParameter.ActualName = TemperatureStartIndexName;
175                op.EndIndexParameter.ActualName = MaximumIterationsParameter.Name;
176                op.ValueParameter.ActualName = TemperatureName;
177                op.ValueParameter.Hidden = true;
178                op.StartValueParameter.ActualName = StartTemperatureName;
179                op.StartValueParameter.Hidden = true;
[15001]180                op.EndValueParameter.ActualName = EndTemperatureName;
[14555]181                op.EndValueParameter.Hidden = true;
182            }
183        }
184
185        public override IOperation Apply()
186        {
[15333]187            var isAccepted = IsAcceptedParameter.ActualValue.Value && LastAcceptedQualityParameter.ActualValue.Value != MoveQualityParameter.ActualValue.Value;
[14555]188            var acceptances = AcceptanceMemoryParameter.ActualValue;
189            var cooling = CoolingParameter.ActualValue.Value;
[15001]190            var ratioAmount = AverageAcceptanceRatioParameter.ActualValue;
[14555]191
[15333]192            acceptances.Add(new BoolValue(isAccepted));
193            ratioAmount.Value += isAccepted ? 1 : 0;
[14555]194
[15001]195            if (acceptances.Count > MemorySizeParameter.Value.Value) {
196                ratioAmount.Value -= acceptances.ElementAt(0).Value ? 1 : 0;
197                acceptances.RemoveAt(0);
[14555]198            }
[15001]199
200            // only reheat when at least MemorySizeParameter.Value iterations have passed
201            if (acceptances.Count == MemorySizeParameter.Value.Value)
[14555]202            {
[15001]203                var ratio = ratioAmount.Value / MemorySizeParameter.Value.Value;
204                var ratioStart = ThresholdParameter.Value.Start;
205                var ratioEnd = ThresholdParameter.Value.End;
[14555]206
[15001]207                if (!cooling && ratio >= ratioEnd)
208                {
209                    // if we are heating, but should be cooling
210                    cooling = true;
211                    TemperatureStartIndexParameter.ActualValue.Value = Math.Max(0, IterationsParameter.ActualValue.Value - 1);
212                    StartTemperatureParameter.ActualValue.Value = TemperatureParameter.ActualValue.Value;
213                    EndTemperatureParameter.ActualValue.Value = LowerTemperatureParameter.ActualValue.Value;
214                }
215                else if (cooling && ratio <= ratioStart)
216                {
217                    // if we are cooling but should be heating
218                    cooling = false;
219                    TemperatureStartIndexParameter.ActualValue.Value = Math.Max(0, IterationsParameter.ActualValue.Value - 1);
220                    StartTemperatureParameter.ActualValue.Value = TemperatureParameter.ActualValue.Value;
221                    EndTemperatureParameter.ActualValue.Value = UpperTemperatureParameter.ActualValue.Value;
[15315]222                    ReheatingOperatorParameter.Value.EndIndexParameter.Value = new IntValue(
223                        Math.Min(MaximumIterationsParameter.ActualValue.Value, IterationsParameter.ActualValue.Value + ReheatWindowSizeParameter.Value.Value));
[15001]224                }
[14555]225
[15001]226                CoolingParameter.ActualValue.Value = cooling;
227            }
[15333]228
229            if (isAccepted)
230            {
231                LastAcceptedQualityParameter.ActualValue.Value = MoveQualityParameter.ActualValue.Value;
232            }
233
[14555]234            return cooling ? Cool() : Heat();
235        }
236
237        private IOperation Heat()
238        {
239            return new OperationCollection {
240                    ExecutionContext.CreateOperation(ReheatingOperatorParameter.Value),
241                    base.Apply()
242                };
243        }
244
245        private IOperation Cool()
246        {
247            return new OperationCollection {
248                    ExecutionContext.CreateOperation(AnnealingOperatorParameter.ActualValue),
249                    base.Apply()
250                };
251        }
252    }
253}
Note: See TracBrowser for help on using the repository browser.