Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 407 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
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 {
[396]31  internal class BakedTreeEvaluator : IEvaluator {
[322]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
[396]42    private Instr[] codeArr;
43    private int PC;
44    private Dataset dataset;
45    private int sampleIndex;
[223]46
[322]47
[396]48    public BakedTreeEvaluator(Dataset dataset) {
49      this.dataset = dataset;
[322]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
[396]56    public void ResetEvaluator(IFunctionTree functionTree) {
57      List<LightWeightFunction> linearRepresentation = ((BakedFunctionTree)functionTree).LinearRepresentation;
[318]58      int i = 0;
59      foreach(LightWeightFunction f in linearRepresentation) {
[322]60        TranslateToInstr(f, codeArr[i++]);
[317]61      }
[223]62    }
63
[396]64    private Instr TranslateToInstr(LightWeightFunction f, Instr instr) {
[318]65      instr.arity = f.arity;
[319]66      instr.symbol = EvaluatorSymbolTable.MapFunction(f.functionType);
[318]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
[396]82    public double Evaluate(int sampleIndex) {
[223]83      PC = 0;
[396]84      this.sampleIndex = sampleIndex;
[223]85      return EvaluateBakedCode();
86    }
87
[396]88    private double EvaluateBakedCode() {
[318]89      Instr currInstr = codeArr[PC++];
90      switch(currInstr.symbol) {
[260]91        case EvaluatorSymbolTable.VARIABLE: {
[318]92            int row = sampleIndex + currInstr.i_arg1;
[227]93            if(row < 0 || row >= dataset.Rows) return double.NaN;
[318]94            else return currInstr.d_arg0 * dataset.GetValue(row, currInstr.i_arg0);
[223]95          }
[260]96        case EvaluatorSymbolTable.CONSTANT: {
[318]97            return currInstr.d_arg0;
[223]98          }
[365]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          }
[260]104        case EvaluatorSymbolTable.MULTIPLICATION: {
[236]105            double result = EvaluateBakedCode();
[318]106            for(int i = 1; i < currInstr.arity; i++) {
[223]107              result *= EvaluateBakedCode();
108            }
109            return result;
110          }
[260]111        case EvaluatorSymbolTable.ADDITION: {
[236]112            double sum = EvaluateBakedCode();
[318]113            for(int i = 1; i < currInstr.arity; i++) {
[223]114              sum += EvaluateBakedCode();
115            }
116            return sum;
117          }
[308]118        case EvaluatorSymbolTable.SUBTRACTION: {
[318]119            if(currInstr.arity == 1) {
[223]120              return -EvaluateBakedCode();
121            } else {
122              double result = EvaluateBakedCode();
[318]123              for(int i = 1; i < currInstr.arity; i++) {
[223]124                result -= EvaluateBakedCode();
125              }
126              return result;
127            }
128          }
[260]129        case EvaluatorSymbolTable.DIVISION: {
[236]130            double result;
[318]131            if(currInstr.arity == 1) {
[236]132              result = 1.0 / EvaluateBakedCode();
[223]133            } else {
[236]134              result = EvaluateBakedCode();
[318]135              for(int i = 1; i < currInstr.arity; i++) {
[236]136                result /= EvaluateBakedCode();
[223]137              }
138            }
[236]139            if(double.IsInfinity(result)) return 0.0;
140            else return result;
[223]141          }
[260]142        case EvaluatorSymbolTable.AVERAGE: {
[236]143            double sum = EvaluateBakedCode();
[318]144            for(int i = 1; i < currInstr.arity; i++) {
[223]145              sum += EvaluateBakedCode();
146            }
[318]147            return sum / currInstr.arity;
[223]148          }
[260]149        case EvaluatorSymbolTable.COSINUS: {
[223]150            return Math.Cos(EvaluateBakedCode());
151          }
[260]152        case EvaluatorSymbolTable.SINUS: {
[223]153            return Math.Sin(EvaluateBakedCode());
154          }
[260]155        case EvaluatorSymbolTable.EXP: {
[223]156            return Math.Exp(EvaluateBakedCode());
157          }
[260]158        case EvaluatorSymbolTable.LOG: {
[223]159            return Math.Log(EvaluateBakedCode());
160          }
[260]161        case EvaluatorSymbolTable.POWER: {
[223]162            double x = EvaluateBakedCode();
163            double p = EvaluateBakedCode();
164            return Math.Pow(x, p);
165          }
[260]166        case EvaluatorSymbolTable.SIGNUM: {
[223]167            double value = EvaluateBakedCode();
[236]168            if(double.IsNaN(value)) return double.NaN;
169            else return Math.Sign(value);
[223]170          }
[260]171        case EvaluatorSymbolTable.SQRT: {
[223]172            return Math.Sqrt(EvaluateBakedCode());
173          }
[260]174        case EvaluatorSymbolTable.TANGENS: {
[223]175            return Math.Tan(EvaluateBakedCode());
176          }
[260]177        case EvaluatorSymbolTable.AND: {
[223]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
[318]181            for(int i = 0; i < currInstr.arity; i++) {
[223]182              double x = Math.Round(EvaluateBakedCode());
[259]183              if(x == 0 || x == 1.0) result *= x;
[236]184              else result = double.NaN;
[223]185            }
186            return result;
187          }
[260]188        case EvaluatorSymbolTable.EQU: {
[223]189            double x = EvaluateBakedCode();
190            double y = EvaluateBakedCode();
191            if(x == y) return 1.0; else return 0.0;
192          }
[260]193        case EvaluatorSymbolTable.GT: {
[223]194            double x = EvaluateBakedCode();
195            double y = EvaluateBakedCode();
196            if(x > y) return 1.0;
197            else return 0.0;
198          }
[260]199        case EvaluatorSymbolTable.IFTE: {
[223]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          }
[260]207        case EvaluatorSymbolTable.LT: {
[223]208            double x = EvaluateBakedCode();
209            double y = EvaluateBakedCode();
210            if(x < y) return 1.0;
211            else return 0.0;
212          }
[260]213        case EvaluatorSymbolTable.NOT: {
[223]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          }
[260]219        case EvaluatorSymbolTable.OR: {
[223]220            double result = 0.0; // default is false
[318]221            for(int i = 0; i < currInstr.arity; i++) {
[223]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          }
[260]228        case EvaluatorSymbolTable.XOR: {
[223]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: {
[318]238            throw new NotImplementedException();
[223]239          }
240      }
241    }
242  }
243}
Note: See TracBrowser for help on using the repository browser.