Free cookie consent management tool by TermsFeed Policy Generator

source: addons/HeuristicLab.FitnessLandscapeAnalysis/HeuristicLab.Analysis.FitnessLandscape/PopDist/PopulationDistributionAnalyzer.cs @ 16573

Last change on this file since 16573 was 16573, checked in by gkronber, 5 years ago

#2520: changed HeuristicLab.FLA addon to compile with new HL.Persistence

File size: 9.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.IO;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Operators;
29using HeuristicLab.Optimization;
30using HeuristicLab.Optimization.Operators;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HEAL.Attic;
34
35namespace HeuristicLab.Analysis.FitnessLandscape {
36
37  [Item("PopulationDistributionAnalyzer", "An operator that analyzes the distribution of fitness values")]
38  [StorableType("B2AD2ACD-FCEA-4D05-856B-63D88F521642")]
39  public class PopulationDistributionAnalyzer : AlgorithmOperator, IAnalyzer {
40    public bool EnabledByDefault {
41      get { return false; }
42    }
43
44    #region Parameters
45    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
46      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
47    }
48    public ValueLookupParameter<DataTable> FitnessQuantilesParameter {
49      get { return (ValueLookupParameter<DataTable>)Parameters["Fitness Quantiles"]; }
50    }
51    public ValueLookupParameter<DataTable> PopulationDispersionParameter {
52      get { return (ValueLookupParameter<DataTable>)Parameters["Population Dispersion"]; }
53    }
54    public ValueLookupParameter<DataTable> HigherPopulationMomentsParameter {
55      get { return (ValueLookupParameter<DataTable>)Parameters["Higher Population Moments"]; }
56    }
57    public ValueLookupParameter<DataTable> PopulationNormalityParameter {
58      get { return (ValueLookupParameter<DataTable>)Parameters["Population Normality"]; }
59    }
60    public ValueLookupParameter<VariableCollection> ResultsParameter {
61      get { return (ValueLookupParameter<VariableCollection>)Parameters["Results"]; }
62    }
63    public ValueLookupParameter<ResultCollection> PopulationDistributionResultsParameter {
64      get { return (ValueLookupParameter<ResultCollection>)Parameters["Population Distribution Results"]; }
65    }
66    public OptionalValueParameter<StringValue> PopulationLogFileNameParameter {
67      get { return (OptionalValueParameter<StringValue>)Parameters["Population Log File Name"]; }
68    }
69    public IConstrainedValueParameter<IntValue> NQuantilesParameter {
70      get { return (IConstrainedValueParameter<IntValue>)Parameters["NQuantiles"]; }
71    }
72    #endregion
73
74    [StorableConstructor]
75    protected PopulationDistributionAnalyzer(StorableConstructorFlag _) : base(_) { }
76    protected PopulationDistributionAnalyzer(PopulationDistributionAnalyzer original, Cloner cloner) : base(original, cloner) { }
77
78    public PopulationDistributionAnalyzer() {
79      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The quality of the solution"));
80      Parameters.Add(new ValueLookupParameter<VariableCollection>("Results", "The collection of all results of this algorithm"));
81      Parameters.Add(new ValueLookupParameter<ResultCollection>("Population Distribution Results", "All results from population distribution analysis"));
82      Parameters.Add(new ValueLookupParameter<DataTable>("Fitness Quantiles", "Data table with quantiles of the fitness distribution"));
83      Parameters.Add(new ValueLookupParameter<DataTable>("Population Dispersion", "Data table dispersion statistics"));
84      Parameters.Add(new ValueLookupParameter<DataTable>("Higher Population Moments", "Data table skewness and kurtosis of population's fitness distribution"));
85      Parameters.Add(new ValueLookupParameter<DataTable>("Population Normality", "Jarque-Bera Normality Test p-value and 0.05 threshold"));
86      Parameters.Add(new OptionalValueParameter<StringValue>("Population Log File Name", "File name of a log file where all population fittness values are logged to"));
87      Parameters.Add(new ConstrainedValueParameter<IntValue>("NQuantiles", "Number of quantiles to plot", new ItemSet<IntValue>(Enumerable.Range(1, 50).Select(v => new IntValue(v)))));
88
89      NQuantilesParameter.Value = NQuantilesParameter.ValidValues.Single(v => v.Value == 10);
90
91      var resultsCollector = new ResultsCollector();
92      resultsCollector.ResultsParameter.ActualName = PopulationDistributionResultsParameter.Name;
93      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(FitnessQuantilesParameter.Name));
94      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(PopulationDispersionParameter.Name));
95      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(HigherPopulationMomentsParameter.Name));
96      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>(PopulationNormalityParameter.Name));
97
98      var globalResultsCollector = new ResultsCollector();
99      globalResultsCollector.CollectedValues.Add(new ValueLookupParameter<ResultCollection>(PopulationDistributionResultsParameter.Name));
100
101      OperatorGraph.InitialOperator = resultsCollector;
102      resultsCollector.Successor = globalResultsCollector;
103      globalResultsCollector.Successor = null;
104    }
105
106    public override IDeepCloneable Clone(Cloner cloner) {
107      return new PopulationDistributionAnalyzer(this, cloner);
108    }
109
110    public override IOperation Apply() {
111      if (PopulationDistributionResultsParameter.ActualValue == null)
112        PopulationDistributionResultsParameter.ActualValue = new ResultCollection();
113      var qualities = QualityParameter.ActualValue.Select(v => v.Value).ToArray();
114      CalculateQuantiles(qualities);
115      CalculateDistributionParameters(qualities);
116      LogPopulationFitnessValues(qualities);
117      return base.Apply();
118    }
119
120    private void CalculateQuantiles(double[] qualities) {
121      DataTable quantiles = FitnessQuantilesParameter.ActualValue;
122      if (quantiles == null) {
123        quantiles = new DataTable("Fitness Quantiles");
124        quantiles.Description = "The population's fitness quantiles";
125        FitnessQuantilesParameter.ActualValue = quantiles;
126        for (int i = 0; i <= NQuantilesParameter.Value.Value; i++)
127          quantiles.Rows.Add(new DataRow((i * 10).ToString()));
128      }
129      int n_quantiles = quantiles.Rows.Count;
130      for (int i = 0; i < n_quantiles; i++) {
131        double v = 0;
132        alglib.basestat.samplepercentile(qualities, qualities.Length, 1.0 * i / n_quantiles, ref v);
133        quantiles.Rows[(i * 10).ToString()].Values.Add(v);
134      }
135    }
136
137    private void CalculateDistributionParameters(double[] qualities) {
138      DataTable populationDispersion = PopulationDispersionParameter.ActualValue;
139      if (populationDispersion == null) {
140        populationDispersion = new DataTable("Population Dispersion");
141        PopulationDispersionParameter.ActualValue = populationDispersion;
142        populationDispersion.Rows.Add(new DataRow("Std. Deviation"));
143        populationDispersion.Rows.Add(new DataRow("Mean Difference"));
144      }
145      DataTable higherPopulationMoments = HigherPopulationMomentsParameter.ActualValue;
146      if (higherPopulationMoments == null) {
147        higherPopulationMoments = new DataTable("Higher Population Moments");
148        HigherPopulationMomentsParameter.ActualValue = higherPopulationMoments;
149        higherPopulationMoments.Rows.Add(new DataRow("Skewness"));
150        higherPopulationMoments.Rows.Add(new DataRow("Kurtosis"));
151      }
152      DataTable populationNormality = PopulationNormalityParameter.ActualValue;
153      if (populationNormality == null) {
154        populationNormality = new DataTable("Population Normality");
155        PopulationNormalityParameter.ActualValue = populationNormality;
156        populationNormality.Rows.Add(new DataRow("Jarque-Bera P-Value"));
157        populationNormality.Rows.Add(new DataRow("0.05"));
158      }
159
160      double mean, variance, skewness, kurtosis, p_value;
161      mean = variance = skewness = kurtosis = p_value = 0;
162      alglib.basestat.samplemoments(qualities, qualities.Length, ref mean, ref variance, ref skewness, ref kurtosis);
163      alglib.jarquebera.jarqueberatest(qualities, qualities.Length, ref p_value);
164      double mean_difference =
165        (from i in Enumerable.Range(0, qualities.Length)
166         from j in Enumerable.Range(0, i)
167         select Math.Abs(qualities[i] - qualities[j])).Sum()
168           * 2 / qualities.Length / (qualities.Length - 1);
169
170      populationDispersion.Rows["Std. Deviation"].Values.Add(Math.Sqrt(variance));
171      populationDispersion.Rows["Mean Difference"].Values.Add(mean_difference);
172      higherPopulationMoments.Rows["Skewness"].Values.Add(skewness);
173      higherPopulationMoments.Rows["Kurtosis"].Values.Add(kurtosis);
174      populationNormality.Rows["Jarque-Bera P-Value"].Values.Add(p_value);
175      populationNormality.Rows["0.05"].Values.Add(0.05);
176    }
177
178    private void LogPopulationFitnessValues(double[] qualities) {
179      if (PopulationLogFileNameParameter.ActualValue == null)
180        return;
181      using (var writer = new StreamWriter(PopulationLogFileNameParameter.Value.Value, true)) {
182        foreach (var q in qualities) {
183          writer.Write(q);
184          writer.Write(";");
185        }
186        writer.WriteLine();
187        writer.Close();
188      }
189    }
190  }
191}
Note: See TracBrowser for help on using the repository browser.