Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs @ 9758

Last change on this file since 9758 was 9758, checked in by bburlacu, 11 years ago

#2021:

  • Derived the LinearInstruction class from Instruction.
  • Added missing symbols to the linear interpreter
  • Changed description for the linear interpreter
  • Added more helpful exception message when a symbol is not supported.
  • Added evaluation test for the linear interpreter
File size: 23.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 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.Globalization;
25using System.Linq;
26using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
27using HeuristicLab.Problems.DataAnalysis.Symbolic;
28using HeuristicLab.Random;
29using Microsoft.VisualStudio.TestTools.UnitTesting;
30namespace HeuristicLab.Problems.DataAnalysis.Symbolic_34.Tests {
31
32
33  [TestClass()]
34  public class SymbolicDataAnalysisExpressionTreeInterpreterTest {
35    private const int N = 1000;
36    private const int Rows = 1000;
37    private const int Columns = 50;
38    private TestContext testContextInstance;
39
40    /// <summary>
41    ///Gets or sets the test context which provides
42    ///information about and functionality for the current test run.
43    ///</summary>
44    public TestContext TestContext {
45      get {
46        return testContextInstance;
47      }
48      set {
49        testContextInstance = value;
50      }
51    }
52
53    [TestMethod]
54    public void SymbolicDataAnalysisExpressionTreeInterpreterTypeCoherentGrammarPerformanceTest() {
55      TypeCoherentGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeInterpreter(), 12.5e6);
56    }
57    [TestMethod]
58    public void SymbolicDataAnalysisExpressionTreeInterpreterFullGrammarPerformanceTest() {
59      FullGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeInterpreter(), 12.5e6);
60    }
61    [TestMethod]
62    public void SymbolicDataAnalysisExpressionTreeInterpreterArithmeticGrammarPerformanceTest() {
63      ArithmeticGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeInterpreter(), 12.5e6);
64    }
65
66    [TestMethod]
67    public void SymbolicDataAnalysisExpressionTreeLinearInterpreterTypeCoherentGrammarPerformanceTest() {
68      TypeCoherentGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), 12.5e6);
69    }
70    [TestMethod]
71    public void SymbolicDataAnalysisExpressionTreeLinearInterpreterFullGrammarPerformanceTest() {
72      FullGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), 12.5e6);
73    }
74    [TestMethod]
75    public void SymbolicDataAnalysisExpressionTreeLinearInterpreterArithmeticGrammarPerformanceTest() {
76      ArithmeticGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), 12.5e6);
77    }
78
79    [TestMethod]
80    public void SymbolicDataAnalysisExpressionTreeILEmittingInterpreterTypeCoherentGrammarPerformanceTest() {
81      TypeCoherentGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
82    }
83    [TestMethod]
84    public void SymbolicDataAnalysisExpressionTreeILEmittingInterpreterFullGrammarPerformanceTest() {
85      FullGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
86    }
87    [TestMethod]
88    public void SymbolicDataAnalysisExpressionTreeILEmittingInterpreterArithmeticGrammarPerformanceTest() {
89      ArithmeticGrammarPerformanceTest(new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(), 7.5e6);
90    }
91
92    private void TypeCoherentGrammarPerformanceTest(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double nodesPerSecThreshold) {
93      var twister = new MersenneTwister(31415);
94      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
95      var grammar = new TypeCoherentExpressionGrammar();
96      grammar.ConfigureAsDefaultRegressionGrammar();
97      grammar.MaximumFunctionArguments = 0;
98      grammar.MaximumFunctionDefinitions = 0;
99      grammar.MinimumFunctionArguments = 0;
100      grammar.MinimumFunctionDefinitions = 0;
101      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
102      foreach (ISymbolicExpressionTree tree in randomTrees) {
103        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
104      }
105      double nodesPerSec = Util.CalculateEvaluatedNodesPerSec(randomTrees, interpreter, dataset, 3);
106      //mkommend: commented due to performance issues on the builder
107      // Assert.IsTrue(nodesPerSec > nodesPerSecThreshold); // evaluated nodes per seconds must be larger than 15mNodes/sec
108    }
109
110    private void FullGrammarPerformanceTest(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double nodesPerSecThreshold) {
111      var twister = new MersenneTwister(31415);
112      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
113      var grammar = new FullFunctionalExpressionGrammar();
114      grammar.MaximumFunctionArguments = 0;
115      grammar.MaximumFunctionDefinitions = 0;
116      grammar.MinimumFunctionArguments = 0;
117      grammar.MinimumFunctionDefinitions = 0;
118      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
119      foreach (ISymbolicExpressionTree tree in randomTrees) {
120        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
121      }
122      double nodesPerSec = Util.CalculateEvaluatedNodesPerSec(randomTrees, interpreter, dataset, 3);
123      //mkommend: commented due to performance issues on the builder
124      //Assert.IsTrue(nodesPerSec > nodesPerSecThreshold); // evaluated nodes per seconds must be larger than 15mNodes/sec
125    }
126
127    private void ArithmeticGrammarPerformanceTest(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, double nodesPerSecThreshold) {
128      var twister = new MersenneTwister(31415);
129      var dataset = Util.CreateRandomDataset(twister, Rows, Columns);
130      var grammar = new ArithmeticExpressionGrammar();
131      grammar.MaximumFunctionArguments = 0;
132      grammar.MaximumFunctionDefinitions = 0;
133      grammar.MinimumFunctionArguments = 0;
134      grammar.MinimumFunctionDefinitions = 0;
135      var randomTrees = Util.CreateRandomTrees(twister, dataset, grammar, N, 1, 100, 0, 0);
136      foreach (SymbolicExpressionTree tree in randomTrees) {
137        Util.InitTree(tree, twister, new List<string>(dataset.VariableNames));
138      }
139
140      double nodesPerSec = Util.CalculateEvaluatedNodesPerSec(randomTrees, interpreter, dataset, 3);
141      //mkommend: commented due to performance issues on the builder
142      //Assert.IsTrue(nodesPerSec > nodesPerSecThreshold); // evaluated nodes per seconds must be larger than 15mNodes/sec
143    }
144
145
146    /// <summary>
147    ///A test for Evaluate
148    ///</summary>
149    [TestMethod]
150    public void SymbolicDataAnalysisExpressionTreeInterpreterEvaluateTest() {
151      var interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
152      Dataset ds = new Dataset(new string[] { "Y", "A", "B" }, new double[,] {
153        { 1.0, 1.0, 1.0 },
154        { 2.0, 2.0, 2.0 },
155        { 3.0, 1.0, 2.0 },
156        { 4.0, 1.0, 1.0 },
157        { 5.0, 2.0, 2.0 },
158        { 6.0, 1.0, 2.0 },
159        { 7.0, 1.0, 1.0 },
160        { 8.0, 2.0, 2.0 },
161        { 9.0, 1.0, 2.0 },
162        { 10.0, 1.0, 1.0 },
163        { 11.0, 2.0, 2.0 },
164        { 12.0, 1.0, 2.0 }
165      });
166
167      EvaluateTerminals(interpreter, ds);
168      EvaluateOperations(interpreter, ds);
169      EvaluateTimeSymbols(interpreter, ds);
170      EvaluateAdf(interpreter, ds);
171    }
172
173    [TestMethod]
174    public void SymbolicDataAnalysisExpressionTreeLinearInterpreterEvaluateTest() {
175      var interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
176      Dataset ds = new Dataset(new string[] { "Y", "A", "B" }, new double[,] {
177        { 1.0, 1.0, 1.0 },
178        { 2.0, 2.0, 2.0 },
179        { 3.0, 1.0, 2.0 },
180        { 4.0, 1.0, 1.0 },
181        { 5.0, 2.0, 2.0 },
182        { 6.0, 1.0, 2.0 },
183        { 7.0, 1.0, 1.0 },
184        { 8.0, 2.0, 2.0 },
185        { 9.0, 1.0, 2.0 },
186        { 10.0, 1.0, 1.0 },
187        { 11.0, 2.0, 2.0 },
188        { 12.0, 1.0, 2.0 }
189      });
190      //time symbols and ADFs not supported by the linear interpreter
191      EvaluateTerminals(interpreter, ds);
192      EvaluateOperations(interpreter, ds);
193    }
194
195    [TestMethod]
196    public void SymbolicDataAnalysisExpressionILEmittingTreeInterpreterEvaluateTest() {
197      Dataset ds = new Dataset(new string[] { "Y", "A", "B" }, new double[,] {
198        { 1.0, 1.0, 1.0 },
199        { 2.0, 2.0, 2.0 },
200        { 3.0, 1.0, 2.0 },
201        { 4.0, 1.0, 1.0 },
202        { 5.0, 2.0, 2.0 },
203        { 6.0, 1.0, 2.0 },
204        { 7.0, 1.0, 1.0 },
205        { 8.0, 2.0, 2.0 },
206        { 9.0, 1.0, 2.0 },
207        { 10.0, 1.0, 1.0 },
208        { 11.0, 2.0, 2.0 },
209        { 12.0, 1.0, 2.0 }
210      });
211
212      var interpreter = new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter();
213      EvaluateTerminals(interpreter, ds);
214      EvaluateOperations(interpreter, ds);
215    }
216
217    private void EvaluateTimeSymbols(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
218      // integral
219      Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
220      Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
221      Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
222      Evaluate(interpreter, ds, "(integral -1.0 (* (variable 1.0 a) (variable 1.0 b)))", 1, ds.GetDoubleValue("A", 0) * ds.GetDoubleValue("B", 0) + ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1));
223      Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
224
225      // derivative
226      // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
227      Evaluate(interpreter, ds, "(diff (variable 1.0 a)) ", 5, (ds.GetDoubleValue("A", 5) + 2 * ds.GetDoubleValue("A", 4) - 2 * ds.GetDoubleValue("A", 2) - ds.GetDoubleValue("A", 1)) / 8.0);
228      Evaluate(interpreter, ds, "(diff (variable 1.0 b)) ", 5, (ds.GetDoubleValue("B", 5) + 2 * ds.GetDoubleValue("B", 4) - 2 * ds.GetDoubleValue("B", 2) - ds.GetDoubleValue("B", 1)) / 8.0);
229      Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
230        (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
231        2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
232        2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
233        ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
234      Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
235
236      // timelag
237      Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
238      Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
239      Evaluate(interpreter, ds, "(lag -1.0 (* (lagVariable 1.0 a 1) (lagVariable 1.0 b 2)))", 1, ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 2));
240      Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
241    }
242
243    private void EvaluateTerminals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
244      // constants
245      Evaluate(interpreter, ds, "(+ 1.5 3.5)", 0, 5.0);
246
247      // variables
248      Evaluate(interpreter, ds, "(variable 2.0 a)", 0, 2.0);
249      Evaluate(interpreter, ds, "(variable 2.0 a)", 1, 4.0);
250    }
251
252    private void EvaluateAdf(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
253
254      // ADF     
255      Evaluate(interpreter, ds, @"(PROG
256                                    (MAIN
257                                      (CALL ADF0))
258                                    (defun ADF0 1.0))", 1, 1.0);
259      Evaluate(interpreter, ds, @"(PROG
260                                    (MAIN
261                                      (* (CALL ADF0) (CALL ADF0)))
262                                    (defun ADF0 2.0))", 1, 4.0);
263      Evaluate(interpreter, ds, @"(PROG
264                                    (MAIN
265                                      (CALL ADF0 2.0 3.0))
266                                    (defun ADF0
267                                      (+ (ARG 0) (ARG 1))))", 1, 5.0);
268      Evaluate(interpreter, ds, @"(PROG
269                                    (MAIN (CALL ADF1 2.0 3.0))
270                                    (defun ADF0
271                                      (- (ARG 1) (ARG 0)))
272                                    (defun ADF1
273                                      (+ (CALL ADF0 (ARG 1) (ARG 0))
274                                         (CALL ADF0 (ARG 0) (ARG 1)))))", 1, 0.0);
275      Evaluate(interpreter, ds, @"(PROG
276                                    (MAIN (CALL ADF1 (variable 2.0 a) 3.0))
277                                    (defun ADF0
278                                      (- (ARG 1) (ARG 0)))
279                                    (defun ADF1                                                                             
280                                      (CALL ADF0 (ARG 1) (ARG 0))))", 1, 1.0);
281      Evaluate(interpreter, ds,
282               @"(PROG
283                                    (MAIN (CALL ADF1 (variable 2.0 a) 3.0))
284                                    (defun ADF0
285                                      (- (ARG 1) (ARG 0)))
286                                    (defun ADF1                                                                             
287                                      (+ (CALL ADF0 (ARG 1) (ARG 0))
288                                         (CALL ADF0 (ARG 0) (ARG 1)))))", 1, 0.0);
289    }
290
291    private void EvaluateOperations(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
292      // addition
293      Evaluate(interpreter, ds, "(+ (variable 2.0 a ))", 1, 4.0);
294      Evaluate(interpreter, ds, "(+ (variable 2.0 a ) (variable 3.0 b ))", 0, 5.0);
295      Evaluate(interpreter, ds, "(+ (variable 2.0 a ) (variable 3.0 b ))", 1, 10.0);
296      Evaluate(interpreter, ds, "(+ (variable 2.0 a) (variable 3.0 b ))", 2, 8.0);
297      Evaluate(interpreter, ds, "(+ 8.0 2.0 2.0)", 0, 12.0);
298
299      // subtraction
300      Evaluate(interpreter, ds, "(- (variable 2.0 a ))", 1, -4.0);
301      Evaluate(interpreter, ds, "(- (variable 2.0 a ) (variable 3.0 b))", 0, -1.0);
302      Evaluate(interpreter, ds, "(- (variable 2.0 a ) (variable 3.0 b ))", 1, -2.0);
303      Evaluate(interpreter, ds, "(- (variable 2.0 a ) (variable 3.0 b ))", 2, -4.0);
304      Evaluate(interpreter, ds, "(- 8.0 2.0 2.0)", 0, 4.0);
305
306      // multiplication
307      Evaluate(interpreter, ds, "(* (variable 2.0 a ))", 0, 2.0);
308      Evaluate(interpreter, ds, "(* (variable 2.0 a ) (variable 3.0 b ))", 0, 6.0);
309      Evaluate(interpreter, ds, "(* (variable 2.0 a ) (variable 3.0 b ))", 1, 24.0);
310      Evaluate(interpreter, ds, "(* (variable 2.0 a ) (variable 3.0 b ))", 2, 12.0);
311      Evaluate(interpreter, ds, "(* 8.0 2.0 2.0)", 0, 32.0);
312
313      // division
314      Evaluate(interpreter, ds, "(/ (variable 2.0 a ))", 1, 1.0 / 4.0);
315      Evaluate(interpreter, ds, "(/ (variable 2.0 a ) 2.0)", 0, 1.0);
316      Evaluate(interpreter, ds, "(/ (variable 2.0 a ) 2.0)", 1, 2.0);
317      Evaluate(interpreter, ds, "(/ (variable 3.0 b ) 2.0)", 2, 3.0);
318      Evaluate(interpreter, ds, "(/ 8.0 2.0 2.0)", 0, 2.0);
319
320      // gt
321      Evaluate(interpreter, ds, "(> (variable 2.0 a) 2.0)", 0, -1.0);
322      Evaluate(interpreter, ds, "(> 2.0 (variable 2.0 a))", 0, -1.0);
323      Evaluate(interpreter, ds, "(> (variable 2.0 a) 1.9)", 0, 1.0);
324      Evaluate(interpreter, ds, "(> 1.9 (variable 2.0 a))", 0, -1.0);
325      Evaluate(interpreter, ds, "(> (log -1.0) (log -1.0))", 0, -1.0); // (> nan nan) should be false
326
327      // lt
328      Evaluate(interpreter, ds, "(< (variable 2.0 a) 2.0)", 0, -1.0);
329      Evaluate(interpreter, ds, "(< 2.0 (variable 2.0 a))", 0, -1.0);
330      Evaluate(interpreter, ds, "(< (variable 2.0 a) 1.9)", 0, -1.0);
331      Evaluate(interpreter, ds, "(< 1.9 (variable 2.0 a))", 0, 1.0);
332      Evaluate(interpreter, ds, "(< (log -1.0) (log -1.0))", 0, -1.0); // (< nan nan) should be false
333
334      // If
335      Evaluate(interpreter, ds, "(if -10.0 2.0 3.0)", 0, 3.0);
336      Evaluate(interpreter, ds, "(if -1.0 2.0 3.0)", 0, 3.0);
337      Evaluate(interpreter, ds, "(if 0.0 2.0 3.0)", 0, 3.0);
338      Evaluate(interpreter, ds, "(if 1.0 2.0 3.0)", 0, 2.0);
339      Evaluate(interpreter, ds, "(if 10.0 2.0 3.0)", 0, 2.0);
340      Evaluate(interpreter, ds, "(if (log -1.0) 2.0 3.0)", 0, 3.0); // if(nan) should return the else branch
341
342      // NOT
343      Evaluate(interpreter, ds, "(not -1.0)", 0, 1.0);
344      Evaluate(interpreter, ds, "(not -2.0)", 0, 1.0);
345      Evaluate(interpreter, ds, "(not 1.0)", 0, -1.0);
346      Evaluate(interpreter, ds, "(not 2.0)", 0, -1.0);
347      Evaluate(interpreter, ds, "(not 0.0)", 0, 1.0);
348      Evaluate(interpreter, ds, "(not (log -1.0))", 0, 1.0);
349
350      // AND
351      Evaluate(interpreter, ds, "(and -1.0 -2.0)", 0, -1.0);
352      Evaluate(interpreter, ds, "(and -1.0 2.0)", 0, -1.0);
353      Evaluate(interpreter, ds, "(and 1.0 -2.0)", 0, -1.0);
354      Evaluate(interpreter, ds, "(and 1.0 0.0)", 0, -1.0);
355      Evaluate(interpreter, ds, "(and 0.0 0.0)", 0, -1.0);
356      Evaluate(interpreter, ds, "(and 1.0 2.0)", 0, 1.0);
357      Evaluate(interpreter, ds, "(and 1.0 2.0 3.0)", 0, 1.0);
358      Evaluate(interpreter, ds, "(and 1.0 -2.0 3.0)", 0, -1.0);
359      Evaluate(interpreter, ds, "(and (log -1.0))", 0, -1.0); // (and NaN)
360      Evaluate(interpreter, ds, "(and (log -1.0)  1.0)", 0, -1.0); // (and NaN 1.0)
361
362
363      // OR
364      Evaluate(interpreter, ds, "(or -1.0 -2.0)", 0, -1.0);
365      Evaluate(interpreter, ds, "(or -1.0 2.0)", 0, 1.0);
366      Evaluate(interpreter, ds, "(or 1.0 -2.0)", 0, 1.0);
367      Evaluate(interpreter, ds, "(or 1.0 2.0)", 0, 1.0);
368      Evaluate(interpreter, ds, "(or 0.0 0.0)", 0, -1.0);
369      Evaluate(interpreter, ds, "(or -1.0 -2.0 -3.0)", 0, -1.0);
370      Evaluate(interpreter, ds, "(or -1.0 -2.0 3.0)", 0, 1.0);
371      Evaluate(interpreter, ds, "(or (log -1.0))", 0, -1.0); // (or NaN)
372      Evaluate(interpreter, ds, "(or (log -1.0)  1.0)", 0, -1.0); // (or NaN 1.0)
373
374      // sin, cos, tan
375      Evaluate(interpreter, ds, "(sin " + Math.PI.ToString(NumberFormatInfo.InvariantInfo) + ")", 0, 0.0);
376      Evaluate(interpreter, ds, "(sin 0.0)", 0, 0.0);
377      Evaluate(interpreter, ds, "(cos " + Math.PI.ToString(NumberFormatInfo.InvariantInfo) + ")", 0, -1.0);
378      Evaluate(interpreter, ds, "(cos 0.0)", 0, 1.0);
379      Evaluate(interpreter, ds, "(tan " + Math.PI.ToString(NumberFormatInfo.InvariantInfo) + ")", 0, Math.Tan(Math.PI));
380      Evaluate(interpreter, ds, "(tan 0.0)", 0, Math.Tan(Math.PI));
381
382      // exp, log
383      Evaluate(interpreter, ds, "(log (exp 7.0))", 0, Math.Log(Math.Exp(7)));
384      Evaluate(interpreter, ds, "(exp (log 7.0))", 0, Math.Exp(Math.Log(7)));
385      Evaluate(interpreter, ds, "(log -3.0)", 0, Math.Log(-3));
386
387      // power
388      Evaluate(interpreter, ds, "(pow 2.0 3.0)", 0, 8.0);
389      Evaluate(interpreter, ds, "(pow 4.0 0.5)", 0, 1.0); // interpreter should round to the nearest integer value value (.5 is rounded to the even number)
390      Evaluate(interpreter, ds, "(pow 4.0 2.5)", 0, 16.0); // interpreter should round to the nearest integer value value (.5 is rounded to the even number)
391      Evaluate(interpreter, ds, "(pow -2.0 3.0)", 0, -8.0);
392      Evaluate(interpreter, ds, "(pow 2.0 -3.0)", 0, 1.0 / 8.0);
393      Evaluate(interpreter, ds, "(pow -2.0 -3.0)", 0, -1.0 / 8.0);
394
395      // root
396      Evaluate(interpreter, ds, "(root 9.0 2.0)", 0, 3.0);
397      Evaluate(interpreter, ds, "(root 27.0 3.0)", 0, 3.0);
398      Evaluate(interpreter, ds, "(root 2.0 -3.0)", 0, Math.Pow(2.0, -1.0 / 3.0));
399
400      // mean
401      Evaluate(interpreter, ds, "(mean -1.0 1.0 -1.0)", 0, -1.0 / 3.0);
402
403      // lag
404      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 1, ds.GetDoubleValue("A", 0));
405      Evaluate(interpreter, ds, "(lagVariable 1.0 a -1) ", 2, ds.GetDoubleValue("A", 1));
406      Evaluate(interpreter, ds, "(lagVariable 1.0 a 0) ", 2, ds.GetDoubleValue("A", 2));
407      Evaluate(interpreter, ds, "(lagVariable 1.0 a 1) ", 0, ds.GetDoubleValue("A", 1));
408
409      {
410        // special functions
411        Action<double> checkAiry = (x) => {
412          double ai, aip, bi, bip;
413          alglib.airy(x, out ai, out aip, out bi, out bip);
414          Evaluate(interpreter, ds, "(airya " + x + ")", 0, ai);
415          Evaluate(interpreter, ds, "(airyb " + x + ")", 0, bi);
416        };
417
418        Action<double> checkBessel = (x) => {
419          Evaluate(interpreter, ds, "(bessel " + x + ")", 0, alglib.besseli0(x));
420        };
421
422        Action<double> checkSinCosIntegrals = (x) => {
423          double si, ci;
424          alglib.sinecosineintegrals(x, out si, out ci);
425          Evaluate(interpreter, ds, "(cosint " + x + ")", 0, ci);
426          Evaluate(interpreter, ds, "(sinint " + x + ")", 0, si);
427        };
428        Action<double> checkHypSinCosIntegrals = (x) => {
429          double shi, chi;
430          alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
431          Evaluate(interpreter, ds, "(hypcosint " + x + ")", 0, chi);
432          Evaluate(interpreter, ds, "(hypsinint " + x + ")", 0, shi);
433        };
434        Action<double> checkFresnelSinCosIntegrals = (x) => {
435          double c = 0, s = 0;
436          alglib.fresnelintegral(x, ref c, ref s);
437          Evaluate(interpreter, ds, "(fresnelcosint " + x + ")", 0, c);
438          Evaluate(interpreter, ds, "(fresnelsinint " + x + ")", 0, s);
439        };
440        Action<double> checkNormErf = (x) => {
441          Evaluate(interpreter, ds, "(norm " + x + ")", 0, alglib.normaldistribution(x));
442          Evaluate(interpreter, ds, "(erf " + x + ")", 0, alglib.errorfunction(x));
443        };
444
445        Action<double> checkGamma = (x) => {
446          Evaluate(interpreter, ds, "(gamma " + x + ")", 0, alglib.gammafunction(x));
447        };
448        Action<double> checkPsi = (x) => {
449          try {
450            Evaluate(interpreter, ds, "(psi " + x + ")", 0, alglib.psi(x));
451          }
452          catch (alglib.alglibexception) { // ignore cases where alglib throws an exception
453          }
454        };
455        Action<double> checkDawson = (x) => {
456          Evaluate(interpreter, ds, "(dawson " + x + ")", 0, alglib.dawsonintegral(x));
457        };
458        Action<double> checkExpInt = (x) => {
459          Evaluate(interpreter, ds, "(expint " + x + ")", 0, alglib.exponentialintegralei(x));
460        };
461
462        foreach (var e in new[] { -2.0, -1.0, 0.0, 1.0, 2.0 }) {
463          checkAiry(e);
464          checkBessel(e);
465          checkSinCosIntegrals(e);
466          checkGamma(e);
467          checkExpInt(e);
468          checkDawson(e);
469          checkPsi(e);
470          checkNormErf(e);
471          checkFresnelSinCosIntegrals(e);
472          checkHypSinCosIntegrals(e);
473        }
474      }
475    }
476
477    private void Evaluate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds, string expr, int index, double expected) {
478      var importer = new SymbolicExpressionImporter();
479      ISymbolicExpressionTree tree = importer.Import(expr);
480
481      double actual = interpreter.GetSymbolicExpressionTreeValues(tree, ds, Enumerable.Range(index, 1)).First();
482
483      Assert.IsFalse(double.IsNaN(actual) && !double.IsNaN(expected));
484      Assert.IsFalse(!double.IsNaN(actual) && double.IsNaN(expected));
485      Assert.AreEqual(expected, actual, 1.0E-12, expr);
486    }
487  }
488}
Note: See TracBrowser for help on using the repository browser.