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

Last change on this file since 17636 was 17636, checked in by chaider, 3 months ago

#3076 Changed variable ranges to be readonly

File size: 8.6 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      var applyLinearScaling = false;
66
67      if (UseConstantOptimization)
68        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows,
69          applyLinearScaling,
70          ConstantOptimizationIterations,
71          ConstantOptimizationUpdateVariableWeights,
72          estimationLimits.Lower,
73          estimationLimits.Upper);
74
75      var qualities = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData,
76        rows, applyLinearScaling, DecimalPlaces, minIntervalWidth, maxIntervalSplitDepth);
77      QualitiesParameter.ActualValue = new DoubleArray(qualities);
78      return base.InstrumentedApply();
79    }
80
81    public override double[] Evaluate(IExecutionContext context, ISymbolicExpressionTree tree,
82                                      IRegressionProblemData problemData,
83                                      IEnumerable<int> rows) {
84      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
85      EstimationLimitsParameter.ExecutionContext                    = context;
86      ApplyLinearScalingParameter.ExecutionContext                  = context;
87
88      var quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
89        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
90        problemData, rows,
91        ApplyLinearScalingParameter.ActualValue.Value, DecimalPlaces, MinSplittingWidth,
92        MaxSplittingDepth);
93
94      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
95      EstimationLimitsParameter.ExecutionContext                    = null;
96      ApplyLinearScalingParameter.ExecutionContext                  = null;
97
98      return quality;
99    }
100
101
102    public static double[] Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
103                                     ISymbolicExpressionTree solution, double lowerEstimationLimit,
104                                     double upperEstimationLimit,
105                                     IRegressionProblemData problemData, IEnumerable<int> rows, bool applyLinearScaling,
106                                     int decimalPlaces, double minIntervalSplitWidth, int maxIntervalSplitDepth) {
107      OnlineCalculatorError errorState;
108      var estimatedValues =
109        interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
110      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
111
112      double nmse;
113
114      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
115      nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out errorState);
116      if (errorState != OnlineCalculatorError.None) nmse = double.NaN;
117
118      if (nmse > 1)
119        nmse = 1;
120
121      var constraints    = problemData.IntervalConstraints.Constraints.Where(c => c.Enabled);
122      var variableRanges = problemData.VariableRanges.GetReadonlyDictionary();
123
124      var objectives          = new List<double> {nmse};
125      var intervalInterpreter = new IntervalInterpreter();
126      /*{MinIntervalSplitWidth = minIntervalSplitWidth, MaxIntervalSplitDepth = maxIntervalSplitDetph};*/
127
128      var constraintObjectives = new List<double>();
129      foreach (var c in constraints) {
130        var penalty = ConstraintExceeded(c, intervalInterpreter, variableRanges,
131          solution /*, problemData.IntervalSplitting*/);
132        var maxP = 0.1;
133
134        if (double.IsNaN(penalty) || double.IsInfinity(penalty) || penalty > maxP)
135          penalty = maxP;
136
137        constraintObjectives.Add(penalty);
138      }
139
140      objectives.AddRange(constraintObjectives);
141
142      return objectives.ToArray();
143    }
144
145    public static double ConstraintExceeded(IntervalConstraint constraint, IntervalInterpreter intervalInterpreter,
146                                            IReadOnlyDictionary<string, Interval> variableRanges,
147                                            ISymbolicExpressionTree solution /*, bool splitting*/) {
148      if (constraint.Variable != null && !variableRanges.ContainsKey(constraint.Variable))
149        throw new ArgumentException(
150          $"The given variable {constraint.Variable} in the constraint does not exists in the model.",
151          nameof(IntervalConstraintsParser));
152      Interval resultInterval;
153      if (!constraint.IsDerivative) {
154        resultInterval =
155          intervalInterpreter.GetSymbolicExpressionTreeInterval(solution, variableRanges /*, splitting:splitting*/);
156      }
157      else {
158        var tree = solution;
159        for (var i = 0; i < constraint.NumberOfDerivations; ++i)
160          tree = DerivativeCalculator.Derive(tree, constraint.Variable);
161
162        resultInterval =
163          intervalInterpreter.GetSymbolicExpressionTreeInterval(tree, variableRanges /*, splitting: splitting*/);
164      }
165
166      //Calculate soft-constraints for intervals
167      if (constraint.Interval.Contains(resultInterval)) return 0;
168      var pLower = 0.0;
169      var pUpper = 0.0;
170      if (constraint.Interval.Contains(resultInterval.LowerBound))
171        pLower = 0;
172      else
173        pLower = constraint.Interval.LowerBound - resultInterval.LowerBound;
174
175      if (constraint.Interval.Contains(resultInterval.UpperBound))
176        pUpper = 0;
177      else
178        pUpper = resultInterval.UpperBound - constraint.Interval.UpperBound;
179      var penalty = Math.Abs(pLower) + Math.Abs(pUpper);
180
181      return penalty;
182    }
183
184    /*
185     * First objective is to maximize the Pearson R² value
186     * All following objectives have to be minimized ==> Constraints
187     */
188    public override IEnumerable<bool> Maximization {
189      get {
190        var objectives = new List<bool> {false};          //First NMSE ==> min
191        objectives.AddRange(Enumerable.Repeat(false, 2)); //Constraints ==> min
192
193        return objectives;
194      }
195    }
196  }
197}
Note: See TracBrowser for help on using the repository browser.