Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 644 was 642, checked in by gkronber, 16 years ago

fixed #169 (Possibility to extend the set of available functions for GP via plugins)

File size: 9.2 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;
[424]29using System.Diagnostics;
[223]30
31namespace HeuristicLab.Functions {
[396]32  internal class BakedTreeEvaluator : IEvaluator {
[322]33    private const int MAX_TREE_SIZE = 4096;
[424]34    private const double EPSILON = 1.0e-7;
[322]35
[321]36    private class Instr {
[318]37      public double d_arg0;
38      public int i_arg0;
39      public int i_arg1;
40      public int arity;
41      public int symbol;
[642]42      public IFunction function;
[318]43    }
44
[396]45    private Instr[] codeArr;
46    private int PC;
47    private Dataset dataset;
48    private int sampleIndex;
[223]49
[322]50
[483]51    public BakedTreeEvaluator() {
[322]52      codeArr = new Instr[MAX_TREE_SIZE];
53      for(int i = 0; i < MAX_TREE_SIZE; i++) {
54        codeArr[i] = new Instr();
55      }
56    }
57
[483]58    public void ResetEvaluator(IFunctionTree functionTree, Dataset dataset) {
59      this.dataset = dataset;
[396]60      List<LightWeightFunction> linearRepresentation = ((BakedFunctionTree)functionTree).LinearRepresentation;
[318]61      int i = 0;
62      foreach(LightWeightFunction f in linearRepresentation) {
[322]63        TranslateToInstr(f, codeArr[i++]);
[317]64      }
[223]65    }
66
[396]67    private Instr TranslateToInstr(LightWeightFunction f, Instr instr) {
[318]68      instr.arity = f.arity;
[319]69      instr.symbol = EvaluatorSymbolTable.MapFunction(f.functionType);
[318]70      switch(instr.symbol) {
[523]71        case EvaluatorSymbolTable.DIFFERENTIAL:
[318]72        case EvaluatorSymbolTable.VARIABLE: {
73            instr.i_arg0 = (int)f.data[0]; // var
74            instr.d_arg0 = f.data[1]; // weight
75            instr.i_arg1 = (int)f.data[2]; // sample-offset
76            break;
77          }
78        case EvaluatorSymbolTable.CONSTANT: {
79            instr.d_arg0 = f.data[0]; // value
80            break;
81          }
[642]82        case EvaluatorSymbolTable.UNKNOWN: {
83            instr.function = f.functionType;
84            break;
85          }
[318]86      }
87      return instr;
88    }
89
[396]90    public double Evaluate(int sampleIndex) {
[223]91      PC = 0;
[396]92      this.sampleIndex = sampleIndex;
[223]93      return EvaluateBakedCode();
94    }
95
[523]96    // skips a whole branch
97    private void SkipBakedCode() {
98      int i = 1;
99      while(i > 0) {
[642]100        i += codeArr[PC++].arity;
[523]101        i--;
102      }
103    }
104
[396]105    private double EvaluateBakedCode() {
[318]106      Instr currInstr = codeArr[PC++];
107      switch(currInstr.symbol) {
[260]108        case EvaluatorSymbolTable.VARIABLE: {
[318]109            int row = sampleIndex + currInstr.i_arg1;
[227]110            if(row < 0 || row >= dataset.Rows) return double.NaN;
[318]111            else return currInstr.d_arg0 * dataset.GetValue(row, currInstr.i_arg0);
[223]112          }
[260]113        case EvaluatorSymbolTable.CONSTANT: {
[318]114            return currInstr.d_arg0;
[223]115          }
[365]116        case EvaluatorSymbolTable.DIFFERENTIAL: {
117            int row = sampleIndex + currInstr.i_arg1;
118            if(row < 1 || row >= dataset.Rows) return double.NaN;
119            else return currInstr.d_arg0 * (dataset.GetValue(row, currInstr.i_arg0) - dataset.GetValue(row - 1, currInstr.i_arg0));
120          }
[260]121        case EvaluatorSymbolTable.MULTIPLICATION: {
[236]122            double result = EvaluateBakedCode();
[318]123            for(int i = 1; i < currInstr.arity; i++) {
[223]124              result *= EvaluateBakedCode();
125            }
126            return result;
127          }
[260]128        case EvaluatorSymbolTable.ADDITION: {
[236]129            double sum = EvaluateBakedCode();
[318]130            for(int i = 1; i < currInstr.arity; i++) {
[223]131              sum += EvaluateBakedCode();
132            }
133            return sum;
134          }
[308]135        case EvaluatorSymbolTable.SUBTRACTION: {
[318]136            if(currInstr.arity == 1) {
[223]137              return -EvaluateBakedCode();
138            } else {
139              double result = EvaluateBakedCode();
[318]140              for(int i = 1; i < currInstr.arity; i++) {
[223]141                result -= EvaluateBakedCode();
142              }
143              return result;
144            }
145          }
[260]146        case EvaluatorSymbolTable.DIVISION: {
[236]147            double result;
[318]148            if(currInstr.arity == 1) {
[236]149              result = 1.0 / EvaluateBakedCode();
[223]150            } else {
[236]151              result = EvaluateBakedCode();
[318]152              for(int i = 1; i < currInstr.arity; i++) {
[236]153                result /= EvaluateBakedCode();
[223]154              }
155            }
[236]156            if(double.IsInfinity(result)) return 0.0;
157            else return result;
[223]158          }
[260]159        case EvaluatorSymbolTable.AVERAGE: {
[236]160            double sum = EvaluateBakedCode();
[318]161            for(int i = 1; i < currInstr.arity; i++) {
[223]162              sum += EvaluateBakedCode();
163            }
[318]164            return sum / currInstr.arity;
[223]165          }
[260]166        case EvaluatorSymbolTable.COSINUS: {
[223]167            return Math.Cos(EvaluateBakedCode());
168          }
[260]169        case EvaluatorSymbolTable.SINUS: {
[223]170            return Math.Sin(EvaluateBakedCode());
171          }
[260]172        case EvaluatorSymbolTable.EXP: {
[223]173            return Math.Exp(EvaluateBakedCode());
174          }
[260]175        case EvaluatorSymbolTable.LOG: {
[223]176            return Math.Log(EvaluateBakedCode());
177          }
[260]178        case EvaluatorSymbolTable.POWER: {
[223]179            double x = EvaluateBakedCode();
180            double p = EvaluateBakedCode();
181            return Math.Pow(x, p);
182          }
[260]183        case EvaluatorSymbolTable.SIGNUM: {
[223]184            double value = EvaluateBakedCode();
[236]185            if(double.IsNaN(value)) return double.NaN;
186            else return Math.Sign(value);
[223]187          }
[260]188        case EvaluatorSymbolTable.SQRT: {
[223]189            return Math.Sqrt(EvaluateBakedCode());
190          }
[260]191        case EvaluatorSymbolTable.TANGENS: {
[223]192            return Math.Tan(EvaluateBakedCode());
193          }
[424]194        case EvaluatorSymbolTable.AND: { // only defined for inputs 1 and 0
[523]195            double result = EvaluateBakedCode();
196            for(int i = 1; i < currInstr.arity; i++) {
197              if(result == 0.0) SkipBakedCode();
198              else {
199                result = EvaluateBakedCode();
200              }
201              Debug.Assert(result == 0.0 || result == 1.0);
[223]202            }
203            return result;
204          }
[260]205        case EvaluatorSymbolTable.EQU: {
[223]206            double x = EvaluateBakedCode();
207            double y = EvaluateBakedCode();
[424]208            if(Math.Abs(x - y) < EPSILON) return 1.0; else return 0.0;
[223]209          }
[260]210        case EvaluatorSymbolTable.GT: {
[223]211            double x = EvaluateBakedCode();
212            double y = EvaluateBakedCode();
213            if(x > y) return 1.0;
214            else return 0.0;
215          }
[424]216        case EvaluatorSymbolTable.IFTE: { // only defined for condition 0 or 1
217            double condition = EvaluateBakedCode();
218            Debug.Assert(condition == 0.0 || condition == 1.0);
[523]219            double result;
220            if(condition == 0.0) {
221              result = EvaluateBakedCode(); SkipBakedCode();
222            } else {
223              SkipBakedCode(); result = EvaluateBakedCode();
224            }
225            return result;
[223]226          }
[260]227        case EvaluatorSymbolTable.LT: {
[223]228            double x = EvaluateBakedCode();
229            double y = EvaluateBakedCode();
230            if(x < y) return 1.0;
231            else return 0.0;
232          }
[424]233        case EvaluatorSymbolTable.NOT: { // only defined for inputs 0 or 1
234            double result = EvaluateBakedCode();
235            Debug.Assert(result == 0.0 || result == 1.0);
[460]236            return Math.Abs(result - 1.0);
[223]237          }
[424]238        case EvaluatorSymbolTable.OR: { // only defined for inputs 0 or 1
[523]239            double result = EvaluateBakedCode();
240            for(int i = 1; i < currInstr.arity; i++) {
241              if(result > 0.0) SkipBakedCode();
242              else {
243                result = EvaluateBakedCode();
244                Debug.Assert(result == 0.0 || result == 1.0);
245              }
[223]246            }
[523]247            return result;
[223]248          }
[424]249        case EvaluatorSymbolTable.XOR: { // only defined for inputs 0 or 1
250            double x = EvaluateBakedCode();
251            double y = EvaluateBakedCode();
252            return Math.Abs(x - y);
[223]253          }
[642]254        case EvaluatorSymbolTable.UNKNOWN: { // evaluate functions which are not statically defined directly
255            return currInstr.function.Apply();
256          }
[223]257        default: {
[318]258            throw new NotImplementedException();
[223]259          }
260      }
261    }
262  }
263}
Note: See TracBrowser for help on using the repository browser.