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

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

#2143: Refactored pruning analyzer and operators as per review.

File size: 10.4 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    #endregion
30    #region private members
31    private DataReducer prunedSubtreesReducer;
32    private DataReducer prunedTreesReducer;
33    private DataTableValuesCollector valuesCollector;
34    private ResultsCollector resultsCollector;
35    private EmptyOperator emptyOp;
36    #endregion
37    #region parameter properties
38    public IValueParameter<SymbolicDataAnalysisExpressionPruningOperator> PruningOperatorParameter {
39      get { return (IValueParameter<SymbolicDataAnalysisExpressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
40    }
41    public IFixedValueParameter<BoolValue> PruneOnlyZeroImpactNodesParameter {
42      get { return (IFixedValueParameter<BoolValue>)Parameters[PruneOnlyZeroImpactNodesParameterName]; }
43    }
44    public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
45      get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
46    }
47    public ILookupParameter<IRandom> RandomParameter {
48      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
49    }
50    private ILookupParameter<IDataAnalysisProblemData> ProblemDataParameter {
51      get { return (ILookupParameter<IDataAnalysisProblemData>)Parameters[ProblemDataParameterName]; }
52    }
53    public IValueParameter<IntValue> UpdateIntervalParameter {
54      get { return (IValueParameter<IntValue>)Parameters[UpdateIntervalParameterName]; }
55    }
56    public IValueParameter<IntValue> UpdateCounterParameter {
57      get { return (IValueParameter<IntValue>)Parameters[UpdateCounterParameterName]; }
58    }
59    public IValueParameter<DoubleRange> PopulationSliceParameter {
60      get { return (IValueParameter<DoubleRange>)Parameters[PopulationSliceParameterName]; }
61    }
62    public IValueParameter<DoubleValue> PruningProbabilityParameter {
63      get { return (IValueParameter<DoubleValue>)Parameters[PruningProbabilityParameterName]; }
64    }
65    #endregion
66    #region properties
67    protected SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get { return PruningOperatorParameter.Value; } }
68    protected IDataAnalysisProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } }
69    protected IntValue UpdateInterval { get { return UpdateIntervalParameter.Value; } }
70    protected IntValue UpdateCounter { get { return UpdateCounterParameter.Value; } }
71    protected DoubleRange PopulationSlice { get { return PopulationSliceParameter.Value; } }
72    protected DoubleValue PruningProbability { get { return PruningProbabilityParameter.Value; } }
73    protected IRandom Random { get { return RandomParameter.ActualValue; } }
74    protected DoubleValue NodeImpactThreshold { get { return NodeImpactThresholdParameter.Value; } }
75    protected BoolValue PruneOnlyZeroImpactNodes { get { return PruneOnlyZeroImpactNodesParameter.Value; } }
76    #endregion
77    #region IStatefulItem members
78    public override void InitializeState() {
79      base.InitializeState();
80      UpdateCounter.Value = 0;
81    }
82    public override void ClearState() {
83      base.ClearState();
84      UpdateCounter.Value = 0;
85    }
86    #endregion
87
88    [StorableConstructor]
89    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(bool deserializing) : base(deserializing) { }
90    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
91      : base(original, cloner) {
92      this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
93      this.prunedTreesReducer = (DataReducer)original.prunedTreesReducer.Clone();
94      this.valuesCollector = (DataTableValuesCollector)original.valuesCollector.Clone();
95      this.resultsCollector = (ResultsCollector)original.resultsCollector.Clone();
96    }
97    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer() {
98      #region add parameters
99      Parameters.Add(new ValueParameter<DoubleRange>(PopulationSliceParameterName, new DoubleRange(0.75, 1)));
100      Parameters.Add(new ValueParameter<DoubleValue>(PruningProbabilityParameterName, new DoubleValue(0.5)));
101      Parameters.Add(new ValueParameter<IntValue>(UpdateIntervalParameterName, "The interval in which the tree length analysis should be applied.", new IntValue(1)));
102      Parameters.Add(new ValueParameter<IntValue>(UpdateCounterParameterName, "The value which counts how many times the operator was called", new IntValue(0)));
103      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName));
104      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
105      Parameters.Add(new FixedValueParameter<DoubleValue>(NodeImpactThresholdParameterName, new DoubleValue(0.0)));
106      Parameters.Add(new FixedValueParameter<BoolValue>(PruneOnlyZeroImpactNodesParameterName, new BoolValue(false)));
107      #endregion
108    }
109
110    private void InitializeOperators() {
111      prunedSubtreesReducer = new DataReducer();
112      prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
113      prunedSubtreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum); // sum all the pruned subtrees parameter values
114      prunedSubtreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign); // asign the sum to the target parameter
115      prunedSubtreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedSubtreesParameterName;
116
117      prunedTreesReducer = new DataReducer();
118      prunedTreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedTreesParameter.ActualName;
119      prunedTreesReducer.ReductionOperation.Value = new ReductionOperation(ReductionOperations.Sum);
120      prunedTreesReducer.TargetOperation.Value = new ReductionOperation(ReductionOperations.Assign);
121      prunedTreesReducer.TargetParameter.ActualName = TotalNumberOfPrunedTreesParameterName;
122
123      valuesCollector = new DataTableValuesCollector();
124      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
125      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
126      valuesCollector.DataTableParameter.ActualName = "Population pruning";
127
128      resultsCollector = new ResultsCollector();
129      resultsCollector.CollectedValues.Add(new LookupParameter<DataTable>("Population pruning"));
130      resultsCollector.ResultsParameter.ActualName = ResultsParameterName;
131
132      emptyOp = new EmptyOperator();
133    }
134
135    //
136    /// <summary>
137    /// Computes the closed interval bounding the portion of the population that is to be pruned.
138    /// </summary>
139    /// <returns>Returns an int range [start, end]</returns>
140    private IntRange GetSliceBounds() {
141      var count = ExecutionContext.Scope.SubScopes.Count;
142      var start = (int)Math.Round(PopulationSlice.Start * count);
143      var end = (int)Math.Round(PopulationSlice.End * count);
144      if (end > count) end = count;
145
146      if (start >= end) throw new ArgumentOutOfRangeException("Invalid PopulationSlice bounds.");
147      return new IntRange(start, end);
148    }
149
150    private IOperation CreatePruningOperation() {
151      var oc = new OperationCollection { Parallel = true };
152      var range = GetSliceBounds();
153      var qualities = Quality.Select(x => x.Value).ToArray();
154      var indices = Enumerable.Range(0, qualities.Length).ToArray();
155      Array.Sort(qualities, indices);
156      if (!Maximization.Value) Array.Reverse(indices);
157
158      var subscopes = ExecutionContext.Scope.SubScopes;
159
160      for (int i = 0; i < subscopes.Count; ++i) {
161        IOperator op;
162        if (range.Start <= i && i < range.End && Random.NextDouble() <= PruningProbability.Value)
163          op = PruningOperator;
164        else op = emptyOp;
165        var index = indices[i];
166        var subscope = subscopes[index];
167        oc.Add(ExecutionContext.CreateChildOperation(op, subscope));
168      }
169      return oc;
170    }
171
172    public override IOperation Apply() {
173      UpdateCounter.Value++;
174      if (UpdateCounter.Value != UpdateInterval.Value) return base.Apply();
175      UpdateCounter.Value = 0;
176
177      if (prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
178
179      var prune = CreatePruningOperation();
180      var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
181      var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
182      var collectValues = ExecutionContext.CreateChildOperation(valuesCollector);
183      var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
184
185      return new OperationCollection { prune, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
186    }
187  }
188}
Note: See TracBrowser for help on using the repository browser.