Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 11013 was 11013, checked in by bburlacu, 8 years ago

#2143: Added missing check for population slice bounds, added PopulationSize parameter to get the number of individuals (instead of counting the subscopes of the current execution context).

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