Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs @ 13460

Last change on this file since 13460 was 12674, checked in by gkronber, 9 years ago

#2359: use stable sort in pruning analyzer

File size: 14.4 KB
RevLine 
[11025]1#region License Information
2
3/* HeuristicLab
[12012]4 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[11025]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
22#endregion
23
24using System;
[10368]25using System.Linq;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
[10469]30using HeuristicLab.Operators;
31using HeuristicLab.Optimization.Operators;
[10368]32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34
35namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
36  [StorableClass]
37  [Item("SymbolicDataAnalysisSingleObjectivePruningAnalyzer", "An analyzer that prunes introns from trees in single objective symbolic data analysis problems.")]
38  public abstract class SymbolicDataAnalysisSingleObjectivePruningAnalyzer : SymbolicDataAnalysisSingleObjectiveAnalyzer {
[10469]39    #region parameter names
[10368]40    private const string ProblemDataParameterName = "ProblemData";
41    private const string UpdateIntervalParameterName = "UpdateInverval";
42    private const string UpdateCounterParameterName = "UpdateCounter";
43    private const string PopulationSliceParameterName = "PopulationSlice";
44    private const string PruningProbabilityParameterName = "PruningProbability";
[10469]45    private const string TotalNumberOfPrunedSubtreesParameterName = "Number of pruned subtrees";
46    private const string TotalNumberOfPrunedTreesParameterName = "Number of pruned trees";
[12361]47    private const string TotalNumberOfPrunedNodesParameterName = "Number of pruned nodes";
[10368]48    private const string RandomParameterName = "Random";
[10469]49    private const string ResultsParameterName = "Results";
[11013]50    private const string PopulationSizeParameterName = "PopulationSize";
[10469]51    #endregion
[11025]52
[10469]53    #region private members
[12361]54    private DataReducer prunedNodesReducer;
[10469]55    private DataReducer prunedSubtreesReducer;
56    private DataReducer prunedTreesReducer;
57    private DataTableValuesCollector valuesCollector;
58    private ResultsCollector resultsCollector;
59    #endregion
[11025]60
[10368]61    #region parameter properties
62    public ILookupParameter<IRandom> RandomParameter {
63      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
64    }
[11026]65    public IFixedValueParameter<IntValue> UpdateIntervalParameter {
66      get { return (IFixedValueParameter<IntValue>)Parameters[UpdateIntervalParameterName]; }
[10368]67    }
[11026]68    public IFixedValueParameter<IntValue> UpdateCounterParameter {
69      get { return (IFixedValueParameter<IntValue>)Parameters[UpdateCounterParameterName]; }
[10368]70    }
[11026]71    public IFixedValueParameter<DoubleRange> PopulationSliceParameter {
72      get { return (IFixedValueParameter<DoubleRange>)Parameters[PopulationSliceParameterName]; }
[10368]73    }
[11026]74    public IFixedValueParameter<DoubleValue> PruningProbabilityParameter {
75      get { return (IFixedValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName]; }
[10368]76    }
[11013]77    public ILookupParameter<IntValue> PopulationSizeParameter {
78      get { return (ILookupParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
79    }
[10368]80    #endregion
[11025]81
[10368]82    #region properties
[12358]83    protected abstract SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get; }
[11026]84    protected int UpdateInterval { get { return UpdateIntervalParameter.Value.Value; } }
[11025]85
[11026]86    protected int UpdateCounter {
87      get { return UpdateCounterParameter.Value.Value; }
88      set { UpdateCounterParameter.Value.Value = value; }
89    }
90
91    protected double PopulationSliceStart {
92      get { return PopulationSliceParameter.Value.Start; }
93      set { PopulationSliceParameter.Value.Start = value; }
94    }
95
96    protected double PopulationSliceEnd {
97      get { return PopulationSliceParameter.Value.End; }
98      set { PopulationSliceParameter.Value.End = value; }
99    }
100
101    protected double PruningProbability {
102      get { return PruningProbabilityParameter.Value.Value; }
103      set { PruningProbabilityParameter.Value.Value = value; }
104    }
[10368]105    #endregion
[11025]106
[10414]107    #region IStatefulItem members
108    public override void InitializeState() {
109      base.InitializeState();
[11026]110      UpdateCounter = 0;
[10414]111    }
112    public override void ClearState() {
113      base.ClearState();
[11026]114      UpdateCounter = 0;
[10414]115    }
116    #endregion
117
[10378]118    [StorableConstructor]
119    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(bool deserializing) : base(deserializing) { }
[11025]120
[10368]121    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
122      : base(original, cloner) {
[12361]123      if (original.prunedNodesReducer != null)
124        this.prunedNodesReducer = (DataReducer)original.prunedNodesReducer.Clone();
[10470]125      if (original.prunedSubtreesReducer != null)
126        this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
127      if (original.prunedTreesReducer != null)
128        this.prunedTreesReducer = (DataReducer)original.prunedTreesReducer.Clone();
129      if (original.valuesCollector != null)
130        this.valuesCollector = (DataTableValuesCollector)original.valuesCollector.Clone();
131      if (original.resultsCollector != null)
132        this.resultsCollector = (ResultsCollector)original.resultsCollector.Clone();
[10368]133    }
[11013]134
135    [StorableHook(HookType.AfterDeserialization)]
136    private void AfterDeserialization() {
137      if (!Parameters.ContainsKey(PopulationSizeParameterName)) {
138        Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
139      }
[11027]140      if (Parameters.ContainsKey(UpdateCounterParameterName)) {
141        var fixedValueParameter = Parameters[UpdateCounterParameterName] as FixedValueParameter<IntValue>;
142        if (fixedValueParameter == null) {
143          var valueParameter = (ValueParameter<IntValue>)Parameters[UpdateCounterParameterName];
144          Parameters.Remove(UpdateCounterParameterName);
145          Parameters.Add(new FixedValueParameter<IntValue>(UpdateCounterParameterName, valueParameter.Value));
146        }
147      }
148      if (Parameters.ContainsKey(UpdateIntervalParameterName)) {
149        var fixedValueParameter = Parameters[UpdateIntervalParameterName] as FixedValueParameter<IntValue>;
150        if (fixedValueParameter == null) {
151          var valueParameter = (ValueParameter<IntValue>)Parameters[UpdateIntervalParameterName];
152          Parameters.Remove(UpdateIntervalParameterName);
153          Parameters.Add(new FixedValueParameter<IntValue>(UpdateIntervalParameterName, valueParameter.Value));
154        }
155      }
156      if (Parameters.ContainsKey(PopulationSliceParameterName)) {
157        var fixedValueParameter = Parameters[PopulationSliceParameterName] as FixedValueParameter<DoubleRange>;
158        if (fixedValueParameter == null) {
159          var valueParameter = (ValueParameter<DoubleRange>)Parameters[PopulationSliceParameterName];
160          Parameters.Remove(PopulationSliceParameterName);
161          Parameters.Add(new FixedValueParameter<DoubleRange>(PopulationSliceParameterName, valueParameter.Value));
162        }
163      }
164      if (Parameters.ContainsKey(PruningProbabilityParameterName)) {
165        var fixedValueParameter = Parameters[PruningProbabilityParameterName] as FixedValueParameter<DoubleValue>;
166        if (fixedValueParameter == null) {
167          var valueParameter = (ValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName];
168          Parameters.Remove(PruningProbabilityParameterName);
169          Parameters.Add(new FixedValueParameter<DoubleValue>(PruningProbabilityParameterName, valueParameter.Value));
170        }
171      }
[11013]172    }
173
[10368]174    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer() {
[10469]175      #region add parameters
[11026]176      Parameters.Add(new FixedValueParameter<DoubleRange>(PopulationSliceParameterName, "The slice of the population where pruning should be applied.", new DoubleRange(0.75, 1)));
177      Parameters.Add(new FixedValueParameter<DoubleValue>(PruningProbabilityParameterName, "The probability for pruning an individual.", new DoubleValue(0.5)));
178      Parameters.Add(new FixedValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
179      Parameters.Add(new FixedValueParameter<IntValue>(UpdateCounterParameterName, "The value which counts how many times the operator was called", new IntValue(0)));
180      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "The random number generator."));
181      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName, "The problem data."));
[11013]182      Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
[10469]183      #endregion
[10368]184    }
185
[10469]186    //
187    /// <summary>
188    /// Computes the closed interval bounding the portion of the population that is to be pruned.
189    /// </summary>
190    /// <returns>Returns an int range [start, end]</returns>
191    private IntRange GetSliceBounds() {
[11026]192      if (PopulationSliceStart < 0 || PopulationSliceEnd < 0) throw new ArgumentOutOfRangeException("The slice bounds cannot be negative.");
193      if (PopulationSliceStart > 1 || PopulationSliceEnd > 1) throw new ArgumentOutOfRangeException("The slice bounds should be expressed as unit percentages.");
[11013]194      var count = PopulationSizeParameter.ActualValue.Value;
[11026]195      var start = (int)Math.Round(PopulationSliceStart * count);
196      var end = (int)Math.Round(PopulationSliceEnd * count);
[10469]197      if (end > count) end = count;
[10368]198
[10469]199      if (start >= end) throw new ArgumentOutOfRangeException("Invalid PopulationSlice bounds.");
200      return new IntRange(start, end);
201    }
[10368]202
[10469]203    private IOperation CreatePruningOperation() {
[11026]204      var operations = new OperationCollection { Parallel = true };
[10469]205      var range = GetSliceBounds();
206      var qualities = Quality.Select(x => x.Value).ToArray();
207      var indices = Enumerable.Range(0, qualities.Length).ToArray();
[12674]208      indices.StableSort((a, b) => qualities[a].CompareTo(qualities[b]));
209
[10469]210      if (!Maximization.Value) Array.Reverse(indices);
[10368]211
[10469]212      var subscopes = ExecutionContext.Scope.SubScopes;
[11025]213      var random = RandomParameter.ActualValue;
[10368]214
[11026]215      var empty = new EmptyOperator();
216
[12674]217      for (int i = 0; i < indices.Length; ++i) {
[11026]218        IOperator @operator;
219        if (range.Start <= i && i < range.End && random.NextDouble() <= PruningProbability)
220          @operator = PruningOperator;
221        else @operator = empty;
[10469]222        var index = indices[i];
223        var subscope = subscopes[index];
[11026]224        operations.Add(ExecutionContext.CreateChildOperation(@operator, subscope));
[10368]225      }
[11026]226      return operations;
[10469]227    }
[10368]228
[10469]229    public override IOperation Apply() {
[11026]230      UpdateCounter++;
231      if (UpdateCounter != UpdateInterval) return base.Apply();
232      UpdateCounter = 0;
[10368]233
[12361]234      if (prunedNodesReducer == null || prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
[10368]235
[10469]236      var prune = CreatePruningOperation();
[12361]237      var reducePrunedNodes = ExecutionContext.CreateChildOperation(prunedNodesReducer);
[10469]238      var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
239      var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
240      var collectValues = ExecutionContext.CreateChildOperation(valuesCollector);
241      var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
[10368]242
[12361]243      return new OperationCollection { prune, reducePrunedNodes, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
[10368]244    }
[11025]245
246    private void InitializeOperators() {
[12361]247      prunedNodesReducer = new DataReducer();
248      prunedNodesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedNodesParameter.ActualName;
249      prunedNodesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
250      prunedNodesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
251      prunedNodesReducer.TargetParameter.ActualName = TotalNumberOfPrunedNodesParameterName;
252
[11025]253      prunedSubtreesReducer = new DataReducer();
254      prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
255      prunedSubtreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
256      prunedSubtreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
257      prunedSubtreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedSubtreesParameterName;
258
259      prunedTreesReducer = new DataReducer();
260      prunedTreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedTreesParameter.ActualName;
261      prunedTreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum);
262      prunedTreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign);
263      prunedTreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedTreesParameterName;
264
265      valuesCollector = new DataTableValuesCollector();
[12361]266      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedNodesParameterName));
[11025]267      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
268      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
269      valuesCollector.DataTableParameter.ActualName = "Population pruning";
270
271      resultsCollector = new ResultsCollector();
272      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Population pruning"));
273      resultsCollector.ResultsParameter.ActualName = ResultsParameterName;
274    }
[10368]275  }
276}
Note: See TracBrowser for help on using the repository browser.