source: branches/3076_IA_evaluators_analyzers/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/MultiObjective/SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator.cs @ 17705

Last change on this file since 17705 was 17705, checked in by chaider, 7 weeks ago

#3076

  • Fixed some formating in SymbolicRegressionSingleObjectiveConstraintScalingNmseEvaluator
  • Added linear scaling check in SymbolicRegressionSingleObjectiveConstraintScalingNmseEvaluator
  • Added linear scaling for SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator
File size: 10.1 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 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.Collections.Generic;
26using System.Linq;
27using HEAL.Attic;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
32
33namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.MultiObjective {
34  [Item("Multi Soft Constraints Evaluator",
35    "Calculates the Person R² and the constraints violations of a symbolic regression solution.")]
36  [StorableType("8E9D76B7-ED9C-43E7-9898-01FBD3633880")]
37  public class
38    SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator : SymbolicRegressionMultiObjectiveSplittingEvaluator {
39    #region Constructors
40
41    public SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator() { }
42
43    [StorableConstructor]
44    protected SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator(StorableConstructorFlag _) : base(_) { }
45
46    protected SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator(
47      SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator original, Cloner cloner) : base(original, cloner) { }
48
49    #endregion
50
51    public override IDeepCloneable Clone(Cloner cloner) {
52      return new SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator(this, cloner);
53    }
54
55
56    public override IOperation InstrumentedApply() {
57      var rows                  = GenerateRowsToEvaluate();
58      var solution              = SymbolicExpressionTreeParameter.ActualValue;
59      var problemData           = ProblemDataParameter.ActualValue;
60      var interpreter           = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
61      var estimationLimits      = EstimationLimitsParameter.ActualValue;
62      var minIntervalWidth      = MinSplittingWidth;
63      var maxIntervalSplitDepth = MaxSplittingDepth;
64      var applyLinearScaling  = ApplyLinearScalingParameter.ActualValue.Value;
65
66      if (applyLinearScaling) {
67        //Check for interval arithmetic grammar
68        //remove scaling nodes for linear scaling evaluation
69        var                    rootNode  = new ProgramRootSymbol().CreateTreeNode();
70        var                    startNode = new StartSymbol().CreateTreeNode();
71        SymbolicExpressionTree newTree   = null;
72        foreach (var node in solution.IterateNodesPrefix())
73          if (node.Symbol.Name == "Scaling") {
74            for (var i = 0; i < node.SubtreeCount; ++i) startNode.AddSubtree(node.GetSubtree(i));
75            rootNode.AddSubtree(startNode);
76            newTree = new SymbolicExpressionTree(rootNode);
77            break;
78          }
79
80        //calculate alpha and beta for scaling
81        var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(newTree, problemData.Dataset, rows);
82        var targetValues    = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
83        OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out var alpha, out var beta,
84          out var errorState);
85        //Set alpha and beta to the scaling nodes from ia grammar
86        foreach (var node in solution.IterateNodesPrefix())
87          if (node.Symbol.Name == "Offset") {
88            node.RemoveSubtree(1);
89            var alphaNode = new ConstantTreeNode(new Constant()) {Value = alpha};
90            node.AddSubtree(alphaNode);
91          } else if (node.Symbol.Name == "Scaling") {
92            node.RemoveSubtree(1);
93            var betaNode = new ConstantTreeNode(new Constant()) {Value = beta};
94            node.AddSubtree(betaNode);
95          }
96      }
97
98      if (UseConstantOptimization)
99        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows,
100          false,
101          ConstantOptimizationIterations,
102          ConstantOptimizationUpdateVariableWeights,
103          estimationLimits.Lower,
104          estimationLimits.Upper);
105
106      var qualities = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData,
107        rows, DecimalPlaces, minIntervalWidth, maxIntervalSplitDepth);
108      QualitiesParameter.ActualValue = new DoubleArray(qualities);
109      return base.InstrumentedApply();
110    }
111
112    public override double[] Evaluate(IExecutionContext context, ISymbolicExpressionTree tree,
113                                      IRegressionProblemData problemData,
114                                      IEnumerable<int> rows) {
115      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
116      EstimationLimitsParameter.ExecutionContext                    = context;
117      ApplyLinearScalingParameter.ExecutionContext                  = context;
118
119      var quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
120        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
121        problemData, rows, DecimalPlaces, MinSplittingWidth,
122        MaxSplittingDepth);
123
124      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
125      EstimationLimitsParameter.ExecutionContext                    = null;
126      ApplyLinearScalingParameter.ExecutionContext                  = null;
127
128      return quality;
129    }
130
131
132    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
133                                     ISymbolicExpressionTree solution, double lowerEstimationLimit,
134                                     double upperEstimationLimit,
135                                     IRegressionProblemData problemData, IEnumerable<int> rows,
136                                     int decimalPlaces, double minIntervalSplitWidth, int maxIntervalSplitDepth) {
137      OnlineCalculatorError errorState;
138      var estimatedValues =
139        interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
140      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
141
142      double nmse;
143
144      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
145      nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out errorState);
146      if (errorState != OnlineCalculatorError.None) nmse = 1.0;
147
148      if (nmse > 1)
149        nmse = 1.0;
150
151      var constraints    = problemData.IntervalConstraints.Constraints.Where(c => c.Enabled);
152      var variableRanges = problemData.VariableRanges.GetReadonlyDictionary();
153
154      var objectives          = new List<double> {nmse};
155      var intervalInterpreter = new IntervalInterpreter();
156      /*{MinIntervalSplitWidth = minIntervalSplitWidth, MaxIntervalSplitDepth = maxIntervalSplitDetph};*/
157
158      var constraintObjectives = new List<double>();
159      foreach (var c in constraints) {
160        var penalty = ConstraintExceeded(c, intervalInterpreter, variableRanges,
161          solution /*, problemData.IntervalSplitting*/);
162        var maxP = 0.1;
163
164        if (double.IsNaN(penalty) || double.IsInfinity(penalty) || penalty > maxP)
165          penalty = maxP;
166
167        constraintObjectives.Add(penalty);
168      }
169
170      objectives.AddRange(constraintObjectives);
171
172      return objectives.ToArray();
173    }
174
175    public static double ConstraintExceeded(IntervalConstraint constraint, IntervalInterpreter intervalInterpreter,
176                                            IReadOnlyDictionary<string, Interval> variableRanges,
177                                            ISymbolicExpressionTree solution /*, bool splitting*/) {
178      if (constraint.Variable != null && !variableRanges.ContainsKey(constraint.Variable))
179        throw new ArgumentException(
180          $"The given variable {constraint.Variable} in the constraint does not exists in the model.",
181          nameof(IntervalConstraintsParser));
182      Interval resultInterval;
183      if (!constraint.IsDerivative) {
184        resultInterval =
185          intervalInterpreter.GetSymbolicExpressionTreeInterval(solution, variableRanges /*, splitting:splitting*/);
186      }
187      else {
188        var tree = solution;
189        for (var i = 0; i < constraint.NumberOfDerivations; ++i)
190          tree = DerivativeCalculator.Derive(tree, constraint.Variable);
191
192        resultInterval =
193          intervalInterpreter.GetSymbolicExpressionTreeInterval(tree, variableRanges /*, splitting: splitting*/);
194      }
195
196      //Calculate soft-constraints for intervals
197      if (constraint.Interval.Contains(resultInterval)) return 0;
198      var pLower = 0.0;
199      var pUpper = 0.0;
200      if (constraint.Interval.Contains(resultInterval.LowerBound))
201        pLower = 0;
202      else
203        pLower = constraint.Interval.LowerBound - resultInterval.LowerBound;
204
205      if (constraint.Interval.Contains(resultInterval.UpperBound))
206        pUpper = 0;
207      else
208        pUpper = resultInterval.UpperBound - constraint.Interval.UpperBound;
209      var penalty = Math.Abs(pLower) + Math.Abs(pUpper);
210
211      return penalty;
212    }
213
214    /*
215     * First objective is to maximize the Pearson R² value
216     * All following objectives have to be minimized ==> Constraints
217     */
218    public override IEnumerable<bool> Maximization {
219      get {
220        var objectives = new List<bool> {false};          //First NMSE ==> min
221        objectives.AddRange(Enumerable.Repeat(false, 2)); //Constraints ==> min
222       
223        return objectives;
224      }
225    }
226  }
227}
Note: See TracBrowser for help on using the repository browser.