Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Functions/BakedTreeEvaluator.cs @ 477

Last change on this file since 477 was 477, checked in by gkronber, 16 years ago

fixed a bug in the function-tree evaluator. trees that contained Differential terminal symbols were evaluated incorrectly.

File size: 8.6 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.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.DataAnalysis;
27using HeuristicLab.Core;
28using System.Xml;
29using System.Diagnostics;
30
31namespace HeuristicLab.Functions {
32  internal class BakedTreeEvaluator : IEvaluator {
33    private const int MAX_TREE_SIZE = 4096;
34    private const double EPSILON = 1.0e-7;
35
36    private class Instr {
37      public double d_arg0;
38      public int i_arg0;
39      public int i_arg1;
40      public int arity;
41      public int symbol;
42    }
43
44    private Instr[] codeArr;
45    private int PC;
46    private Dataset dataset;
47    private int sampleIndex;
48
49
50    public BakedTreeEvaluator(Dataset dataset) {
51      this.dataset = dataset;
52      codeArr = new Instr[MAX_TREE_SIZE];
53      for(int i = 0; i < MAX_TREE_SIZE; i++) {
54        codeArr[i] = new Instr();
55      }
56    }
57
58    public void ResetEvaluator(IFunctionTree functionTree) {
59      List<LightWeightFunction> linearRepresentation = ((BakedFunctionTree)functionTree).LinearRepresentation;
60      int i = 0;
61      foreach(LightWeightFunction f in linearRepresentation) {
62        TranslateToInstr(f, codeArr[i++]);
63      }
64    }
65
66    private Instr TranslateToInstr(LightWeightFunction f, Instr instr) {
67      instr.arity = f.arity;
68      instr.symbol = EvaluatorSymbolTable.MapFunction(f.functionType);
69      switch(instr.symbol) {
70        case EvaluatorSymbolTable.DIFFERENTIAL:
71        case EvaluatorSymbolTable.VARIABLE: {
72            instr.i_arg0 = (int)f.data[0]; // var
73            instr.d_arg0 = f.data[1]; // weight
74            instr.i_arg1 = (int)f.data[2]; // sample-offset
75            break;
76          }
77        case EvaluatorSymbolTable.CONSTANT: {
78            instr.d_arg0 = f.data[0]; // value
79            break;
80          }
81      }
82      return instr;
83    }
84
85    public double Evaluate(int sampleIndex) {
86      PC = 0;
87      this.sampleIndex = sampleIndex;
88      return EvaluateBakedCode();
89    }
90
91    private double EvaluateBakedCode() {
92      Instr currInstr = codeArr[PC++];
93      switch(currInstr.symbol) {
94        case EvaluatorSymbolTable.VARIABLE: {
95            int row = sampleIndex + currInstr.i_arg1;
96            if(row < 0 || row >= dataset.Rows) return double.NaN;
97            else return currInstr.d_arg0 * dataset.GetValue(row, currInstr.i_arg0);
98          }
99        case EvaluatorSymbolTable.CONSTANT: {
100            return currInstr.d_arg0;
101          }
102        case EvaluatorSymbolTable.DIFFERENTIAL: {
103            int row = sampleIndex + currInstr.i_arg1;
104            if(row < 1 || row >= dataset.Rows) return double.NaN;
105            else return currInstr.d_arg0 * (dataset.GetValue(row, currInstr.i_arg0) - dataset.GetValue(row - 1, currInstr.i_arg0));
106          }
107        case EvaluatorSymbolTable.MULTIPLICATION: {
108            double result = EvaluateBakedCode();
109            for(int i = 1; i < currInstr.arity; i++) {
110              result *= EvaluateBakedCode();
111            }
112            return result;
113          }
114        case EvaluatorSymbolTable.ADDITION: {
115            double sum = EvaluateBakedCode();
116            for(int i = 1; i < currInstr.arity; i++) {
117              sum += EvaluateBakedCode();
118            }
119            return sum;
120          }
121        case EvaluatorSymbolTable.SUBTRACTION: {
122            if(currInstr.arity == 1) {
123              return -EvaluateBakedCode();
124            } else {
125              double result = EvaluateBakedCode();
126              for(int i = 1; i < currInstr.arity; i++) {
127                result -= EvaluateBakedCode();
128              }
129              return result;
130            }
131          }
132        case EvaluatorSymbolTable.DIVISION: {
133            double result;
134            if(currInstr.arity == 1) {
135              result = 1.0 / EvaluateBakedCode();
136            } else {
137              result = EvaluateBakedCode();
138              for(int i = 1; i < currInstr.arity; i++) {
139                result /= EvaluateBakedCode();
140              }
141            }
142            if(double.IsInfinity(result)) return 0.0;
143            else return result;
144          }
145        case EvaluatorSymbolTable.AVERAGE: {
146            double sum = EvaluateBakedCode();
147            for(int i = 1; i < currInstr.arity; i++) {
148              sum += EvaluateBakedCode();
149            }
150            return sum / currInstr.arity;
151          }
152        case EvaluatorSymbolTable.COSINUS: {
153            return Math.Cos(EvaluateBakedCode());
154          }
155        case EvaluatorSymbolTable.SINUS: {
156            return Math.Sin(EvaluateBakedCode());
157          }
158        case EvaluatorSymbolTable.EXP: {
159            return Math.Exp(EvaluateBakedCode());
160          }
161        case EvaluatorSymbolTable.LOG: {
162            return Math.Log(EvaluateBakedCode());
163          }
164        case EvaluatorSymbolTable.POWER: {
165            double x = EvaluateBakedCode();
166            double p = EvaluateBakedCode();
167            return Math.Pow(x, p);
168          }
169        case EvaluatorSymbolTable.SIGNUM: {
170            double value = EvaluateBakedCode();
171            if(double.IsNaN(value)) return double.NaN;
172            else return Math.Sign(value);
173          }
174        case EvaluatorSymbolTable.SQRT: {
175            return Math.Sqrt(EvaluateBakedCode());
176          }
177        case EvaluatorSymbolTable.TANGENS: {
178            return Math.Tan(EvaluateBakedCode());
179          }
180        case EvaluatorSymbolTable.AND: { // only defined for inputs 1 and 0
181            double result = 1.0;
182            // have to evaluate all sub-trees, skipping would probably not lead to a big gain because
183            // we have to iterate over the linear structure anyway
184            for(int i = 0; i < currInstr.arity; i++) {
185              double x = EvaluateBakedCode();
186              Debug.Assert(x == 0.0 || x == 1.0);
187              result *= x;
188            }
189            return result;
190          }
191        case EvaluatorSymbolTable.EQU: {
192            double x = EvaluateBakedCode();
193            double y = EvaluateBakedCode();
194            if(Math.Abs(x - y) < EPSILON) return 1.0; else return 0.0;
195          }
196        case EvaluatorSymbolTable.GT: {
197            double x = EvaluateBakedCode();
198            double y = EvaluateBakedCode();
199            if(x > y) return 1.0;
200            else return 0.0;
201          }
202        case EvaluatorSymbolTable.IFTE: { // only defined for condition 0 or 1
203            double condition = EvaluateBakedCode();
204            Debug.Assert(condition == 0.0 || condition == 1.0);
205            double x = EvaluateBakedCode();
206            double y = EvaluateBakedCode();
207            return condition * y - (condition - 1) * x;
208          }
209        case EvaluatorSymbolTable.LT: {
210            double x = EvaluateBakedCode();
211            double y = EvaluateBakedCode();
212            if(x < y) return 1.0;
213            else return 0.0;
214          }
215        case EvaluatorSymbolTable.NOT: { // only defined for inputs 0 or 1
216            double result = EvaluateBakedCode();
217            Debug.Assert(result == 0.0 || result == 1.0);
218            return Math.Abs(result - 1.0);
219          }
220        case EvaluatorSymbolTable.OR: { // only defined for inputs 0 or 1
221            double result = 0.0; // default is false
222            for(int i = 0; i < currInstr.arity; i++) {
223              double x = EvaluateBakedCode();
224              Debug.Assert(x == 0.0 || x == 1.0);
225              result += x;
226            }
227            return Math.Sign(result);
228          }
229        case EvaluatorSymbolTable.XOR: { // only defined for inputs 0 or 1
230            double x = EvaluateBakedCode();
231            double y = EvaluateBakedCode();
232            return Math.Abs(x - y);
233          }
234        default: {
235            throw new NotImplementedException();
236          }
237      }
238    }
239  }
240}
Note: See TracBrowser for help on using the repository browser.