Changeset 16096 for branches/2457_ExpertSystem/HeuristicLab.Analysis.FitnessLandscape/3.3/ProblemCharacteristicAnalysis/CurveAnalysis.cs
- Timestamp:
- 08/29/18 18:16:05 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2457_ExpertSystem/HeuristicLab.Analysis.FitnessLandscape/3.3/ProblemCharacteristicAnalysis/CurveAnalysis.cs
r14691 r16096 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2018 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 22 using System; 2 23 using System.Collections.Generic; 3 24 using System.Linq; … … 7 28 public static CurveAnalysisResult GetCharacteristics(List<List<Tuple<T, double>>> trajectories, Func<T, T, double> distFunc) { 8 29 trajectories = trajectories.Where(x => x.Count > 5).ToList(); 30 var symbols = GetSymbols(trajectories); 9 31 var f1 = trajectories.Select(path => ApproximateDerivative(path, distFunc).ToList()).ToList(); 10 32 var f2 = f1.Select(d1 => ApproximateDerivative(d1, distFunc).ToList()).ToList(); 11 33 12 var sharpness = f1.Average(x => x.Average(y => Math.Abs(y.Item2))); //f2.Average(x => Area(x, distFunc));34 var sharpness = f1.Average(x => x.Average(y => Math.Abs(y.Item2))); 13 35 var bumpiness = 0.0; 14 36 var flatness = 0.0; 15 37 var count = 0; 16 38 for (var p = 0; p < f2.Count; p++) { 17 39 if (f2[p].Count <= 2) continue; 40 count++; 18 41 var bump = 0; 19 42 var flat = 0; … … 28 51 flatness += flat / (f2[p].Count - 1.0); 29 52 } 30 bumpiness /= f2.Count; 31 flatness /= f2.Count; 32 return new CurveAnalysisResult(sharpness, bumpiness, flatness); 53 bumpiness /= count; 54 flatness /= count; 55 var per = new[] { 25, 50, 75 }; 56 return new CurveAnalysisResult(sharpness, bumpiness, flatness, 57 per.Select(p => symbols.Downward.GetPercentileOrDefault(p, 0)).ToArray(), 58 per.Select(p => symbols.Neutral.GetPercentileOrDefault(p, 0)).ToArray(), 59 per.Select(p => symbols.Upward.GetPercentileOrDefault(p, 0)).ToArray()); 33 60 } 34 61 35 private static double Area(IEnumerable<Tuple<T, double>> path, Func<T, T, double> distFunc) {36 var iter = path.GetEnumerator();37 if (!iter.MoveNext()) return 0.0;38 var area = 0.0;39 var prev = iter.Current;40 while (iter.MoveNext()) {41 area += TrapezoidArea(prev, iter.Current, distFunc);42 prev = iter.Current;62 private static Symbols GetSymbols(List<List<Tuple<T, double>>> trajectories) { 63 var sym = new Symbols(); 64 foreach (var t in trajectories) { 65 var prev = t[0]; 66 for (var i = 1; i < t.Count; i++) { 67 sym.Add(i / (double)t.Count, t[i].Item2, prev.Item2); 68 prev = t[i]; 69 } 43 70 } 44 return area; 45 } 46 47 private static double TrapezoidArea(Tuple<T, double> a, Tuple<T, double> b, Func<T, T, double> distFunc) { 48 var area = 0.0; 49 var dist = distFunc(a.Item1, b.Item1); 50 if ((a.Item2 <= 0 && b.Item2 <= 0) || (a.Item2 >= 0 && b.Item2 >= 0)) 51 area += dist * (Math.Abs(a.Item2) + Math.Abs(b.Item2)) / 2.0; 52 else { 53 var k = (b.Item2 - a.Item2) / dist; 54 var d = a.Item2; 55 var x = -d / k; 56 area += Math.Abs(x * a.Item2 / 2.0); 57 area += Math.Abs((dist - x) * b.Item2 / 2.0); 58 } 59 return area; 71 return sym; 60 72 } 61 73 … … 80 92 } 81 93 94 public enum CurveAnalysisFeature { Sharpness, Bumpiness, Flatness, 95 DownQ1, DownQ2, DownQ3, 96 NeutQ1, NeutQ2, NeutQ3, 97 UpQ1, UpQ2, UpQ3 } 98 82 99 public class CurveAnalysisResult { 83 public double Sharpness { get; private set; } 84 public double Bumpiness { get; private set; } 85 public double Flatness { get; private set; } 100 private Dictionary<CurveAnalysisFeature, double> results = new Dictionary<CurveAnalysisFeature, double>(); 86 101 87 public string[] GetNames() { 88 return new[] { "Sharpness", "Bumpiness", "Flatness" }; 102 public double GetValue(CurveAnalysisFeature name) { 103 return results[name]; 104 } 105 106 public static IEnumerable<CurveAnalysisFeature> AllFeatures { 107 get { return Enum.GetValues(typeof(CurveAnalysisFeature)).Cast<CurveAnalysisFeature>(); } 89 108 } 90 109 91 110 public double[] GetValues() { 92 return new[] { Sharpness, Bumpiness, Flatness };111 return AllFeatures.Select(x => results[x]).ToArray(); 93 112 } 94 113 95 public CurveAnalysisResult(double sharpness, double bumpiness, double flatness) { 96 Sharpness = sharpness; 97 Bumpiness = bumpiness; 98 Flatness = flatness; 114 public CurveAnalysisResult(double sharpness, double bumpiness, double flatness, double[] down, double[] neut, double[] up) { 115 foreach (var v in AllFeatures.Zip(new[] { sharpness, bumpiness, flatness }.Concat(down).Concat(neut).Concat(up), (n, v) => Tuple.Create(n, v))) { 116 results[v.Item1] = v.Item2; 117 } 118 } 119 } 120 121 public class Symbols { 122 public Statistics Downward { get; } = new Statistics(); 123 public Statistics Neutral { get; } = new Statistics(); 124 public Statistics Upward { get; } = new Statistics(); 125 126 public void Add(double step, double fit, double prev) { 127 if (fit < prev) Downward.Add(step); 128 else if (fit > prev) Upward.Add(step); 129 else Neutral.Add(step); 130 } 131 } 132 133 public sealed class Statistics { 134 private List<double> values = new List<double>(); 135 136 public int Count { get { return values.Count; } } 137 138 public double Min { get; private set; } 139 public double Max { get; private set; } 140 public double Total { get; private set; } 141 public double Mean { get; private set; } 142 public double StdDev { get { return Math.Sqrt(Variance); } } 143 public double Variance { get { return Count > 0 ? variance / Count : 0.0; } } 144 145 private double variance; 146 private bool sorted = false; 147 148 public double GetPercentileOrDefault(int p, double @default = default(double)) { 149 if (p < 0 || p > 100) throw new ArgumentOutOfRangeException(nameof(p), p, "Must be in range [0;100]"); 150 SortIfNecessary(); 151 if (Count == 0) return @default; 152 else if (Count == 1) return values[0]; 153 if (p == 100) return values[Count - 1]; 154 155 var x = p / 100.0 * (Count - 1); 156 var inte = (int)x; 157 var frac = x - inte; 158 159 return values[inte] + frac * (values[inte + 1] - values[inte]); 160 } 161 162 public void Add(double value) { 163 sorted = false; 164 values.Add(value); 165 166 if (Count == 1) { 167 Min = Max = Mean = Total = value; 168 } else { 169 if (value < Min) Min = value; 170 if (value > Max) Max = value; 171 172 Total += value; 173 var oldMean = Mean; 174 Mean = oldMean + (value - oldMean) / Count; 175 variance = variance + (value - oldMean) * (value - Mean); 176 } 177 } 178 179 public void AddRange(IEnumerable<double> values) { 180 foreach (var v in values) Add(v); 181 } 182 183 private void SortIfNecessary() { 184 if (!sorted) { 185 values.Sort(); 186 sorted = true; 187 } 99 188 } 100 189 }
Note: See TracChangeset
for help on using the changeset viewer.