Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 303 was 266, checked in by gkronber, 16 years ago

added missing GPL headers

File size: 8.6 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 : StorableBase {
32    private int[] codeArr;
33    private double[] dataArr;
34    private static EvaluatorSymbolTable symbolTable = EvaluatorSymbolTable.SymbolTable;
35
36    // for persistence mechanism only
37    public BakedTreeEvaluator() {
38    }
39
40    public BakedTreeEvaluator(List<int> code, List<double> data) {
41      codeArr = code.ToArray();
42      dataArr = data.ToArray();
43    }
44
45    private int PC;
46    private int DP;
47    private Dataset dataset;
48    private int sampleIndex;
49
50    internal double Evaluate(Dataset _dataset, int _sampleIndex) {
51      PC = 0;
52      DP = 0;
53      sampleIndex = _sampleIndex;
54      dataset = _dataset;
55      return EvaluateBakedCode();
56    }
57
58    private double EvaluateBakedCode() {
59      int arity = codeArr[PC];
60      int functionSymbol = codeArr[PC + 1];
61      int nLocalVariables = codeArr[PC + 2];
62      PC += 3;
63      switch(functionSymbol) {
64        case EvaluatorSymbolTable.VARIABLE: {
65            int var = (int)dataArr[DP];
66            double weight = dataArr[DP + 1];
67            int row = sampleIndex + (int)dataArr[DP + 2];
68            DP += 3;
69            if(row < 0 || row >= dataset.Rows) return double.NaN;
70            else return weight * dataset.GetValue(row, var);
71          }
72        case EvaluatorSymbolTable.CONSTANT: {
73            return dataArr[DP++];
74          }
75        case EvaluatorSymbolTable.MULTIPLICATION: {
76            double result = EvaluateBakedCode();
77            for(int i = 1; i < arity; i++) {
78              result *= EvaluateBakedCode();
79            }
80            return result;
81          }
82        case EvaluatorSymbolTable.ADDITION: {
83            double sum = EvaluateBakedCode();
84            for(int i = 1; i < arity; i++) {
85              sum += EvaluateBakedCode();
86            }
87            return sum;
88          }
89        case EvaluatorSymbolTable.SUBSTRACTION: {
90            if(arity == 1) {
91              return -EvaluateBakedCode();
92            } else {
93              double result = EvaluateBakedCode();
94              for(int i = 1; i < arity; i++) {
95                result -= EvaluateBakedCode();
96              }
97              return result;
98            }
99          }
100        case EvaluatorSymbolTable.DIVISION: {
101            double result;
102            if(arity == 1) {
103              result = 1.0 / EvaluateBakedCode();
104            } else {
105              result = EvaluateBakedCode();
106              for(int i = 1; i < arity; i++) {
107                result /= EvaluateBakedCode();
108              }
109            }
110            if(double.IsInfinity(result)) return 0.0;
111            else return result;
112          }
113        case EvaluatorSymbolTable.AVERAGE: {
114            double sum = EvaluateBakedCode();
115            for(int i = 1; i < arity; i++) {
116              sum += EvaluateBakedCode();
117            }
118            return sum / arity;
119          }
120        case EvaluatorSymbolTable.COSINUS: {
121            return Math.Cos(EvaluateBakedCode());
122          }
123        case EvaluatorSymbolTable.SINUS: {
124            return Math.Sin(EvaluateBakedCode());
125          }
126        case EvaluatorSymbolTable.EXP: {
127            return Math.Exp(EvaluateBakedCode());
128          }
129        case EvaluatorSymbolTable.LOG: {
130            return Math.Log(EvaluateBakedCode());
131          }
132        case EvaluatorSymbolTable.POWER: {
133            double x = EvaluateBakedCode();
134            double p = EvaluateBakedCode();
135            return Math.Pow(x, p);
136          }
137        case EvaluatorSymbolTable.SIGNUM: {
138            double value = EvaluateBakedCode();
139            if(double.IsNaN(value)) return double.NaN;
140            else return Math.Sign(value);
141          }
142        case EvaluatorSymbolTable.SQRT: {
143            return Math.Sqrt(EvaluateBakedCode());
144          }
145        case EvaluatorSymbolTable.TANGENS: {
146            return Math.Tan(EvaluateBakedCode());
147          }
148        case EvaluatorSymbolTable.AND: {
149            double result = 1.0;
150            // have to evaluate all sub-trees, skipping would probably not lead to a big gain because
151            // we have to iterate over the linear structure anyway
152            for(int i = 0; i < arity; i++) {
153              double x = Math.Round(EvaluateBakedCode());
154              if(x == 0 || x == 1.0) result *= x;
155              else result = double.NaN;
156            }
157            return result;
158          }
159        case EvaluatorSymbolTable.EQU: {
160            double x = EvaluateBakedCode();
161            double y = EvaluateBakedCode();
162            if(x == y) return 1.0; else return 0.0;
163          }
164        case EvaluatorSymbolTable.GT: {
165            double x = EvaluateBakedCode();
166            double y = EvaluateBakedCode();
167            if(x > y) return 1.0;
168            else return 0.0;
169          }
170        case EvaluatorSymbolTable.IFTE: {
171            double condition = Math.Round(EvaluateBakedCode());
172            double x = EvaluateBakedCode();
173            double y = EvaluateBakedCode();
174            if(condition < .5) return x;
175            else if(condition >= .5) return y;
176            else return double.NaN;
177          }
178        case EvaluatorSymbolTable.LT: {
179            double x = EvaluateBakedCode();
180            double y = EvaluateBakedCode();
181            if(x < y) return 1.0;
182            else return 0.0;
183          }
184        case EvaluatorSymbolTable.NOT: {
185            double result = Math.Round(EvaluateBakedCode());
186            if(result == 0.0) return 1.0;
187            else if(result == 1.0) return 0.0;
188            else return double.NaN;
189          }
190        case EvaluatorSymbolTable.OR: {
191            double result = 0.0; // default is false
192            for(int i = 0; i < arity; i++) {
193              double x = Math.Round(EvaluateBakedCode());
194              if(x == 1.0 && result == 0.0) result = 1.0; // found first true (1.0) => set to true
195              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)
196            }
197            return result;
198          }
199        case EvaluatorSymbolTable.XOR: {
200            double x = Math.Round(EvaluateBakedCode());
201            double y = Math.Round(EvaluateBakedCode());
202            if(x == 0.0 && y == 0.0) return 0.0;
203            if(x == 1.0 && y == 0.0) return 1.0;
204            if(x == 0.0 && y == 1.0) return 1.0;
205            if(x == 1.0 && y == 1.0) return 0.0;
206            return double.NaN;
207          }
208        default: {
209            IFunction function = symbolTable.MapSymbol(functionSymbol);
210            double[] args = new double[nLocalVariables + arity];
211            for(int i = 0; i < nLocalVariables; i++) {
212              args[i] = dataArr[DP++];
213            }
214            for(int j = 0; j < arity; j++) {
215              args[nLocalVariables + j] = EvaluateBakedCode();
216            }
217            return function.Apply(dataset, sampleIndex, args);
218          }
219      }
220    }
221
222    public override object Clone(IDictionary<Guid, object> clonedObjects) {
223      throw new NotImplementedException();
224    }
225
226    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
227      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
228      node.AppendChild(PersistenceManager.Persist("SymbolTable", symbolTable, document, persistedObjects));
229      return node;
230    }
231
232    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
233      base.Populate(node, restoredObjects);
234      PersistenceManager.Restore(node.SelectSingleNode("SymbolTable"), restoredObjects);
235    }
236  }
237}
Note: See TracBrowser for help on using the repository browser.