Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2457_ExpertSystem/HeuristicLab.Analysis.FitnessLandscape/3.3/Analysis/InformationAnalysis.cs @ 17946

Last change on this file since 17946 was 16955, checked in by abeham, 5 years ago

#2457: worked on thesis

File size: 12.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Collections.Generic;
24using System.Linq;
25
26namespace HeuristicLab.Analysis.FitnessLandscape {
27
28  public class InformationAnalysis {
29
30    public class Peak {
31      public double QualityDelta { get; private set; }
32      public double Value { get; private set; }
33      public Peak(double qualityDelta, double value) {
34        QualityDelta = qualityDelta;
35        Value = value;
36      }
37    }
38
39    public List<double> InformationContent { get; private set; }
40    public List<double> SymmetricInformationContent { get; private set; }
41    public List<double> PartialInformationContent { get; private set; }
42    public List<double> DensityBasinInformation { get; private set; }
43    public List<double> SymmetricDensityBasinInformation { get; private set; }
44    public List<double> TotalEntropy { get; private set; }
45    public List<double> SymmetricTotalEntropy { get; private set; }
46    public List<double> QualityDelta { get; private set; }
47    public double InformationStability { get; private set; }
48    public double Regularity { get; private set; }
49    public double Diversity { get; private set; }
50    public Peak PeakInformationContent { get; private set; }
51    public Peak PeakSymmetricInformationContent { get; private set; }
52    public Peak PeakDensityBasinInformation { get; private set; }
53    public Peak PeakSymmetricDensityBasinInformation { get; private set; }
54    public Peak PeakTotalEntropy { get; private set; }
55    public Peak PeakSymmetricTotalEntropy { get; private set; }
56
57    public InformationAnalysis(IList<double> qualities, int nQuantiles = 20) {
58      InformationContent = new List<double>(nQuantiles);
59      SymmetricInformationContent = new List<double>(nQuantiles);
60      PartialInformationContent = new List<double>(nQuantiles);
61      DensityBasinInformation = new List<double>(nQuantiles);
62      SymmetricDensityBasinInformation = new List<double>(nQuantiles);
63      TotalEntropy = new List<double>(nQuantiles);
64      SymmetricTotalEntropy = new List<double>(nQuantiles);
65      QualityDelta = new List<double>(nQuantiles);
66      if (qualities.Count > 1)
67        PerformAnalysis(qualities, nQuantiles);
68    }
69
70    private void PerformAnalysis(IList<double> qualities, int nQuantiles) {
71      var differences = Differences(qualities).ToList();
72      InformationStability = differences.Select(Math.Abs).Max();
73      Regularity = new HashSet<double>(differences).Count / (double)differences.Count;
74      Diversity = new HashSet<double>(qualities).Count / (double)qualities.Count;
75      var absDifferences = differences.Select(Math.Abs).OrderBy(d => d).ToList();
76      nQuantiles = Math.Min(nQuantiles, absDifferences.Count);
77      var thresholds = (nQuantiles == 0
78                         ? absDifferences
79                         : UniqueThresholdCalculator.DetermineThresholds(differences, nQuantiles)).ToList();
80      foreach (var eps in thresholds) {
81        if (QualityDelta.Count > 0 && QualityDelta.Last() == eps) {
82          QualityDelta.DuplicateLast();
83          InformationContent.DuplicateLast();
84          DensityBasinInformation.DuplicateLast();
85          TotalEntropy.DuplicateLast();
86          PartialInformationContent.DuplicateLast();
87        } else {
88          var slopes = ToSlopes(eps, differences).ToList();
89          var shapes = ToShapes(slopes).ToList();
90          var symmetricShapes = shapes.Select(x => Shape.GetSymmetric(x)).ToList();
91
92          var shapeFreqs = GetFrequencies(shapes);
93          var symShapeFreqs = GetFrequencies(symmetricShapes);
94
95          foreach (var symShape in Shape.Symmetric.Where(x => x.Sum > 0)) {
96            if (symShapeFreqs.TryGetValue(symShape, out var freq)) {
97              symShapeFreqs[symShape] = freq / 2;
98            }
99          }
100          QualityDelta.Add(eps);
101
102          InformationContent.Add(CalculateEntropy(shapeFreqs, Shape.NonUniform.ToList(), shapes.Count));
103          SymmetricInformationContent.Add(CalculateEntropy(symShapeFreqs, Shape.SymmetricNonUniform.ToList(), symmetricShapes.Count));
104
105          DensityBasinInformation.Add(CalculateEntropy(shapeFreqs, Shape.Uniform.ToList(), shapes.Count));
106          SymmetricDensityBasinInformation.Add(CalculateEntropy(symShapeFreqs, Shape.SymmetricUniform.ToList(), symmetricShapes.Count));
107
108          TotalEntropy.Add(CalculateEntropy(shapeFreqs, Shape.All.ToList(), shapes.Count));
109          SymmetricTotalEntropy.Add(CalculateEntropy(symShapeFreqs, Shape.Symmetric.ToList(), symmetricShapes.Count));
110
111          PartialInformationContent.Add(CalculatePartialInformationContent(eps, differences));
112        }
113      }
114      PeakInformationContent = GetPeak(QualityDelta, InformationContent);
115      PeakSymmetricInformationContent = GetPeak(QualityDelta, SymmetricInformationContent);
116      PeakDensityBasinInformation = GetPeak(QualityDelta, DensityBasinInformation);
117      PeakSymmetricDensityBasinInformation = GetPeak(QualityDelta, SymmetricDensityBasinInformation);
118      PeakTotalEntropy = GetPeak(QualityDelta, TotalEntropy);
119      PeakSymmetricTotalEntropy = GetPeak(QualityDelta, SymmetricTotalEntropy);
120    }
121
122    public IEnumerable<Tuple<string, object>> GetFeatures() {
123      yield return Tuple.Create("InformationContent", (object)InformationContent[0]);
124      yield return Tuple.Create("DensityBasinInformation", (object)DensityBasinInformation[0]);
125      yield return Tuple.Create("PartialInformationContent", (object)PartialInformationContent[0]);
126      yield return Tuple.Create("TotalEntropy", (object)TotalEntropy[0]);
127      yield return Tuple.Create("InformationStability", (object)InformationStability);
128      yield return Tuple.Create("Regularity", (object)Regularity);
129      yield return Tuple.Create("Diversity", (object)Diversity);
130      yield return Tuple.Create("SymmetricInformationContent", (object)SymmetricInformationContent[0]);
131      yield return Tuple.Create("SymmetricDensityBasinInformation", (object)SymmetricDensityBasinInformation[0]);
132      yield return Tuple.Create("SymmetricTotalEntropy", (object)SymmetricTotalEntropy[0]);
133      yield return Tuple.Create("PeakInformationContent", (object)PeakInformationContent.Value);
134      yield return Tuple.Create("PeakDensityBasinInformation", (object)PeakDensityBasinInformation.Value);
135      yield return Tuple.Create("PeakTotalEntropy", (object)PeakTotalEntropy.Value);
136      yield return Tuple.Create("PeakSymmetricInformationContent", (object)PeakSymmetricInformationContent.Value);
137      yield return Tuple.Create("PeakSymmetricDensityBasinInformation", (object)PeakSymmetricDensityBasinInformation.Value);
138      yield return Tuple.Create("PeakSymmetricTotalEntropy", (object)PeakSymmetricTotalEntropy.Value);
139    }
140
141    public static Peak GetPeak(IEnumerable<double> indexes, IEnumerable<double> values) {
142      var max = indexes.Zip(values, (i, v) => new { i, v }).OrderByDescending(p => p.v).First();
143      return new Peak(max.i, max.v);
144    }
145
146    public enum Slope {
147      Up = 1,
148      Flat = 0,
149      Down = -1
150    }
151
152    public class Shape {
153      private static readonly Shape[] s = new Shape[] {
154        new Shape() { First = Slope.Down, Second = Slope.Down }, // 0
155        new Shape() { First = Slope.Down, Second = Slope.Flat }, // 1
156        new Shape() { First = Slope.Down, Second = Slope.Up   }, // 2
157        new Shape() { First = Slope.Flat, Second = Slope.Down }, // 3
158        new Shape() { First = Slope.Flat, Second = Slope.Flat }, // 4
159        new Shape() { First = Slope.Flat, Second = Slope.Up   }, // 5
160        new Shape() { First = Slope.Up,   Second = Slope.Down }, // 6
161        new Shape() { First = Slope.Up,   Second = Slope.Flat }, // 7
162        new Shape() { First = Slope.Up,   Second = Slope.Up   }, // 8
163      };
164      public static IEnumerable<Shape> All { get { return s; } }
165      public static IEnumerable<Shape> Uniform { get { return All.Where(x => x.First == x.Second); } }
166      public static IEnumerable<Shape> NonUniform { get { return All.Where(x => x.First != x.Second); } }
167      public static IEnumerable<Shape> Symmetric { get { return All.Where(x => x.Sum >= 0); } }
168      public static IEnumerable<Shape> SymmetricUniform { get { return Uniform.Where(x => x.First != Slope.Down); } }
169      public static IEnumerable<Shape> SymmetricNonUniform { get { return NonUniform.Where(x => x.Sum >= 0); } }
170
171      public Slope First { get; private set; }
172      public Slope Second { get; private set; }
173
174      internal int Sum { get { return (int)First + (int)Second; } }
175
176      public IEnumerable<Slope> Slopes {
177        get {
178          yield return First;
179          yield return Second;
180        }
181      }
182
183      private Shape() {
184
185      }
186
187      public static Shape Get(Slope first, Slope second) {
188        var a = 1 + (int)first; var b = 1 + (int)second;
189        return s[a * 3 + b];
190      }
191
192      public static Shape GetSymmetric(Shape shape) {
193        if (shape.Sum >= 0) return shape;
194        if (shape.Sum == -2) return s[8]; // both are Slope.Down
195        if (shape.First == Slope.Down) return s[5];
196        return s[7]; // shape.Second == Slope.Down
197      }
198
199      public override string ToString() {
200        return string.Join("", Slopes.Select(s => (s == Slope.Down ? "\\" : (s == Slope.Up ? "/" : "-"))));
201      }
202    }
203
204   
205
206    private static IEnumerable<Slope> ToSlopes(double eps, IEnumerable<double> differences) {
207      return differences.Select(d => (d > eps ? Slope.Up : (d < -eps ? Slope.Down : Slope.Flat)));
208    }
209
210    private static IEnumerable<Shape> ToShapes(IEnumerable<Slope> slopes) {
211      var iter = slopes.GetEnumerator();
212      if (!iter.MoveNext()) yield break;
213      var prev = iter.Current;
214      while (iter.MoveNext()) {
215        var cur = iter.Current;
216        yield return Shape.Get(prev, cur);
217        prev = cur;
218      }
219    }
220
221    private static double CalculateEntropy(Dictionary<Shape, int> shapeCounts, ICollection<Shape> shapeTypes, int totalShapes) {
222      return shapeTypes.Where(x => shapeCounts.ContainsKey(x))
223        .Aggregate(0.0, (current, s) => current - Entropy(shapeCounts[s], totalShapes, shapeTypes.Count));
224    }
225
226    private static double CalculatePartialInformationContent(double eps, ICollection<double> differences) {
227      var iter = differences.GetEnumerator();
228      if (!iter.MoveNext()) return 0;
229
230      var slope = iter.Current < -eps ? -1 : (iter.Current > eps ? 1 : 0);
231      var nPeaks = Math.Abs(slope);
232      var count = 1;
233      while (iter.MoveNext()) {
234        var d = iter.Current;
235        if (d > eps) {
236          if (slope < 0) nPeaks++;
237          slope = +1;
238        } else if (d < -eps) {
239          if (slope > 0) nPeaks++;
240          slope = -1;
241        }
242        count++;
243      }
244      return nPeaks / (double)count;
245    }
246
247    private static Dictionary<Shape, int> GetFrequencies(IEnumerable<Shape> shapes) {
248      return shapes.GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count());
249    }
250
251    private static double Entropy(int count, int total, int nCases) {
252      if (count == 0) return 0;
253      var freq = 1.0 * count / total;
254      return freq * Math.Log(freq, nCases);
255    }
256
257    private static IEnumerable<double> Differences(IEnumerable<double> values) {
258      return values.Delta((x, y) => y - x);
259    }
260
261  }
262}
Note: See TracBrowser for help on using the repository browser.