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

Last change on this file since 17792 was 17792, checked in by dpiringe, 20 months ago

#3076

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