1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022013 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 


22  using System;


23  using System.Drawing;


24  using HeuristicLab.Common;


25  using HeuristicLab.Core;


26  using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;


27  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;


28 


29  namespace HeuristicLab.Problems.DataAnalysis.Symbolic {


30  /// <summary>


31  /// Abstract base class for symbolic data analysis models


32  /// </summary>


33  [StorableClass]


34  public abstract class SymbolicDataAnalysisModel : NamedItem, ISymbolicDataAnalysisModel {


35  public static new Image StaticItemImage {


36  get { return HeuristicLab.Common.Resources.VSImageLibrary.Function; }


37  }


38 


39  #region properties


40 


41  [Storable]


42  private ISymbolicExpressionTree symbolicExpressionTree;


43  public ISymbolicExpressionTree SymbolicExpressionTree {


44  get { return symbolicExpressionTree; }


45  }


46 


47  [Storable]


48  private ISymbolicDataAnalysisExpressionTreeInterpreter interpreter;


49  public ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter {


50  get { return interpreter; }


51  }


52 


53  #endregion


54 


55  [StorableConstructor]


56  protected SymbolicDataAnalysisModel(bool deserializing) : base(deserializing) { }


57  protected SymbolicDataAnalysisModel(SymbolicDataAnalysisModel original, Cloner cloner)


58  : base(original, cloner) {


59  this.symbolicExpressionTree = cloner.Clone(original.symbolicExpressionTree);


60  this.interpreter = cloner.Clone(original.interpreter);


61  }


62  public SymbolicDataAnalysisModel(ISymbolicExpressionTree tree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter)


63  : base() {


64  this.name = ItemName;


65  this.description = ItemDescription;


66  this.symbolicExpressionTree = tree;


67  this.interpreter = interpreter;


68  }


69 


70  #region Scaling


71  protected void Scale(IDataAnalysisProblemData problemData, string targetVariable) {


72  var dataset = problemData.Dataset;


73  var rows = problemData.TrainingIndices;


74  var estimatedValues = Interpreter.GetSymbolicExpressionTreeValues(SymbolicExpressionTree, dataset, rows);


75  var targetValues = dataset.GetDoubleValues(targetVariable, rows);


76 


77  var linearScalingCalculator = new OnlineLinearScalingParameterCalculator();


78  var targetValuesEnumerator = targetValues.GetEnumerator();


79  var estimatedValuesEnumerator = estimatedValues.GetEnumerator();


80  while (targetValuesEnumerator.MoveNext() & estimatedValuesEnumerator.MoveNext()) {


81  double target = targetValuesEnumerator.Current;


82  double estimated = estimatedValuesEnumerator.Current;


83  if (!double.IsNaN(estimated) && !double.IsInfinity(estimated))


84  linearScalingCalculator.Add(estimated, target);


85  }


86  if (linearScalingCalculator.ErrorState == OnlineCalculatorError.None && (targetValuesEnumerator.MoveNext()  estimatedValuesEnumerator.MoveNext()))


87  throw new ArgumentException("Number of elements in target and estimated values enumeration do not match.");


88 


89  double alpha = linearScalingCalculator.Alpha;


90  double beta = linearScalingCalculator.Beta;


91  if (linearScalingCalculator.ErrorState != OnlineCalculatorError.None) return;


92 


93  ConstantTreeNode alphaTreeNode = null;


94  ConstantTreeNode betaTreeNode = null;


95  // check if model has been scaled previously by analyzing the structure of the tree


96  var startNode = SymbolicExpressionTree.Root.GetSubtree(0);


97  if (startNode.GetSubtree(0).Symbol is Addition) {


98  var addNode = startNode.GetSubtree(0);


99  if (addNode.SubtreeCount == 2 && addNode.GetSubtree(0).Symbol is Multiplication && addNode.GetSubtree(1).Symbol is Constant) {


100  alphaTreeNode = addNode.GetSubtree(1) as ConstantTreeNode;


101  var mulNode = addNode.GetSubtree(0);


102  if (mulNode.SubtreeCount == 2 && mulNode.GetSubtree(1).Symbol is Constant) {


103  betaTreeNode = mulNode.GetSubtree(1) as ConstantTreeNode;


104  }


105  }


106  }


107  // if tree structure matches the structure necessary for linear scaling then reuse the existing tree nodes


108  if (alphaTreeNode != null && betaTreeNode != null) {


109  betaTreeNode.Value *= beta;


110  alphaTreeNode.Value *= beta;


111  alphaTreeNode.Value += alpha;


112  } else {


113  var mainBranch = startNode.GetSubtree(0);


114  startNode.RemoveSubtree(0);


115  var scaledMainBranch = MakeSum(MakeProduct(mainBranch, beta), alpha);


116  startNode.AddSubtree(scaledMainBranch);


117  }


118  }


119 


120  private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode treeNode, double alpha) {


121  if (alpha.IsAlmost(0.0)) {


122  return treeNode;


123  } else {


124  var addition = new Addition();


125  var node = addition.CreateTreeNode();


126  var alphaConst = MakeConstant(alpha);


127  node.AddSubtree(treeNode);


128  node.AddSubtree(alphaConst);


129  return node;


130  }


131  }


132 


133  private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode treeNode, double beta) {


134  if (beta.IsAlmost(1.0)) {


135  return treeNode;


136  } else {


137  var multipliciation = new Multiplication();


138  var node = multipliciation.CreateTreeNode();


139  var betaConst = MakeConstant(beta);


140  node.AddSubtree(treeNode);


141  node.AddSubtree(betaConst);


142  return node;


143  }


144  }


145 


146  private static ISymbolicExpressionTreeNode MakeConstant(double c) {


147  var node = (ConstantTreeNode)(new Constant()).CreateTreeNode();


148  node.Value = c;


149  return node;


150  }


151  #endregion


152  }


153  }

