Free cookie consent management tool by TermsFeed Policy Generator

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

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