source: trunk/sources/HeuristicLab.GP.StructureIdentification/3.3/HL3TreeEvaluator.cs @ 2449

Last change on this file since 2449 was 2449, checked in by gkronber, 13 years ago

Fixed minor evaluation inconsistencies in HL3 tree evaluator. #791

File size: 7.2 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.Diagnostics;
24using HeuristicLab.Common; // double.IsAlmost extension
25
26namespace HeuristicLab.GP.StructureIdentification {
27  /// <summary>
28  /// Evaluates FunctionTrees recursively by interpretation of the function symbols in each node.
29  /// Not thread-safe!
30  /// </summary>
31  public class HL3TreeEvaluator : TreeEvaluatorBase {
32    public HL3TreeEvaluator() : base() { } // for persistence
33    public HL3TreeEvaluator(double minValue, double maxValue) : base(minValue, maxValue) { }
34
35    protected override double EvaluateBakedCode() {
36      Instr currInstr = codeArr[PC++];
37      switch (currInstr.symbol) {
38        case EvaluatorSymbolTable.VARIABLE: {
39            int row = sampleIndex + currInstr.i_arg1;
40            if (row < 0 || row >= dataset.Rows) throw new ArgumentException("Out of range access to dataset row: " + row);
41            else return currInstr.d_arg0 * dataset.GetValue(row, currInstr.i_arg0);
42          }
43        case EvaluatorSymbolTable.CONSTANT: {
44            return currInstr.d_arg0;
45          }
46        case EvaluatorSymbolTable.DIFFERENTIAL: {
47            int row = sampleIndex + currInstr.i_arg1;
48            if (row < 0 || row >= dataset.Rows) throw new ArgumentException("Out of range access to dataset row: " + row);
49            else if (row < 1) return 0.0;
50            else {
51              double prevValue = dataset.GetValue(row - 1, currInstr.i_arg0);
52              if (double.IsNaN(prevValue) || double.IsInfinity(prevValue)) return 0.0;
53              else return currInstr.d_arg0 * (dataset.GetValue(row, currInstr.i_arg0) - prevValue);
54            }
55          }
56        case EvaluatorSymbolTable.MULTIPLICATION: {
57            double result = EvaluateBakedCode();
58            for (int i = 1; i < currInstr.arity; i++) {
59              result *= EvaluateBakedCode();
60            }
61            return result;
62          }
63        case EvaluatorSymbolTable.ADDITION: {
64            double sum = EvaluateBakedCode();
65            for (int i = 1; i < currInstr.arity; i++) {
66              sum += EvaluateBakedCode();
67            }
68            return sum;
69          }
70        case EvaluatorSymbolTable.SUBTRACTION: {
71            double result = EvaluateBakedCode();
72            if (currInstr.arity == 1) return -result;
73            for (int i = 1; i < currInstr.arity; i++) {
74              result -= EvaluateBakedCode();
75            }
76            return result;
77          }
78        case EvaluatorSymbolTable.DIVISION: {
79            double result;
80            result = EvaluateBakedCode();
81            if (currInstr.arity == 1) {
82              return result.IsAlmost(0.0) ? 0.0 : 1.0 / result;
83            }
84            for (int i = 1; i < currInstr.arity; i++) {
85              double tmp = EvaluateBakedCode();
86              result = tmp.IsAlmost(0.0) ? 0.0 : result /= tmp;
87            }
88            return result;
89          }
90        case EvaluatorSymbolTable.AVERAGE: {
91            double sum = EvaluateBakedCode();
92            for (int i = 1; i < currInstr.arity; i++) {
93              sum += EvaluateBakedCode();
94            }
95            return sum / currInstr.arity;
96          }
97        case EvaluatorSymbolTable.COSINUS: {
98            return Math.Cos(EvaluateBakedCode());
99          }
100        case EvaluatorSymbolTable.SINUS: {
101            return Math.Sin(EvaluateBakedCode());
102          }
103        case EvaluatorSymbolTable.EXP: {
104            return Math.Exp(EvaluateBakedCode());
105          }
106        case EvaluatorSymbolTable.LOG: {
107            return Math.Log(EvaluateBakedCode());
108          }
109        case EvaluatorSymbolTable.POWER: {
110            double x = EvaluateBakedCode();
111            double p = EvaluateBakedCode();
112            return Math.Pow(x, p);
113          }
114        case EvaluatorSymbolTable.SIGNUM: {
115            double value = EvaluateBakedCode();
116            if (double.IsNaN(value)) return double.NaN;
117            else return Math.Sign(value);
118          }
119        case EvaluatorSymbolTable.SQRT: {
120            return Math.Sqrt(EvaluateBakedCode());
121          }
122        case EvaluatorSymbolTable.TANGENS: {
123            return Math.Tan(EvaluateBakedCode());
124          }
125        case EvaluatorSymbolTable.AND: {
126            double result = EvaluateBakedCode();
127            for (int i = 1; i < currInstr.arity; i++) {
128              if (result <= 0.0) SkipBakedCode();
129              else {
130                result = EvaluateBakedCode();
131              }
132            }
133            return result <= 0.0 ? -1.0 : 1.0;
134          }
135        case EvaluatorSymbolTable.EQU: {
136            double x = EvaluateBakedCode();
137            double y = EvaluateBakedCode();
138            if (x.IsAlmost(y)) return 1.0; else return -1.0;
139          }
140        case EvaluatorSymbolTable.GT: {
141            double x = EvaluateBakedCode();
142            double y = EvaluateBakedCode();
143            if (x > y) return 1.0;
144            else return -1.0;
145          }
146        case EvaluatorSymbolTable.IFTE: {
147            double condition = EvaluateBakedCode();
148            double result;
149            if (condition > 0.0) {
150              result = EvaluateBakedCode(); SkipBakedCode();
151            } else {
152              SkipBakedCode(); result = EvaluateBakedCode();
153            }
154            return result;
155          }
156        case EvaluatorSymbolTable.LT: {
157            double x = EvaluateBakedCode();
158            double y = EvaluateBakedCode();
159            if (x < y) return 1.0;
160            else return -1.0;
161          }
162        case EvaluatorSymbolTable.NOT: {
163            return -EvaluateBakedCode();
164          }
165        case EvaluatorSymbolTable.OR: {
166            double result = EvaluateBakedCode();
167            for (int i = 1; i < currInstr.arity; i++) {
168              if (result > 0.0) SkipBakedCode();
169              else {
170                result = EvaluateBakedCode();
171              }
172            }
173            return result > 0.0 ? 1.0 : -1.0;
174          }
175        case EvaluatorSymbolTable.XOR: {
176            double x = EvaluateBakedCode();
177            double y = EvaluateBakedCode();
178            if (x > y) {
179              double tmp = x;
180              x = y;
181              y = tmp;
182            }
183            // invariant y >= x
184            if (y <= 0.0 || x > 0.0) return -1.0;
185            else return 1.0;
186          }
187        default: {
188            throw new NotImplementedException();
189          }
190      }
191    }
192  }
193}
Note: See TracBrowser for help on using the repository browser.