source: branches/3076_IA_evaluators_analyzers/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionSingleObjectiveConstraintEvaluator.cs @ 17744

Last change on this file since 17744 was 17744, checked in by chaider, 9 months ago

#3076 Removed Pearson R² Evaluators and added a new single-objective configurable evaluator

File size: 10.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6using HEAL.Attic;
7using HeuristicLab.Common;
8using HeuristicLab.Core;
9using HeuristicLab.Data;
10using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
11using HeuristicLab.Parameters;
12using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression;
13
14namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
15  [Item("Constraints Evaluator", "Calculates NMSE of a symbolic regression solution with respect to constraints.")]
16  [StorableType("27473973-DD8D-4375-997D-942E2280AE8E")]
17  class SymbolicRegressionSingleObjectiveConstraintEvaluator : SymbolicRegressionSingleObjectiveEvaluator {
18    #region Parameter/Properties
19
20    private const string UseConstantOptimizationParameterName = "Use Constant Optimization";
21
22    private const string ConstantOptimizationIterationsParameterName = "Constant Optimization Iterations";
23
24    private const string UseSoftConstraintsParameterName = "Use Soft Constraints Evaluation";
25
26    private const string PenaltyMultiplierParameterName = "Constraints Penalty Multiplier";
27
28    public IFixedValueParameter<BoolValue> UseConstantOptimizationParameter =>
29      (IFixedValueParameter<BoolValue>) Parameters[UseConstantOptimizationParameterName];
30
31    public IFixedValueParameter<IntValue> ConstantOptimizationIterationsParameter =>
32      (IFixedValueParameter<IntValue>) Parameters[ConstantOptimizationIterationsParameterName];
33
34    public IFixedValueParameter<BoolValue> UseSoftConstraintsParameter =>
35      (IFixedValueParameter<BoolValue>) Parameters[UseSoftConstraintsParameterName];
36
37    public IFixedValueParameter<DoubleValue> PenaltyMultiplierParameter =>
38      (IFixedValueParameter<DoubleValue>) Parameters[PenaltyMultiplierParameterName];
39
40    public bool UseConstantOptimization {
41      get => UseConstantOptimizationParameter.Value.Value;
42      set => UseConstantOptimizationParameter.Value.Value = value;
43    }
44
45    public int ConstantOptimizationIterations {
46      get => ConstantOptimizationIterationsParameter.Value.Value;
47      set => ConstantOptimizationIterationsParameter.Value.Value = value;
48    }
49
50    public bool UseSoftConstraints {
51      get => UseSoftConstraintsParameter.Value.Value;
52      set => UseSoftConstraintsParameter.Value.Value = value;
53    }
54
55    public double PenaltyMultiplier {
56      get => PenaltyMultiplierParameter.Value.Value;
57      set => PenaltyMultiplierParameter.Value.Value = value;
58    }
59
60    //Use false for maximization, because we try to minimize the NMSE
61    public override bool Maximization => false;
62
63    #endregion
64
65    #region Constructors/Cloning
66
67    [StorableConstructor]
68    protected SymbolicRegressionSingleObjectiveConstraintEvaluator(StorableConstructorFlag _) : base(_) { }
69
70    protected SymbolicRegressionSingleObjectiveConstraintEvaluator(
71      SymbolicRegressionSingleObjectiveConstraintEvaluator original, Cloner cloner) : base(original, cloner) { }
72
73    public SymbolicRegressionSingleObjectiveConstraintEvaluator() {
74      Parameters.Add(new FixedValueParameter<BoolValue>(UseConstantOptimizationParameterName,
75        "Define whether constant optimization is active or not.", new BoolValue(false)));
76      Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName,
77        "Define how many constant optimization steps should be performed.", new IntValue(10)));
78      Parameters.Add(new FixedValueParameter<BoolValue>(UseSoftConstraintsParameterName,
79        "Define whether the constraints are penalized by soft or hard constraints.", new BoolValue(false)));
80      Parameters.Add(new FixedValueParameter<DoubleValue>(PenaltyMultiplierParameterName,
81        "Specify how hard constraints violations should be punished", new DoubleValue(1.0)));
82    }
83
84    [StorableHook(HookType.AfterDeserialization)]
85    private void AfterDeserialization() {
86      if (!Parameters.ContainsKey(UseConstantOptimizationParameterName)) {
87        Parameters.Add(new FixedValueParameter<BoolValue>(UseConstantOptimizationParameterName,
88          "Define whether constant optimization is active or not.", new BoolValue(false)));
89      }
90
91      if (!Parameters.ContainsKey(ConstantOptimizationIterationsParameterName)) {
92        Parameters.Add(new FixedValueParameter<IntValue>(ConstantOptimizationIterationsParameterName,
93          "Define how many constant optimization steps should be performed.", new IntValue(10)));
94      }
95
96      if (!Parameters.ContainsKey(UseSoftConstraintsParameterName)) {
97        Parameters.Add(new FixedValueParameter<BoolValue>(UseSoftConstraintsParameterName,
98          "Define whether the constraints are penalized by soft or hard constraints.", new BoolValue(false)));
99      }
100
101      if (!Parameters.ContainsKey(PenaltyMultiplierParameterName)) {
102        Parameters.Add(new FixedValueParameter<DoubleValue>(PenaltyMultiplierParameterName,
103          "Specify how hard constraints violations should be punished", new DoubleValue(1.0)));
104      }
105    }
106
107    public override IDeepCloneable Clone(Cloner cloner) {
108      return new SymbolicRegressionSingleObjectiveConstraintEvaluator(this, cloner);
109    }
110
111    #endregion
112
113    public override IOperation InstrumentedApply() {
114      var rows               = GenerateRowsToEvaluate();
115      var solution           = SymbolicExpressionTreeParameter.ActualValue;
116      var problemData        = ProblemDataParameter.ActualValue;
117      var interpreter        = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
118      var estimationLimits   = EstimationLimitsParameter.ActualValue;
119      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
120
121      if (applyLinearScaling) {
122        //Check for interval arithmetic grammar
123        //remove scaling nodes for linear scaling evaluation
124        var                    rootNode  = new ProgramRootSymbol().CreateTreeNode();
125        var                    startNode = new StartSymbol().CreateTreeNode();
126        SymbolicExpressionTree newTree   = null;
127        foreach (var node in solution.IterateNodesPrefix())
128          if (node.Symbol.Name == "Scaling") {
129            for (var i = 0; i < node.SubtreeCount; ++i) startNode.AddSubtree(node.GetSubtree(i));
130            rootNode.AddSubtree(startNode);
131            newTree = new SymbolicExpressionTree(rootNode);
132            break;
133          }
134
135        //calculate alpha and beta for scaling
136        var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(newTree, problemData.Dataset, rows);
137        var targetValues    = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
138        OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out var alpha, out var beta,
139          out var errorState);
140        //Set alpha and beta to the scaling nodes from ia grammar
141        foreach (var node in solution.IterateNodesPrefix())
142          if (node.Symbol.Name == "Offset") {
143            node.RemoveSubtree(1);
144            var alphaNode = new ConstantTreeNode(new Constant()) {Value = alpha};
145            node.AddSubtree(alphaNode);
146          } else if (node.Symbol.Name == "Scaling") {
147            node.RemoveSubtree(1);
148            var betaNode = new ConstantTreeNode(new Constant()) {Value = beta};
149            node.AddSubtree(betaNode);
150          }
151      }
152
153      if (UseConstantOptimization) {
154        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows,
155          false, ConstantOptimizationIterations, true,
156          estimationLimits.Lower, estimationLimits.Upper);
157      }
158
159      var quality = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, UseSoftConstraints,
160        PenaltyMultiplier);
161      QualityParameter.ActualValue = new DoubleValue(quality);
162
163      return base.InstrumentedApply();
164    }
165
166    public static double Calculate(
167      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
168      ISymbolicExpressionTree solution, double lowerEstimationLimit,
169      double upperEstimationLimit,
170      IRegressionProblemData problemData, IEnumerable<int> rows, bool useSoftConstraints,
171      double penaltyMultiplier) {
172      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
173      var targetValues   = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
174      var constraints    = problemData.IntervalConstraints.EnabledConstraints;
175      var variableRanges = problemData.VariableRanges.GetReadonlyDictionary();
176
177      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
178      var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues,
179        out var errorState);
180
181      if (!SymbolicRegressionConstraintAnalyzer.ConstraintsSatisfied(constraints, variableRanges, solution, out var error)) {
182        if (useSoftConstraints) {
183          if (double.IsNaN(error) || double.IsInfinity(error)) {
184            nmse += penaltyMultiplier * 1.0;
185          } else {
186            nmse += penaltyMultiplier * error;
187          }
188
189          nmse = Math.Min(1.0, nmse);
190        } else {
191          nmse = 1.0;
192        }
193      }
194
195      if (errorState != OnlineCalculatorError.None) {
196        nmse = 1.0;
197      }
198
199      return nmse;
200    }
201
202    public override double Evaluate(
203      IExecutionContext context, ISymbolicExpressionTree tree, IRegressionProblemData problemData,
204      IEnumerable<int> rows) {
205      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
206      EstimationLimitsParameter.ExecutionContext                    = context;
207      ApplyLinearScalingParameter.ExecutionContext = context;
208
209      var nmse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
210        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
211        problemData, rows, UseSoftConstraints, PenaltyMultiplier);
212
213      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
214      EstimationLimitsParameter.ExecutionContext                    = null;
215      ApplyLinearScalingParameter.ExecutionContext                  = null;
216
217      return nmse;
218    }
219  }
220}
Note: See TracBrowser for help on using the repository browser.