1 | using HeuristicLab.Operators;
|
---|
2 | using System;
|
---|
3 | using System.Collections.Generic;
|
---|
4 | using System.Linq;
|
---|
5 | using System.Text;
|
---|
6 | using System.Threading.Tasks;
|
---|
7 | using HeuristicLab.Common;
|
---|
8 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
9 | using HeuristicLab.Core;
|
---|
10 | using HeuristicLab.Data;
|
---|
11 | using HeuristicLab.Parameters;
|
---|
12 | using HeuristicLab.Optimization;
|
---|
13 | using HeuristicLab.PluginInfrastructure;
|
---|
14 | using HeuristicLab.Analysis;
|
---|
15 |
|
---|
16 | namespace HeuristicLab.Algorithms.SimulatedAnnealing
|
---|
17 | {
|
---|
18 | [Item("AcceptanceRatioReheatingOperator", "Reheats the temperature if the acceptance is below a threshold.")]
|
---|
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";
|
---|
39 |
|
---|
40 |
|
---|
41 | #endregion
|
---|
42 | #region Parameters
|
---|
43 | public ILookupParameter<DoubleValue> TemperatureParameter
|
---|
44 | {
|
---|
45 | get { return (ILookupParameter<DoubleValue>)Parameters[TemperatureName]; }
|
---|
46 | }
|
---|
47 | public ILookupParameter<DoubleValue> LowerTemperatureParameter
|
---|
48 | {
|
---|
49 | get { return (ILookupParameter<DoubleValue>)Parameters[LowerTemperatureName]; }
|
---|
50 | }
|
---|
51 | public ILookupParameter<DoubleValue> StartTemperatureParameter
|
---|
52 | {
|
---|
53 | get { return (ILookupParameter<DoubleValue>)Parameters[StartTemperatureName]; }
|
---|
54 | }
|
---|
55 | public ILookupParameter<DoubleValue> EndTemperatureParameter
|
---|
56 | {
|
---|
57 | get { return (ILookupParameter<DoubleValue>)Parameters[EndTemperatureName]; }
|
---|
58 | }
|
---|
59 | public ILookupParameter<IntValue> TemperatureStartIndexParameter
|
---|
60 | {
|
---|
61 | get { return (ILookupParameter<IntValue>)Parameters[TemperatureStartIndexName]; }
|
---|
62 | }
|
---|
63 | public ILookupParameter<IntValue> IterationsParameter
|
---|
64 | {
|
---|
65 | get { return (ILookupParameter<IntValue>)Parameters[IterationsName]; }
|
---|
66 | }
|
---|
67 | public ILookupParameter<IOperator> AnnealingOperatorParameter
|
---|
68 | {
|
---|
69 | get { return (ILookupParameter<IOperator>)Parameters[AnnealingOperatorName]; }
|
---|
70 | }
|
---|
71 | public ILookupParameter<IntValue> MaximumIterationsParameter
|
---|
72 | {
|
---|
73 | get { return (ILookupParameter<IntValue>)Parameters[MaximumIterationsName]; }
|
---|
74 | }
|
---|
75 | private ValueParameter<DoubleValue> UpperTemperatureParameter
|
---|
76 | {
|
---|
77 | get { return (ValueParameter<DoubleValue>)Parameters[UpperTemperatureName]; }
|
---|
78 | }
|
---|
79 | private IConstrainedValueParameter<IDiscreteDoubleValueModifier> ReheatingOperatorParameter
|
---|
80 | {
|
---|
81 | get { return (IConstrainedValueParameter<IDiscreteDoubleValueModifier>)Parameters[ReheatingOperatorName]; }
|
---|
82 | }
|
---|
83 | private ValueParameter<DoubleRange> ThresholdParameter
|
---|
84 | {
|
---|
85 | get { return (ValueParameter<DoubleRange>)Parameters[ThresholdName]; }
|
---|
86 | }
|
---|
87 | private ValueParameter<IntValue> MemorySizeParameter
|
---|
88 | {
|
---|
89 | get { return (ValueParameter<IntValue>)Parameters[MemorySizeName]; }
|
---|
90 | }
|
---|
91 | public ILookupParameter<BoolValue> CoolingParameter
|
---|
92 | {
|
---|
93 | get { return (ILookupParameter<BoolValue>)Parameters[CoolingName]; }
|
---|
94 | }
|
---|
95 | public ILookupParameter<BoolValue> IsAcceptedParameter
|
---|
96 | {
|
---|
97 | get { return (ILookupParameter<BoolValue>)Parameters[IsAcceptedName]; }
|
---|
98 | }
|
---|
99 | public ILookupParameter<ItemList<BoolValue>> AcceptanceMemoryParameter
|
---|
100 | {
|
---|
101 | get { return (ILookupParameter<ItemList<BoolValue>>)Parameters[AcceptanceMemoryName]; }
|
---|
102 | }
|
---|
103 |
|
---|
104 | #endregion
|
---|
105 |
|
---|
106 | public AcceptanceRatioReheatingOperator() : base()
|
---|
107 | {
|
---|
108 | #region Create parameters
|
---|
109 | Parameters.Add(new LookupParameter<DoubleValue>(TemperatureName, "The current temperature."));
|
---|
110 | Parameters.Add(new LookupParameter<DoubleValue>(LowerTemperatureName, "The lower bound of the temperature."));
|
---|
111 | Parameters.Add(new LookupParameter<IntValue>(IterationsName, "The number of iterations."));
|
---|
112 | Parameters.Add(new LookupParameter<IOperator>(AnnealingOperatorName, "The operator that cools the temperature."));
|
---|
113 | Parameters.Add(new LookupParameter<IntValue>(TemperatureStartIndexName, "The index where the annealing or heating was last changed."));
|
---|
114 | Parameters.Add(new LookupParameter<DoubleValue>(StartTemperatureName, "The temperature from which cooling or reheating should occur."));
|
---|
115 | Parameters.Add(new LookupParameter<DoubleValue>(EndTemperatureName, "The temperature to which should be cooled or heated."));
|
---|
116 | Parameters.Add(new LookupParameter<IntValue>(MaximumIterationsName, "The maximum number of iterations which should be processed."));
|
---|
117 | Parameters.Add(new LookupParameter<BoolValue>(IsAcceptedName, "Whether the move was accepted or not."));
|
---|
118 | Parameters.Add(new LookupParameter<ItemList<BoolValue>>(AcceptanceMemoryName, "Memorizes the last N acceptance decisions."));
|
---|
119 | Parameters.Add(new LookupParameter<BoolValue>(CoolingName, "True when the temperature should be cooled, false otherwise."));
|
---|
120 | Parameters.Add(new ValueParameter<DoubleValue>(UpperTemperatureName, "The upper bound of the temperature.", new DoubleValue(100d)));
|
---|
121 | Parameters.Add(new ConstrainedValueParameter<IDiscreteDoubleValueModifier>(ReheatingOperatorName, "The operator that reheats the temperature."));
|
---|
122 | 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.2, 0.1)));
|
---|
123 | Parameters.Add(new ValueParameter<IntValue>(MemorySizeName, "The maximum size of the acceptance memory.", new IntValue(100)));
|
---|
124 |
|
---|
125 | #endregion
|
---|
126 |
|
---|
127 | foreach (var op in ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>().OrderBy(x => x.Name))
|
---|
128 | {
|
---|
129 | ReheatingOperatorParameter.ValidValues.Add((IDiscreteDoubleValueModifier) op);
|
---|
130 | }
|
---|
131 | Parameterize();
|
---|
132 | }
|
---|
133 |
|
---|
134 | [StorableConstructor]
|
---|
135 | protected AcceptanceRatioReheatingOperator(bool deserializing) : base(deserializing) { }
|
---|
136 | protected AcceptanceRatioReheatingOperator(AcceptanceRatioReheatingOperator original, Cloner cloner) : base(original, cloner) { }
|
---|
137 |
|
---|
138 |
|
---|
139 | public override IDeepCloneable Clone(Cloner cloner)
|
---|
140 | {
|
---|
141 | return new AcceptanceRatioReheatingOperator(this, cloner);
|
---|
142 | }
|
---|
143 |
|
---|
144 | public void Parameterize()
|
---|
145 | {
|
---|
146 | foreach (var op in ReheatingOperatorParameter.ValidValues)
|
---|
147 | {
|
---|
148 | op.IndexParameter.ActualName = IterationsName;
|
---|
149 | op.IndexParameter.Hidden = true;
|
---|
150 | op.StartIndexParameter.Value = null;
|
---|
151 | op.StartIndexParameter.ActualName = TemperatureStartIndexName;
|
---|
152 | op.EndIndexParameter.ActualName = MaximumIterationsParameter.Name;
|
---|
153 | op.ValueParameter.ActualName = TemperatureName;
|
---|
154 | op.ValueParameter.Hidden = true;
|
---|
155 | op.StartValueParameter.ActualName = StartTemperatureName;
|
---|
156 | op.StartValueParameter.Hidden = true;
|
---|
157 | op.EndValueParameter.ActualName = UpperTemperatureName;
|
---|
158 | op.EndValueParameter.Value = UpperTemperatureParameter.Value;
|
---|
159 | op.EndValueParameter.Hidden = true;
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 | public override IOperation Apply()
|
---|
164 | {
|
---|
165 |
|
---|
166 | var acceptances = AcceptanceMemoryParameter.ActualValue;
|
---|
167 | var cooling = CoolingParameter.ActualValue.Value;
|
---|
168 |
|
---|
169 | acceptances.Add(IsAcceptedParameter.ActualValue);
|
---|
170 |
|
---|
171 | if (acceptances.Count > MemorySizeParameter.Value.Value) acceptances.RemoveAt(0);
|
---|
172 |
|
---|
173 | var ratioStart = ThresholdParameter.Value.Start;
|
---|
174 | var ratioEnd = ThresholdParameter.Value.End;
|
---|
175 | var ratio = acceptances.Average(x => x.Value ? 1.0 : 0.0);
|
---|
176 |
|
---|
177 |
|
---|
178 | if (!cooling && ratio >= ratioEnd)
|
---|
179 | {
|
---|
180 | // if we are heating, but should be cooling
|
---|
181 | cooling = true;
|
---|
182 | TemperatureStartIndexParameter.ActualValue.Value = Math.Max(0, IterationsParameter.ActualValue.Value - 1);
|
---|
183 | StartTemperatureParameter.ActualValue.Value = TemperatureParameter.ActualValue.Value;
|
---|
184 | EndTemperatureParameter.ActualValue.Value = LowerTemperatureParameter.ActualValue.Value;
|
---|
185 | }
|
---|
186 | else if (cooling && ratio <= ratioStart)
|
---|
187 | {
|
---|
188 | // if we are cooling but should be heating
|
---|
189 | cooling = false;
|
---|
190 | TemperatureStartIndexParameter.ActualValue.Value = Math.Max(0, IterationsParameter.ActualValue.Value - 1);
|
---|
191 | StartTemperatureParameter.ActualValue.Value = TemperatureParameter.ActualValue.Value;
|
---|
192 | EndTemperatureParameter.ActualValue.Value = UpperTemperatureParameter.Value.Value;
|
---|
193 | }
|
---|
194 |
|
---|
195 | CoolingParameter.ActualValue.Value = cooling;
|
---|
196 |
|
---|
197 | return cooling ? Cool() : Heat();
|
---|
198 | }
|
---|
199 |
|
---|
200 | private IOperation Heat()
|
---|
201 | {
|
---|
202 | return new OperationCollection {
|
---|
203 | ExecutionContext.CreateOperation(ReheatingOperatorParameter.Value),
|
---|
204 | base.Apply()
|
---|
205 | };
|
---|
206 | }
|
---|
207 |
|
---|
208 | private IOperation Cool()
|
---|
209 | {
|
---|
210 | return new OperationCollection {
|
---|
211 | ExecutionContext.CreateOperation(AnnealingOperatorParameter.ActualValue),
|
---|
212 | base.Apply()
|
---|
213 | };
|
---|
214 | }
|
---|
215 | }
|
---|
216 | }
|
---|