Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 449 was 424, checked in by gkronber, 16 years ago

worked on #223 (Recheck and improve evaluation of boolean functions and conditionals)

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