Free cookie consent management tool by TermsFeed Policy Generator

source: branches/DataAnalysis/HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression/3.3/Symbolic/Evaluators/PartialSymbolicDifferential.cs @ 10764

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

Added new files for data analysis feature exploration. #1142

File size: 11.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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.Diagnostics;
24using HeuristicLab.Common;
25using System.Linq;
26
27using System.Collections.Generic;
28using HeuristicLab.Problems.DataAnalysis.Symbolic.Symbols;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Symbols;
30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; // double.IsAlmost extension
31
32namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression.Symbolic.Evaluators {
33  public static class PartialSymbolicDifferential {
34    private static readonly DifferentialVariable differential = new DifferentialVariable();
35    private static readonly Constant @const = new Constant();
36    private static readonly ConstantTreeNode const0 = new ConstantTreeNode(@const);
37    private static readonly ConstantTreeNode const1 = new ConstantTreeNode(@const);
38    private static readonly Symbol addition = new Addition();
39    private static readonly Symbol subtraction = new Subtraction();
40    private static readonly Symbol multiplication = new Multiplication();
41    private static readonly Symbol division = new Division();
42    //private static readonly Symbol power = new Power();
43    private static readonly Symbol exp = new Exponential();
44    private static readonly Symbol ln = new Logarithm();
45    private static readonly Symbol cos = new Cosine();
46    private static readonly Symbol sin = new Sine();
47    private static readonly Symbol tan = new Tangent();
48
49    static PartialSymbolicDifferential() {
50      const0.Value = 0.0;
51      const1.Value = 1.0;
52    }
53
54    public static SymbolicExpressionTreeNode Apply(SymbolicExpressionTreeNode expression, string variableName, params string[] interdependentVariable) {
55      Symbol symbol = expression.Symbol;
56      if (symbol is Variable) {
57        var variable = (VariableTreeNode)expression;
58        if (variable.VariableName == variableName) return MakeConstant(variable.Weight);
59        else if (interdependentVariable.Contains(variable.VariableName)) {
60          return MakeProduct(MakeConstant(variable.Weight), MakeDivision(MakeDifferential(1.0, variable.VariableName), MakeDifferential(1.0, variableName)));
61        } else return const0;
62      } else if (symbol is Constant) {
63        return const0;
64      } else if (symbol is Addition) {
65        var sum = addition.CreateTreeNode();
66        foreach (var subExp in expression.SubTrees) {
67          sum.AddSubTree(Apply(subExp, variableName, interdependentVariable));
68        }
69        return sum;
70      } else if (symbol is Subtraction) {
71        var diff = subtraction.CreateTreeNode();
72        foreach (var subExp in expression.SubTrees) {
73          diff.AddSubTree(Apply(subExp, variableName, interdependentVariable));
74        }
75        return diff;
76
77      } else if (symbol is Multiplication) {
78        if (expression.SubTrees.Count() == 1) return Apply(expression.SubTrees[0], variableName, interdependentVariable);
79        SymbolicExpressionTreeNode sum = const0;
80
81        for (int i = 0; i < expression.SubTrees.Count; i++) {
82          SymbolicExpressionTreeNode prod = const1;
83
84          for (int j = 0; j < expression.SubTrees.Count; j++) {
85            if (j != i)
86              prod = MakeProduct(prod, expression.SubTrees[j]);
87            else
88              prod = MakeProduct(prod, Apply(expression.SubTrees[j], variableName, interdependentVariable));
89          }
90          sum = MakeSum(sum, prod);
91        }
92        return sum;
93      } else if (symbol is Division) {
94        // u/v  (v*du/dx-u*dv/dx)/v^2
95        if (expression.SubTrees.Count == 1) {
96          SymbolicExpressionTreeNode v = expression.SubTrees[0];
97          SymbolicExpressionTreeNode dv = Apply(v, variableName, interdependentVariable);
98          return MakeDifference(const1, MakeDivision(dv, MakeSqr(v)));
99        } else if (expression.SubTrees.Count == 2) {
100          SymbolicExpressionTreeNode u = expression.SubTrees[0];
101          SymbolicExpressionTreeNode v = expression.SubTrees[1];
102          SymbolicExpressionTreeNode du = Apply(u, variableName, interdependentVariable);
103          SymbolicExpressionTreeNode dv = Apply(v, variableName, interdependentVariable);
104          u = MakeDivision(MakeDifference(MakeProduct(v, du), MakeProduct(u, dv)), MakeSqr(v));
105          for (int i = 2; i < expression.SubTrees.Count; i++) {
106            v = expression.SubTrees[i];
107            dv = Apply(v, variableName, interdependentVariable);
108            du = Apply(u, variableName, interdependentVariable);
109            u = MakeDivision(MakeDifference(MakeProduct(v, du), MakeProduct(u, dv)), MakeSqr(v));
110          }
111          return u;
112        } else throw new NotSupportedException("Derivative of division with arity " + expression.SubTrees.Count + " is not supported.");
113      } else if (symbol is Exponential) {
114        // e^u  e^u*du/dx
115        return MakeProduct(MakeExp(expression.SubTrees[0]), Apply(expression.SubTrees[0], variableName, interdependentVariable));
116      } else if (symbol is Logarithm) {
117        return MakeProduct(MakeDivision(const1, expression.SubTrees[0]), Apply(expression.SubTrees[0], variableName, interdependentVariable));
118      }
119        //case EvaluatorSymbolTable.POWER: {
120        //    var a = expression.SubTrees[0];
121        //    var b = expression.SubTrees[1];
122        //    return Apply(MakeExp(MakeProduct(b, MakeLn(a))), variableName, interdependentVariable);
123        //  }
124        //case EvaluatorSymbolTable.SIGNUM: {
125        //    return const0;
126        //  }
127        else if (symbol is Sine) {
128        return MakeProduct(MakeCos(expression.SubTrees[0]), Apply(expression.SubTrees[0], variableName, interdependentVariable));
129      } else if (symbol is Cosine) {
130        return MakeProduct(MakeNegSin(expression.SubTrees[0]), Apply(expression.SubTrees[0], variableName, interdependentVariable));
131      } else if (symbol is Tangent) {
132        return MakeProduct(MakeSum(const1, MakeTanSqr(expression.SubTrees[0])), Apply(expression.SubTrees[0], variableName, interdependentVariable));
133      }
134        //else if(symbol is Sqrt) {
135        //      var powTree = new FunctionTreeBase(power);
136        //      powTree.AddSubTree(expression.SubTrees[0]);
137        //      powTree.AddSubTree(MakeConstant(0.5));
138        //      return Apply(powTree, variableName, interdependentVariable);
139        //    }
140      else if (symbol is ProgramRootSymbol) {
141        var branch = Apply(expression.SubTrees[0], variableName, interdependentVariable);
142        expression.RemoveSubTree(0);
143        expression.InsertSubTree(0, branch);
144        return expression;
145      } else if (symbol is StartSymbol) {
146        var branch = Apply(expression.SubTrees[0], variableName, interdependentVariable);
147        expression.RemoveSubTree(0);
148        expression.InsertSubTree(0, branch);
149        return expression;
150      } else {
151        throw new NotImplementedException();
152      }
153    }
154
155    private static SymbolicExpressionTreeNode MakeDifferential(double c, string v) {
156      DifferentialVariableTreeNode diffTree = (DifferentialVariableTreeNode)differential.CreateTreeNode();
157      diffTree.VariableName = v;
158      diffTree.Weight = c;
159      return diffTree;
160    }
161
162    private static SymbolicExpressionTreeNode MakeTanSqr(SymbolicExpressionTreeNode expression) {
163      var tanTree1 = tan.CreateTreeNode();
164      var tanTree2 = tan.CreateTreeNode();
165      tanTree2.AddSubTree(expression);
166      tanTree1.AddSubTree(tanTree2);
167      return tanTree1;
168    }
169
170    private static SymbolicExpressionTreeNode MakeNegSin(SymbolicExpressionTreeNode expression) {
171      var sinTree = sin.CreateTreeNode();
172      sinTree.AddSubTree(expression);
173      return MakeDifference(const0, sinTree);
174    }
175
176    private static SymbolicExpressionTreeNode MakeCos(SymbolicExpressionTreeNode expression) {
177      var cosTree = cos.CreateTreeNode();
178      cosTree.AddSubTree(expression);
179      return cosTree;
180    }
181
182    private static SymbolicExpressionTreeNode MakeLn(SymbolicExpressionTreeNode a) {
183      var lnTree = ln.CreateTreeNode();
184      lnTree.AddSubTree(a);
185      return lnTree;
186    }
187
188    private static SymbolicExpressionTreeNode MakeExp(SymbolicExpressionTreeNode expression) {
189      if (IsConstantZero(expression)) return const1;
190      var expTree = exp.CreateTreeNode();
191      expTree.AddSubTree(expression);
192      return expTree;
193    }
194
195    private static SymbolicExpressionTreeNode MakeDivision(SymbolicExpressionTreeNode x, SymbolicExpressionTreeNode y) {
196      if (IsConstantZero(x)) return const0;
197      var div = division.CreateTreeNode();
198      div.AddSubTree(x);
199      div.AddSubTree(y);
200      return div;
201    }
202
203    private static SymbolicExpressionTreeNode MakeSqr(SymbolicExpressionTreeNode x) {
204      var sqr = multiplication.CreateTreeNode();
205      sqr.AddSubTree(x);
206      sqr.AddSubTree((SymbolicExpressionTreeNode)x.Clone());
207      return sqr;
208    }
209
210    private static SymbolicExpressionTreeNode MakeProduct(SymbolicExpressionTreeNode x, SymbolicExpressionTreeNode y) {
211      if (IsConstantZero(x) || IsConstantZero(y)) {
212        return const0;
213      } else if (IsConstantOne(x)) return y;
214      else if (IsConstantOne(y)) return x;
215      var product = multiplication.CreateTreeNode();
216      product.AddSubTree(x);
217      product.AddSubTree(y);
218      return product;
219    }
220
221    private static bool IsConstantOne(SymbolicExpressionTreeNode x) {
222      return x == const1;
223    }
224
225    private static bool IsConstantZero(SymbolicExpressionTreeNode x) {
226      return x == const0;
227    }
228
229    private static SymbolicExpressionTreeNode MakeSum(SymbolicExpressionTreeNode a, SymbolicExpressionTreeNode b) {
230      if (IsConstantZero(a) && IsConstantZero(b)) return const0;
231      else if (IsConstantZero(a)) return b;
232      else if (IsConstantZero(b)) return a;
233      var product = addition.CreateTreeNode();
234      product.AddSubTree(a);
235      product.AddSubTree(b);
236      return product;
237    }
238
239    private static SymbolicExpressionTreeNode MakeDifference(SymbolicExpressionTreeNode a, SymbolicExpressionTreeNode b) {
240      if (IsConstantZero(a) && IsConstantZero(b)) return const0;
241      else if (IsConstantZero(b)) return a;
242      var diff = subtraction.CreateTreeNode();
243      diff.AddSubTree(a);
244      diff.AddSubTree(b);
245      return diff;
246    }
247
248    private static SymbolicExpressionTreeNode MakeConstant(double c) {
249      if (c.IsAlmost(1.0)) return const1;
250      else if (c.IsAlmost(0.0)) return const0;
251      var cExp = new ConstantTreeNode(@const);
252      cExp.Value = c;
253      return cExp;
254    }
255  }
256}
Note: See TracBrowser for help on using the repository browser.