Free cookie consent management tool by TermsFeed Policy Generator

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

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

#3076: refactoring to prepare for trunk reintegration

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