Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 11027 was 11027, checked in by bburlacu, 10 years ago

#2143: SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs: Added some code in the AfterDeserialization hook to replace ValueParameters with FixedValueParameters in order to avoid an InvalidCastException when trying to run older saved algorithms.

File size: 15.0 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    #endregion
61
62    #region parameter properties
63    public IValueParameter<SymbolicDataAnalysisExpressionPruningOperator> PruningOperatorParameter {
64      get { return (IValueParameter<SymbolicDataAnalysisExpressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
65    }
66    public IFixedValueParameter<BoolValue> PruneOnlyZeroImpactNodesParameter {
67      get { return (IFixedValueParameter<BoolValue>)Parameters[PruneOnlyZeroImpactNodesParameterName]; }
68    }
69    public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
70      get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
71    }
72    public ILookupParameter<IRandom> RandomParameter {
73      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
74    }
75    public IFixedValueParameter<IntValue> UpdateIntervalParameter {
76      get { return (IFixedValueParameter<IntValue>)Parameters[UpdateIntervalParameterName]; }
77    }
78    public IFixedValueParameter<IntValue> UpdateCounterParameter {
79      get { return (IFixedValueParameter<IntValue>)Parameters[UpdateCounterParameterName]; }
80    }
81    public IFixedValueParameter<DoubleRange> PopulationSliceParameter {
82      get { return (IFixedValueParameter<DoubleRange>)Parameters[PopulationSliceParameterName]; }
83    }
84    public IFixedValueParameter<DoubleValue> PruningProbabilityParameter {
85      get { return (IFixedValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName]; }
86    }
87    public ILookupParameter<IntValue> PopulationSizeParameter {
88      get { return (ILookupParameter<IntValue>)Parameters[PopulationSizeParameterName]; }
89    }
90    #endregion
91
92    #region properties
93    protected SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get { return PruningOperatorParameter.Value; } }
94    protected int UpdateInterval { get { return UpdateIntervalParameter.Value.Value; } }
95
96    protected int UpdateCounter {
97      get { return UpdateCounterParameter.Value.Value; }
98      set { UpdateCounterParameter.Value.Value = value; }
99    }
100
101    protected double PopulationSliceStart {
102      get { return PopulationSliceParameter.Value.Start; }
103      set { PopulationSliceParameter.Value.Start = value; }
104    }
105
106    protected double PopulationSliceEnd {
107      get { return PopulationSliceParameter.Value.End; }
108      set { PopulationSliceParameter.Value.End = value; }
109    }
110
111    protected double PruningProbability {
112      get { return PruningProbabilityParameter.Value.Value; }
113      set { PruningProbabilityParameter.Value.Value = value; }
114    }
115
116    protected bool PruneOnlyZeroImpactNodes {
117      get { return PruneOnlyZeroImpactNodesParameter.Value.Value; }
118      set { PruneOnlyZeroImpactNodesParameter.Value.Value = value; }
119    }
120    protected double NodeImpactThreshold {
121      get { return NodeImpactThresholdParameter.Value.Value; }
122      set { NodeImpactThresholdParameter.Value.Value = value; }
123    }
124    #endregion
125
126    #region IStatefulItem members
127    public override void InitializeState() {
128      base.InitializeState();
129      UpdateCounter = 0;
130    }
131    public override void ClearState() {
132      base.ClearState();
133      UpdateCounter = 0;
134    }
135    #endregion
136
137    [StorableConstructor]
138    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(bool deserializing) : base(deserializing) { }
139
140    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
141      : base(original, cloner) {
142      if (original.prunedSubtreesReducer != null)
143        this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
144      if (original.prunedTreesReducer != null)
145        this.prunedTreesReducer = (DataReducer)original.prunedTreesReducer.Clone();
146      if (original.valuesCollector != null)
147        this.valuesCollector = (DataTableValuesCollector)original.valuesCollector.Clone();
148      if (original.resultsCollector != null)
149        this.resultsCollector = (ResultsCollector)original.resultsCollector.Clone();
150    }
151
152    [StorableHook(HookType.AfterDeserialization)]
153    private void AfterDeserialization() {
154      if (!Parameters.ContainsKey(PopulationSizeParameterName)) {
155        Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
156      }
157      if (Parameters.ContainsKey(UpdateCounterParameterName)) {
158        var fixedValueParameter = Parameters[UpdateCounterParameterName] as FixedValueParameter<IntValue>;
159        if (fixedValueParameter == null) {
160          var valueParameter = (ValueParameter<IntValue>)Parameters[UpdateCounterParameterName];
161          Parameters.Remove(UpdateCounterParameterName);
162          Parameters.Add(new FixedValueParameter<IntValue>(UpdateCounterParameterName, valueParameter.Value));
163        }
164      }
165      if (Parameters.ContainsKey(UpdateIntervalParameterName)) {
166        var fixedValueParameter = Parameters[UpdateIntervalParameterName] as FixedValueParameter<IntValue>;
167        if (fixedValueParameter == null) {
168          var valueParameter = (ValueParameter<IntValue>)Parameters[UpdateIntervalParameterName];
169          Parameters.Remove(UpdateIntervalParameterName);
170          Parameters.Add(new FixedValueParameter<IntValue>(UpdateIntervalParameterName, valueParameter.Value));
171        }
172      }
173      if (Parameters.ContainsKey(PopulationSliceParameterName)) {
174        var fixedValueParameter = Parameters[PopulationSliceParameterName] as FixedValueParameter<DoubleRange>;
175        if (fixedValueParameter == null) {
176          var valueParameter = (ValueParameter<DoubleRange>)Parameters[PopulationSliceParameterName];
177          Parameters.Remove(PopulationSliceParameterName);
178          Parameters.Add(new FixedValueParameter<DoubleRange>(PopulationSliceParameterName, valueParameter.Value));
179        }
180      }
181      if (Parameters.ContainsKey(PruningProbabilityParameterName)) {
182        var fixedValueParameter = Parameters[PruningProbabilityParameterName] as FixedValueParameter<DoubleValue>;
183        if (fixedValueParameter == null) {
184          var valueParameter = (ValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName];
185          Parameters.Remove(PruningProbabilityParameterName);
186          Parameters.Add(new FixedValueParameter<DoubleValue>(PruningProbabilityParameterName, valueParameter.Value));
187        }
188      }
189    }
190
191    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer() {
192      #region add parameters
193      Parameters.Add(new FixedValueParameter<DoubleRange>(PopulationSliceParameterName, "The slice of the population where pruning should be applied.", new DoubleRange(0.75, 1)));
194      Parameters.Add(new FixedValueParameter<DoubleValue>(PruningProbabilityParameterName, "The probability for pruning an individual.", new DoubleValue(0.5)));
195      Parameters.Add(new FixedValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
196      Parameters.Add(new FixedValueParameter<IntValue>(UpdateCounterParameterName, "The value which counts how many times the operator was called", new IntValue(0)));
197      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "The random number generator."));
198      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName, "The problem data."));
199      Parameters.Add(new FixedValueParameter<DoubleValue>(NodeImpactThresholdParameterName, "The impact threshold  below which an individual should be pruned.", new DoubleValue(0.0)));
200      Parameters.Add(new FixedValueParameter<BoolValue>(PruneOnlyZeroImpactNodesParameterName, "Switch to determine of only zero impact individuals should be pruned.", new BoolValue(false)));
201      Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
202      #endregion
203    }
204
205    //
206    /// <summary>
207    /// Computes the closed interval bounding the portion of the population that is to be pruned.
208    /// </summary>
209    /// <returns>Returns an int range [start, end]</returns>
210    private IntRange GetSliceBounds() {
211      if (PopulationSliceStart < 0 || PopulationSliceEnd < 0) throw new ArgumentOutOfRangeException("The slice bounds cannot be negative.");
212      if (PopulationSliceStart > 1 || PopulationSliceEnd > 1) throw new ArgumentOutOfRangeException("The slice bounds should be expressed as unit percentages.");
213      var count = PopulationSizeParameter.ActualValue.Value;
214      var start = (int)Math.Round(PopulationSliceStart * count);
215      var end = (int)Math.Round(PopulationSliceEnd * count);
216      if (end > count) end = count;
217
218      if (start >= end) throw new ArgumentOutOfRangeException("Invalid PopulationSlice bounds.");
219      return new IntRange(start, end);
220    }
221
222    private IOperation CreatePruningOperation() {
223      var operations = new OperationCollection { Parallel = true };
224      var range = GetSliceBounds();
225      var qualities = Quality.Select(x => x.Value).ToArray();
226      var indices = Enumerable.Range(0, qualities.Length).ToArray();
227      Array.Sort(qualities, indices);
228      if (!Maximization.Value) Array.Reverse(indices);
229
230      var subscopes = ExecutionContext.Scope.SubScopes;
231      var random = RandomParameter.ActualValue;
232
233      var empty = new EmptyOperator();
234
235      for (int i = 0; i < subscopes.Count; ++i) {
236        IOperator @operator;
237        if (range.Start <= i && i < range.End && random.NextDouble() <= PruningProbability)
238          @operator = PruningOperator;
239        else @operator = empty;
240        var index = indices[i];
241        var subscope = subscopes[index];
242        operations.Add(ExecutionContext.CreateChildOperation(@operator, subscope));
243      }
244      return operations;
245    }
246
247    public override IOperation Apply() {
248      UpdateCounter++;
249      if (UpdateCounter != UpdateInterval) return base.Apply();
250      UpdateCounter = 0;
251
252      if (prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
253
254      var prune = CreatePruningOperation();
255      var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
256      var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
257      var collectValues = ExecutionContext.CreateChildOperation(valuesCollector);
258      var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
259
260      return new OperationCollection { prune, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
261    }
262
263    private void InitializeOperators() {
264      prunedSubtreesReducer = new DataReducer();
265      prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
266      prunedSubtreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
267      prunedSubtreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
268      prunedSubtreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedSubtreesParameterName;
269
270      prunedTreesReducer = new DataReducer();
271      prunedTreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedTreesParameter.ActualName;
272      prunedTreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum);
273      prunedTreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign);
274      prunedTreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedTreesParameterName;
275
276      valuesCollector = new DataTableValuesCollector();
277      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
278      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
279      valuesCollector.DataTableParameter.ActualName = "Population pruning";
280
281      resultsCollector = new ResultsCollector();
282      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Population pruning"));
283      resultsCollector.ResultsParameter.ActualName = ResultsParameterName;
284    }
285  }
286}
Note: See TracBrowser for help on using the repository browser.