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

Last change on this file since 11025 was 11025, checked in by bburlacu, 6 years ago

#2143: Attempted to fix the problems described above.

File size: 12.2 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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;
25using System.Linq;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Operators;
31using HeuristicLab.Optimization.Operators;
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 {
39    #region parameter names
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";
45    private const string TotalNumberOfPrunedSubtreesParameterName = "Number of pruned subtrees";
46    private const string TotalNumberOfPrunedTreesParameterName = "Number of pruned trees";
47    private const string RandomParameterName = "Random";
48    private const string PruneOnlyZeroImpactNodesParameterName = "PruneOnlyZeroImpactNodes";
49    private const string NodeImpactThresholdParameterName = "ImpactThreshold";
50    private const string PruningOperatorParameterName = "PruningOperator";
51    private const string ResultsParameterName = "Results";
52    private const string PopulationSizeParameterName = "PopulationSize";
53    #endregion
54
55    #region private members
56    private DataReducer prunedSubtreesReducer;
57    private DataReducer prunedTreesReducer;
58    private DataTableValuesCollector valuesCollector;
59    private ResultsCollector resultsCollector;
60    private EmptyOperator emptyOp;
61    #endregion
62
63    #region parameter properties
64    public IValueParameter<SymbolicDataAnalysisExpressionPruningOperator> PruningOperatorParameter {
65      get { return (IValueParameter<SymbolicDataAnalysisExpressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
66    }
67    public IFixedValueParameter<BoolValue> PruneOnlyZeroImpactNodesParameter {
68      get { return (IFixedValueParameter<BoolValue>)Parameters[PruneOnlyZeroImpactNodesParameterName]; }
69    }
70    public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
71      get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
72    }
73    public ILookupParameter<IRandom> RandomParameter {
74      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
75    }
76    public IValueParameter<IntValue> UpdateIntervalParameter {
77      get { return (IValueParameter<IntValue>)Parameters[UpdateIntervalParameterName]; }
78    }
79    public IValueParameter<IntValue> UpdateCounterParameter {
80      get { return (IValueParameter<IntValue>)Parameters[UpdateCounterParameterName]; }
81    }
82    public IValueParameter<DoubleRange> PopulationSliceParameter {
83      get { return (IValueParameter<DoubleRange>)Parameters[PopulationSliceParameterName]; }
84    }
85    public IValueParameter<DoubleValue> PruningProbabilityParameter {
86      get { return (IValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName]; }
87    }
88    public ILookupParameter<IntValue> PopulationSizeParameter {
89      get { return (ILookupParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
90    }
91    #endregion
92
93    #region properties
94    protected SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get { return PruningOperatorParameter.Value; } }
95    protected IntValue UpdateInterval { get { return UpdateIntervalParameter.Value; } }
96    protected IntValue UpdateCounter { get { return UpdateCounterParameter.Value; } }
97    protected DoubleRange PopulationSlice { get { return PopulationSliceParameter.Value; } }
98    protected DoubleValue PruningProbability { get { return PruningProbabilityParameter.Value; } }
99
100    protected bool PruneOnlyZeroImpactNodes {
101      get { return PruneOnlyZeroImpactNodesParameter.Value.Value; }
102      set { PruneOnlyZeroImpactNodesParameter.Value.Value = value; }
103    }
104    protected double NodeImpactThreshold {
105      get { return NodeImpactThresholdParameter.Value.Value; }
106      set { NodeImpactThresholdParameter.Value.Value = value; }
107    }
108    #endregion
109
110    #region IStatefulItem members
111    public override void InitializeState() {
112      base.InitializeState();
113      UpdateCounter.Value = 0;
114    }
115    public override void ClearState() {
116      base.ClearState();
117      UpdateCounter.Value = 0;
118    }
119    #endregion
120
121    [StorableConstructor]
122    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(bool deserializing) : base(deserializing) { }
123
124    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
125      : base(original, cloner) {
126      if (original.prunedSubtreesReducer != null)
127        this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
128      if (original.prunedTreesReducer != null)
129        this.prunedTreesReducer = (DataReducer)original.prunedTreesReducer.Clone();
130      if (original.valuesCollector != null)
131        this.valuesCollector = (DataTableValuesCollector)original.valuesCollector.Clone();
132      if (original.resultsCollector != null)
133        this.resultsCollector = (ResultsCollector)original.resultsCollector.Clone();
134    }
135
136    [StorableHook(HookType.AfterDeserialization)]
137    private void AfterDeserialization() {
138      if (!Parameters.ContainsKey(PopulationSizeParameterName)) {
139        Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
140      }
141    }
142
143    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer() {
144      #region add parameters
145      Parameters.Add(new ValueParameter<DoubleRange>(PopulationSliceParameterName, new DoubleRange(0.75, 1)));
146      Parameters.Add(new ValueParameter<DoubleValue>(PruningProbabilityParameterName, new DoubleValue(0.5)));
147      Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
148      Parameters.Add(new ValueParameter<IntValue>(UpdateCounterParameterName, "The value which counts how many times the operator was called", new IntValue(0)));
149      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName));
150      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
151      Parameters.Add(new FixedValueParameter<DoubleValue>(NodeImpactThresholdParameterName, new DoubleValue(0.0)));
152      Parameters.Add(new FixedValueParameter<BoolValue>(PruneOnlyZeroImpactNodesParameterName, new BoolValue(false)));
153      Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
154      #endregion
155    }
156
157    //
158    /// <summary>
159    /// Computes the closed interval bounding the portion of the population that is to be pruned.
160    /// </summary>
161    /// <returns>Returns an int range [start, end]</returns>
162    private IntRange GetSliceBounds() {
163      if (PopulationSlice.Start < 0 || PopulationSlice.End < 0) throw new ArgumentOutOfRangeException("The slice bounds cannot be negative.");
164      if (PopulationSlice.Start > 1 || PopulationSlice.End > 1) throw new ArgumentOutOfRangeException("The slice bounds should be expressed as unit percentages.");
165      var count = PopulationSizeParameter.ActualValue.Value;
166      var start = (int)Math.Round(PopulationSlice.Start * count);
167      var end = (int)Math.Round(PopulationSlice.End * count);
168      if (end > count) end = count;
169
170      if (start >= end) throw new ArgumentOutOfRangeException("Invalid PopulationSlice bounds.");
171      return new IntRange(start, end);
172    }
173
174    private IOperation CreatePruningOperation() {
175      var oc = new OperationCollection { Parallel = true };
176      var range = GetSliceBounds();
177      var qualities = Quality.Select(x => x.Value).ToArray();
178      var indices = Enumerable.Range(0, qualities.Length).ToArray();
179      Array.Sort(qualities, indices);
180      if (!Maximization.Value) Array.Reverse(indices);
181
182      var subscopes = ExecutionContext.Scope.SubScopes;
183      var random = RandomParameter.ActualValue;
184
185      for (int i = 0; i < subscopes.Count; ++i) {
186        IOperator op;
187        if (range.Start <= i && i < range.End && random.NextDouble() <= PruningProbability.Value)
188          op = PruningOperator;
189        else op = emptyOp;
190        var index = indices[i];
191        var subscope = subscopes[index];
192        oc.Add(ExecutionContext.CreateChildOperation(op, subscope));
193      }
194      return oc;
195    }
196
197    public override IOperation Apply() {
198      UpdateCounter.Value++;
199      if (UpdateCounter.Value != UpdateInterval.Value) return base.Apply();
200      UpdateCounter.Value = 0;
201
202      if (prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
203
204      var prune = CreatePruningOperation();
205      var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
206      var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
207      var collectValues = ExecutionContext.CreateChildOperation(valuesCollector);
208      var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
209
210      return new OperationCollection { prune, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
211    }
212
213    private void InitializeOperators() {
214      prunedSubtreesReducer = new DataReducer();
215      prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
216      prunedSubtreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
217      prunedSubtreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
218      prunedSubtreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedSubtreesParameterName;
219
220      prunedTreesReducer = new DataReducer();
221      prunedTreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedTreesParameter.ActualName;
222      prunedTreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum);
223      prunedTreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign);
224      prunedTreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedTreesParameterName;
225
226      valuesCollector = new DataTableValuesCollector();
227      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
228      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
229      valuesCollector.DataTableParameter.ActualName = "Population pruning";
230
231      resultsCollector = new ResultsCollector();
232      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Population pruning"));
233      resultsCollector.ResultsParameter.ActualName = ResultsParameterName;
234
235      emptyOp = new EmptyOperator();
236    }
237  }
238}
Note: See TracBrowser for help on using the repository browser.