Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Regression/3.3/Symbolic/SymbolicRegressionProblemBase.cs @ 4190

Last change on this file since 4190 was 4190, checked in by gkronber, 14 years ago

Moved upper and lower estimation limit parameters into ISymbolicRegressionEvaluator interface and introduced an Evaluate method in the interface in preparation for a ISymbolicRegressionEvaluator parameter for the validation best solution analyzer. #1117

File size: 18.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Analyzers;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Creators;
31using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Interfaces;
32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35using HeuristicLab.PluginInfrastructure;
36using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic.Analyzers;
37using HeuristicLab.Problems.DataAnalysis.Symbolic;
38
39namespace HeuristicLab.Problems.DataAnalysis.Regression.Symbolic {
40  [StorableClass]
41  public abstract class SymbolicRegressionProblemBase : DataAnalysisProblem, IProblem {
42
43    #region Parameter Properties
44    public new ValueParameter<SymbolicExpressionTreeCreator> SolutionCreatorParameter {
45      get { return (ValueParameter<SymbolicExpressionTreeCreator>)Parameters["SolutionCreator"]; }
46    }
47    IParameter IProblem.SolutionCreatorParameter {
48      get { return SolutionCreatorParameter; }
49    }
50    public ValueParameter<DoubleValue> LowerEstimationLimitParameter {
51      get { return (ValueParameter<DoubleValue>)Parameters["LowerEstimationLimit"]; }
52    }
53    public ValueParameter<DoubleValue> UpperEstimationLimitParameter {
54      get { return (ValueParameter<DoubleValue>)Parameters["UpperEstimationLimit"]; }
55    }
56    public ValueParameter<ISymbolicExpressionTreeInterpreter> SymbolicExpressionTreeInterpreterParameter {
57      get { return (ValueParameter<ISymbolicExpressionTreeInterpreter>)Parameters["SymbolicExpressionTreeInterpreter"]; }
58    }
59    public ValueParameter<ISymbolicExpressionGrammar> FunctionTreeGrammarParameter {
60      get { return (ValueParameter<ISymbolicExpressionGrammar>)Parameters["FunctionTreeGrammar"]; }
61    }
62    public ValueParameter<IntValue> MaxExpressionLengthParameter {
63      get { return (ValueParameter<IntValue>)Parameters["MaxExpressionLength"]; }
64    }
65    public ValueParameter<IntValue> MaxExpressionDepthParameter {
66      get { return (ValueParameter<IntValue>)Parameters["MaxExpressionDepth"]; }
67    }
68    public ValueParameter<IntValue> MaxFunctionDefiningBranchesParameter {
69      get { return (ValueParameter<IntValue>)Parameters["MaxFunctionDefiningBranches"]; }
70    }
71    public ValueParameter<IntValue> MaxFunctionArgumentsParameter {
72      get { return (ValueParameter<IntValue>)Parameters["MaxFunctionArguments"]; }
73    }
74    #endregion
75
76    #region Properties
77    public IntValue MaxExpressionLength {
78      get { return MaxExpressionLengthParameter.Value; }
79      set { MaxExpressionLengthParameter.Value = value; }
80    }
81    public IntValue MaxExpressionDepth {
82      get { return MaxExpressionDepthParameter.Value; }
83      set { MaxExpressionDepthParameter.Value = value; }
84    }
85    public IntValue MaxFunctionDefiningBranches {
86      get { return MaxFunctionDefiningBranchesParameter.Value; }
87      set { MaxFunctionDefiningBranchesParameter.Value = value; }
88    }
89    public IntValue MaxFunctionArguments {
90      get { return MaxFunctionArgumentsParameter.Value; }
91      set { MaxFunctionArgumentsParameter.Value = value; }
92    }
93    public new SymbolicExpressionTreeCreator SolutionCreator {
94      get { return SolutionCreatorParameter.Value; }
95      set { SolutionCreatorParameter.Value = value; }
96    }
97    ISolutionCreator IProblem.SolutionCreator {
98      get { return SolutionCreatorParameter.Value; }
99    }
100    public ISymbolicExpressionTreeInterpreter SymbolicExpressionTreeInterpreter {
101      get { return SymbolicExpressionTreeInterpreterParameter.Value; }
102      set { SymbolicExpressionTreeInterpreterParameter.Value = value; }
103    }
104    public DoubleValue LowerEstimationLimit {
105      get { return LowerEstimationLimitParameter.Value; }
106      set { LowerEstimationLimitParameter.Value = value; }
107    }
108    public DoubleValue UpperEstimationLimit {
109      get { return UpperEstimationLimitParameter.Value; }
110      set { UpperEstimationLimitParameter.Value = value; }
111    }
112
113    public ISymbolicExpressionGrammar FunctionTreeGrammar {
114      get { return (ISymbolicExpressionGrammar)FunctionTreeGrammarParameter.Value; }
115    }
116    public override IEnumerable<IOperator> Operators {
117      get { return operators; }
118    }
119    public IEnumerable<ISymbolicRegressionAnalyzer> Analyzers {
120      get { return operators.OfType<ISymbolicRegressionAnalyzer>(); }
121    }
122    public DoubleValue PunishmentFactor {
123      get { return new DoubleValue(10.0); }
124    }
125    public IntValue TrainingSamplesStart {
126      get { return new IntValue(DataAnalysisProblemData.TrainingSamplesStart.Value); }
127    }
128    public IntValue TrainingSamplesEnd {
129      get {
130        return new IntValue((DataAnalysisProblemData.TrainingSamplesStart.Value +
131          DataAnalysisProblemData.TrainingSamplesEnd.Value) / 2);
132      }
133    }
134    public IntValue ValidationSamplesStart {
135      get { return TrainingSamplesEnd; }
136    }
137    public IntValue ValidationSamplesEnd {
138      get { return new IntValue(DataAnalysisProblemData.TrainingSamplesEnd.Value); }
139    }
140    public IntValue TestSamplesStart {
141      get { return DataAnalysisProblemData.TestSamplesStart; }
142    }
143    public IntValue TestSamplesEnd {
144      get { return DataAnalysisProblemData.TestSamplesEnd; }
145    }
146    #endregion
147
148    [Storable]
149    private List<IOperator> operators;
150
151    [StorableConstructor]
152    protected SymbolicRegressionProblemBase(bool deserializing) : base(deserializing) { }
153    public SymbolicRegressionProblemBase()
154      : base() {
155      SymbolicExpressionTreeCreator creator = new ProbabilisticTreeCreator();
156      var grammar = new BasicExpressionGrammar();
157      var globalGrammar = new GlobalSymbolicExpressionGrammar(grammar);
158      var interpreter = new SimpleArithmeticExpressionInterpreter();
159      Parameters.Add(new ValueParameter<SymbolicExpressionTreeCreator>("SolutionCreator", "The operator which should be used to create new symbolic regression solutions.", creator));
160      Parameters.Add(new ValueParameter<ISymbolicExpressionTreeInterpreter>("SymbolicExpressionTreeInterpreter", "The interpreter that should be used to evaluate the symbolic expression tree.", interpreter));
161      Parameters.Add(new ValueParameter<DoubleValue>("LowerEstimationLimit", "The lower limit for the estimated value that can be returned by the symbolic regression model.", new DoubleValue(double.NegativeInfinity)));
162      Parameters.Add(new ValueParameter<DoubleValue>("UpperEstimationLimit", "The upper limit for the estimated value that can be returned by the symbolic regression model.", new DoubleValue(double.PositiveInfinity)));
163      Parameters.Add(new ValueParameter<ISymbolicExpressionGrammar>("FunctionTreeGrammar", "The grammar that should be used for symbolic regression models.", globalGrammar));
164      Parameters.Add(new ValueParameter<IntValue>("MaxExpressionLength", "Maximal length of the symbolic expression.", new IntValue(100)));
165      Parameters.Add(new ValueParameter<IntValue>("MaxExpressionDepth", "Maximal depth of the symbolic expression.", new IntValue(10)));
166      Parameters.Add(new ValueParameter<IntValue>("MaxFunctionDefiningBranches", "Maximal number of automatically defined functions.", (IntValue)new IntValue(0).AsReadOnly()));
167      Parameters.Add(new ValueParameter<IntValue>("MaxFunctionArguments", "Maximal number of arguments of automatically defined functions.", (IntValue)new IntValue(0).AsReadOnly()));
168
169      creator.SymbolicExpressionTreeParameter.ActualName = "SymbolicRegressionModel";
170
171      ParameterizeSolutionCreator();
172
173      UpdateGrammar();
174      UpdateEstimationLimits();
175      InitializeOperators();
176      RegisterParameterEvents();
177      RegisterParameterValueEvents();
178    }
179
180    public override IDeepCloneable Clone(Cloner cloner) {
181      SymbolicRegressionProblemBase clone = (SymbolicRegressionProblemBase)base.Clone(cloner);
182      clone.operators = operators.Select(x => (IOperator)cloner.Clone(x)).ToList();
183      clone.RegisterParameterEvents();
184      clone.RegisterParameterValueEvents();
185      return clone;
186    }
187
188    private void RegisterParameterValueEvents() {
189      MaxFunctionArgumentsParameter.ValueChanged += new EventHandler(ArchitectureParameter_ValueChanged);
190      MaxFunctionDefiningBranchesParameter.ValueChanged += new EventHandler(ArchitectureParameter_ValueChanged);
191      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
192    }
193
194    private void RegisterParameterEvents() {
195      MaxFunctionArgumentsParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
196      MaxFunctionDefiningBranchesParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
197      SolutionCreator.SymbolicExpressionTreeParameter.ActualNameChanged += new EventHandler(SolutionCreator_SymbolicExpressionTreeParameter_ActualNameChanged);
198    }
199
200    #region event handling
201    protected override void OnDataAnalysisProblemChanged(EventArgs e) {
202      base.OnDataAnalysisProblemChanged(e);
203      // paritions could be changed
204      ParameterizeAnalyzers();
205      // input variables could have been changed
206      UpdateGrammar();
207      // estimation limits have to be recalculated
208      UpdateEstimationLimits();
209    }
210    protected virtual void OnArchitectureParameterChanged(EventArgs e) {
211      UpdateGrammar();
212    }
213    protected virtual void OnGrammarChanged(EventArgs e) { }
214    protected virtual void OnOperatorsChanged(EventArgs e) { RaiseOperatorsChanged(e); }
215    protected virtual void OnSolutionCreatorChanged(EventArgs e) {
216      SolutionCreator.SymbolicExpressionTreeParameter.ActualNameChanged += new EventHandler(SolutionCreator_SymbolicExpressionTreeParameter_ActualNameChanged);
217      ParameterizeSolutionCreator();
218      OnSolutionParameterNameChanged(e);
219      RaiseSolutionCreatorChanged(e);
220    }
221
222    protected virtual void OnSolutionParameterNameChanged(EventArgs e) {
223      ParameterizeAnalyzers();
224      ParameterizeOperators();
225    }
226
227    protected virtual void OnEvaluatorChanged(EventArgs e) {
228      RaiseEvaluatorChanged(e);
229    }
230    #endregion
231
232    #region event handlers
233    private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
234      OnSolutionCreatorChanged(e);
235    }
236    private void SolutionCreator_SymbolicExpressionTreeParameter_ActualNameChanged(object sender, EventArgs e) {
237      OnSolutionParameterNameChanged(e);
238    }
239    private void ArchitectureParameter_ValueChanged(object sender, EventArgs e) {
240      MaxFunctionArgumentsParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
241      MaxFunctionDefiningBranchesParameter.Value.ValueChanged += new EventHandler(ArchitectureParameterValue_ValueChanged);
242      OnArchitectureParameterChanged(e);
243    }
244    private void ArchitectureParameterValue_ValueChanged(object sender, EventArgs e) {
245      OnArchitectureParameterChanged(e);
246    }
247    #endregion
248
249    #region Helpers
250    [StorableHook(HookType.AfterDeserialization)]
251    private void AfterDeserializationHook() {
252      // BackwardsCompatibility3.3
253      #region Backwards compatible code (remove with 3.4)
254      if (operators == null) InitializeOperators();
255      #endregion
256      RegisterParameterEvents();
257      RegisterParameterValueEvents();
258    }
259
260    protected void AddOperator(IOperator op) {
261      operators.Add(op);
262    }
263
264    private void UpdateGrammar() {
265      foreach (var varSymbol in FunctionTreeGrammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols.Variable>()) {
266        varSymbol.VariableNames = DataAnalysisProblemData.InputVariables.CheckedItems.Select(x => x.Value.Value);
267      }
268      var globalGrammar = FunctionTreeGrammar as GlobalSymbolicExpressionGrammar;
269      if (globalGrammar != null) {
270        globalGrammar.MaxFunctionArguments = MaxFunctionArguments.Value;
271        globalGrammar.MaxFunctionDefinitions = MaxFunctionDefiningBranches.Value;
272      }
273    }
274
275    private void UpdateEstimationLimits() {
276      if (TrainingSamplesStart.Value < TrainingSamplesEnd.Value &&
277        DataAnalysisProblemData.Dataset.VariableNames.Contains(DataAnalysisProblemData.TargetVariable.Value)) {
278        var targetValues = DataAnalysisProblemData.Dataset.GetVariableValues(DataAnalysisProblemData.TargetVariable.Value, TrainingSamplesStart.Value, TrainingSamplesEnd.Value);
279        var mean = targetValues.Average();
280        var range = targetValues.Max() - targetValues.Min();
281        UpperEstimationLimit = new DoubleValue(mean + PunishmentFactor.Value * range);
282        LowerEstimationLimit = new DoubleValue(mean - PunishmentFactor.Value * range);
283      }
284    }
285
286    private void InitializeOperators() {
287      operators = new List<IOperator>();
288      operators.AddRange(ApplicationManager.Manager.GetInstances<ISymbolicExpressionTreeOperator>().OfType<IOperator>());
289      operators.Add(new SymbolicRegressionTournamentPruning());
290      operators.Add(new SymbolicRegressionVariableFrequencyAnalyzer());
291      operators.Add(new MinAverageMaxSymbolicExpressionTreeSizeAnalyzer());
292      operators.Add(new SymbolicRegressionModelQualityAnalyzer());
293      ParameterizeOperators();
294      ParameterizeAnalyzers();
295    }
296
297    private void ParameterizeSolutionCreator() {
298      SolutionCreator.SymbolicExpressionGrammarParameter.ActualName = FunctionTreeGrammarParameter.Name;
299      SolutionCreator.MaxTreeHeightParameter.ActualName = MaxExpressionDepthParameter.Name;
300      SolutionCreator.MaxTreeSizeParameter.ActualName = MaxExpressionLengthParameter.Name;
301      SolutionCreator.MaxFunctionArgumentsParameter.ActualName = MaxFunctionArgumentsParameter.Name;
302      SolutionCreator.MaxFunctionDefinitionsParameter.ActualName = MaxFunctionDefiningBranchesParameter.Name;
303    }
304
305    private void ParameterizeAnalyzers() {
306      foreach (var analyzer in Analyzers) {
307        analyzer.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
308        var symbolicRegressionModelQualityAnalyzer = analyzer as SymbolicRegressionModelQualityAnalyzer;
309        if (symbolicRegressionModelQualityAnalyzer != null) {
310          symbolicRegressionModelQualityAnalyzer.ProblemDataParameter.ActualName = DataAnalysisProblemDataParameter.Name;
311          symbolicRegressionModelQualityAnalyzer.UpperEstimationLimitParameter.ActualName = UpperEstimationLimitParameter.Name;
312          symbolicRegressionModelQualityAnalyzer.LowerEstimationLimitParameter.ActualName = LowerEstimationLimitParameter.Name;
313          symbolicRegressionModelQualityAnalyzer.SymbolicExpressionTreeInterpreterParameter.ActualName = SymbolicExpressionTreeInterpreterParameter.Name;
314          symbolicRegressionModelQualityAnalyzer.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
315        }
316        var varFreqAnalyzer = analyzer as SymbolicRegressionVariableFrequencyAnalyzer;
317        if (varFreqAnalyzer != null) {
318          varFreqAnalyzer.ProblemDataParameter.ActualName = DataAnalysisProblemDataParameter.Name;
319        }
320        var pruningOperator = analyzer as SymbolicRegressionTournamentPruning;
321        if (pruningOperator != null) {
322          pruningOperator.SamplesStartParameter.Value = TrainingSamplesStart;
323          pruningOperator.SamplesEndParameter.Value = TrainingSamplesEnd;
324          pruningOperator.DataAnalysisProblemDataParameter.ActualName = DataAnalysisProblemDataParameter.Name;
325          pruningOperator.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
326          pruningOperator.SymbolicExpressionTreeInterpreterParameter.ActualName = SymbolicExpressionTreeInterpreterParameter.Name;
327          pruningOperator.LowerEstimationLimitParameter.ActualName = LowerEstimationLimitParameter.Name;
328          pruningOperator.UpperEstimationLimitParameter.ActualName = UpperEstimationLimitParameter.Name;
329        }
330      }
331      foreach (ISymbolicExpressionTreeAnalyzer analyzer in Operators.OfType<ISymbolicExpressionTreeAnalyzer>()) {
332        analyzer.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
333      }
334    }
335
336    private void ParameterizeOperators() {
337      foreach (ISymbolicExpressionTreeOperator op in Operators.OfType<ISymbolicExpressionTreeOperator>()) {
338        op.MaxTreeHeightParameter.ActualName = MaxExpressionDepthParameter.Name;
339        op.MaxTreeSizeParameter.ActualName = MaxExpressionLengthParameter.Name;
340        op.SymbolicExpressionGrammarParameter.ActualName = FunctionTreeGrammarParameter.Name;
341      }
342      foreach (ISymbolicExpressionTreeCrossover op in Operators.OfType<ISymbolicExpressionTreeCrossover>()) {
343        op.ParentsParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
344        op.ChildParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
345      }
346      foreach (ISymbolicExpressionTreeManipulator op in Operators.OfType<ISymbolicExpressionTreeManipulator>()) {
347        op.SymbolicExpressionTreeParameter.ActualName = SolutionCreator.SymbolicExpressionTreeParameter.ActualName;
348      }
349      foreach (ISymbolicExpressionTreeArchitectureManipulator op in Operators.OfType<ISymbolicExpressionTreeArchitectureManipulator>()) {
350        op.MaxFunctionArgumentsParameter.ActualName = MaxFunctionArgumentsParameter.Name;
351        op.MaxFunctionDefinitionsParameter.ActualName = MaxFunctionDefiningBranchesParameter.Name;
352      }
353    }
354    #endregion
355  }
356}
Note: See TracBrowser for help on using the repository browser.