Changeset 12745


Ignore:
Timestamp:
07/12/15 11:23:06 (6 years ago)
Author:
gkronber
Message:

#2359, #2398: merged r12189,r12358,r12359,r12361,r12461,r12674,r12720,r12744 from trunk to stable

Location:
stable
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • stable

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/InteractiveSymbolicClassificationSolutionSimplifierViewBase.cs

    r12009 r12745  
    7474      var impactAndReplacementValues = new Dictionary<ISymbolicExpressionTreeNode, Tuple<double, double>>();
    7575      foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix()) {
    76         double impactValue, replacementValue;
    77         calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue);
     76        double impactValue, replacementValue, newQualityForImpactsCalculation;
     77        calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue, out newQualityForImpactsCalculation);
    7878        impactAndReplacementValues.Add(node, new Tuple<double, double>(impactValue, replacementValue));
    7979      }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningAnalyzer.cs

    r12009 r12745  
    2222using HeuristicLab.Common;
    2323using HeuristicLab.Core;
     24using HeuristicLab.Data;
    2425using HeuristicLab.Parameters;
    2526using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    2930  [StorableClass]
    3031  public sealed class SymbolicClassificationPruningAnalyzer : SymbolicDataAnalysisSingleObjectivePruningAnalyzer {
    31     private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
    3232    private const string PruningOperatorParameterName = "PruningOperator";
    33     private SymbolicClassificationPruningAnalyzer(SymbolicClassificationPruningAnalyzer original, Cloner cloner)
    34       : base(original, cloner) {
     33    public IValueParameter<SymbolicClassificationPruningOperator> PruningOperatorParameter {
     34      get { return (IValueParameter<SymbolicClassificationPruningOperator>)Parameters[PruningOperatorParameterName]; }
    3535    }
    36     public override IDeepCloneable Clone(Cloner cloner) {
    37       return new SymbolicClassificationPruningAnalyzer(this, cloner);
     36
     37    protected override SymbolicDataAnalysisExpressionPruningOperator PruningOperator {
     38      get { return PruningOperatorParameter.Value; }
    3839    }
     40
     41    private SymbolicClassificationPruningAnalyzer(SymbolicClassificationPruningAnalyzer original, Cloner cloner) : base(original, cloner) { }
     42    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicClassificationPruningAnalyzer(this, cloner); }
    3943
    4044    [StorableConstructor]
     
    4246
    4347    public SymbolicClassificationPruningAnalyzer() {
    44       Parameters.Add(new ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, "The impact values calculator", new SymbolicClassificationSolutionImpactValuesCalculator()));
    45       Parameters.Add(new ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator()));
     48      Parameters.Add(new ValueParameter<SymbolicClassificationPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
     49    }
     50
     51    [StorableHook(HookType.AfterDeserialization)]
     52    private void AfterDeserialization() {
     53      // BackwardsCompatibility3.3
     54
     55      #region Backwards compatible code, remove with 3.4
     56      if (Parameters.ContainsKey(PruningOperatorParameterName)) {
     57        var oldParam = Parameters[PruningOperatorParameterName] as ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>;
     58        if (oldParam != null) {
     59          Parameters.Remove(oldParam);
     60          Parameters.Add(new ValueParameter<SymbolicClassificationPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
     61        }
     62      } else {
     63        // not yet contained
     64        Parameters.Add(new ValueParameter<SymbolicClassificationPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicClassificationPruningOperator(new SymbolicClassificationSolutionImpactValuesCalculator())));
     65      }
     66
     67      if (Parameters.ContainsKey("PruneOnlyZeroImpactNodes")) {
     68        PruningOperator.PruneOnlyZeroImpactNodes = ((IFixedValueParameter<BoolValue>)Parameters["PruneOnlyZeroImpactNodes"]).Value.Value;
     69        Parameters.Remove(Parameters["PruneOnlyZeroImpactNodes"]);
     70      }
     71      if (Parameters.ContainsKey("ImpactThreshold")) {
     72        PruningOperator.NodeImpactThreshold = ((IFixedValueParameter<DoubleValue>)Parameters["ImpactThreshold"]).Value.Value;
     73        Parameters.Remove(Parameters["ImpactThreshold"]);
     74      }
     75      if (Parameters.ContainsKey("ImpactValuesCalculator")) {
     76        PruningOperator.ImpactValuesCalculator = ((ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>)Parameters["ImpactValuesCalculator"]).Value;
     77        Parameters.Remove(Parameters["ImpactValuesCalculator"]);
     78      }
     79      #endregion
    4680    }
    4781  }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationPruningOperator.cs

    r12009 r12745  
    2222#endregion
    2323
     24using System.Collections.Generic;
    2425using System.Linq;
    2526using HeuristicLab.Common;
    2627using HeuristicLab.Core;
     28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2729using HeuristicLab.Parameters;
    2830using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    3234  [Item("SymbolicClassificationPruningOperator", "An operator which prunes symbolic classificaton trees.")]
    3335  public class SymbolicClassificationPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
    34     private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
    3536    private const string ModelCreatorParameterName = "ModelCreator";
     37    private const string EvaluatorParameterName = "Evaluator";
    3638
    3739    #region parameter properties
     
    3941      get { return (ILookupParameter<ISymbolicClassificationModelCreator>)Parameters[ModelCreatorParameterName]; }
    4042    }
     43
     44    public ILookupParameter<ISymbolicClassificationSingleObjectiveEvaluator> EvaluatorParameter {
     45      get {
     46        return (ILookupParameter<ISymbolicClassificationSingleObjectiveEvaluator>)Parameters[EvaluatorParameterName];
     47      }
     48    }
    4149    #endregion
    4250
    43     protected SymbolicClassificationPruningOperator(SymbolicClassificationPruningOperator original, Cloner cloner)
    44       : base(original, cloner) {
    45     }
    46 
    47     public override IDeepCloneable Clone(Cloner cloner) {
    48       return new SymbolicClassificationPruningOperator(this, cloner);
    49     }
     51    protected SymbolicClassificationPruningOperator(SymbolicClassificationPruningOperator original, Cloner cloner) : base(original, cloner) { }
     52    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicClassificationPruningOperator(this, cloner); }
    5053
    5154    [StorableConstructor]
    5255    protected SymbolicClassificationPruningOperator(bool deserializing) : base(deserializing) { }
    5356
    54     public SymbolicClassificationPruningOperator() {
    55       Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, new SymbolicClassificationSolutionImpactValuesCalculator()));
     57    public SymbolicClassificationPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator)
     58      : base(impactValuesCalculator) {
    5659      Parameters.Add(new LookupParameter<ISymbolicClassificationModelCreator>(ModelCreatorParameterName));
     60      Parameters.Add(new LookupParameter<ISymbolicClassificationSingleObjectiveEvaluator>(EvaluatorParameterName));
    5761    }
    5862
    59     protected override ISymbolicDataAnalysisModel CreateModel() {
    60       var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
    61       var problemData = (IClassificationProblemData)ProblemData;
    62       var rows = problemData.TrainingIndices;
    63       model.RecalculateModelParameters(problemData, rows);
     63    [StorableHook(HookType.AfterDeserialization)]
     64    private void AfterDeserialization() {
     65      // BackwardsCompatibility3.3
     66      #region Backwards compatible code, remove with 3.4
     67      base.ImpactValuesCalculator = new SymbolicClassificationSolutionImpactValuesCalculator();
     68      if (!Parameters.ContainsKey(EvaluatorParameterName)) {
     69        Parameters.Add(new LookupParameter<ISymbolicClassificationSingleObjectiveEvaluator>(EvaluatorParameterName));
     70      }
     71      #endregion
     72    }
     73
     74    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits) {
     75      var model = ModelCreatorParameter.ActualValue.CreateSymbolicClassificationModel(tree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
     76      var classificationProblemData = (IClassificationProblemData)problemData;
     77      var rows = classificationProblemData.TrainingIndices;
     78      model.RecalculateModelParameters(classificationProblemData, rows);
    6479      return model;
    6580    }
    6681
    6782    protected override double Evaluate(IDataAnalysisModel model) {
    68       var classificationModel = (IClassificationModel)model;
    69       var classificationProblemData = (IClassificationProblemData)ProblemData;
    70       var trainingIndices = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
    71       var estimatedValues = classificationModel.GetEstimatedClassValues(ProblemData.Dataset, trainingIndices);
    72       var targetValues = ProblemData.Dataset.GetDoubleValues(classificationProblemData.TargetVariable, trainingIndices);
    73       OnlineCalculatorError errorState;
    74       var quality = OnlineAccuracyCalculator.Calculate(targetValues, estimatedValues, out errorState);
    75       if (errorState != OnlineCalculatorError.None) return double.NaN;
    76       return quality;
     83      var evaluator = EvaluatorParameter.ActualValue;
     84      var classificationModel = (ISymbolicClassificationModel)model;
     85      var classificationProblemData = (IClassificationProblemData)ProblemDataParameter.ActualValue;
     86      var rows = Enumerable.Range(FitnessCalculationPartitionParameter.ActualValue.Start, FitnessCalculationPartitionParameter.ActualValue.Size);
     87      return evaluator.Evaluate(this.ExecutionContext, classificationModel.SymbolicExpressionTree, classificationProblemData, rows);
     88    }
     89
     90    public static ISymbolicExpressionTree Prune(ISymbolicExpressionTree tree, ISymbolicClassificationModelCreator modelCreator,
     91      SymbolicClassificationSolutionImpactValuesCalculator impactValuesCalculator, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
     92      IClassificationProblemData problemData, DoubleLimit estimationLimits, IEnumerable<int> rows,
     93      double nodeImpactThreshold = 0.0, bool pruneOnlyZeroImpactNodes = false) {
     94      var clonedTree = (ISymbolicExpressionTree)tree.Clone();
     95      var model = modelCreator.CreateSymbolicClassificationModel(clonedTree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
     96
     97      var nodes = clonedTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
     98      double qualityForImpactsCalculation = double.NaN;
     99
     100      for (int i = 0; i < nodes.Count; ++i) {
     101        var node = nodes[i];
     102        if (node is ConstantTreeNode) continue;
     103
     104        double impactValue, replacementValue, newQualityForImpactsCalculation;
     105        impactValuesCalculator.CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
     106
     107        if (pruneOnlyZeroImpactNodes && !impactValue.IsAlmost(0.0)) continue;
     108        if (!pruneOnlyZeroImpactNodes && impactValue > nodeImpactThreshold) continue;
     109
     110        var constantNode = (ConstantTreeNode)node.Grammar.GetSymbol("Constant").CreateTreeNode();
     111        constantNode.Value = replacementValue;
     112
     113        ReplaceWithConstant(node, constantNode);
     114        i += node.GetLength() - 1; // skip subtrees under the node that was folded
     115
     116        qualityForImpactsCalculation = newQualityForImpactsCalculation;
     117      }
     118      return model.SymbolicExpressionTree;
    77119    }
    78120  }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification/3.4/SymbolicClassificationSolutionImpactValuesCalculator.cs

    r12009 r12745  
    4747    }
    4848
    49     public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN) {
     49    public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN) {
    5050      double impactValue, replacementValue;
    51       CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, originalQuality);
     51      double newQualityForImpactsCalculation;
     52      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
    5253      return impactValue;
    5354    }
    5455
    5556    public override void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node,
    56       IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue,
    57       double originalQuality = Double.NaN) {
     57      IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation,
     58      double qualityForImpactsCalculation = Double.NaN) {
    5859      var classificationModel = (ISymbolicClassificationModel)model;
    5960      var classificationProblemData = (IClassificationProblemData)problemData;
    6061
    61       var dataset = classificationProblemData.Dataset;
    62       var targetClassValues = dataset.GetDoubleValues(classificationProblemData.TargetVariable, rows);
    63 
    64       OnlineCalculatorError errorState;
    65       if (double.IsNaN(originalQuality)) {
    66         var originalClassValues = classificationModel.GetEstimatedClassValues(dataset, rows);
    67         originalQuality = OnlineAccuracyCalculator.Calculate(targetClassValues, originalClassValues, out errorState);
    68         if (errorState != OnlineCalculatorError.None) originalQuality = 0.0;
    69       }
     62      if (double.IsNaN(qualityForImpactsCalculation))
     63        qualityForImpactsCalculation = CalculateQualityForImpacts(classificationModel, classificationProblemData, rows);
    7064
    7165      replacementValue = CalculateReplacementValue(classificationModel, node, classificationProblemData, rows);
     
    8175      tempModelParentNode.InsertSubtree(i, constantNode);
    8276
     77      OnlineCalculatorError errorState;
     78      var dataset = classificationProblemData.Dataset;
     79      var targetClassValues = dataset.GetDoubleValues(classificationProblemData.TargetVariable, rows);
    8380      var estimatedClassValues = tempModel.GetEstimatedClassValues(dataset, rows);
    84       double newQuality = OnlineAccuracyCalculator.Calculate(targetClassValues, estimatedClassValues, out errorState);
    85       if (errorState != OnlineCalculatorError.None) newQuality = 0.0;
     81      newQualityForImpactsCalculation = OnlineAccuracyCalculator.Calculate(targetClassValues, estimatedClassValues, out errorState);
     82      if (errorState != OnlineCalculatorError.None) newQualityForImpactsCalculation = 0.0;
    8683
    87       impactValue = originalQuality - newQuality;
     84      impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
     85    }
     86
     87    public static double CalculateQualityForImpacts(ISymbolicClassificationModel model, IClassificationProblemData problemData, IEnumerable<int> rows) {
     88      OnlineCalculatorError errorState;
     89      var dataset = problemData.Dataset;
     90      var targetClassValues = dataset.GetDoubleValues(problemData.TargetVariable, rows);
     91      var originalClassValues = model.GetEstimatedClassValues(dataset, rows);
     92      var qualityForImpactsCalculation = OnlineAccuracyCalculator.Calculate(targetClassValues, originalClassValues, out errorState);
     93      if (errorState != OnlineCalculatorError.None) qualityForImpactsCalculation = 0.0;
     94
     95      return qualityForImpactsCalculation;
    8896    }
    8997  }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views

  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/InteractiveSymbolicRegressionSolutionSimplifierView.cs

    r12009 r12745  
    6363      var impactAndReplacementValues = new Dictionary<ISymbolicExpressionTreeNode, Tuple<double, double>>();
    6464      foreach (var node in tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix()) {
    65         double impactValue, replacementValue;
    66         calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue);
     65        double impactValue, replacementValue, newQualityForImpactsCalculation;
     66        calculator.CalculateImpactAndReplacementValues(Content.Model, node, Content.ProblemData, Content.ProblemData.TrainingIndices, out impactValue, out replacementValue, out newQualityForImpactsCalculation);
    6767        impactAndReplacementValues.Add(node, new Tuple<double, double>(impactValue, replacementValue));
    6868      }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningAnalyzer.cs

    r12009 r12745  
    2424using HeuristicLab.Common;
    2525using HeuristicLab.Core;
     26using HeuristicLab.Data;
    2627using HeuristicLab.Parameters;
    2728using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    3132  [StorableClass]
    3233  public sealed class SymbolicRegressionPruningAnalyzer : SymbolicDataAnalysisSingleObjectivePruningAnalyzer {
    33     private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
    3434    private const string PruningOperatorParameterName = "PruningOperator";
    35     private SymbolicRegressionPruningAnalyzer(SymbolicRegressionPruningAnalyzer original, Cloner cloner)
    36       : base(original, cloner) {
     35    public IValueParameter<SymbolicRegressionPruningOperator> PruningOperatorParameter {
     36      get { return (IValueParameter<SymbolicRegressionPruningOperator>)Parameters[PruningOperatorParameterName]; }
    3737    }
    38     public override IDeepCloneable Clone(Cloner cloner) {
    39       return new SymbolicRegressionPruningAnalyzer(this, cloner);
     38
     39    protected override SymbolicDataAnalysisExpressionPruningOperator PruningOperator {
     40      get { return PruningOperatorParameter.Value; }
    4041    }
     42
     43    private SymbolicRegressionPruningAnalyzer(SymbolicRegressionPruningAnalyzer original, Cloner cloner) : base(original, cloner) { }
     44    public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicRegressionPruningAnalyzer(this, cloner); }
    4145
    4246    [StorableConstructor]
     
    4448
    4549    public SymbolicRegressionPruningAnalyzer() {
    46       Parameters.Add(new ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, "The impact values calculator", new SymbolicRegressionSolutionImpactValuesCalculator()));
    47       Parameters.Add(new ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator()));
     50      Parameters.Add(new ValueParameter<SymbolicRegressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
     51    }
     52
     53    [StorableHook(HookType.AfterDeserialization)]
     54    private void AfterDeserialization() {
     55      // BackwardsCompatibility3.3
     56
     57      #region Backwards compatible code, remove with 3.4
     58      if (Parameters.ContainsKey(PruningOperatorParameterName)) {
     59        var oldParam = Parameters[PruningOperatorParameterName] as ValueParameter<SymbolicDataAnalysisExpressionPruningOperator>;
     60        if (oldParam != null) {
     61          Parameters.Remove(oldParam);
     62          Parameters.Add(new ValueParameter<SymbolicRegressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
     63        }
     64      } else {
     65        // not yet contained
     66        Parameters.Add(new ValueParameter<SymbolicRegressionPruningOperator>(PruningOperatorParameterName, "The operator used to prune trees", new SymbolicRegressionPruningOperator(new SymbolicRegressionSolutionImpactValuesCalculator())));
     67      }
     68
     69
     70      if (Parameters.ContainsKey("PruneOnlyZeroImpactNodes")) {
     71        PruningOperator.PruneOnlyZeroImpactNodes = ((IFixedValueParameter<BoolValue>)Parameters["PruneOnlyZeroImpactNodes"]).Value.Value;
     72        Parameters.Remove(Parameters["PruneOnlyZeroImpactNodes"]);
     73      }
     74      if (Parameters.ContainsKey("ImpactThreshold")) {
     75        PruningOperator.NodeImpactThreshold = ((IFixedValueParameter<DoubleValue>)Parameters["ImpactThreshold"]).Value.Value;
     76        Parameters.Remove(Parameters["ImpactThreshold"]);
     77      }
     78      if (Parameters.ContainsKey("ImpactValuesCalculator")) {
     79        PruningOperator.ImpactValuesCalculator = ((ValueParameter<SymbolicDataAnalysisSolutionImpactValuesCalculator>)Parameters["ImpactValuesCalculator"]).Value;
     80        Parameters.Remove(Parameters["ImpactValuesCalculator"]);
     81      }
     82
     83      #endregion
    4884    }
    4985  }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionPruningOperator.cs

    r12669 r12745  
    2222#endregion
    2323
     24using System.Collections.Generic;
    2425using System.Linq;
    2526using HeuristicLab.Common;
    2627using HeuristicLab.Core;
     28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2729using HeuristicLab.Parameters;
    2830using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    3234  [Item("SymbolicRegressionPruningOperator", "An operator which prunes symbolic regression trees.")]
    3335  public class SymbolicRegressionPruningOperator : SymbolicDataAnalysisExpressionPruningOperator {
    34     private const string ImpactValuesCalculatorParameterName = "ImpactValuesCalculator";
     36    private const string EvaluatorParameterName = "Evaluator";
     37
     38    #region parameter properties
     39    public ILookupParameter<ISymbolicRegressionSingleObjectiveEvaluator> EvaluatorParameter {
     40      get { return (ILookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>)Parameters[EvaluatorParameterName]; }
     41    }
     42    #endregion
    3543
    3644    protected SymbolicRegressionPruningOperator(SymbolicRegressionPruningOperator original, Cloner cloner)
     
    4452    protected SymbolicRegressionPruningOperator(bool deserializing) : base(deserializing) { }
    4553
    46     public SymbolicRegressionPruningOperator() {
    47       var impactValuesCalculator = new SymbolicRegressionSolutionImpactValuesCalculator();
    48       Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, "The impact values calculator to be used for figuring out the node impacts.", impactValuesCalculator));
     54    public SymbolicRegressionPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator)
     55      : base(impactValuesCalculator) {
     56      Parameters.Add(new LookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>(EvaluatorParameterName));
    4957    }
    5058
    51     protected override ISymbolicDataAnalysisModel CreateModel() {
    52       return new SymbolicRegressionModel(SymbolicExpressionTree, Interpreter, EstimationLimits.Lower, EstimationLimits.Upper);
     59    [StorableHook(HookType.AfterDeserialization)]
     60    private void AfterDeserialization() {
     61      // BackwardsCompatibility3.3
     62      #region Backwards compatible code, remove with 3.4
     63      base.ImpactValuesCalculator = new SymbolicRegressionSolutionImpactValuesCalculator();
     64      if (!Parameters.ContainsKey(EvaluatorParameterName)) {
     65        Parameters.Add(new LookupParameter<ISymbolicRegressionSingleObjectiveEvaluator>(EvaluatorParameterName));
     66      }
     67      #endregion
     68    }
     69
     70    protected override ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits) {
     71      return new SymbolicRegressionModel(tree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
    5372    }
    5473
    5574    protected override double Evaluate(IDataAnalysisModel model) {
    56       var regressionModel = (IRegressionModel)model;
    57       var regressionProblemData = (IRegressionProblemData)ProblemData;
    58       var trainingIndices = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
    59       var estimatedValues = regressionModel.GetEstimatedValues(ProblemData.Dataset, trainingIndices); // also bounds the values
    60       var targetValues = ProblemData.Dataset.GetDoubleValues(regressionProblemData.TargetVariable, trainingIndices);
    61       OnlineCalculatorError errorState;
    62       var quality = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
    63       if (errorState != OnlineCalculatorError.None) return double.NaN;
    64       return quality*quality;
     75      var regressionModel = (ISymbolicRegressionModel)model;
     76      var regressionProblemData = (IRegressionProblemData)ProblemDataParameter.ActualValue;
     77      var evaluator = EvaluatorParameter.ActualValue;
     78      var fitnessEvaluationPartition = FitnessCalculationPartitionParameter.ActualValue;
     79      var rows = Enumerable.Range(fitnessEvaluationPartition.Start, fitnessEvaluationPartition.Size);
     80      return evaluator.Evaluate(this.ExecutionContext, regressionModel.SymbolicExpressionTree, regressionProblemData, rows);
     81    }
     82
     83    public static ISymbolicExpressionTree Prune(ISymbolicExpressionTree tree, SymbolicRegressionSolutionImpactValuesCalculator impactValuesCalculator, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IRegressionProblemData problemData, DoubleLimit estimationLimits, IEnumerable<int> rows, double nodeImpactThreshold = 0.0, bool pruneOnlyZeroImpactNodes = false) {
     84      var clonedTree = (ISymbolicExpressionTree)tree.Clone();
     85      var model = new SymbolicRegressionModel(clonedTree, interpreter, estimationLimits.Lower, estimationLimits.Upper);
     86      var nodes = clonedTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList(); // skip the nodes corresponding to the ProgramRootSymbol and the StartSymbol
     87
     88      double qualityForImpactsCalculation = double.NaN; // pass a NaN value initially so the impact calculator will calculate the quality
     89
     90      for (int i = 0; i < nodes.Count; ++i) {
     91        var node = nodes[i];
     92        if (node is ConstantTreeNode) continue;
     93
     94        double impactValue, replacementValue;
     95        double newQualityForImpactsCalculation;
     96        impactValuesCalculator.CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
     97
     98        if (pruneOnlyZeroImpactNodes && !impactValue.IsAlmost(0.0)) continue;
     99        if (!pruneOnlyZeroImpactNodes && impactValue > nodeImpactThreshold) continue;
     100
     101        var constantNode = (ConstantTreeNode)node.Grammar.GetSymbol("Constant").CreateTreeNode();
     102        constantNode.Value = replacementValue;
     103
     104        ReplaceWithConstant(node, constantNode);
     105        i += node.GetLength() - 1; // skip subtrees under the node that was folded
     106
     107        qualityForImpactsCalculation = newQualityForImpactsCalculation;
     108      }
     109      return model.SymbolicExpressionTree;
    65110    }
    66111  }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SymbolicRegressionSolutionImpactValuesCalculator.cs

    r12669 r12745  
    4848    }
    4949
    50     public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN) {
    51       double impactValue, replacementValue;
    52       CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, originalQuality);
     50    public override double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN) {
     51      double impactValue, replacementValue, newQualityForImpactsCalculation;
     52      CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpactsCalculation, qualityForImpactsCalculation);
    5353      return impactValue;
    5454    }
    5555
    5656    public override void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node,
    57       IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue,
    58       double originalQuality = Double.NaN) {
     57      IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation,
     58      double qualityForImpactsCalculation = Double.NaN) {
    5959      var regressionModel = (ISymbolicRegressionModel)model;
    6060      var regressionProblemData = (IRegressionProblemData)problemData;
     
    6464
    6565      OnlineCalculatorError errorState;
    66       if (double.IsNaN(originalQuality)) {
    67         var originalValues = regressionModel.GetEstimatedValues(dataset, rows);
    68         originalQuality = OnlinePearsonsRCalculator.Calculate(targetValues, originalValues, out errorState);
    69         if (errorState != OnlineCalculatorError.None) originalQuality = 0.0;
    70       }
     66      if (double.IsNaN(qualityForImpactsCalculation))
     67        qualityForImpactsCalculation = CalculateQualityForImpacts(regressionModel, regressionProblemData, rows);
    7168
    7269      replacementValue = CalculateReplacementValue(regressionModel, node, regressionProblemData, rows);
     
    8380
    8481      var estimatedValues = tempModel.GetEstimatedValues(dataset, rows);
    85       double newQuality = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
    86       if (errorState != OnlineCalculatorError.None) newQuality = 0.0;
     82      double r = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
     83      if (errorState != OnlineCalculatorError.None) r = 0.0;
     84      newQualityForImpactsCalculation = r * r;
    8785
    88       impactValue = (originalQuality*originalQuality) - (newQuality*newQuality);
     86      impactValue = qualityForImpactsCalculation - newQualityForImpactsCalculation;
     87    }
     88
     89    public static double CalculateQualityForImpacts(ISymbolicRegressionModel model, IRegressionProblemData problemData, IEnumerable<int> rows) {
     90      var estimatedValues = model.GetEstimatedValues(problemData.Dataset, rows); // also bounds the values
     91      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
     92      OnlineCalculatorError errorState;
     93      var r = OnlinePearsonsRCalculator.Calculate(targetValues, estimatedValues, out errorState);
     94      var quality = r * r;
     95      if (errorState != OnlineCalculatorError.None) return double.NaN;
     96      return quality;
    8997    }
    9098  }
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisSingleObjectivePruningAnalyzer.cs

    r12009 r12745  
    4545    private const string TotalNumberOfPrunedSubtreesParameterName = "Number of pruned subtrees";
    4646    private const string TotalNumberOfPrunedTreesParameterName = "Number of pruned trees";
     47    private const string TotalNumberOfPrunedNodesParameterName = "Number of pruned nodes";
    4748    private const string RandomParameterName = "Random";
    48     private const string PruneOnlyZeroImpactNodesParameterName = "PruneOnlyZeroImpactNodes";
    49     private const string NodeImpactThresholdParameterName = "ImpactThreshold";
    50     private const string PruningOperatorParameterName = "PruningOperator";
    5149    private const string ResultsParameterName = "Results";
    5250    private const string PopulationSizeParameterName = "PopulationSize";
     
    5452
    5553    #region private members
     54    private DataReducer prunedNodesReducer;
    5655    private DataReducer prunedSubtreesReducer;
    5756    private DataReducer prunedTreesReducer;
     
    6160
    6261    #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     }
    7262    public ILookupParameter<IRandom> RandomParameter {
    7363      get { return (ILookupParameter<IRandom>)Parameters[RandomParameterName]; }
     
    9181
    9282    #region properties
    93     protected SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get { return PruningOperatorParameter.Value; } }
     83    protected abstract SymbolicDataAnalysisExpressionPruningOperator PruningOperator { get; }
    9484    protected int UpdateInterval { get { return UpdateIntervalParameter.Value.Value; } }
    9585
     
    112102      get { return PruningProbabilityParameter.Value.Value; }
    113103      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; }
    123104    }
    124105    #endregion
     
    140121    protected SymbolicDataAnalysisSingleObjectivePruningAnalyzer(SymbolicDataAnalysisSingleObjectivePruningAnalyzer original, Cloner cloner)
    141122      : base(original, cloner) {
     123      if (original.prunedNodesReducer != null)
     124        this.prunedNodesReducer = (DataReducer)original.prunedNodesReducer.Clone();
    142125      if (original.prunedSubtreesReducer != null)
    143126        this.prunedSubtreesReducer = (DataReducer)original.prunedSubtreesReducer.Clone();
     
    197180      Parameters.Add(new LookupParameter<IRandom>(RandomParameterName, "The random number generator."));
    198181      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)));
    201182      Parameters.Add(new LookupParameter<IntValue>(PopulationSizeParameterName, "The population of individuals."));
    202183      #endregion
     
    225206      var qualities = Quality.Select(x => x.Value).ToArray();
    226207      var indices = Enumerable.Range(0, qualities.Length).ToArray();
    227       Array.Sort(qualities, indices);
     208      indices.StableSort((a, b) => qualities[a].CompareTo(qualities[b]));
     209
    228210      if (!Maximization.Value) Array.Reverse(indices);
    229211
     
    233215      var empty = new EmptyOperator();
    234216
    235       for (int i = 0; i < subscopes.Count; ++i) {
     217      for (int i = 0; i < indices.Length; ++i) {
    236218        IOperator @operator;
    237219        if (range.Start <= i && i < range.End && random.NextDouble() <= PruningProbability)
     
    250232      UpdateCounter = 0;
    251233
    252       if (prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
     234      if (prunedNodesReducer == null || prunedSubtreesReducer == null || prunedTreesReducer == null || valuesCollector == null || resultsCollector == null) { InitializeOperators(); }
    253235
    254236      var prune = CreatePruningOperation();
     237      var reducePrunedNodes = ExecutionContext.CreateChildOperation(prunedNodesReducer);
    255238      var reducePrunedSubtrees = ExecutionContext.CreateChildOperation(prunedSubtreesReducer);
    256239      var reducePrunedTrees = ExecutionContext.CreateChildOperation(prunedTreesReducer);
     
    258241      var collectResults = ExecutionContext.CreateChildOperation(resultsCollector);
    259242
    260       return new OperationCollection { prune, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
     243      return new OperationCollection { prune, reducePrunedNodes, reducePrunedSubtrees, reducePrunedTrees, collectValues, collectResults, base.Apply() };
    261244    }
    262245
    263246    private void InitializeOperators() {
     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
    264253      prunedSubtreesReducer = new DataReducer();
    265254      prunedSubtreesReducer.ParameterToReduce.ActualName = PruningOperator.PrunedSubtreesParameter.ActualName;
     
    275264
    276265      valuesCollector = new DataTableValuesCollector();
     266      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedNodesParameterName));
    277267      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedSubtreesParameterName));
    278268      valuesCollector.CollectedValues.Add(new LookupParameter<IntValue>(TotalNumberOfPrunedTreesParameterName));
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs

    r11145 r12745  
    66  public interface ISymbolicDataAnalysisSolutionImpactValuesCalculator : IItem {
    77    double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
    8     double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN);
     8    double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);
    99    void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData,
    10       IEnumerable<int> rows, out double impactValue, out double replacementValue, double originalQuality = double.NaN);
     10      IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN);
    1111  }
    1212}
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionPruningOperator.cs

    r12009 r12745  
    3434  [StorableClass]
    3535  [Item("SymbolicExpressionTreePruningOperator", "An operator that replaces introns with constant values in a symbolic expression tree.")]
    36   public abstract class SymbolicDataAnalysisExpressionPruningOperator : SingleSuccessorOperator {
     36  public abstract class SymbolicDataAnalysisExpressionPruningOperator : SingleSuccessorOperator, ISymbolicExpressionTreeOperator {
    3737    #region parameter names
    3838    private const string ProblemDataParameterName = "ProblemData";
     
    4141    private const string PrunedSubtreesParameterName = "PrunedSubtrees";
    4242    private const string PrunedTreesParameterName = "PrunedTrees";
     43    private const string PrunedNodesParameterName = "PrunedNodes";
    4344    private const string FitnessCalculationPartitionParameterName = "FitnessCalculationPartition";
    4445    private const string NodeImpactThresholdParameterName = "ImpactThreshold";
     
    4849    private const string EstimationLimitsParameterName = "EstimationLimits";
    4950    private const string InterpreterParameterName = "SymbolicExpressionTreeInterpreter";
     51    private const string ApplyLinearScalingParameterName = "ApplyLinearScaling";
    5052    #endregion
    5153
     
    7274      get { return (ILookupParameter<IntValue>)Parameters[PrunedTreesParameterName]; }
    7375    }
     76    public ILookupParameter<IntValue> PrunedNodesParameter {
     77      get { return (ILookupParameter<IntValue>)Parameters[PrunedNodesParameterName]; }
     78    }
    7479    public IFixedValueParameter<DoubleValue> NodeImpactThresholdParameter {
    7580      get { return (IFixedValueParameter<DoubleValue>)Parameters[NodeImpactThresholdParameterName]; }
     
    8489      get { return (ILookupParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[InterpreterParameterName]; }
    8590    }
     91    public ILookupParameter<BoolValue> ApplyLinearScalingParameter {
     92      get { return (ILookupParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName]; }
     93    }
    8694    #endregion
    8795
    8896    #region properties
    89     protected IDataAnalysisProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } }
    90     protected ISymbolicDataAnalysisSolutionImpactValuesCalculator ImpactValuesCalculator { get { return ImpactValuesCalculatorParameter.Value; } }
    91     protected IntRange FitnessCalculationPartition { get { return FitnessCalculationPartitionParameter.ActualValue; } }
    92     protected bool PruneOnlyZeroImpactNodes {
     97    public ISymbolicDataAnalysisSolutionImpactValuesCalculator ImpactValuesCalculator {
     98      get { return ImpactValuesCalculatorParameter.Value; }
     99      set { ImpactValuesCalculatorParameter.Value = value; }
     100    }
     101    public bool PruneOnlyZeroImpactNodes {
    93102      get { return PruneOnlyZeroImpactNodesParameter.Value.Value; }
    94103      set { PruneOnlyZeroImpactNodesParameter.Value.Value = value; }
    95104    }
    96     protected double NodeImpactThreshold {
     105    public double NodeImpactThreshold {
    97106      get { return NodeImpactThresholdParameter.Value.Value; }
    98107      set { NodeImpactThresholdParameter.Value.Value = value; }
    99108    }
    100     protected ISymbolicExpressionTree SymbolicExpressionTree { get { return SymbolicExpressionTreeParameter.ActualValue; } }
    101     protected DoubleValue Quality { get { return QualityParameter.ActualValue; } }
    102     protected DoubleLimit EstimationLimits { get { return EstimationLimitsParameter.ActualValue; } }
    103     protected ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter { get { return InterpreterParameter.ActualValue; } }
    104109    #endregion
    105110
     
    109114      : base(original, cloner) { }
    110115
    111     protected SymbolicDataAnalysisExpressionPruningOperator() {
     116    protected SymbolicDataAnalysisExpressionPruningOperator(ISymbolicDataAnalysisSolutionImpactValuesCalculator impactValuesCalculator) {
    112117      #region add parameters
    113118      Parameters.Add(new LookupParameter<IDataAnalysisProblemData>(ProblemDataParameterName));
    114119      Parameters.Add(new LookupParameter<ISymbolicDataAnalysisModel>(SymbolicDataAnalysisModelParameterName));
    115120      Parameters.Add(new LookupParameter<IntRange>(FitnessCalculationPartitionParameterName));
     121      Parameters.Add(new LookupParameter<IntValue>(PrunedNodesParameterName, "A counter of how many nodes were pruned."));
    116122      Parameters.Add(new LookupParameter<IntValue>(PrunedSubtreesParameterName, "A counter of how many subtrees were replaced."));
    117123      Parameters.Add(new LookupParameter<IntValue>(PrunedTreesParameterName, "A counter of how many trees were pruned."));
     
    122128      Parameters.Add(new LookupParameter<ISymbolicExpressionTree>(SymbolicExpressionTreeParameterName));
    123129      Parameters.Add(new LookupParameter<DoubleValue>(QualityParameterName));
     130      Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName));
     131      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName, impactValuesCalculator));
    124132      #endregion
    125133    }
    126134
    127     protected abstract ISymbolicDataAnalysisModel CreateModel();
     135    [StorableHook(HookType.AfterDeserialization)]
     136    private void AfterDeserialization() {
     137      // BackwardsCompatibility3.3
     138      #region Backwards compatible code, remove with 3.4
     139      if (!Parameters.ContainsKey(PrunedNodesParameterName)) {
     140        Parameters.Add(new LookupParameter<IntValue>(PrunedNodesParameterName, "A counter of how many nodes were pruned."));
     141      }
     142      if (!Parameters.ContainsKey(ApplyLinearScalingParameterName)) {
     143        Parameters.Add(new LookupParameter<BoolValue>(ApplyLinearScalingParameterName));
     144      }
     145      if (!Parameters.ContainsKey(ImpactValuesCalculatorParameterName)) {
     146        // value must be set by derived operators (regression/classification)
     147        Parameters.Add(new ValueParameter<ISymbolicDataAnalysisSolutionImpactValuesCalculator>(ImpactValuesCalculatorParameterName));
     148      }
     149      #endregion
     150    }
     151
     152    protected abstract ISymbolicDataAnalysisModel CreateModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, IDataAnalysisProblemData problemData, DoubleLimit estimationLimits);
    128153
    129154    protected abstract double Evaluate(IDataAnalysisModel model);
    130155
    131156    public override IOperation Apply() {
    132       var model = CreateModel();
    133       var nodes = SymbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
    134       var rows = Enumerable.Range(FitnessCalculationPartition.Start, FitnessCalculationPartition.Size);
     157      var tree = SymbolicExpressionTreeParameter.ActualValue;
     158      var problemData = ProblemDataParameter.ActualValue;
     159      var fitnessCalculationPartition = FitnessCalculationPartitionParameter.ActualValue;
     160      var estimationLimits = EstimationLimitsParameter.ActualValue;
     161      var interpreter = InterpreterParameter.ActualValue;
     162
     163      var model = CreateModel(tree, interpreter, problemData, estimationLimits);
     164      var nodes = tree.Root.GetSubtree(0).GetSubtree(0).IterateNodesPrefix().ToList();
     165      var rows = Enumerable.Range(fitnessCalculationPartition.Start, fitnessCalculationPartition.Size).ToList();
    135166      var prunedSubtrees = 0;
    136167      var prunedTrees = 0;
    137 
    138       double quality = Evaluate(model);
     168      var prunedNodes = 0;
     169
     170      double qualityForImpactsCalculation = double.NaN;
    139171
    140172      for (int i = 0; i < nodes.Count; ++i) {
     
    143175
    144176        double impactValue, replacementValue;
    145         ImpactValuesCalculator.CalculateImpactAndReplacementValues(model, node, ProblemData, rows, out impactValue, out replacementValue, quality);
    146 
    147         if (PruneOnlyZeroImpactNodes) {
    148           if (!impactValue.IsAlmost(0.0)) continue;
    149         } else if (NodeImpactThreshold < impactValue) {
    150           continue;
    151         }
     177        double newQualityForImpacts;
     178        ImpactValuesCalculator.CalculateImpactAndReplacementValues(model, node, problemData, rows, out impactValue, out replacementValue, out newQualityForImpacts, qualityForImpactsCalculation);
     179
     180        if (PruneOnlyZeroImpactNodes && !impactValue.IsAlmost(0.0)) continue;
     181        if (!PruneOnlyZeroImpactNodes && impactValue > NodeImpactThreshold) continue;
    152182
    153183        var constantNode = (ConstantTreeNode)node.Grammar.GetSymbol("Constant").CreateTreeNode();
    154184        constantNode.Value = replacementValue;
    155185
     186        var length = node.GetLength();
    156187        ReplaceWithConstant(node, constantNode);
    157         i += node.GetLength() - 1; // skip subtrees under the node that was folded
    158 
    159         quality -= impactValue;
     188        i += length - 1; // skip subtrees under the node that was folded
    160189
    161190        prunedSubtrees++;
     191        prunedNodes += length;
     192
     193        qualityForImpactsCalculation = newQualityForImpacts;
    162194      }
    163195
     
    165197      PrunedSubtreesParameter.ActualValue = new IntValue(prunedSubtrees);
    166198      PrunedTreesParameter.ActualValue = new IntValue(prunedTrees);
     199      PrunedNodesParameter.ActualValue = new IntValue(prunedNodes);
     200
     201      if (prunedSubtrees > 0) // if nothing was pruned then there's no need to re-evaluate the tree
     202        QualityParameter.ActualValue.Value = Evaluate(model);
    167203
    168204      return base.Apply();
    169205    }
    170206
    171     private static void ReplaceWithConstant(ISymbolicExpressionTreeNode original, ISymbolicExpressionTreeNode replacement) {
     207    protected static void ReplaceWithConstant(ISymbolicExpressionTreeNode original, ISymbolicExpressionTreeNode replacement) {
    172208      var parent = original.Parent;
    173209      var i = parent.IndexOfSubtree(original);
  • stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs

    r12702 r12745  
    3737    protected SymbolicDataAnalysisSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { }
    3838    public abstract double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);
    39     public abstract double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double originalQuality = double.NaN);
    40     public abstract void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, double originalQuality = double.NaN);
     39    public abstract double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);
     40    public abstract void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN);
    4141
    4242    protected static double CalculateReplacementValue(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
Note: See TracChangeset for help on using the changeset viewer.