source: branches/3136_Structural_GP/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/StructuredSymbolicRegressionSingleObjectiveProblem.cs @ 18191

Last change on this file since 18191 was 18191, checked in by mkommend, 5 months ago

#3136: Extracted linear scaling functionality in a dedicated helper class.

File size: 13.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Linq;
24using HEAL.Attic;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Optimization;
30using HeuristicLab.Parameters;
31using HeuristicLab.PluginInfrastructure;
32using HeuristicLab.Problems.Instances;
33using HeuristicLab.Problems.Instances.DataAnalysis;
34
35namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
36  [StorableType("7464E84B-65CC-440A-91F0-9FA920D730F9")]
37  [Item(Name = "Structured Symbolic Regression Single Objective Problem (single-objective)", Description = "A problem with a structural definition and unfixed subfunctions.")]
38  [Creatable(CreatableAttribute.Categories.GeneticProgrammingProblems, Priority = 150)]
39  public class StructuredSymbolicRegressionSingleObjectiveProblem : SingleObjectiveBasicProblem<MultiEncoding>, IRegressionProblem, IProblemInstanceConsumer<IRegressionProblemData> {
40
41    #region Constants
42    private const string TreeEvaluatorParameterName = "TreeEvaluator";
43    private const string ProblemDataParameterName = "ProblemData";
44    private const string StructureTemplateParameterName = "Structure Template";
45    private const string InterpreterParameterName = "Interpreter";
46    private const string EstimationLimitsParameterName = "EstimationLimits";
47    private const string BestTrainingSolutionParameterName = "Best Training Solution";
48    private const string ApplyLinearScalingParameterName = "Apply Linear Scaling";
49    private const string OptimizeParametersParameterName = "Optimize Parameters";
50
51    private const string SymbolicExpressionTreeName = "SymbolicExpressionTree";
52
53    private const string StructureTemplateDescriptionText =
54      "Enter your expression as string in infix format into the empty input field.\n" +
55      "By checking the \"Apply Linear Scaling\" checkbox you can add the relevant scaling terms to your expression.\n" +
56      "After entering the expression click parse to build the tree.\n" +
57      "To edit the defined sub-functions, click on the corresponding-colored node in the tree view.\n" +
58      "Check the info box besides the input field for more information.";
59    #endregion
60
61    #region Parameters
62    public IConstrainedValueParameter<SymbolicRegressionSingleObjectiveEvaluator> TreeEvaluatorParameter => (IConstrainedValueParameter<SymbolicRegressionSingleObjectiveEvaluator>)Parameters[TreeEvaluatorParameterName];
63    public IValueParameter<IRegressionProblemData> ProblemDataParameter => (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName];
64    public IFixedValueParameter<StructureTemplate> StructureTemplateParameter => (IFixedValueParameter<StructureTemplate>)Parameters[StructureTemplateParameterName];
65    public IValueParameter<ISymbolicDataAnalysisExpressionTreeInterpreter> InterpreterParameter => (IValueParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>)Parameters[InterpreterParameterName];
66    public IFixedValueParameter<DoubleLimit> EstimationLimitsParameter => (IFixedValueParameter<DoubleLimit>)Parameters[EstimationLimitsParameterName];
67    public IResultParameter<ISymbolicRegressionSolution> BestTrainingSolutionParameter => (IResultParameter<ISymbolicRegressionSolution>)Parameters[BestTrainingSolutionParameterName];
68
69    public IFixedValueParameter<BoolValue> ApplyLinearScalingParameter => (IFixedValueParameter<BoolValue>)Parameters[ApplyLinearScalingParameterName];
70    public IFixedValueParameter<BoolValue> OptimizeParametersParameter => (IFixedValueParameter<BoolValue>)Parameters[OptimizeParametersParameterName];
71    #endregion
72
73    #region Properties
74
75    public IRegressionProblemData ProblemData {
76      get => ProblemDataParameter.Value;
77      set {
78        ProblemDataParameter.Value = value;
79        ProblemDataChanged?.Invoke(this, EventArgs.Empty);
80      }
81    }
82
83    public SymbolicRegressionSingleObjectiveEvaluator TreeEvaluator => TreeEvaluatorParameter.Value;
84
85    public StructureTemplate StructureTemplate => StructureTemplateParameter.Value;
86
87    public ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter => InterpreterParameter.Value;
88
89    IParameter IDataAnalysisProblem.ProblemDataParameter => ProblemDataParameter;
90    IDataAnalysisProblemData IDataAnalysisProblem.ProblemData => ProblemData;
91
92    public DoubleLimit EstimationLimits => EstimationLimitsParameter.Value;
93
94    public bool ApplyLinearScaling {
95      get => ApplyLinearScalingParameter.Value.Value;
96      set => ApplyLinearScalingParameter.Value.Value = value;
97    }
98
99    public bool OptimizeParameters {
100      get => OptimizeParametersParameter.Value.Value;
101      set => OptimizeParametersParameter.Value.Value = value;
102    }
103
104    public override bool Maximization => false;
105    #endregion
106
107    #region EventHandlers
108    public event EventHandler ProblemDataChanged;
109    #endregion
110
111    #region Constructors & Cloning
112    public StructuredSymbolicRegressionSingleObjectiveProblem() {
113      var provider = new PhysicsInstanceProvider();
114      var descriptor = new SheetBendingProcess();
115      var problemData = provider.LoadData(descriptor);
116      var shapeConstraintProblemData = new ShapeConstrainedRegressionProblemData(problemData);
117
118      var structureTemplate = new StructureTemplate();
119
120      var evaluators = new ItemSet<SymbolicRegressionSingleObjectiveEvaluator>(
121        ApplicationManager.Manager.GetInstances<SymbolicRegressionSingleObjectiveEvaluator>()
122        .Where(x => x.Maximization == Maximization));
123
124      Parameters.Add(new ConstrainedValueParameter<SymbolicRegressionSingleObjectiveEvaluator>(
125        TreeEvaluatorParameterName,
126        evaluators,
127        evaluators.First()));
128
129      Parameters.Add(new ValueParameter<IRegressionProblemData>(
130        ProblemDataParameterName,
131        shapeConstraintProblemData));
132
133      Parameters.Add(new FixedValueParameter<StructureTemplate>(
134        StructureTemplateParameterName,
135        StructureTemplateDescriptionText,
136        structureTemplate));
137
138      Parameters.Add(new FixedValueParameter<BoolValue>(
139        ApplyLinearScalingParameterName, new BoolValue(true)
140        ));
141
142      Parameters.Add(new FixedValueParameter<BoolValue>(
143        OptimizeParametersParameterName, new BoolValue(true)
144        ));
145
146      Parameters.Add(new ValueParameter<ISymbolicDataAnalysisExpressionTreeInterpreter>(
147        InterpreterParameterName,
148        new SymbolicDataAnalysisExpressionTreeBatchInterpreter()) { Hidden = true });
149      Parameters.Add(new FixedValueParameter<DoubleLimit>(
150        EstimationLimitsParameterName,
151        new DoubleLimit(double.NegativeInfinity, double.PositiveInfinity)) { Hidden = true });
152      Parameters.Add(new ResultParameter<ISymbolicRegressionSolution>(BestTrainingSolutionParameterName, "") { Hidden = true });
153
154      this.EvaluatorParameter.Hidden = true;
155
156      Operators.Add(new SymbolicDataAnalysisVariableFrequencyAnalyzer());
157      Operators.Add(new MinAverageMaxSymbolicExpressionTreeLengthAnalyzer());
158      Operators.Add(new SymbolicExpressionSymbolFrequencyAnalyzer());
159
160      RegisterEventHandlers();
161
162      StructureTemplate.ApplyLinearScaling = ApplyLinearScaling;
163      StructureTemplate.Template =
164        "(" +
165          "(210000 / (210000 + h)) * ((sigma_y * t * t) / (wR * Rt * t)) + " +
166          "PlasticHardening(_) - Elasticity(_)" +
167        ")" +
168        " * C(_)";
169    }
170
171    public StructuredSymbolicRegressionSingleObjectiveProblem(StructuredSymbolicRegressionSingleObjectiveProblem original, Cloner cloner) : base(original, cloner) {
172      RegisterEventHandlers();
173    }
174
175    public override IDeepCloneable Clone(Cloner cloner) =>
176      new StructuredSymbolicRegressionSingleObjectiveProblem(this, cloner);
177
178    [StorableConstructor]
179    protected StructuredSymbolicRegressionSingleObjectiveProblem(StorableConstructorFlag _) : base(_) { }
180
181
182    [StorableHook(HookType.AfterDeserialization)]
183    private void AfterDeserialization() {
184      if (!Parameters.ContainsKey(ApplyLinearScalingParameterName)) {
185        Parameters.Add(new FixedValueParameter<BoolValue>(ApplyLinearScalingParameterName, new BoolValue(StructureTemplate.ApplyLinearScaling)));
186      }
187
188      if (!Parameters.ContainsKey(OptimizeParametersParameterName)) {
189        Parameters.Add(new FixedValueParameter<BoolValue>(OptimizeParametersParameterName, new BoolValue(false)));
190      }
191
192      RegisterEventHandlers();
193    }
194
195    #endregion
196
197    private void RegisterEventHandlers() {
198      if (StructureTemplate != null) {
199        StructureTemplate.Changed += OnTemplateChanged;
200      }
201
202      ProblemDataParameter.ValueChanged += ProblemDataParameterValueChanged;
203      ApplyLinearScalingParameter.Value.ValueChanged += (o, e) => StructureTemplate.ApplyLinearScaling = ApplyLinearScaling;
204      OptimizeParametersParameter.Value.ValueChanged += (o, e) => {
205        if (OptimizeParameters) ApplyLinearScaling = true;
206      };
207
208    }
209
210    private void ProblemDataParameterValueChanged(object sender, EventArgs e) {
211      StructureTemplate.Reset();
212      // InfoBox for Reset?
213    }
214
215    private void OnTemplateChanged(object sender, EventArgs args) {
216      ApplyLinearScaling = StructureTemplate.ApplyLinearScaling;
217      SetupEncoding();
218    }
219
220    private void SetupEncoding() {
221      foreach (var e in Encoding.Encodings.ToArray())
222        Encoding.Remove(e);
223
224      foreach (var subFunction in StructureTemplate.SubFunctions) {
225        subFunction.SetupVariables(ProblemData.AllowedInputVariables);
226        // prevent the same encoding twice
227        if (Encoding.Encodings.Any(x => x.Name == subFunction.Name)) continue;
228
229        var encoding = new SymbolicExpressionTreeEncoding(
230          subFunction.Name,
231          subFunction.Grammar,
232          subFunction.MaximumSymbolicExpressionTreeLength,
233          subFunction.MaximumSymbolicExpressionTreeDepth);
234        Encoding.Add(encoding);
235      }
236
237      //set multi manipulator as default manipulator for all encoding parts
238      var manipulator = (IParameterizedItem)Encoding.Operators.OfType<MultiEncodingManipulator>().FirstOrDefault();
239      if (manipulator != null) {
240        foreach (var param in manipulator.Parameters.OfType<ConstrainedValueParameter<IManipulator>>()) {
241          var m = param.ValidValues.OfType<MultiSymbolicExpressionTreeManipulator>().FirstOrDefault();
242          param.Value = m == null ? param.ValidValues.First() : m;
243        }
244      }
245    }
246
247    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
248      base.Analyze(individuals, qualities, results, random);
249
250      var best = GetBestIndividual(individuals, qualities).Item1;
251
252      if (!results.ContainsKey(BestTrainingSolutionParameter.ActualName)) {
253        results.Add(new Result(BestTrainingSolutionParameter.ActualName, typeof(SymbolicRegressionSolution)));
254      }
255
256      var tree = (ISymbolicExpressionTree)best[SymbolicExpressionTreeName];
257      var model = new SymbolicRegressionModel(ProblemData.TargetVariable, tree, Interpreter);
258      var solution = model.CreateRegressionSolution(ProblemData);
259
260      results[BestTrainingSolutionParameter.ActualName].Value = solution;
261    }
262
263
264    public override double Evaluate(Individual individual, IRandom random) {
265      var templateTree = StructureTemplate.Tree;
266      if (templateTree == null)
267        throw new ArgumentException("No structure template defined!");
268
269      var tree = BuildTree(templateTree, individual);
270
271      // NMSEConstraintsEvaluator sets linear scaling terms itself
272      if (ApplyLinearScaling && !(TreeEvaluator is NMSESingleObjectiveConstraintsEvaluator)) {
273        LinearScaling.AdjustLinearScalingParams(ProblemData, tree, Interpreter);
274      }
275
276      individual[SymbolicExpressionTreeName] = tree;
277
278      return TreeEvaluator.Evaluate(
279        tree, ProblemData,
280        ProblemData.TrainingIndices,
281        Interpreter,
282        StructureTemplate.ApplyLinearScaling,
283        EstimationLimits.Lower,
284        EstimationLimits.Upper);
285    }
286
287    private static ISymbolicExpressionTree BuildTree(ISymbolicExpressionTree template, Individual individual) {
288      var resolvedTree = (ISymbolicExpressionTree)template.Clone();
289      // build main tree
290      foreach (var subFunctionTreeNode in resolvedTree.IterateNodesPrefix().OfType<SubFunctionTreeNode>()) {
291        var subFunctionTree = individual.SymbolicExpressionTree(subFunctionTreeNode.Name);
292
293        // extract function tree
294        var subTree = subFunctionTree.Root.GetSubtree(0)  // StartSymbol
295                                          .GetSubtree(0); // First Symbol
296        subTree = (ISymbolicExpressionTreeNode)subTree.Clone();
297        subFunctionTreeNode.AddSubtree(subTree);
298      }
299      return resolvedTree;
300    }
301
302    public void Load(IRegressionProblemData data) {
303      ProblemData = data;
304    }
305  }
306}
Note: See TracBrowser for help on using the repository browser.