Free cookie consent management tool by TermsFeed Policy Generator

source: branches/BottomUpTreeEvaluation/BakedTreeEvaluator.cs @ 330

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

small improvements

File size: 13.9 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;
29using System.Runtime.InteropServices;
30
31namespace HeuristicLab.Functions {
32  internal static class BakedTreeEvaluator {
33    private const int MAX_TREE_SIZE = 128;
34    private const int MAX_TREE_DEPTH = 20;
35    private class Instr {
36      public double result;
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
44    private static int[] nInstr;
45    private static Instr[] variables;
46    private static int variablesCount;
47    private static Instr[] evaluationTable;
48    private static Dataset dataset;
49    private static int sampleIndex;
50
51
52    static BakedTreeEvaluator() {
53      variables = new Instr[100];
54      evaluationTable = new Instr[MAX_TREE_SIZE* MAX_TREE_DEPTH];
55      nInstr = new int[MAX_TREE_DEPTH];
56      for(int j = 0; j < MAX_TREE_DEPTH; j++) {
57        for(int i = 0; i < MAX_TREE_SIZE; i++) {
58          evaluationTable[j*MAX_TREE_SIZE+i] = new Instr();
59        }
60      }
61    }
62
63    public static void ResetEvaluator(List<LightWeightFunction> linearRepresentation) {
64      int length;
65      variablesCount = 0;
66      for(int i = 0; i < MAX_TREE_DEPTH; i++) nInstr[i] = 0;
67      //TranslateToInstr(0, linearRepresentation, out length);
68      int[] heights = new int[linearRepresentation.Count];
69      CalcHeights(linearRepresentation, heights, 0, out length);
70      TranslateToTable(0, linearRepresentation, heights);
71    }
72
73    private static int CalcHeights(List<LightWeightFunction> linearRepresentation, int[] heights, int p, out int branchLength) {
74      if(linearRepresentation[p].arity == 0) {
75        heights[p] = 1;
76        branchLength = 1;
77        return 1;
78      }
79      int height = 0;
80      int length = 1;
81      for(int i = 0; i < linearRepresentation[p].arity; i++) {
82        int curBranchLength;
83        int curHeight = CalcHeights(linearRepresentation, heights, p + length, out curBranchLength);
84        if(curHeight > height) {
85          height = curHeight;
86        }
87        length += curBranchLength;
88      }
89      heights[p] = height + 1;
90      branchLength = length;
91      return height + 1;
92    }
93
94    private static int TranslateToTable(int pos, List<LightWeightFunction> list, int[] heights) {
95      LightWeightFunction f = list[pos];
96      if(f.arity == 0) {
97        Instr instr = evaluationTable[nInstr[0]];
98        instr.symbol = EvaluatorSymbolTable.MapFunction(f.functionType);
99        switch(instr.symbol) {
100          case EvaluatorSymbolTable.VARIABLE: {
101              instr.i_arg0 = (int)f.data[0]; // var
102              instr.d_arg0 = f.data[1]; // weight
103              instr.i_arg1 = (int)f.data[2]; // sample-offset
104              variables[variablesCount++] = instr;
105              break;
106            }
107          case EvaluatorSymbolTable.CONSTANT: {
108              instr.result = f.data[0]; // value
109              break;
110            }
111        }
112        nInstr[0]++;
113        return 1;
114      } else {
115        int length = 1;
116        int height = heights[pos];
117        for(int i = 0; i < f.arity; i++) {
118          int curBranchHeight = heights[pos + length];
119          if(curBranchHeight < height - 1) {
120            for(int j = curBranchHeight; j < height - 1; j++) {
121              evaluationTable[nInstr[j]+ j*MAX_TREE_SIZE].symbol = EvaluatorSymbolTable.IDENTITY;
122              nInstr[j]++;
123            }
124          }
125          int curBranchLength = TranslateToTable(pos + length, list, heights);
126          length += curBranchLength;
127        }
128
129        Instr cell = evaluationTable[nInstr[height - 1]+MAX_TREE_SIZE*( height - 1)];
130        nInstr[height - 1]++;
131        cell.arity = f.arity;
132        cell.symbol = EvaluatorSymbolTable.MapFunction(f.functionType);
133        return length;
134      }
135    }
136
137
138    //private static int TranslateToInstr(int pos, List<LightWeightFunction> linearRepresentation, out int branchLength) {
139    //  int height = 0;
140    //  int length = 1;
141    //  LightWeightFunction f = linearRepresentation[pos];
142    //  for(int i = 0; i < f.arity; i++) {
143    //    int curBranchLength;
144    //    int curBranchHeight = TranslateToInstr(pos + length, linearRepresentation, out curBranchLength);
145    //    if(curBranchHeight > height) height = curBranchHeight;
146    //    length += curBranchLength;
147    //  }
148    //  Instr instr = evaluationTable[nInstr[height], height];
149    //  instr.arity = f.arity;
150    //  instr.symbol = EvaluatorSymbolTable.MapFunction(f.functionType);
151    //  switch(instr.symbol) {
152    //    case EvaluatorSymbolTable.VARIABLE: {
153    //        instr.i_arg0 = (int)f.data[0]; // var
154    //        instr.d_arg0 = f.data[1]; // weight
155    //        instr.i_arg1 = (int)f.data[2]; // sample-offset
156    //        break;
157    //      }
158    //    case EvaluatorSymbolTable.CONSTANT: {
159    //        instr.result = f.data[0]; // value
160    //        break;
161    //      }
162    //  }
163    //  nInstr[height]++;
164    //  branchLength = length;
165    //  return height + 1;
166    //}
167
168    internal static double Evaluate(Dataset dataset, int sampleIndex) {
169      BakedTreeEvaluator.sampleIndex = sampleIndex;
170      BakedTreeEvaluator.dataset = dataset;
171      return EvaluateTable();
172    }
173
174    private static double EvaluateTable() {
175      for(int i = 0; i < variablesCount; i++) {
176        Instr curInstr = variables[i];
177        int row = sampleIndex + curInstr.i_arg1;
178        if(row < 0 || row >= dataset.Rows) curInstr.result = double.NaN;
179        else curInstr.result = curInstr.d_arg0 * dataset.GetValue(row, curInstr.i_arg0);
180      }
181      int curLevel = 1;
182      int lastLayerInstrP = 0;
183      int curLayerOffset = MAX_TREE_SIZE;
184      while(nInstr[curLevel] > 0) {
185        for(int curLayerInstrP = 0; curLayerInstrP < nInstr[curLevel]; curLayerInstrP++) {
186          Instr curInstr = evaluationTable[curLayerInstrP+curLayerOffset];
187          switch(curInstr.symbol) {
188            case EvaluatorSymbolTable.MULTIPLICATION: {
189                curInstr.result = evaluationTable[lastLayerInstrP++].result;
190                for(int i = 1; i < curInstr.arity; i++) {
191                  curInstr.result *= evaluationTable[lastLayerInstrP++].result;
192                }
193                break;
194              }
195            case EvaluatorSymbolTable.ADDITION: {
196                curInstr.result = evaluationTable[lastLayerInstrP++].result;
197                for(int i = 1; i < curInstr.arity; i++) {
198                  curInstr.result += evaluationTable[lastLayerInstrP++].result;
199                }
200                break;
201              }
202            case EvaluatorSymbolTable.SUBTRACTION: {
203                if(curInstr.arity == 1) {
204                  curInstr.result = -evaluationTable[lastLayerInstrP++].result;
205                } else {
206                  curInstr.result = evaluationTable[lastLayerInstrP++].result;
207                  for(int i = 1; i < curInstr.arity; i++) {
208                    curInstr.result -= evaluationTable[lastLayerInstrP++].result;
209                  }
210                }
211                break;
212              }
213            case EvaluatorSymbolTable.DIVISION: {
214                if(curInstr.arity == 1) {
215                  curInstr.result = 1.0 / evaluationTable[lastLayerInstrP++].result;
216                } else {
217                  curInstr.result = evaluationTable[lastLayerInstrP++].result;
218                  for(int i = 1; i < curInstr.arity; i++) {
219                    curInstr.result /= evaluationTable[lastLayerInstrP++].result;
220                  }
221                }
222                if(double.IsInfinity(curInstr.result)) curInstr.result = 0.0;
223                break;
224              }
225            case EvaluatorSymbolTable.AVERAGE: {
226                curInstr.result = evaluationTable[lastLayerInstrP++].result;
227                for(int i = 1; i < curInstr.arity; i++) {
228                  curInstr.result += evaluationTable[lastLayerInstrP++].result;
229                }
230                curInstr.result /= curInstr.arity;
231                break;
232              }
233            case EvaluatorSymbolTable.COSINUS: {
234                curInstr.result = Math.Cos(evaluationTable[lastLayerInstrP++].result);
235                break;
236              }
237            case EvaluatorSymbolTable.SINUS: {
238                curInstr.result = Math.Sin(evaluationTable[lastLayerInstrP++].result);
239                break;
240              }
241            case EvaluatorSymbolTable.EXP: {
242                curInstr.result = Math.Exp(evaluationTable[lastLayerInstrP++].result);
243                break;
244              }
245            case EvaluatorSymbolTable.LOG: {
246                curInstr.result = Math.Log(evaluationTable[lastLayerInstrP++].result);
247                break;
248              }
249            case EvaluatorSymbolTable.POWER: {
250                double x = evaluationTable[lastLayerInstrP++].result;
251                double p = evaluationTable[lastLayerInstrP++].result;
252                curInstr.result = Math.Pow(x, p);
253                break;
254              }
255            case EvaluatorSymbolTable.SIGNUM: {
256                double value = evaluationTable[lastLayerInstrP++].result;
257                if(double.IsNaN(value)) curInstr.result = double.NaN;
258                else curInstr.result = Math.Sign(value);
259                break;
260              }
261            case EvaluatorSymbolTable.SQRT: {
262                curInstr.result = Math.Sqrt(evaluationTable[lastLayerInstrP++].result);
263                break;
264              }
265            case EvaluatorSymbolTable.TANGENS: {
266                curInstr.result = Math.Tan(evaluationTable[lastLayerInstrP++].result);
267                break;
268              }
269            //case EvaluatorSymbolTable.AND: {
270            //    double result = 1.0;
271            //    // have to evaluate all sub-trees, skipping would probably not lead to a big gain because
272            //    // we have to iterate over the linear structure anyway
273            //    for(int i = 0; i < currInstr.arity; i++) {
274            //      double x = Math.Round(EvaluateBakedCode());
275            //      if(x == 0 || x == 1.0) result *= x;
276            //      else result = double.NaN;
277            //    }
278            //    return result;
279            //  }
280            //case EvaluatorSymbolTable.EQU: {
281            //    double x = EvaluateBakedCode();
282            //    double y = EvaluateBakedCode();
283            //    if(x == y) return 1.0; else return 0.0;
284            //  }
285            //case EvaluatorSymbolTable.GT: {
286            //    double x = EvaluateBakedCode();
287            //    double y = EvaluateBakedCode();
288            //    if(x > y) return 1.0;
289            //    else return 0.0;
290            //  }
291            //case EvaluatorSymbolTable.IFTE: {
292            //    double condition = Math.Round(EvaluateBakedCode());
293            //    double x = EvaluateBakedCode();
294            //    double y = EvaluateBakedCode();
295            //    if(condition < .5) return x;
296            //    else if(condition >= .5) return y;
297            //    else return double.NaN;
298            //  }
299            //case EvaluatorSymbolTable.LT: {
300            //    double x = EvaluateBakedCode();
301            //    double y = EvaluateBakedCode();
302            //    if(x < y) return 1.0;
303            //    else return 0.0;
304            //  }
305            //case EvaluatorSymbolTable.NOT: {
306            //    double result = Math.Round(EvaluateBakedCode());
307            //    if(result == 0.0) return 1.0;
308            //    else if(result == 1.0) return 0.0;
309            //    else return double.NaN;
310            //  }
311            //case EvaluatorSymbolTable.OR: {
312            //    double result = 0.0; // default is false
313            //    for(int i = 0; i < currInstr.arity; i++) {
314            //      double x = Math.Round(EvaluateBakedCode());
315            //      if(x == 1.0 && result == 0.0) result = 1.0; // found first true (1.0) => set to true
316            //      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)
317            //    }
318            //    return result;
319            //  }
320            //case EvaluatorSymbolTable.XOR: {
321            //    double x = Math.Round(EvaluateBakedCode());
322            //    double y = Math.Round(EvaluateBakedCode());
323            //    if(x == 0.0 && y == 0.0) return 0.0;
324            //    if(x == 1.0 && y == 0.0) return 1.0;
325            //    if(x == 0.0 && y == 1.0) return 1.0;
326            //    if(x == 1.0 && y == 1.0) return 0.0;
327            //    return double.NaN;
328            //  }
329            case EvaluatorSymbolTable.IDENTITY: {
330                curInstr.result = evaluationTable[lastLayerInstrP++].result;
331                break;
332              }
333            default: {
334                throw new NotImplementedException();
335              }
336          }
337        }
338        curLevel++;
339        lastLayerInstrP = curLayerOffset;
340        curLayerOffset += MAX_TREE_SIZE;
341      }
342      return evaluationTable[lastLayerInstrP].result;
343    }
344  }
345}
Note: See TracBrowser for help on using the repository browser.