Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17892 was 17892, checked in by gkronber, 3 years ago

#3076: refactoring to prepare for trunk reintegration

File size: 9.0 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.Collections.Generic;
25using System.Linq;
26using HEAL.Attic;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
31using HeuristicLab.Parameters;
32
33namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.MultiObjective {
34  [Item("Multi Soft Constraints Evaluator",
35    "Calculates the NMSE and the constraints violations of a symbolic regression solution.")]
36  [StorableType("8E9D76B7-ED9C-43E7-9898-01FBD3633880")]
37  public class
38    SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator : SymbolicRegressionMultiObjectiveEvaluator {
39    public const string DimensionsParameterName = "Dimensions";
40    private const string BoundsEstimatorParameterName = "Bounds estimator";
41
42    public IFixedValueParameter<IntValue> DimensionsParameter =>
43      (IFixedValueParameter<IntValue>)Parameters[DimensionsParameterName];
44
45    public IValueParameter<IBoundsEstimator> BoundsEstimatorParameter =>
46      (IValueParameter<IBoundsEstimator>)Parameters[BoundsEstimatorParameterName];
47
48    public int Dimensions {
49      get => DimensionsParameter.Value.Value;
50      set => DimensionsParameter.Value.Value = value;
51    }
52
53    public IBoundsEstimator BoundsEstimator {
54      get => BoundsEstimatorParameter.Value;
55      set => BoundsEstimatorParameter.Value = value;
56    }
57
58    #region Constructors
59
60    public SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator() {
61      Parameters.Add(new FixedValueParameter<IntValue>(DimensionsParameterName, new IntValue(2)));
62      Parameters.Add(new ValueParameter<IBoundsEstimator>(BoundsEstimatorParameterName, new IntervalArithBoundsEstimator()));
63    }
64
65    [StorableConstructor]
66    protected SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator(StorableConstructorFlag _) : base(_) { }
67
68    protected SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator(
69      SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator original, Cloner cloner) : base(original, cloner) { }
70
71    #endregion
72
73    [StorableHook(HookType.AfterDeserialization)]
74    private void AfterDeserialization() {
75      if (!Parameters.ContainsKey(DimensionsParameterName))
76        Parameters.Add(new FixedValueParameter<IntValue>(DimensionsParameterName, new IntValue(2)));
77
78      if (!Parameters.ContainsKey(BoundsEstimatorParameterName))
79        Parameters.Add(new ValueParameter<IBoundsEstimator>(BoundsEstimatorParameterName, new IntervalArithBoundsEstimator()));
80    }
81
82    public override IDeepCloneable Clone(Cloner cloner) {
83      return new SymbolicRegressionMultiObjectiveMultiSoftConstraintEvaluator(this, cloner);
84    }
85
86
87    public override IOperation InstrumentedApply() {
88      var rows = GenerateRowsToEvaluate();
89      var solution = SymbolicExpressionTreeParameter.ActualValue;
90      var problemData = ProblemDataParameter.ActualValue;
91      var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue;
92      var estimationLimits = EstimationLimitsParameter.ActualValue;
93      var applyLinearScaling = ApplyLinearScalingParameter.ActualValue.Value;
94
95      if (UseConstantOptimization) {
96        SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows,
97          false,
98          ConstantOptimizationIterations,
99          ConstantOptimizationUpdateVariableWeights,
100          estimationLimits.Lower,
101          estimationLimits.Upper);
102      } else {
103        if (applyLinearScaling) {
104          //Check for interval arithmetic grammar
105          //remove scaling nodes for linear scaling evaluation
106          var rootNode = new ProgramRootSymbol().CreateTreeNode();
107          var startNode = new StartSymbol().CreateTreeNode();
108          SymbolicExpressionTree newTree = null;
109          foreach (var node in solution.IterateNodesPrefix())
110            if (node.Symbol.Name == "Scaling") {
111              for (var i = 0; i < node.SubtreeCount; ++i) startNode.AddSubtree(node.GetSubtree(i));
112              rootNode.AddSubtree(startNode);
113              newTree = new SymbolicExpressionTree(rootNode);
114              break;
115            }
116
117          //calculate alpha and beta for scaling
118          var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(newTree, problemData.Dataset, rows);
119          var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
120          OnlineLinearScalingParameterCalculator.Calculate(estimatedValues, targetValues, out var alpha, out var beta,
121            out var errorState);
122          //Set alpha and beta to the scaling nodes from ia grammar
123          foreach (var node in solution.IterateNodesPrefix())
124            if (node.Symbol.Name == "Offset") {
125              node.RemoveSubtree(1);
126              var alphaNode = new ConstantTreeNode(new Constant()) { Value = alpha };
127              node.AddSubtree(alphaNode);
128            } else if (node.Symbol.Name == "Scaling") {
129              node.RemoveSubtree(1);
130              var betaNode = new ConstantTreeNode(new Constant()) { Value = beta };
131              node.AddSubtree(betaNode);
132            }
133        }
134      }
135
136      var qualities = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData,
137        rows, BoundsEstimator);
138      QualitiesParameter.ActualValue = new DoubleArray(qualities);
139      return base.InstrumentedApply();
140    }
141
142    public override double[] Evaluate(
143      IExecutionContext context, ISymbolicExpressionTree tree,
144      IRegressionProblemData problemData,
145      IEnumerable<int> rows) {
146      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
147      EstimationLimitsParameter.ExecutionContext = context;
148      ApplyLinearScalingParameter.ExecutionContext = context;
149
150      var quality = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree,
151        EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper,
152        problemData, rows, BoundsEstimator);
153
154      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
155      EstimationLimitsParameter.ExecutionContext = null;
156      ApplyLinearScalingParameter.ExecutionContext = null;
157
158      return quality;
159    }
160
161
162    public static double[] Calculate(
163      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,
164      ISymbolicExpressionTree solution, double lowerEstimationLimit,
165      double upperEstimationLimit,
166      IRegressionProblemData problemData, IEnumerable<int> rows, IBoundsEstimator estimator) {
167      OnlineCalculatorError errorState;
168      var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows);
169      var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
170      var constraints = problemData.ShapeConstraints.Where(c => c.Enabled);
171      var intervalCollection = problemData.VariableRanges;
172
173      double nmse;
174
175      var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
176      nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out errorState);
177      if (errorState != OnlineCalculatorError.None) nmse = 1.0;
178
179      if (nmse > 1)
180        nmse = 1.0;
181
182      var objectives = new List<double> { nmse };
183      var violations = IntervalUtil.GetConstraintViolations(constraints, estimator, intervalCollection, solution);
184      foreach (var violation in violations) {
185        if (double.IsNaN(violation) || double.IsInfinity(violation)) {
186          objectives.Add(double.MaxValue);
187        } else {
188          objectives.Add(violation);
189        }
190      }
191
192      return objectives.ToArray();
193    }
194
195    /*
196     * First objective is to maximize the Pearson R² value
197     * All following objectives have to be minimized ==> Constraints
198     */
199
200    public override IEnumerable<bool> Maximization {
201      get {
202        var objectives = new List<bool> { false }; // NMSE ==> min
203        var dim = Dimensions;
204        objectives.AddRange(Enumerable.Repeat(false, dim)); // Constraints ==> min
205
206        return objectives;
207      }
208    }
209  }
210}
Note: See TracBrowser for help on using the repository browser.