source: trunk/sources/HeuristicLab.Encodings.RealVectorEncoding/3.3/ParticleOperators/RealVectorSwarmUpdater.cs @ 12012

Last change on this file since 12012 was 12012, checked in by ascheibe, 5 years ago

#2212 merged r12008, r12009, r12010 back into trunk

File size: 16.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Linq;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.Operators;
28using HeuristicLab.Optimization;
29using HeuristicLab.Optimization.Operators;
30using HeuristicLab.Parameters;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32using HeuristicLab.PluginInfrastructure;
33
34namespace HeuristicLab.Encodings.RealVectorEncoding {
35  [Item("RealVectorSwarmUpdater", "Updates personal best point and quality as well as global best point and quality.")]
36  [StorableClass]
37  public sealed class RealVectorSwarmUpdater : SingleSuccessorOperator, IRealVectorSwarmUpdater, ISingleObjectiveOperator {
38
39    [Storable]
40    private ResultsCollector ResultsCollector;
41
42    public override bool CanChangeName {
43      get { return false; }
44    }
45
46    #region Parameter properties
47    public IScopeTreeLookupParameter<DoubleValue> QualityParameter {
48      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
49    }
50    public IScopeTreeLookupParameter<DoubleValue> PersonalBestQualityParameter {
51      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["PersonalBestQuality"]; }
52    }
53    public IScopeTreeLookupParameter<DoubleValue> NeighborBestQualityParameter {
54      get { return (IScopeTreeLookupParameter<DoubleValue>)Parameters["NeighborBestQuality"]; }
55    }
56    public IScopeTreeLookupParameter<RealVector> RealVectorParameter {
57      get { return (IScopeTreeLookupParameter<RealVector>)Parameters["RealVector"]; }
58    }
59    public IScopeTreeLookupParameter<RealVector> PersonalBestParameter {
60      get { return (IScopeTreeLookupParameter<RealVector>)Parameters["PersonalBest"]; }
61    }
62    public IScopeTreeLookupParameter<RealVector> NeighborBestParameter {
63      get { return (IScopeTreeLookupParameter<RealVector>)Parameters["NeighborBest"]; }
64    }
65    public ILookupParameter<BoolValue> MaximizationParameter {
66      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
67    }
68    public ILookupParameter<DoubleValue> SwarmBestQualityParameter {
69      get { return (ILookupParameter<DoubleValue>)Parameters["SwarmBestQuality"]; }
70    }
71    public ILookupParameter<RealVector> BestRealVectorParameter {
72      get { return (ILookupParameter<RealVector>)Parameters["BestRealVector"]; }
73    }
74    public IScopeTreeLookupParameter<IntArray> NeighborsParameter {
75      get { return (IScopeTreeLookupParameter<IntArray>)Parameters["Neighbors"]; }
76    }
77    public IValueLookupParameter<DoubleMatrix> VelocityBoundsParameter {
78      get { return (ValueLookupParameter<DoubleMatrix>)Parameters["VelocityBounds"]; }
79    }
80    public ILookupParameter<DoubleMatrix> CurrentVelocityBoundsParameter {
81      get { return (ILookupParameter<DoubleMatrix>)Parameters["CurrentVelocityBounds"]; }
82    }
83    public LookupParameter<ResultCollection> ResultsParameter {
84      get { return (LookupParameter<ResultCollection>)Parameters["Results"]; }
85    }
86
87    #region Velocity Bounds Updating
88    public ILookupParameter<DoubleValue> VelocityBoundsScaleParameter {
89      get { return (ILookupParameter<DoubleValue>)Parameters["VelocityBoundsScale"]; }
90    }
91    public IConstrainedValueParameter<IDiscreteDoubleValueModifier> VelocityBoundsScalingOperatorParameter {
92      get { return (IConstrainedValueParameter<IDiscreteDoubleValueModifier>)Parameters["VelocityBoundsScalingOperator"]; }
93    }
94    public IValueLookupParameter<DoubleValue> VelocityBoundsStartValueParameter {
95      get { return (IValueLookupParameter<DoubleValue>)Parameters["VelocityBoundsStartValue"]; }
96    }
97    public IValueLookupParameter<DoubleValue> VelocityBoundsEndValueParameter {
98      get { return (IValueLookupParameter<DoubleValue>)Parameters["VelocityBoundsEndValue"]; }
99    }
100    public ILookupParameter<IntValue> VelocityBoundsIndexParameter {
101      get { return (ILookupParameter<IntValue>)Parameters["VelocityBoundsIndex"]; }
102    }
103    public IValueLookupParameter<IntValue> VelocityBoundsStartIndexParameter {
104      get { return (IValueLookupParameter<IntValue>)Parameters["VelocityBoundsStartIndex"]; }
105    }
106    public IValueLookupParameter<IntValue> VelocityBoundsEndIndexParameter {
107      get { return (IValueLookupParameter<IntValue>)Parameters["VelocityBoundsEndIndex"]; }
108    }
109    #endregion
110
111    #endregion
112
113    #region Parameter values
114    private DoubleValue SwarmBestQuality {
115      get { return SwarmBestQualityParameter.ActualValue; }
116      set { SwarmBestQualityParameter.ActualValue = value; }
117    }
118    private RealVector BestRealVector {
119      get { return BestRealVectorParameter.ActualValue; }
120      set { BestRealVectorParameter.ActualValue = value; }
121    }
122    private ItemArray<DoubleValue> Quality {
123      get { return QualityParameter.ActualValue; }
124    }
125    private ItemArray<DoubleValue> PersonalBestQuality {
126      get { return PersonalBestQualityParameter.ActualValue; }
127      set { PersonalBestQualityParameter.ActualValue = value; }
128    }
129    private ItemArray<DoubleValue> NeighborBestQuality {
130      get { return NeighborBestQualityParameter.ActualValue; }
131      set { NeighborBestQualityParameter.ActualValue = value; }
132    }
133    private ItemArray<RealVector> RealVector {
134      get { return RealVectorParameter.ActualValue; }
135    }
136    private ItemArray<RealVector> PersonalBest {
137      get { return PersonalBestParameter.ActualValue; }
138      set { PersonalBestParameter.ActualValue = value; }
139    }
140    private ItemArray<RealVector> NeighborBest {
141      get { return NeighborBestParameter.ActualValue; }
142      set { NeighborBestParameter.ActualValue = value; }
143    }
144    private bool Maximization {
145      get { return MaximizationParameter.ActualValue.Value; }
146    }
147    private ItemArray<IntArray> Neighbors {
148      get { return NeighborsParameter.ActualValue; }
149    }
150    private DoubleMatrix VelocityBounds {
151      get { return VelocityBoundsParameter.ActualValue; }
152    }
153    private DoubleMatrix CurrentVelocityBounds {
154      get { return CurrentVelocityBoundsParameter.ActualValue; }
155      set { CurrentVelocityBoundsParameter.ActualValue = value; }
156    }
157    private DoubleValue VelocityBoundsScale {
158      get { return VelocityBoundsScaleParameter.ActualValue; }
159      set { VelocityBoundsScaleParameter.ActualValue = value; }
160    }
161    private DoubleValue VelocityBoundsStartValue {
162      get { return VelocityBoundsStartValueParameter.ActualValue; }
163    }
164    public IDiscreteDoubleValueModifier VelocityBoundsScalingOperator {
165      get { return VelocityBoundsScalingOperatorParameter.Value; }
166      set { VelocityBoundsScalingOperatorParameter.Value = value; }
167    }
168    private ResultCollection Results {
169      get { return ResultsParameter.ActualValue; }
170    }
171    #endregion
172
173    #region Construction & Cloning
174
175    [StorableConstructor]
176    private RealVectorSwarmUpdater(bool deserializing) : base(deserializing) { }
177    private RealVectorSwarmUpdater(RealVectorSwarmUpdater original, Cloner cloner)
178      : base(original, cloner) {
179      ResultsCollector = cloner.Clone(original.ResultsCollector);
180    }
181    public RealVectorSwarmUpdater()
182      : base() {
183      Parameters.Add(new LookupParameter<DoubleValue>("SwarmBestQuality", "Swarm's best quality."));
184      Parameters.Add(new LookupParameter<RealVector>("BestRealVector", "Global best particle position."));
185      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "Particles' qualities."));
186      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("PersonalBestQuality", "Particles' personal best qualities."));
187      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("NeighborBestQuality", "Best neighbor particles' qualities."));
188      Parameters.Add(new ScopeTreeLookupParameter<RealVector>("RealVector", "Particles' positions."));
189      Parameters.Add(new ScopeTreeLookupParameter<RealVector>("PersonalBest", "Particles' personal best positions."));
190      Parameters.Add(new ScopeTreeLookupParameter<RealVector>("NeighborBest", "Neighborhood (or global in case of totally connected neighborhood) best particle positions."));
191      Parameters.Add(new ScopeTreeLookupParameter<IntArray>("Neighbors", "The list of neighbors for each particle."));
192      Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
193      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("VelocityBounds", "Maximum velocity for each dimension.", new DoubleMatrix(new double[,] { { -1, 1 } })));
194      Parameters.Add(new LookupParameter<DoubleMatrix>("CurrentVelocityBounds", "Current value of velocity bounds."));
195      Parameters.Add(new LookupParameter<ResultCollection>("Results", "Results"));
196
197      #region Velocity Bounds Updating
198      Parameters.Add(new LookupParameter<DoubleValue>("VelocityBoundsScale", "Scale parameter."));
199      Parameters.Add(new OptionalConstrainedValueParameter<IDiscreteDoubleValueModifier>("VelocityBoundsScalingOperator", "Modifies the value"));
200      Parameters.Add(new ValueLookupParameter<DoubleValue>("VelocityBoundsStartValue", "The start value of 'Value'.", new DoubleValue(1)));
201      Parameters.Add(new ValueLookupParameter<DoubleValue>("VelocityBoundsEndValue", "The end value of 'Value'.", new DoubleValue(1E-10)));
202      Parameters.Add(new LookupParameter<IntValue>("VelocityBoundsIndex", "The current index.", "Iterations"));
203      Parameters.Add(new ValueLookupParameter<IntValue>("VelocityBoundsStartIndex", "The start index at which to start modifying 'Value'.", new IntValue(0)));
204      Parameters.Add(new ValueLookupParameter<IntValue>("VelocityBoundsEndIndex", "The end index by which 'Value' should have reached 'EndValue'.", "MaxIterations"));
205      VelocityBoundsStartIndexParameter.Hidden = true;
206      VelocityBoundsEndIndexParameter.Hidden = true;
207      #endregion
208
209      Initialize();
210      RegisterEvents();
211    }
212
213    public override IDeepCloneable Clone(Cloner cloner) {
214      return new RealVectorSwarmUpdater(this, cloner);
215    }
216
217    #endregion
218
219    [StorableHook(HookType.AfterDeserialization)]
220    private void AfterDeserialization() {
221      if (!Parameters.ContainsKey("SwarmBestQuality")) {
222        ILookupParameter<DoubleValue> oldBestQualityParameter = Parameters["BestQuality"] as ILookupParameter<DoubleValue>;
223        Parameters.Add(new LookupParameter<DoubleValue>("SwarmBestQuality", "Swarm's best quality."));
224        if (oldBestQualityParameter.ActualName != oldBestQualityParameter.Name)
225          SwarmBestQualityParameter.ActualName = oldBestQualityParameter.ActualName;
226        Parameters.Remove("BestQuality");
227      }
228      RegisterEvents();
229    }
230
231    private void RegisterEvents() {
232      VelocityBoundsStartValueParameter.ValueChanged += new EventHandler(VelocityBoundsStartValueParameter_ValueChanged);
233      VelocityBoundsStartValueParameter.Value.ValueChanged += new EventHandler(VelocityBoundsStartValueParameter_Value_ValueChanged);
234    }
235
236    void VelocityBoundsStartValueParameter_Value_ValueChanged(object sender, EventArgs e) {
237      UpdateVelocityBoundsParamater();
238    }
239
240    void UpdateVelocityBoundsParamater() {
241      if (VelocityBoundsParameter.Value == null) {
242        VelocityBoundsParameter.Value = new DoubleMatrix(1, 2);
243      } else if (VelocityBoundsParameter.Value.Columns != 2) {
244        VelocityBoundsParameter.Value = new DoubleMatrix(VelocityBoundsParameter.Value.Rows, 2);
245      }
246      if (VelocityBoundsStartValueParameter.Value != null) {
247        DoubleMatrix matrix = VelocityBoundsParameter.Value;
248        for (int i = 0; i < matrix.Rows; i++) {
249          matrix[i, 0] = (-1) * VelocityBoundsStartValueParameter.Value.Value;
250          matrix[i, 1] = VelocityBoundsStartValueParameter.Value.Value;
251        }
252      }
253    }
254
255    void VelocityBoundsStartValueParameter_ValueChanged(object sender, EventArgs e) {
256      if (VelocityBoundsStartValueParameter.Value != null) {
257        VelocityBoundsStartValueParameter.Value.ValueChanged += new EventHandler(VelocityBoundsStartValueParameter_Value_ValueChanged);
258      }
259      UpdateVelocityBoundsParamater();
260    }
261
262    private void Initialize() {
263      ResultsCollector = new ResultsCollector();
264      ResultsCollector.CollectedValues.Add(CurrentVelocityBoundsParameter);
265      ResultsCollector.CollectedValues.Add(VelocityBoundsParameter);
266
267      foreach (IDiscreteDoubleValueModifier op in ApplicationManager.Manager.GetInstances<IDiscreteDoubleValueModifier>()) {
268        VelocityBoundsScalingOperatorParameter.ValidValues.Add(op);
269        op.ValueParameter.ActualName = VelocityBoundsScaleParameter.Name;
270        op.StartValueParameter.ActualName = VelocityBoundsStartValueParameter.Name;
271        op.EndValueParameter.ActualName = VelocityBoundsEndValueParameter.Name;
272        op.IndexParameter.ActualName = VelocityBoundsIndexParameter.Name;
273        op.StartIndexParameter.ActualName = VelocityBoundsStartIndexParameter.Name;
274        op.EndIndexParameter.ActualName = VelocityBoundsEndIndexParameter.Name;
275      }
276      VelocityBoundsScalingOperatorParameter.Value = null;
277    }
278
279    public override IOperation Apply() {
280      UpdateGlobalBest();
281      UpdateNeighborBest();
282      UpdatePersonalBest();
283      return UpdateVelocityBounds();
284    }
285
286    private void UpdateGlobalBest() {
287      if (SwarmBestQuality == null)
288        SwarmBestQuality = new DoubleValue();
289      SwarmBestQuality.Value = Maximization ? Quality.Max(v => v.Value) : Quality.Min(v => v.Value);
290      BestRealVector = (RealVector)RealVector[Quality.FindIndex(v => v.Value == SwarmBestQuality.Value)].Clone();
291    }
292
293    private void UpdateNeighborBest() {
294      if (Neighbors.Length > 0) {
295        var neighborBest = new ItemArray<RealVector>(Neighbors.Length);
296        var neighborBestQuality = new ItemArray<DoubleValue>(Neighbors.Length);
297        for (int n = 0; n < Neighbors.Length; n++) {
298          var pairs = Quality.Zip(RealVector, (q, p) => new { Quality = q, Point = p })
299            .Where((p, i) => i == n || Neighbors[n].Contains(i));
300          var bestNeighbor = Maximization ?
301            pairs.OrderByDescending(p => p.Quality.Value).First() :
302            pairs.OrderBy(p => p.Quality.Value).First();
303          neighborBest[n] = bestNeighbor.Point;
304          neighborBestQuality[n] = bestNeighbor.Quality;
305        }
306        NeighborBest = neighborBest;
307        NeighborBestQuality = neighborBestQuality;
308      }
309    }
310
311    private void UpdatePersonalBest() {
312      if (PersonalBestQuality.Length == 0)
313        PersonalBestQuality = (ItemArray<DoubleValue>)Quality.Clone();
314      for (int i = 0; i < RealVector.Length; i++) {
315        if (Maximization && Quality[i].Value > PersonalBestQuality[i].Value ||
316          !Maximization && Quality[i].Value < PersonalBestQuality[i].Value) {
317          PersonalBestQuality[i].Value = Quality[i].Value;
318          PersonalBest[i] = RealVector[i];
319        }
320      }
321    }
322
323    private IOperation UpdateVelocityBounds() {
324      if (CurrentVelocityBounds == null)
325        CurrentVelocityBounds = (DoubleMatrix)VelocityBounds.Clone();
326
327      if (VelocityBoundsScalingOperator == null)
328        return new OperationCollection() {
329          ExecutionContext.CreateChildOperation(ResultsCollector),       
330          base.Apply()
331        };
332
333      DoubleMatrix matrix = CurrentVelocityBounds;
334      if (VelocityBoundsScale == null && VelocityBoundsStartValue != null) {
335        VelocityBoundsScale = new DoubleValue(VelocityBoundsStartValue.Value);
336      }
337      for (int i = 0; i < matrix.Rows; i++) {
338        for (int j = 0; j < matrix.Columns; j++) {
339          if (matrix[i, j] >= 0) {
340            matrix[i, j] = VelocityBoundsScale.Value;
341          } else {
342            matrix[i, j] = (-1) * VelocityBoundsScale.Value;
343          }
344        }
345      }
346
347      return new OperationCollection() {
348        ExecutionContext.CreateChildOperation(ResultsCollector),
349        ExecutionContext.CreateChildOperation(VelocityBoundsScalingOperator),       
350        base.Apply()
351      };
352    }
353  }
354}
Note: See TracBrowser for help on using the repository browser.