Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 329 was 322, checked in by gkronber, 17 years ago

made evaluator static (related to ticket #168)

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