Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CMAES/HeuristicLab.Encodings.RealVectorEncoding/3.3/CMAESOperators/CMAUpdater.cs @ 9118

Last change on this file since 9118 was 9118, checked in by abeham, 11 years ago

#1961: Updated CMA-ES (working version), but no wiring

File size: 8.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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 HeuristicLab.Common;
23using HeuristicLab.Core;
24using HeuristicLab.Data;
25using HeuristicLab.Operators;
26using HeuristicLab.Optimization;
27using HeuristicLab.Parameters;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29using System;
30using System.Linq;
31
32namespace HeuristicLab.Encodings.RealVectorEncoding {
33  [Item("CMAUpdater", "Updates the covariance matrix and strategy parameters of CMA-ES.")]
34  [StorableClass]
35  public class CMAUpdater : SingleSuccessorOperator, IRealVectorOperator, ICMAESUpdater, IIterationBasedOperator {
36
37    public Type CMAType {
38      get { return typeof(CMAParameters); }
39    }
40
41    #region Parameter Properties
42
43    public ILookupParameter<CMAParameters> StrategyParametersParameter {
44      get { return (ILookupParameter<CMAParameters>)Parameters["StrategyParameters"]; }
45    }
46
47    public IScopeTreeLookupParameter<RealVector> MeansParameter {
48      get { return (IScopeTreeLookupParameter<RealVector>)Parameters["Means"]; }
49    }
50
51    public IScopeTreeLookupParameter<RealVector> OffspringParameter {
52      get { return (IScopeTreeLookupParameter<RealVector>)Parameters["Offspring"]; }
53    }
54
55    public ILookupParameter<IntValue> IterationsParameter {
56      get { return (ILookupParameter<IntValue>)Parameters["Iterations"]; }
57    }
58
59    public IValueLookupParameter<IntValue> MaximumIterationsParameter {
60      get { return (IValueLookupParameter<IntValue>)Parameters["MaximumIterations"]; }
61    }
62    #endregion
63
64    [StorableConstructor]
65    protected CMAUpdater(bool deserializing) : base(deserializing) { }
66    protected CMAUpdater(CMAUpdater original, Cloner cloner) : base(original, cloner) { }
67    public CMAUpdater()
68      : base() {
69      Parameters.Add(new LookupParameter<CMAParameters>("StrategyParameters", "The strategy parameters of CMA-ES."));
70      Parameters.Add(new ScopeTreeLookupParameter<RealVector>("Means", "The old and the new mean.", 2));
71      Parameters.Add(new ScopeTreeLookupParameter<RealVector>("Offspring", "The created offspring solutions.", 3));
72      Parameters.Add(new LookupParameter<IntValue>("Iterations", "The number of iterations passed."));
73      Parameters.Add(new ValueLookupParameter<IntValue>("MaximumIterations", "The maximum number of iterations."));
74      MeansParameter.ActualName = "RealVector";
75      OffspringParameter.ActualName = "RealVector";
76    }
77
78    public override IDeepCloneable Clone(Cloner cloner) {
79      return new CMAUpdater(this, cloner);
80    }
81
82    public override IOperation Apply() {
83      var iterations = IterationsParameter.ActualValue.Value;
84
85      var xold = MeansParameter.ActualValue[0];
86      var xmean = MeansParameter.ActualValue[1];
87      var offspring = OffspringParameter.ActualValue;
88
89      var sp = StrategyParametersParameter.ActualValue;
90      var N = sp.C.Rows;
91
92      for (int i = 0; i < N; i++) {
93        sp.BDz[i] = Math.Sqrt(sp.MuEff.Value) * (xmean[i] - xold[i]) / sp.Sigma.Value;
94      }
95
96      if (sp.InitialIterations.Value >= iterations) {
97        for (int i = 0; i < N; i++) {
98          sp.PS[i] = (1 - sp.CS.Value) * sp.PS[i]
99                     + Math.Sqrt(sp.CS.Value * (2 - sp.CS.Value)) * sp.BDz[i] / sp.D[i];
100        }
101      } else {
102        var artmp = new double[N];
103        for (int i = 0; i < N; i++) {
104          var sum = 0.0;
105          for (int j = 0; j < N; j++) {
106            sum += sp.B[j, i] * sp.BDz[j];
107          }
108          artmp[i] = sum / sp.D[i];
109        }
110        for (int i = 0; i < N; i++) {
111          var sum = 0.0;
112          for (int j = 0; j < N; j++) {
113            sum += sp.B[i, j] * artmp[j];
114          }
115          sp.PS[i] = (1 - sp.CS.Value) * sp.PS[i] + Math.Sqrt(sp.CS.Value * (2 - sp.CS.Value)) * sum;
116        }
117      }
118      var normPS = Math.Sqrt(sp.PS.Select(x => x * x).Sum());
119      var hsig = normPS / Math.Sqrt(1 - Math.Pow(1 - sp.CS.Value, 2 * iterations)) / sp.ChiN.Value < 1.4 + 2.0 / (N + 1) ? 1.0 : 0.0;
120      for (int i = 0; i < sp.PC.Length; i++) {
121        sp.PC[i] = (1 - sp.CC.Value) * sp.PC[i]
122                   + hsig * Math.Sqrt(sp.CC.Value * (2 - sp.CC.Value)) * sp.BDz[i];
123      }
124
125      if (sp.CCov.Value > 0) {
126        if (sp.InitialIterations.Value >= iterations) {
127          for (int i = 0; i < N; i++) {
128            sp.C[i, i] = (1 - sp.CCovSep.Value) * sp.C[i, i]
129                         + sp.CCov.Value * (1 / sp.MuCov.Value)
130                         * (sp.PC[i] * sp.PC[i] + (1 - hsig) * sp.CC.Value * (2 - sp.CC.Value) * sp.C[i, i]);
131            for (int k = 0; k < sp.Mu.Value; k++) {
132              sp.C[i, i] += sp.CCov.Value * (1 - 1 / sp.MuCov.Value) * sp.Weights[k] * (offspring[k][i] - xold[i]) *
133                            (offspring[k][i] - xold[i]) / (sp.Sigma.Value * sp.Sigma.Value);
134            }
135          }
136        } else {
137          for (int i = 0; i < N; i++) {
138            for (int j = 0; j < N; j++) {
139              sp.C[i, j] = (1 - sp.CCov.Value) * sp.C[i, j]
140                           + sp.CCov.Value * (1 / sp.MuCov.Value)
141                           * (sp.PC[i] * sp.PC[j] + (1 - hsig) * sp.CC.Value * (2 - sp.CC.Value) * sp.C[i, j]);
142              for (int k = 0; k < sp.Mu.Value; k++) {
143                sp.C[i, j] += sp.CCov.Value * (1 - 1 / sp.MuCov.Value) * sp.Weights[k] * (offspring[k][i] - xold[i]) *
144                              (offspring[k][j] - xold[j]) / (sp.Sigma.Value * sp.Sigma.Value);
145              }
146            }
147          }
148        }
149      }
150      sp.Sigma.Value *= Math.Exp((sp.CS.Value / sp.Damps.Value) * (normPS / sp.ChiN.Value - 1));
151
152      double minSqrtdiagC = int.MaxValue, maxSqrtdiagC = int.MinValue;
153      for (int i = 0; i < N; i++) {
154        if (Math.Sqrt(sp.C[i, i]) < minSqrtdiagC) minSqrtdiagC = Math.Sqrt(sp.C[i, i]);
155        if (Math.Sqrt(sp.C[i, i]) > maxSqrtdiagC) maxSqrtdiagC = Math.Sqrt(sp.C[i, i]);
156      }
157
158      // ensure maximal and minimal standard deviations
159      if (sp.MinSigma != null && sp.MinSigma.Length > 0) {
160        for (int i = 0; i < N; i++) {
161          var d = sp.MinSigma[Math.Min(i, sp.MinSigma.Length - 1)];
162          if (d > sp.Sigma.Value * minSqrtdiagC) sp.Sigma.Value = d / minSqrtdiagC;
163        }
164      }
165      if (sp.MaxSigma != null && sp.MaxSigma.Length > 0) {
166        for (int i = 0; i < N; i++) {
167          var d = sp.MaxSigma[Math.Min(i, sp.MaxSigma.Length - 1)];
168          if (d > sp.Sigma.Value * maxSqrtdiagC) sp.Sigma.Value = d / maxSqrtdiagC;
169        }
170      }
171      // end ensure ...
172
173      // testAndCorrectNumerics
174      double fac = 1;
175      if (sp.D.Max() < 1e-6)
176        fac = 1.0 / sp.D.Max();
177      else if (sp.D.Min() > 1e4)
178        fac = 1.0 / sp.D.Min();
179
180      if (fac != 1.0) {
181        sp.Sigma.Value /= fac;
182        for (int i = 0; i < N; i++) {
183          sp.PC[i] *= fac;
184          sp.D[i] *= fac;
185          for (int j = 0; j < N; j++)
186            sp.C[i, j] *= fac * fac;
187        }
188      }
189      // end testAndCorrectNumerics
190
191      if (sp.InitialIterations.Value >= iterations) {
192        for (int i = 0; i < N; i++)
193          sp.D[i] = Math.Sqrt(sp.C[i, i]);
194      } else {
195        var c = new double[sp.C.Rows, sp.C.Columns];
196        for (int i = 0; i < sp.C.Rows; i++)
197          for (int j = 0; j < sp.C.Columns; j++)
198            c[i, j] = sp.C[i, j];
199        double[] eVal;
200        double[,] eVec;
201        if (!alglib.smatrixevd(c, N, 1, false, out eVal, out eVec))
202          throw new InvalidOperationException("Unable to perform eigendecomposition of matrix.");
203        sp.B = new DoubleMatrix(eVec);
204
205        for (int i = 0; i < sp.D.Length; i++)
206          sp.D[i] = Math.Sqrt(eVal[i]);
207
208        if (sp.D.Min() == 0.0) sp.AxisRatio.Value = double.PositiveInfinity;
209        else sp.AxisRatio.Value = sp.D.Max() / sp.D.Min();
210      }
211      return base.Apply();
212    }
213  }
214}
Note: See TracBrowser for help on using the repository browser.