Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 381 was 365, checked in by gkronber, 17 years ago

implemented #195

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