Free cookie consent management tool by TermsFeed Policy Generator

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

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

fixed ticket #205 by creating the function-specific evaluator in the evaluation operators.

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