source: branches/MOCMAEvolutionStrategy/HeuristicLab.Algorithms.MOCMAEvolutionStrategy/3.3/Individual.cs @ 15089

Last change on this file since 15089 was 15089, checked in by bwerth, 4 years ago

#2592 removed effectively unused field "rank" from Individual, removed non-dominated sorting

File size: 8.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 * and the BEACON Center for the Study of Evolution in Action.
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21#endregion
22
23using System;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Encodings.RealVectorEncoding;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using HeuristicLab.Random;
29
30namespace HeuristicLab.Algorithms.MOCMAEvolutionStrategy {
31  [StorableClass]
32  public class Individual : IDeepCloneable {
33
34    public enum OffspringSuccess {
35      Success, NoSuccess
36    }
37
38    #region Properties
39    [Storable]
40    private MOCMAEvolutionStrategy strategy;
41
42    //Chromosome
43    [Storable]
44    public RealVector Mean { get; private set; }
45    [Storable]
46    private double sigma;//stepsize
47    [Storable]
48    private RealVector evolutionPath; // pc
49    [Storable]
50    private RealVector lastStep;
51    [Storable]
52    private RealVector lastZ;
53    [Storable]
54    private double[,] lowerCholesky;
55
56
57    //Phenotype
58    [Storable]
59    public double[] Fitness { get; set; }
60    [Storable]
61    public double[] PenalizedFitness { get; set; }
62    [Storable]
63    public bool Selected { get; set; }
64    [Storable]
65    public double SuccessProbability { get; set; }
66    #endregion
67
68    #region Constructors and Cloning
69    [StorableConstructor]
70    protected Individual(bool deserializing) { }
71
72    /// <summary>
73    ///
74    /// </summary>
75    /// <param name="mean">has to be 0-vector with correct lenght</param>
76    /// <param name="pSucc">has to be ptargetsucc</param>
77    /// <param name="sigma">initialSigma</param>
78    /// <param name="pc">has to be 0-vector with correct lenght</param>
79    /// <param name="c">has to be a symmetric positive definit Covariance matrix</param>
80    public Individual(RealVector mean, double pSucc, double sigma, RealVector pc, double[,] c, MOCMAEvolutionStrategy strategy) {
81      Mean = mean;
82      lastStep = new RealVector(mean.Length);
83      SuccessProbability = pSucc;
84      this.sigma = sigma;
85      evolutionPath = pc;
86      CholeskyDecomposition(c);
87      Selected = true;
88      this.strategy = strategy;
89    }
90
91    public Individual(Individual other) {
92      SuccessProbability = other.SuccessProbability;
93      sigma = other.sigma;
94      evolutionPath = (RealVector)other.evolutionPath.Clone();
95      Mean = (RealVector)other.Mean.Clone();
96      lowerCholesky = (double[,])other.lowerCholesky.Clone();
97      Selected = true;
98      strategy = other.strategy;
99    }
100
101    public Individual(Individual other, Cloner cloner) {
102      strategy = cloner.Clone(other.strategy);
103      Mean = cloner.Clone(other.Mean);
104      sigma = other.sigma;
105      evolutionPath = cloner.Clone(other.evolutionPath);
106      lastStep = cloner.Clone(other.evolutionPath);
107      lastZ = cloner.Clone(other.lastZ);
108      lowerCholesky = other.lowerCholesky != null ? other.lowerCholesky.Clone() as double[,] : null;
109      Fitness = other.Fitness != null ? other.Fitness.Select(x => x).ToArray() : null;
110      PenalizedFitness = other.PenalizedFitness != null ? other.PenalizedFitness.Select(x => x).ToArray() : null;
111      Selected = other.Selected;
112      SuccessProbability = other.SuccessProbability;
113    }
114
115    public object Clone() {
116      return new Cloner().Clone(this);
117    }
118
119    public IDeepCloneable Clone(Cloner cloner) {
120      return new Individual(this, cloner);
121    }
122    #endregion
123
124    public void Mutate(NormalDistributedRandom gauss) {
125      //sampling a random z from N(0,I) where I is the Identity matrix;
126      lastZ = new RealVector(Mean.Length);
127      var n = lastZ.Length;
128      for (var i = 0; i < n; i++) lastZ[i] = gauss.NextDouble();
129      //Matrixmultiplication: lastStep = lowerCholesky * lastZ;
130      lastStep = new RealVector(Mean.Length);
131      for (var i = 0; i < n; i++) {
132        double sum = 0;
133        for (var j = 0; j <= i; j++) sum += lowerCholesky[i, j] * lastZ[j];
134        lastStep[i] = sum;
135      }
136      //add the step to x weighted by stepsize;
137      for (var i = 0; i < Mean.Length; i++) Mean[i] += sigma * lastStep[i];
138    }
139
140    public void UpdateAsParent(bool offspringSuccessful) {
141      SuccessProbability = (1 - strategy.StepSizeLearningRate) * SuccessProbability + strategy.StepSizeLearningRate * (offspringSuccessful ? 1 : 0);
142      sigma *= Math.Exp(1 / strategy.StepSizeDampeningFactor * (SuccessProbability - strategy.TargetSuccessProbability) / (1 - strategy.TargetSuccessProbability));
143      if (!offspringSuccessful) return;
144      if (SuccessProbability < strategy.SuccessThreshold && lastZ != null) {
145        var stepNormSqr = lastZ.Sum(d => d * d);
146        var rate = strategy.CovarianceMatrixUnlearningRate;
147        if (stepNormSqr > 1 && 1 < strategy.CovarianceMatrixUnlearningRate * (2 * stepNormSqr - 1)) rate = 1 / (2 * stepNormSqr - 1);
148        CholeskyUpdate(lastStep, 1 + rate, -rate);
149
150      } else RoundUpdate();
151
152    }
153
154    public void UpdateAsOffspring() {
155      SuccessProbability = (1 - strategy.StepSizeLearningRate) * SuccessProbability + strategy.StepSizeLearningRate;
156      sigma *= Math.Exp(1 / strategy.StepSizeDampeningFactor * (SuccessProbability - strategy.TargetSuccessProbability) / (1 - strategy.TargetSuccessProbability));
157      var evolutionpathUpdateWeight = strategy.EvolutionPathLearningRate * (2.0 - strategy.EvolutionPathLearningRate);
158      if (SuccessProbability < strategy.SuccessThreshold) {
159        UpdateEvolutionPath(1 - strategy.EvolutionPathLearningRate, evolutionpathUpdateWeight);
160        CholeskyUpdate(evolutionPath, 1 - strategy.CovarianceMatrixLearningRate, strategy.CovarianceMatrixLearningRate);
161      } else {
162        RoundUpdate();
163      }
164    }
165
166    public void UpdateEvolutionPath(double learningRate, double updateWeight) {
167      updateWeight = Math.Sqrt(updateWeight);
168      for (var i = 0; i < evolutionPath.Length; i++) {
169        evolutionPath[i] *= learningRate;
170        evolutionPath[i] += updateWeight * lastStep[i];
171      }
172    }
173
174    #region helpers
175    private void CholeskyDecomposition(double[,] c) {
176      if (!alglib.spdmatrixcholesky(ref c, c.GetLength(0), false))
177        throw new ArgumentException("Covariancematrix is not symmetric positiv definit");
178      lowerCholesky = (double[,])c.Clone();
179    }
180
181    private void CholeskyUpdate(RealVector v, double alpha, double beta) {
182      var n = v.Length;
183      var temp = new double[n];
184      for (var i = 0; i < n; i++) temp[i] = v[i];
185      double betaPrime = 1;
186      var a = Math.Sqrt(alpha);
187      for (var j = 0; j < n; j++) {
188        var ljj = a * lowerCholesky[j, j];
189        var dj = ljj * ljj;
190        var wj = temp[j];
191        var swj2 = beta * wj * wj;
192        var gamma = dj * betaPrime + swj2;
193        var x1 = dj + swj2 / betaPrime;
194        if (x1 < 0.0) return;//throw new ArgumentException("Update makes Covariancematrix indefinite");//TODO check wether ignoring this update is valid
195        var nLjj = Math.Sqrt(x1);
196        lowerCholesky[j, j] = nLjj;
197        betaPrime += swj2 / dj;
198        if (j + 1 >= n) continue;
199        for (var i = j + 1; i < n; i++) lowerCholesky[i, j] *= a;
200        for (var i = j + 1; i < n; i++) temp[i] = wj / ljj * lowerCholesky[i, j];
201        if (gamma.IsAlmost(0)) continue;
202        for (var i = j + 1; i < n; i++) lowerCholesky[i, j] *= nLjj / ljj;
203        for (var i = j + 1; i < n; i++) lowerCholesky[i, j] += nLjj * beta * wj / gamma * temp[i];
204
205      }
206
207    }
208
209    private void RoundUpdate() {
210      var evolutionPathUpdateWeight = strategy.EvolutionPathLearningRate * (2.0 - strategy.EvolutionPathLearningRate);
211      UpdateEvolutionPath(1 - strategy.EvolutionPathLearningRate, 0);
212      CholeskyUpdate(evolutionPath, 1 - strategy.CovarianceMatrixLearningRate + evolutionPathUpdateWeight, strategy.CovarianceMatrixLearningRate);
213    }
214    #endregion
215
216  }
217
218}
Note: See TracBrowser for help on using the repository browser.