Free cookie consent management tool by TermsFeed Policy Generator

source: branches/MCTS-SymbReg-2796/Tests/HeuristicLab.Algorithms.DataAnalysis-3.4/MctsSymbolicRegressionTest.cs @ 15426

Last change on this file since 15426 was 15426, checked in by gkronber, 7 years ago

#2796 testing interaction heuristics

File size: 64.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Threading;
5using HeuristicLab.Algorithms.DataAnalysis.MctsSymbolicRegression.Policies;
6using HeuristicLab.Algorithms.DataAnalysis.MCTSSymbReg;
7using HeuristicLab.Data;
8using HeuristicLab.Optimization;
9using HeuristicLab.Problems.DataAnalysis;
10using HeuristicLab.Problems.Instances.DataAnalysis;
11using HeuristicLab.Random;
12using Microsoft.VisualStudio.TestTools.UnitTesting;
13
14namespace HeuristicLab.Algorithms.DataAnalysis.MctsSymbolicRegression {
15  [TestClass()]
16  public class MctsSymbolicRegressionTest {
17    #region heuristics
18    [TestMethod]
19    [TestCategory("Algorithms.DataAnalysis")]
20    [TestProperty("Time", "short")]
21    public void TestSimple2dInteractions() {
22      {
23        // a, b ~ U(0, 1) should be trivial
24        var nRand = new MersenneTwister(1234);
25
26        int n = 10000; // large sample so that we can use the thresholds below
27        var a = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
28        var b = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
29        var x = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
30        var y = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
31
32        var z = a.Zip(b, (ai, bi) => ai * bi).ToArray();
33
34        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, z) > 0.05); // should be detected as relevant
35        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) > 0.05); // a and b > 0 so these should be detected as well
36        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) > 0.05);
37        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) > 0.05);
38        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) > 0.05);
39        Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z) < 0.05);
40      }
41      {
42        // a, b ~ U(1000, 2000) also trivial
43        var nRand = new UniformDistributedRandom(new MersenneTwister(1234), 1000, 2000);
44
45        int n = 10000; // large sample so that we can use the thresholds below
46        var a = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
47        var b = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
48        var x = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
49        var y = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
50
51        var z = a.Zip(b, (ai, bi) => ai * bi).ToArray();
52
53        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, z) > 0.05); // should be detected as relevant
54        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) > 0.05);
55        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) > 0.05);
56        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) > 0.05);
57        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) > 0.05);
58        Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z) < 0.05);
59      }
60      {
61        // a, b ~ U(-1, 1)
62        var nRand = new UniformDistributedRandom(new MersenneTwister(1234), -1, 1);
63
64        int n = 10000; // large sample so that we can use the thresholds below
65        var a = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
66        var b = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
67        var x = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
68        var y = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
69
70        var z = a.Zip(b, (ai, bi) => ai * bi).ToArray();
71
72        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, z) > 0.05); // should be detected as relevant
73        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) < 0.05);
74        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) < 0.05);
75        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) < 0.05);
76        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) < 0.05);
77        Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z) < 0.05);
78      }
79      {
80        // a, b ~ N(0, 1)
81        var nRand = new NormalDistributedRandom(new MersenneTwister(1234), 0, 1);
82
83        int n = 10000; // large sample so that we can use the thresholds below
84        var a = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
85        var b = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
86        var x = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
87        var y = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
88
89        var z = a.Zip(b, (ai, bi) => ai * bi).ToArray();
90
91        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, z) > 0.05); // should be detected as relevant
92        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) < 0.05);
93        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) < 0.05);
94        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) < 0.05);
95        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) < 0.05);
96        Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z) < 0.05);
97      }
98      {
99        var rand = new MersenneTwister(1234);
100        // a ~ N(100, 1), b ~ N(-100, 1)
101        var nRand = new NormalDistributedRandom(rand, 0, 1);
102        var aRand = new NormalDistributedRandom(rand, 100, 1);
103        var bRand = new NormalDistributedRandom(rand, -100, 1);
104
105        int n = 10000; // large sample so that we can use the thresholds below
106        var a = Enumerable.Range(0, n).Select(_ => aRand.NextDouble()).ToArray();
107        var b = Enumerable.Range(0, n).Select(_ => bRand.NextDouble()).ToArray();
108        var x = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
109        var y = Enumerable.Range(0, n).Select(_ => nRand.NextDouble()).ToArray();
110
111        var z = a.Zip(b, (ai, bi) => ai * bi).ToArray();
112
113        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, z) > 0.05); // should be detected as relevant
114        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) > 0.05); // a > 0
115        Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) > 0.05);
116        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) > 0.05); // b < 0
117        Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) > 0.05);
118        Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z) < 0.05); // random variables are not correlated
119      }
120    }
121
122    [TestMethod]
123    [TestCategory("Algorithms.DataAnalysis")]
124    [TestProperty("Time", "short")]
125    public void TestGeneral2dInteractions() {
126      {
127        // we should be able to reliably detect when a product of two variables is correlated with the target variable       
128
129        // the test samples x from a two dimensional normal distribution
130        // the covariance matrix for the normal distribution is randomly sampled
131        // this means x_1 and x_2 might be highly correlated
132        // the mean of the normal distribution is randomly sampled (most critical are probably zero-mean distributions)
133        // y is calculated as x_1*x_2
134
135        var conditionNumber = 10000;
136        for (int iter = 0; iter < 100; iter++) {
137          double m0 = 0.0; double m1 = 0.0;
138          alglib.hqrndstate randState;
139          alglib.hqrndseed(1234, 31415, out randState);
140
141          // uncomment if non-zero mean distributions should be tested
142          //alglib.hqrndnormal2(randState, out m0, out m1);
143
144          double[,] cov_ab = new double[2, 2];
145          double[,] cov_xy = new double[2, 2];
146          alglib.matgen.spdmatrixrndcond(2, conditionNumber, ref cov_ab);
147          alglib.spdmatrixcholesky(ref cov_ab, 2, true);
148
149          alglib.matgen.spdmatrixrndcond(2, conditionNumber, ref cov_xy);
150          alglib.spdmatrixcholesky(ref cov_xy, 2, true);
151
152          // generate a, b by sampling from a 2dim multivariate normal distribution
153          // generate x, y by sampling from another 2dim multivariate normal distribution
154          // a,b and x,y might be correlated but x,y are not correlated to a,b
155          int N = 1000; // large sample size to make sure the test thresholds hold
156          double[] a = new double[N];
157          double[] b = new double[N];
158          double[] x = new double[N];
159          double[] y = new double[N];
160          double[] z = new double[N];
161
162          for (int i = 0; i < N; i++) {
163            double r1, r2, r3, r4;
164            alglib.hqrndnormal2(randState, out r1, out r2);
165            alglib.hqrndnormal2(randState, out r3, out r4);
166
167            var r_ab = new double[] { r1, r2 };
168            var r_xy = new double[] { r3, r4 };
169            double[] s_ab = new double[2];
170            double[] s_xy = new double[2];
171            alglib.ablas.rmatrixmv(2, 2, cov_ab, 0, 0, 0, r_ab, 0, ref s_ab, 0);
172            alglib.ablas.rmatrixmv(2, 2, cov_xy, 0, 0, 0, r_xy, 0, ref s_xy, 0);
173
174            a[i] = s_ab[0] + m0;
175            b[i] = s_ab[1] + m1;
176            x[i] = s_xy[0] + m0; // use same mean (just for the sake of it)
177            y[i] = s_xy[1] + m1;
178
179            z[i] = a[i] * b[i];
180          }
181
182          Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, z) > 0.05);
183          Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z) < 0.05);
184
185          /* we might see correlations when only using one of the two relevant factors.
186           * this depends on the distribution / location of a and b
187          // for zero-mean distributions the following should all be quasi-zero
188          Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) < 0.05);
189          Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) < 0.05);
190          Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) < 0.05);
191          Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) < 0.05);
192          */
193          Console.WriteLine("a,b: {0:N3}\tx,y: {1:N3}\ta,x: {2:N3}\tb,x: {3:N3}\ta,y: {4:N3}\tb,y: {5:N3}\tcov(a,b): {6:N3}",
194            Heuristics.CorrelationForInteraction(a, b, z),
195            Heuristics.CorrelationForInteraction(x, y, z),
196            Heuristics.CorrelationForInteraction(a, x, z),
197            Heuristics.CorrelationForInteraction(b, x, z),
198            Heuristics.CorrelationForInteraction(a, y, z),
199            Heuristics.CorrelationForInteraction(b, y, z),
200            alglib.cov2(a, b)
201            );
202        }
203      }
204    }
205    [TestMethod]
206    [TestCategory("Algorithms.DataAnalysis")]
207    [TestProperty("Time", "short")]
208    public void TestGeneral3dInteractions() {
209      {
210        // same as TestGeneral2dInteractions but for terms with three variables
211
212        var conditionNumber = 100;
213        for (int iter = 0; iter < 100; iter++) {
214          double m0 = 0.0; double m1 = 0.0; double m2 = 0.0;
215          alglib.hqrndstate randState;
216          alglib.hqrndseed(1234, 31415, out randState);
217
218          // uncomment if non-zero mean distributions should be tested
219          //alglib.hqrndnormal2(randState, out m0, out m1);
220          //alglib.hqrndnormal2(randState, out m1, out m2);
221
222          double[,] cov_abc = new double[3, 3];
223          double[,] cov_xyz = new double[3, 3];
224          alglib.matgen.spdmatrixrndcond(3, conditionNumber, ref cov_abc);
225          alglib.spdmatrixcholesky(ref cov_abc, 3, true);
226
227          alglib.matgen.spdmatrixrndcond(3, conditionNumber, ref cov_xyz);
228          alglib.spdmatrixcholesky(ref cov_xyz, 3, true);
229
230          int N = 1000; // large sample size to make sure the test thresholds hold
231          double[] a = new double[N];
232          double[] b = new double[N];
233          double[] c = new double[N];
234          double[] x = new double[N];
235          double[] y = new double[N];
236          double[] z = new double[N];
237          double[] t = new double[N];
238
239          for (int i = 0; i < N; i++) {
240            double r1, r2, r3, r4, r5, r6;
241            alglib.hqrndnormal2(randState, out r1, out r2);
242            alglib.hqrndnormal2(randState, out r3, out r4);
243            alglib.hqrndnormal2(randState, out r5, out r6);
244
245            var r_abc = new double[] { r1, r2, r3 };
246            var r_xyz = new double[] { r4, r5, r6 };
247            double[] s_abc = new double[3];
248            double[] s_xyz = new double[3];
249            alglib.ablas.rmatrixmv(3, 3, cov_abc, 0, 0, 0, r_abc, 0, ref s_abc, 0);
250            alglib.ablas.rmatrixmv(3, 3, cov_xyz, 0, 0, 0, r_xyz, 0, ref s_xyz, 0);
251
252            a[i] = s_abc[0] + m0;
253            b[i] = s_abc[1] + m1;
254            c[i] = s_abc[2] + m2;
255            x[i] = s_xyz[0] + m0; // use same mean (just for the sake of it)
256            y[i] = s_xyz[1] + m1;
257            z[i] = s_xyz[2] + m2;
258
259            t[i] = a[i] * b[i] * c[i];
260          }
261
262          Assert.IsTrue(Heuristics.CorrelationForInteraction(a, b, c, z) > 0.05);
263          Assert.IsTrue(Heuristics.CorrelationForInteraction(x, y, z, z) < 0.05);
264
265          /* we might see correlations when only using one of the two relevant factors.
266           * this depends on the distribution / location of a and b
267          // for zero-mean distributions the following should all be quasi-zero
268          Assert.IsTrue(Heuristics.CorrelationForInteraction(a, x, z) < 0.05);
269          Assert.IsTrue(Heuristics.CorrelationForInteraction(b, x, z) < 0.05);
270          Assert.IsTrue(Heuristics.CorrelationForInteraction(a, y, z) < 0.05);
271          Assert.IsTrue(Heuristics.CorrelationForInteraction(b, y, z) < 0.05);
272          */
273          Console.WriteLine("a,b: {0:N3}\tx,y: {1:N3}\ta,x: {2:N3}\tb,x: {3:N3}\ta,y: {4:N3}\tb,y: {5:N3}\tcov(a,b): {6:N3}",
274            Heuristics.CorrelationForInteraction(a, b, z),
275            Heuristics.CorrelationForInteraction(x, y, z),
276            Heuristics.CorrelationForInteraction(a, x, z),
277            Heuristics.CorrelationForInteraction(b, x, z),
278            Heuristics.CorrelationForInteraction(a, y, z),
279            Heuristics.CorrelationForInteraction(b, y, z),
280            alglib.cov2(a, b)
281            );
282        }
283      }
284    }
285    #endregion
286
287
288    #region expression hashing
289    [TestMethod]
290    [TestCategory("Algorithms.DataAnalysis")]
291    [TestProperty("Time", "short")]
292    public void ExprHashTest() {
293      int nParams;
294      byte[] code;
295
296      {
297        // addition of variables
298        var codeGen = new CodeGenerator();
299        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
300        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
301        codeGen.Emit1(OpCodes.Add);
302        codeGen.Emit1(OpCodes.Exit);
303        codeGen.GetCode(out code, out nParams);
304        var h1 = ExprHash.GetHash(code, nParams);
305
306        codeGen = new CodeGenerator();
307        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
308        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
309        codeGen.Emit1(OpCodes.Add);
310        codeGen.Emit1(OpCodes.Exit);
311        codeGen.GetCode(out code, out nParams);
312        var h2 = ExprHash.GetHash(code, nParams);
313
314        Assert.AreEqual(h1, h2);
315      }
316
317      {
318        // multiplication of variables
319        var codeGen = new CodeGenerator();
320        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
321        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
322        codeGen.Emit1(OpCodes.Mul);
323        codeGen.Emit1(OpCodes.Exit);
324        codeGen.GetCode(out code, out nParams);
325        var h1 = ExprHash.GetHash(code, nParams);
326
327        codeGen = new CodeGenerator();
328        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
329        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
330        codeGen.Emit1(OpCodes.Mul);
331        codeGen.Emit1(OpCodes.Exit);
332        codeGen.GetCode(out code, out nParams);
333        var h2 = ExprHash.GetHash(code, nParams);
334
335        Assert.AreEqual(h1, h2);
336      }
337
338      {
339        // distributivity
340        var codeGen = new CodeGenerator();
341        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
342        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
343        codeGen.Emit1(OpCodes.Add);
344        codeGen.Emit2(OpCodes.LoadVar, 3);
345        codeGen.Emit1(OpCodes.Mul);
346        codeGen.Emit1(OpCodes.Exit);
347        codeGen.GetCode(out code, out nParams);
348        var h1 = ExprHash.GetHash(code, nParams);
349
350        codeGen = new CodeGenerator();
351        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
352        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 3);
353        codeGen.Emit1(OpCodes.Mul);
354        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
355        codeGen.Emit2(OpCodes.LoadVar, 3);
356        codeGen.Emit1(OpCodes.Mul);
357        codeGen.Emit1(OpCodes.Add);
358        codeGen.Emit1(OpCodes.Exit);
359        codeGen.GetCode(out code, out nParams);
360        var h2 = ExprHash.GetHash(code, nParams);
361
362        Assert.AreEqual(h1, h2);
363      }
364
365
366      {
367        // div
368        var codeGen = new CodeGenerator();
369        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
370        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
371        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
372        codeGen.Emit1(OpCodes.Inv);
373        codeGen.Emit1(OpCodes.Exit);
374        codeGen.GetCode(out code, out nParams);
375        var h1 = ExprHash.GetHash(code, nParams);
376
377        codeGen = new CodeGenerator();
378        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
379        codeGen.Emit1(OpCodes.Inv);
380        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
381        codeGen.Emit1(OpCodes.Inv);
382        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
383        codeGen.Emit1(OpCodes.Exit);
384        codeGen.GetCode(out code, out nParams);
385        var h2 = ExprHash.GetHash(code, nParams);
386
387        Assert.AreEqual(h1, h2);
388      }
389      {
390        // exp
391        var codeGen = new CodeGenerator();
392        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
393        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
394        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Add);
395        codeGen.Emit1(OpCodes.Exp);
396        codeGen.Emit1(OpCodes.Exit);
397        codeGen.GetCode(out code, out nParams);
398        var h1 = ExprHash.GetHash(code, nParams);
399
400        codeGen = new CodeGenerator();
401        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
402        codeGen.Emit1(OpCodes.Exp);
403        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
404        codeGen.Emit1(OpCodes.Exp);
405        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
406        codeGen.GetCode(out code, out nParams);
407        codeGen.Emit1(OpCodes.Exit);
408        var h2 = ExprHash.GetHash(code, nParams);
409
410        Assert.AreEqual(h1, h2);
411      }
412      {
413        // log
414        var codeGen = new CodeGenerator();
415        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
416        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
417        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
418        codeGen.Emit1(OpCodes.Log);
419        codeGen.Emit1(OpCodes.Exit);
420        codeGen.GetCode(out code, out nParams);
421        var h1 = ExprHash.GetHash(code, nParams);
422
423        codeGen = new CodeGenerator();
424        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
425        codeGen.Emit1(OpCodes.Log);
426        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 2);
427        codeGen.Emit1(OpCodes.Log);
428        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Add);
429        codeGen.Emit1(OpCodes.Exit);
430        codeGen.GetCode(out code, out nParams);
431        var h2 = ExprHash.GetHash(code, nParams);
432
433        Assert.AreEqual(h1, h2);
434      }
435
436      {
437        // x1 + x1 is equivalent to x1
438        var codeGen = new CodeGenerator();
439        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
440        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
441        codeGen.Emit1(OpCodes.Add);
442        codeGen.Emit1(OpCodes.Exit);
443        codeGen.GetCode(out code, out nParams);
444        var h1 = ExprHash.GetHash(code, nParams);
445
446        codeGen = new CodeGenerator();
447        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
448        codeGen.Emit1(OpCodes.Exit);
449        codeGen.GetCode(out code, out nParams);
450        var h2 = ExprHash.GetHash(code, nParams);
451
452        Assert.AreEqual(h1, h2);
453      }
454      {
455        // c1*x1 + c2*x1 is equivalent to c3*x1
456        var codeGen = new CodeGenerator();
457        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadParamN);
458        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
459        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
460
461        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadParamN);
462        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
463        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
464
465        codeGen.Emit1(OpCodes.Add);
466        codeGen.Emit1(OpCodes.Exit);
467        codeGen.GetCode(out code, out nParams);
468        var h1 = ExprHash.GetHash(code, nParams);
469
470        codeGen = new CodeGenerator();
471        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadParamN);
472        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
473        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
474        codeGen.Emit1(OpCodes.Exit);
475        codeGen.GetCode(out code, out nParams);
476        var h2 = ExprHash.GetHash(code, nParams);
477
478        Assert.AreEqual(h1, h2);
479      }
480
481      {
482        var codeGen = new CodeGenerator();
483        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadConst0);
484        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadConst1);
485        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadParamN);
486        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
487        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
488
489        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadParamN);
490        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
491        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
492
493        codeGen.Emit1(OpCodes.Add);
494
495        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
496        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Add);
497
498        codeGen.Emit1(OpCodes.Exit);
499        codeGen.GetCode(out code, out nParams);
500        var h1 = ExprHash.GetHash(code, nParams);
501
502        codeGen = new CodeGenerator();
503        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadConst0);
504        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadConst1);
505        codeGen.Emit1(MctsSymbolicRegression.OpCodes.LoadParamN);
506        codeGen.Emit2(MctsSymbolicRegression.OpCodes.LoadVar, 1);
507        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
508        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Mul);
509        codeGen.Emit1(MctsSymbolicRegression.OpCodes.Add);
510        codeGen.Emit1(OpCodes.Exit);
511        codeGen.GetCode(out code, out nParams);
512        var h2 = ExprHash.GetHash(code, nParams);
513
514        Assert.AreEqual(h1, h2);
515      }
516    }
517    #endregion
518
519    #region number of solutions
520    // the algorithm should visits each solution only once
521    [TestMethod]
522    [TestCategory("Algorithms.DataAnalysis")]
523    [TestProperty("Time", "short")]
524    public void MctsSymbRegNumberOfSolutionsOneVariable() {
525      // this problem has only one variable
526      var provider = new NguyenInstanceProvider();
527      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F1 ")));
528      {
529        // possible solutions with max one variable reference:
530        // x
531        // log(x)
532        // exp(x)
533        // 1/x
534        TestMctsNumberOfSolutions(regProblem, 1, 4);
535      }
536      {
537        // possible solutions with max two variable references:
538        // TODO: equal terms should not be allowed (see ConstraintHandler)
539        // x
540        // log(x)
541        // exp(x)
542        // 1/x
543        //              -- 4
544        // x * x
545        // x * log(x)
546        // x * exp(x)
547        // x * 1/x
548        // x + x                                        ?
549        // x + log(x)
550        // x + exp(x)
551        // x + 1/x
552        //              -- 8
553        // log(x) * log(x)
554        // log(x) * exp(x)
555        // log(x) * 1/x
556        // log(x) + log(x)                              ?
557        // log(x) + exp(x)                              ?
558        // log(x) + 1/x
559        //              -- 6
560        // exp(x) * exp(x)
561        // exp(x) * 1/x
562        // exp(x) + exp(x)                              ?
563        // exp(x) + 1/x
564        //              -- 4
565        // 1/x * 1/x
566        // 1/x + 1/x                                    ?
567        //              -- 2
568        // log(x+x)                                     ?
569        // log(x*x)
570        // exp(x*x)
571        // 1/(x+x)                                      ?
572        // 1/(x*x)
573        //              -- 5
574
575
576        TestMctsNumberOfSolutions(regProblem, 2, 29);
577      }
578      {
579        // possible solutions with max three variable references:
580        // without log and inv
581        // x
582        // exp(x)
583        //              -- 2
584        // x * x
585        // x + x                                            ?
586        // x * exp(x)
587        // x + exp(x)
588        // exp(x) * exp(x)
589        // exp(x) + exp(x)                                  ?
590        // exp(x*x)
591        //              -- 7
592        // x * x * x
593        // x + x * x                                       
594        // x + x + x                                        ?
595        // x * x * exp(x)
596        // x + x * exp(x)                                   
597        // x + x + exp(x)                                   ?
598        // exp(x) + x*x
599        // exp(x) + x*exp(x)                               
600        // x + exp(x) * exp(x)                             
601        // x + exp(x) + exp(x)                              ?
602        // x * exp(x) * exp(x)
603        // x * exp(x*x)
604        // x + exp(x*x)
605        //              -- 13
606
607        // exp(x) * exp(x) * exp(x)
608        // exp(x) + exp(x) * exp(x)                         
609        // exp(x) + exp(x) + exp(x)                         ?
610        //              -- 3
611
612        // exp(x)   * exp(x*x)
613        // exp(x)   + exp(x*x)
614        //              -- 2
615        // exp(x*x*x)
616        //              -- 1
617        TestMctsNumberOfSolutions(regProblem, 3, 2 + 7 + 13 + 3 + 2 + 1, allowLog: false, allowInv: false);
618      }
619      {
620        // possible solutions with max 4 variable references:
621        // without exp, log and inv
622        // x       
623        // x*x
624        // x+x                                             ?
625        // x*x*x
626        // x+x*x
627        // x+x+x                                           ?
628        // x*x*x*x
629        // x+x*x*x
630        // x*x+x*x                                         ?
631        // x+x+x*x                                         ?
632        // x+x+x+x                                         ?
633
634        TestMctsNumberOfSolutions(regProblem, 4, 11, allowLog: false, allowInv: false, allowExp: false);
635      }
636      {
637        // possible solutions with max 5 variable references:
638        // without exp, log and inv
639        // x       
640        // xx
641        // x+x                                             ?
642        // xxx
643        // x+xx
644        // x+x+x                                           ?
645        // xxxx
646        // x+xxx
647        // xx+xx                                           ?
648        // x+x+xx                                          ?
649        // x+x+x+x                                         ?
650        // xxxxx
651        // x+xxxx
652        // xx+xxx
653        // x+x+xxx                                         ?
654        // x+xx+xx                                         ?
655        // x+x+x+xx                                        ?
656        // x+x+x+x+x                                       ?
657        TestMctsNumberOfSolutions(regProblem, 5, 18, allowLog: false, allowInv: false, allowExp: false);
658      }
659    }
660
661    [TestMethod]
662    [TestCategory("Algorithms.DataAnalysis")]
663    [TestProperty("Time", "short")]
664    public void MctsSymbRegNumberOfSolutionsTwoVariables() {
665      // this problem has only two input variables
666      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider();
667      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F9 ")));
668      {
669        // possible solutions with max one variable reference:
670        // x
671        // log(x)
672        // exp(x)
673        // 1/x
674        // y
675        // log(y)
676        // exp(y)
677        // 1/y
678        TestMctsNumberOfSolutions(regProblem, 1, 8);
679      }
680      {
681        // possible solutions with max one variable reference:
682        // without log and inv
683
684        // x
685        // exp(x)
686        // y
687        // exp(y)
688        TestMctsNumberOfSolutions(regProblem, 1, 4, allowLog: false, allowInv: false);
689      }
690      {
691        // possible solutions with max two variable references:
692        // without log and inv
693
694        // x
695        // y
696        // exp(x)
697        // exp(y)
698        //                  -- 4
699        // x (*|+) x
700        // x (*|+) exp(x)
701        // x (*|+) y
702        // x (*|+) exp(y)
703        //                  -- 8
704        // exp(x) (*|+) exp(x)
705        // exp(x) (*|+) exp(y)
706        //                  -- 4
707        // y (*|+) y
708        // y (*|+) exp(x)
709        // y (*|+) exp(y)
710        //                  -- 6
711        // exp(y) (*|+) exp(y)
712        //                  -- 2
713        //
714        // exp(x*x)
715        // exp(x*y)
716        // exp(y*y)
717        //                  -- 3
718
719        TestMctsNumberOfSolutions(regProblem, 2, 4 + 8 + 4 + 6 + 2 + 3, allowLog: false, allowInv: false);
720      }
721
722      {
723        // possible solutions with max two variable references:
724        // without exp and sum
725        // x
726        // y
727        // log(x)
728        // log(y)
729        // inv(x)
730        // inv(y)
731        //              -- 6
732        // x * x
733        // x * y
734        // x * log(x)
735        // x * log(y)
736        // x * inv(x)
737        // x * inv(y)
738        //              -- 6
739        // log(x) * log(x)
740        // log(x) * log(y)
741        // log(x) * inv(x)
742        // log(x) * inv(y)
743        //              -- 4
744        // inv(x) * inv(x)
745        // inv(x) * inv(y)
746        //              -- 2
747        // y * y
748        // y * log(x)
749        // y * log(y)
750        // y * inv(x)
751        // y * inv(y)
752        //              -- 5
753        // log(y) * log(y)
754        // log(y) * inv(x)
755        // log(y) * inv(y)
756        //              -- 3
757        // inv(y) * inv(y)
758        //              -- 1
759        // log(x*x)
760        // log(x*y)
761        // log(y*y)
762
763        // inv(x*x)
764        // inv(x*y)
765        // inv(y*y)
766        //             -- 6
767        // log(x+x)
768        // log(x+y)
769        // log(y+y)
770
771        // inv(x+x)
772        // inv(x+y)
773        // inv(y+y)
774        //             -- 6
775        TestMctsNumberOfSolutions(regProblem, 2, 6 + 6 + 4 + 2 + 5 + 3 + 1 + 6 + 6, allowExp: false, allowSum: false);
776      }
777    }
778    #endregion
779
780
781    #region test structure search (no constants)
782    [TestMethod]
783    [TestCategory("Algorithms.DataAnalysis")]
784    [TestProperty("Time", "short")]
785    public void MctsSymbReg_NoConstants_Nguyen1() {
786      // x³ + x² + x
787      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
788      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F1 ")));
789      TestMctsWithoutConstants(regProblem, nVarRefs: 10, allowExp: false, allowLog: false, allowInv: false);
790    }
791    [TestMethod]
792    [TestCategory("Algorithms.DataAnalysis")]
793    [TestProperty("Time", "short")]
794    public void MctsSymbReg_NoConstants_Nguyen2() {
795      // x^4 + x³ + x² + x
796      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
797      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F2 ")));
798      TestMctsWithoutConstants(regProblem, allowExp: false, allowLog: false, allowInv: false);
799    }
800    [TestMethod]
801    [TestCategory("Algorithms.DataAnalysis")]
802    [TestProperty("Time", "short")]
803    public void MctsSymbReg_NoConstants_Nguyen3() {
804      // x^5 + x^4 + x³ + x² + x
805      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
806      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F3 ")));
807      TestMctsWithoutConstants(regProblem, nVarRefs: 15, iterations: 1000000, allowExp: false, allowLog: false, allowInv: false);
808    }
809    [TestMethod]
810    [TestCategory("Algorithms.DataAnalysis")]
811    [TestProperty("Time", "short")]
812    public void MctsSymbReg_NoConstants_Nguyen4() {
813      // x^6 + x^5 + x^4 + x³ + x² + x
814      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
815      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F4 ")));
816      TestMctsWithoutConstants(regProblem, nVarRefs: 25, iterations: 1000000, allowExp: false, allowLog: false, allowInv: false);
817    }
818
819    [TestMethod]
820    [TestCategory("Algorithms.DataAnalysis")]
821    [TestProperty("Time", "short")]
822    public void MctsSymbReg_NoConstants_Nguyen7() {
823      // log(x + 1) + log(x² + 1)
824      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
825      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F7 ")));
826      TestMctsWithoutConstants(regProblem, nVarRefs: 10, iterations: 100000, allowExp: false, allowLog: true, allowInv: false);
827    }
828
829    [TestMethod]
830    [TestCategory("Algorithms.DataAnalysis")]
831    [TestProperty("Time", "short")]
832    public void MctsSymbReg_NoConstants_Poly10_Part1() {
833      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
834      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
835
836      //  Y = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9 + X3*X6*X10
837      //  Y' = X1*X2 + X3*X4 + X5*X6
838      // simplify problem by changing target
839      var ds = ((Dataset)regProblem.Dataset).ToModifiable();
840      var ys = ds.GetDoubleValues("Y").ToArray();
841      var x1 = ds.GetDoubleValues("X1").ToArray();
842      var x2 = ds.GetDoubleValues("X2").ToArray();
843      var x3 = ds.GetDoubleValues("X3").ToArray();
844      var x4 = ds.GetDoubleValues("X4").ToArray();
845      var x5 = ds.GetDoubleValues("X5").ToArray();
846      var x6 = ds.GetDoubleValues("X6").ToArray();
847      var x7 = ds.GetDoubleValues("X7").ToArray();
848      var x8 = ds.GetDoubleValues("X8").ToArray();
849      var x9 = ds.GetDoubleValues("X9").ToArray();
850      var x10 = ds.GetDoubleValues("X10").ToArray();
851      for (int i = 0; i < ys.Length; i++) {
852        ys[i] -= x1[i] * x7[i] * x9[i];
853        ys[i] -= x3[i] * x6[i] * x10[i];
854      }
855      ds.ReplaceVariable("Y", ys.ToList());
856
857      var modifiedProblemData = new RegressionProblemData(ds, regProblem.AllowedInputVariables, regProblem.TargetVariable);
858
859
860      TestMctsWithoutConstants(modifiedProblemData, nVarRefs: 15, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
861    }
862
863    [TestMethod]
864    [TestCategory("Algorithms.DataAnalysis")]
865    [TestProperty("Time", "short")]
866    public void MctsSymbReg_NoConstants_Poly10_Part2() {
867      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
868      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
869
870      //  Y = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9 + X3*X6*X10
871      //  Y' = X1*X7*X9 + X3*X6*X10
872      // simplify problem by changing target
873      var ds = ((Dataset)regProblem.Dataset).ToModifiable();
874      var ys = ds.GetDoubleValues("Y").ToArray();
875      var x1 = ds.GetDoubleValues("X1").ToArray();
876      var x2 = ds.GetDoubleValues("X2").ToArray();
877      var x3 = ds.GetDoubleValues("X3").ToArray();
878      var x4 = ds.GetDoubleValues("X4").ToArray();
879      var x5 = ds.GetDoubleValues("X5").ToArray();
880      var x6 = ds.GetDoubleValues("X6").ToArray();
881      var x7 = ds.GetDoubleValues("X7").ToArray();
882      var x8 = ds.GetDoubleValues("X8").ToArray();
883      var x9 = ds.GetDoubleValues("X9").ToArray();
884      var x10 = ds.GetDoubleValues("X10").ToArray();
885      for (int i = 0; i < ys.Length; i++) {
886        ys[i] -= x1[i] * x2[i];
887        ys[i] -= x3[i] * x4[i];
888        ys[i] -= x5[i] * x6[i];
889      }
890      ds.ReplaceVariable("Y", ys.ToList());
891
892      var modifiedProblemData = new RegressionProblemData(ds, regProblem.AllowedInputVariables, regProblem.TargetVariable);
893
894
895      TestMctsWithoutConstants(modifiedProblemData, nVarRefs: 15, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
896    }
897
898    [TestMethod]
899    [TestCategory("Algorithms.DataAnalysis")]
900    [TestProperty("Time", "short")]
901    public void MctsSymbReg_NoConstants_Poly10_Part3() {
902      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
903      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
904
905      //  Y = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9 + X3*X6*X10
906      //  Y' = X1*X2 + X1*X7*X9
907      // simplify problem by changing target
908      var ds = ((Dataset)regProblem.Dataset).ToModifiable();
909      var ys = ds.GetDoubleValues("Y").ToArray();
910      var x1 = ds.GetDoubleValues("X1").ToArray();
911      var x2 = ds.GetDoubleValues("X2").ToArray();
912      var x3 = ds.GetDoubleValues("X3").ToArray();
913      var x4 = ds.GetDoubleValues("X4").ToArray();
914      var x5 = ds.GetDoubleValues("X5").ToArray();
915      var x6 = ds.GetDoubleValues("X6").ToArray();
916      var x7 = ds.GetDoubleValues("X7").ToArray();
917      var x8 = ds.GetDoubleValues("X8").ToArray();
918      var x9 = ds.GetDoubleValues("X9").ToArray();
919      var x10 = ds.GetDoubleValues("X10").ToArray();
920      for (int i = 0; i < ys.Length; i++) {
921        ys[i] -= x3[i] * x4[i];
922        ys[i] -= x5[i] * x6[i];
923        ys[i] -= x3[i] * x6[i] * x10[i];
924      }
925      ds.ReplaceVariable("Y", ys.ToList());
926
927      var modifiedProblemData = new RegressionProblemData(ds, regProblem.AllowedInputVariables, regProblem.TargetVariable);
928
929
930      TestMctsWithoutConstants(modifiedProblemData, nVarRefs: 15, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
931    }
932
933    [TestMethod]
934    [TestCategory("Algorithms.DataAnalysis")]
935    [TestProperty("Time", "short")]
936    public void MctsSymbReg_NoConstants_Poly10_Part4() {
937      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
938      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
939
940      //  Y = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9 + X3*X6*X10
941      //  Y' = X3*X4 + X5*X6 + X3*X6*X10
942      // simplify problem by changing target
943      var ds = ((Dataset)regProblem.Dataset).ToModifiable();
944      var ys = ds.GetDoubleValues("Y").ToArray();
945      var x1 = ds.GetDoubleValues("X1").ToArray();
946      var x2 = ds.GetDoubleValues("X2").ToArray();
947      var x3 = ds.GetDoubleValues("X3").ToArray();
948      var x4 = ds.GetDoubleValues("X4").ToArray();
949      var x5 = ds.GetDoubleValues("X5").ToArray();
950      var x6 = ds.GetDoubleValues("X6").ToArray();
951      var x7 = ds.GetDoubleValues("X7").ToArray();
952      var x8 = ds.GetDoubleValues("X8").ToArray();
953      var x9 = ds.GetDoubleValues("X9").ToArray();
954      var x10 = ds.GetDoubleValues("X10").ToArray();
955      for (int i = 0; i < ys.Length; i++) {
956        ys[i] -= x1[i] * x2[i];
957        ys[i] -= x1[i] * x7[i] * x9[i];
958      }
959      ds.ReplaceVariable("Y", ys.ToList());
960      var modifiedProblemData = new RegressionProblemData(ds, regProblem.AllowedInputVariables, regProblem.TargetVariable);
961
962
963      TestMctsWithoutConstants(modifiedProblemData, nVarRefs: 15, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
964    }
965
966    [TestMethod]
967    [TestCategory("Algorithms.DataAnalysis")]
968    [TestProperty("Time", "short")]
969    public void MctsSymbReg_NoConstants_Poly10_Part5() {
970      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
971      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
972
973      //  Y = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9 + X3*X6*X10
974      //  Y' = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9
975      // simplify problem by changing target
976      var ds = ((Dataset)regProblem.Dataset).ToModifiable();
977      var ys = ds.GetDoubleValues("Y").ToArray();
978      var x1 = ds.GetDoubleValues("X1").ToArray();
979      var x2 = ds.GetDoubleValues("X2").ToArray();
980      var x3 = ds.GetDoubleValues("X3").ToArray();
981      var x4 = ds.GetDoubleValues("X4").ToArray();
982      var x5 = ds.GetDoubleValues("X5").ToArray();
983      var x6 = ds.GetDoubleValues("X6").ToArray();
984      var x7 = ds.GetDoubleValues("X7").ToArray();
985      var x8 = ds.GetDoubleValues("X8").ToArray();
986      var x9 = ds.GetDoubleValues("X9").ToArray();
987      var x10 = ds.GetDoubleValues("X10").ToArray();
988      for (int i = 0; i < ys.Length; i++) {
989        ys[i] -= x3[i] * x6[i] * x10[i];
990      }
991      ds.ReplaceVariable("Y", ys.ToList());
992      var modifiedProblemData = new RegressionProblemData(ds, regProblem.AllowedInputVariables, regProblem.TargetVariable);
993
994
995      TestMctsWithoutConstants(modifiedProblemData, nVarRefs: 15, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
996    }
997
998    [TestMethod]
999    [TestCategory("Algorithms.DataAnalysis")]
1000    [TestProperty("Time", "short")]
1001    public void MctsSymbReg_NoConstants_Poly10_Part6() {
1002      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
1003      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
1004
1005      //  Y = X1*X2 + X3*X4 + X5*X6 + X1*X7*X9 + X3*X6*X10
1006      //  Y' = X1*X2 + X3*X4 + X5*X6 + X3*X6*X10
1007      // simplify problem by changing target
1008      var ds = ((Dataset)regProblem.Dataset).ToModifiable();
1009      var ys = ds.GetDoubleValues("Y").ToArray();
1010      var x1 = ds.GetDoubleValues("X1").ToArray();
1011      var x2 = ds.GetDoubleValues("X2").ToArray();
1012      var x3 = ds.GetDoubleValues("X3").ToArray();
1013      var x4 = ds.GetDoubleValues("X4").ToArray();
1014      var x5 = ds.GetDoubleValues("X5").ToArray();
1015      var x6 = ds.GetDoubleValues("X6").ToArray();
1016      var x7 = ds.GetDoubleValues("X7").ToArray();
1017      var x8 = ds.GetDoubleValues("X8").ToArray();
1018      var x9 = ds.GetDoubleValues("X9").ToArray();
1019      var x10 = ds.GetDoubleValues("X10").ToArray();
1020      for (int i = 0; i < ys.Length; i++) {
1021        ys[i] -= x1[i] * x7[i] * x9[i];
1022      }
1023      ds.ReplaceVariable("Y", ys.ToList());
1024      var modifiedProblemData = new RegressionProblemData(ds, regProblem.AllowedInputVariables, regProblem.TargetVariable);
1025
1026
1027      TestMctsWithoutConstants(modifiedProblemData, nVarRefs: 9, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
1028    }
1029
1030
1031    [TestMethod]
1032    [TestCategory("Algorithms.DataAnalysis")]
1033    [TestProperty("Time", "long")]
1034    public void MctsSymbReg_NoConstants_Poly10_250rows() {
1035      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.VariousInstanceProvider(seed: 1234);
1036      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Poly-10")));
1037      regProblem.TrainingPartition.Start = 0;
1038      regProblem.TrainingPartition.End = regProblem.Dataset.Rows;
1039      regProblem.TestPartition.Start = 0;
1040      regProblem.TestPartition.End = 2;
1041      TestMctsWithoutConstants(regProblem, nVarRefs: 15, iterations: 200000, allowExp: false, allowLog: false, allowInv: false);
1042    }
1043    [TestMethod]
1044    [TestCategory("Algorithms.DataAnalysis")]
1045    [TestProperty("Time", "long")]
1046    public void MctsSymbReg_NoConstants_Poly10_10000rows() {
1047      // as poly-10 but more rows
1048      var rand = new FastRandom(1234);
1049      var x1 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1050      var x2 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1051      var x3 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1052      var x4 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1053      var x5 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1054      var x6 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1055      var x7 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1056      var x8 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1057      var x9 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1058      var x10 = Enumerable.Range(0, 10000).Select(_ => rand.NextDouble()).ToList();
1059      var ys = new List<double>();
1060      for (int i = 0; i < x1.Count; i++) {
1061        ys.Add(x1[i] * x2[i] + x3[i] * x4[i] + x5[i] * x6[i] + x1[i] * x7[i] * x9[i] + x3[i] * x6[i] * x10[i]);
1062      }
1063
1064      var ds = new Dataset(new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "y" },
1065        new[] { x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, ys });
1066
1067
1068      var problemData = new RegressionProblemData(ds, new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" }, "y");
1069
1070      problemData.TrainingPartition.Start = 0;
1071      problemData.TrainingPartition.End = problemData.Dataset.Rows;
1072      problemData.TestPartition.Start = 0;
1073      problemData.TestPartition.End = 2; // must not be empty
1074
1075
1076      TestMctsWithoutConstants(problemData, nVarRefs: 15, iterations: 100000, allowExp: false, allowLog: false, allowInv: false);
1077    }
1078
1079    [TestMethod]
1080    [TestCategory("Algorithms.DataAnalysis")]
1081    [TestProperty("Time", "short")]
1082    public void MctsSymbReg_NoConstants_TwoVars() {
1083
1084      // y = x1 + x2 + x1*x2 + x1*x2*x2 + x1*x1*x2
1085      var rand = new FastRandom(1234);
1086      var x1 = Enumerable.Range(0, 100).Select(_ => rand.NextDouble()).ToList();
1087      var x2 = Enumerable.Range(0, 100).Select(_ => rand.NextDouble()).ToList();
1088      var ys = x1.Zip(x2, (x1i, x2i) => x1i + x2i + x1i * x2i + x1i * x2i * x2i + x1i * x1i * x2i).ToList();
1089
1090      var ds = new Dataset(new string[] { "a", "b", "y" }, new[] { x1, x2, ys });
1091
1092      var problemData = new RegressionProblemData(ds, new string[] { "a", "b" }, "y");
1093
1094
1095      TestMctsWithoutConstants(problemData, nVarRefs: 10, iterations: 10000, allowExp: false, allowLog: false, allowInv: false);
1096    }
1097
1098    [TestMethod]
1099    [TestCategory("Algorithms.DataAnalysis")]
1100    [TestProperty("Time", "short")]
1101    public void MctsSymbReg_NoConstants_Misleading() {
1102
1103      // y = a + baaaaa (the effect of the second term should be very small)
1104      // the alg will quickly find that a has big effect and will search below a
1105      // since we prevent a + a... the algorithm must find the correct expression via a + b...
1106      // however b has a small effect so the branch might not be identified as relevant
1107
1108      var rand = new FastRandom(1234);
1109      var @as = Enumerable.Range(0, 100).Select(_ => rand.NextDouble()).ToList();
1110      var bs = Enumerable.Range(0, 100).Select(_ => rand.NextDouble()).ToList();
1111      var cs = Enumerable.Range(0, 100).Select(_ => rand.NextDouble() * 1.0e-3).ToList();
1112      var ds = Enumerable.Range(0, 100).Select(_ => rand.NextDouble()).ToList();
1113      var es = Enumerable.Range(0, 100).Select(_ => rand.NextDouble()).ToList();
1114      var ys = new double[@as.Count];
1115      for (int i = 0; i < ys.Length; i++)
1116        ys[i] = @as[i] + bs[i] + @as[i] * bs[i] * cs[i];
1117
1118      var dataset = new Dataset(new string[] { "a", "b", "c", "d", "e", "y" }, new[] { @as, bs, cs, ds, es, ys.ToList() });
1119
1120      var problemData = new RegressionProblemData(dataset, new string[] { "a", "b", "c", "d", "e" }, "y");
1121
1122
1123      TestMctsWithoutConstants(problemData, nVarRefs: 10, iterations: 10000, allowExp: false, allowLog: false, allowInv: false);
1124    }
1125    #endregion
1126
1127    #region restricted structure but including numeric constants
1128
1129    [TestMethod]
1130    [TestCategory("Algorithms.DataAnalysis")]
1131    [TestProperty("Time", "short")]
1132    public void MctsSymbRegKeijzer7() {
1133      // ln(x)
1134      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1135      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 7 f(")));
1136      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1137      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1138      TestMcts(regProblem, allowExp: false, allowLog: true, allowInv: false);
1139    }
1140
1141    /*
1142    // [TestMethod]
1143    [TestCategory("Algorithms.DataAnalysis")]
1144    [TestProperty("Time", "short")]
1145    public void MctsSymbRegBenchmarkNguyen5() {
1146      // sin(x²)cos(x) - 1
1147      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider();
1148      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F5 ")));
1149      TestMcts(regProblem);
1150    }
1151    // [TestMethod]
1152    [TestCategory("Algorithms.DataAnalysis")]
1153    [TestProperty("Time", "short")]
1154    public void MctsSymbRegBenchmarkNguyen6() {
1155      // sin(x) + sin(x + x²)
1156      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider();
1157      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F6 ")));
1158      TestMcts(regProblem);
1159    }
1160    */
1161    [TestMethod]
1162    [TestCategory("Algorithms.DataAnalysis")]
1163    [TestProperty("Time", "short")]
1164    public void MctsSymbRegBenchmarkNguyen7() {
1165      //  log(x + 1) + log(x² + 1)
1166      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
1167      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F7 ")));
1168      TestMcts(regProblem, maxVariableReferences: 5, allowExp: false, allowLog: true, allowInv: false);
1169    }
1170    [TestMethod]
1171    [TestCategory("Algorithms.DataAnalysis")]
1172    [TestProperty("Time", "short")]
1173    public void MctsSymbRegBenchmarkNguyen8() {
1174      // Sqrt(x)
1175      // = x ^ 0.5
1176      // = exp(0.5 * log(x))
1177      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
1178      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F8 ")));
1179      TestMcts(regProblem, maxVariableReferences: 5, allowExp: true, allowLog: true, allowInv: false);
1180    }
1181    /*
1182    // [TestMethod]
1183    [TestCategory("Algorithms.DataAnalysis")]
1184    [TestProperty("Time", "short")]
1185    public void MctsSymbRegBenchmarkNguyen9() {
1186      //  sin(x) + sin(y²)
1187      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider();
1188      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F9 ")));
1189      TestMcts(regProblem);
1190    }
1191    // [TestMethod]
1192    [TestCategory("Algorithms.DataAnalysis")]
1193    [TestProperty("Time", "short")]
1194    public void MctsSymbRegBenchmarkNguyen10() {
1195      // 2sin(x)cos(y)
1196      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider();
1197      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F10 ")));
1198      TestMcts(regProblem);
1199    }
1200    */
1201    [TestMethod]
1202    [TestCategory("Algorithms.DataAnalysis")]
1203    [TestProperty("Time", "short")]
1204    public void MctsSymbRegBenchmarkNguyen11() {
1205      // x ^ y  , x > 0, y > 0   
1206      // = exp(y * log(x))
1207      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
1208      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F11 ")));
1209      TestMcts(regProblem, maxVariableReferences: 5, allowExp: true, allowLog: true, allowInv: false);
1210    }
1211    [TestMethod]
1212    [TestCategory("Algorithms.DataAnalysis")]
1213    [TestProperty("Time", "short")]
1214    public void MctsSymbRegBenchmarkNguyen12() {
1215      // x^4 - x³ + y²/2 - y
1216      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.NguyenInstanceProvider(seed: 1234);
1217      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("F12 ")));
1218      TestMcts(regProblem, maxVariableReferences: 20, allowExp: false, allowLog: false, allowInv: false);
1219    }
1220
1221    #endregion
1222
1223    #region keijzer
1224    [TestMethod]
1225    [TestCategory("Algorithms.DataAnalysis")]
1226    [TestProperty("Time", "long")]
1227    public void MctsSymbRegBenchmarkKeijzer5() {
1228      // (30 * x * z) / ((x - 10)  * y²)
1229      // = 30 x z / (xy² - y²)
1230      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1231      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 5 f(")));
1232      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1233      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1234      TestMcts(regProblem, maxVariableReferences: 20, allowExp: false, allowLog: false, allowInv: true);
1235    }
1236
1237    [TestMethod]
1238    [TestCategory("Algorithms.DataAnalysis")]
1239    [TestProperty("Time", "short")]
1240    public void MctsSymbRegBenchmarkKeijzer6() {
1241      // Keijzer 6 f(x) = Sum(1 / i) From 1 to X  , x \in [0..120]
1242      // we can only approximate this
1243      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1244      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 6 f(")));
1245      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1246      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1247      TestMcts(regProblem, maxVariableReferences: 20, allowExp: false, allowLog: false, allowInv: true);
1248    }
1249
1250
1251    [TestMethod]
1252    [TestCategory("Algorithms.DataAnalysis")]
1253    [TestProperty("Time", "short")]
1254    public void MctsSymbRegBenchmarkKeijzer8() {
1255      // sqrt(x)
1256      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1257      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 8 f(")));
1258      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1259      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1260      TestMcts(regProblem, maxVariableReferences: 5, allowExp: true, allowLog: true, allowInv: false);
1261    }
1262
1263    [TestMethod]
1264    [TestCategory("Algorithms.DataAnalysis")]
1265    [TestProperty("Time", "short")]
1266    public void MctsSymbRegBenchmarkKeijzer9() {
1267      // arcsinh(x)  i.e. ln(x + sqrt(x² + 1))
1268      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1269      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 9 f(")));
1270      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1271      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1272      TestMcts(regProblem, maxVariableReferences: 5, allowExp: true, allowLog: true, allowInv: false);
1273    }
1274
1275    /*
1276    [TestMethod]
1277    [TestCategory("Algorithms.DataAnalysis")]
1278    [TestProperty("Time", "short")]
1279    public void MctsSymbRegBenchmarkKeijzer11() {
1280      // xy + sin( (x-1) (y-1) )
1281      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider();
1282      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 11 f(")));
1283      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1284      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1285      TestMcts(regProblem, successThreshold: 0.99); // cannot solve this yet
1286    }
1287     */
1288    [TestMethod]
1289    [TestCategory("Algorithms.DataAnalysis")]
1290    [TestProperty("Time", "short")]
1291    public void MctsSymbRegBenchmarkKeijzer12() {
1292      // x^4 - x³ + y² / 2 - y,  same as Nguyen 12             
1293      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1294      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 12 f(")));
1295      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1296      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1297      TestMcts(regProblem, maxVariableReferences: 15, allowExp: false, allowLog: false, allowInv: false);
1298    }
1299    [TestMethod]
1300    [TestCategory("Algorithms.DataAnalysis")]
1301    [TestProperty("Time", "short")]
1302    public void MctsSymbRegBenchmarkKeijzer14() {
1303      // 8 / (2 + x² + y²)
1304      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1305      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 14 f(")));
1306      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1307      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1308      TestMcts(regProblem, maxVariableReferences: 10, allowExp: false, allowLog: false, allowInv: true);
1309    }
1310    [TestMethod]
1311    [TestCategory("Algorithms.DataAnalysis")]
1312    [TestProperty("Time", "short")]
1313    public void MctsSymbRegBenchmarkKeijzer15() {
1314      // x³ / 5 + y³ / 2 - y - x
1315      var provider = new HeuristicLab.Problems.Instances.DataAnalysis.KeijzerInstanceProvider(seed: 1234);
1316      var regProblem = provider.LoadData(provider.GetDataDescriptors().Single(x => x.Name.Contains("Keijzer 15 f(")));
1317      // some Keijzer problem instances have very large test partitions (here we are not concerened about test performance)
1318      if (regProblem.TestPartition.End - regProblem.TestPartition.Start > 1000) regProblem.TestPartition.End = regProblem.TestPartition.Start + 1000;
1319      TestMcts(regProblem, maxVariableReferences: 10, allowExp: false, allowLog: false, allowInv: false);
1320    }
1321    #endregion
1322
1323    private void TestMcts(IRegressionProblemData problemData,
1324      int iterations = 20000,
1325      double successThreshold = 0.99999,
1326      int maxVariableReferences = 5,
1327      bool allowExp = true,
1328      bool allowLog = true,
1329      bool allowInv = true,
1330      bool allowSum = true
1331      ) {
1332      var mctsSymbReg = new MctsSymbolicRegressionAlgorithm();
1333      var regProblem = new RegressionProblem();
1334      regProblem.ProblemDataParameter.Value = problemData;
1335      #region Algorithm Configuration
1336      mctsSymbReg.Problem = regProblem;
1337      mctsSymbReg.Iterations = iterations;
1338      mctsSymbReg.MaxVariableReferences = maxVariableReferences;
1339
1340      mctsSymbReg.SetSeedRandomly = false;
1341      mctsSymbReg.Seed = 1234;
1342      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("exp")), allowExp);
1343      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("log")), allowLog);
1344      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("1 /")), allowInv);
1345      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("t1(x) + t2(x) + ... ")), allowSum);
1346
1347      mctsSymbReg.ScaleVariables = true;
1348      mctsSymbReg.ConstantOptimizationIterations = 0;
1349
1350      #endregion
1351      RunAlgorithm(mctsSymbReg);
1352
1353      Console.WriteLine(mctsSymbReg.ExecutionTime);
1354      var eps = 1.0 - successThreshold;
1355      Assert.AreEqual(1.0, ((DoubleValue)mctsSymbReg.Results["Best solution quality (train)"].Value).Value, eps);
1356      Assert.AreEqual(1.0, ((DoubleValue)mctsSymbReg.Results["Best solution quality (test)"].Value).Value, eps);
1357    }
1358
1359
1360    private void TestMctsWithoutConstants(IRegressionProblemData problemData,
1361      int nVarRefs = 10,
1362      int iterations = 200000, double successThreshold = 0.99999,
1363      bool allowExp = true,
1364      bool allowLog = true,
1365      bool allowInv = true,
1366      bool allowSum = true
1367      ) {
1368      var mctsSymbReg = new MctsSymbolicRegressionAlgorithm();
1369      var regProblem = new RegressionProblem();
1370      regProblem.ProblemDataParameter.Value = problemData;
1371      #region Algorithm Configuration
1372      mctsSymbReg.Problem = regProblem;
1373      mctsSymbReg.Iterations = iterations;
1374      mctsSymbReg.MaxVariableReferences = nVarRefs;
1375      mctsSymbReg.SetSeedRandomly = false;
1376      mctsSymbReg.Seed = 1234;
1377      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("exp")), allowExp);
1378      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("log")), allowLog);
1379      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("1 /")), allowInv);
1380      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("t1(x) + t2(x) + ... ")), allowSum);
1381
1382      // no constants
1383      mctsSymbReg.ScaleVariables = false;
1384      mctsSymbReg.ConstantOptimizationIterations = -1;
1385
1386      // random policy
1387      // var epsPolicy = new EpsilonGreedy();
1388      // epsPolicy.Eps = 1.0;
1389      // mctsSymbReg.Policy = epsPolicy;
1390
1391      // UCB tuned
1392      var ucbTuned = new UcbTuned();
1393      ucbTuned.C = 1;
1394      mctsSymbReg.Policy = ucbTuned;
1395
1396
1397      #endregion
1398      RunAlgorithm(mctsSymbReg);
1399
1400      Console.WriteLine(mctsSymbReg.ExecutionTime);
1401      var eps = 1.0 - successThreshold;
1402      Assert.AreEqual(1.0, ((DoubleValue)mctsSymbReg.Results["Best solution quality (train)"].Value).Value, eps);
1403      Assert.AreEqual(1.0, ((DoubleValue)mctsSymbReg.Results["Best solution quality (test)"].Value).Value, eps);
1404    }
1405
1406    private void TestMctsNumberOfSolutions(IRegressionProblemData problemData, int maxNumberOfVariables, int expectedNumberOfSolutions,
1407      bool allowProd = true,
1408      bool allowExp = true,
1409      bool allowLog = true,
1410      bool allowInv = true,
1411      bool allowSum = true
1412  ) {
1413      var mctsSymbReg = new MctsSymbolicRegressionAlgorithm();
1414      var regProblem = new RegressionProblem();
1415      regProblem.ProblemDataParameter.Value = problemData;
1416      #region Algorithm Configuration
1417
1418      mctsSymbReg.SetSeedRandomly = false;
1419      mctsSymbReg.Seed = 1234;
1420      mctsSymbReg.Problem = regProblem;
1421      mctsSymbReg.Iterations = int.MaxValue; // stopping when all solutions have been enumerated
1422      mctsSymbReg.MaxVariableReferences = maxNumberOfVariables;
1423      var ucbPolicy = new Ucb();
1424      ucbPolicy.C = 1000; // essentially breadth first search
1425      mctsSymbReg.Policy = ucbPolicy;
1426      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.StartsWith("x * y * ...")), allowProd);
1427      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("exp(c * x * y ...)")), allowExp);
1428      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("log(c + c1 x + c2 x + ...)")), allowLog);
1429      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("1 / (1 + c1 x + c2 x + ...)")), allowInv);
1430      mctsSymbReg.AllowedFactors.SetItemCheckedState(mctsSymbReg.AllowedFactors.Single(s => s.Value.Contains("t1(x) + t2(x) + ... ")), allowSum);
1431      #endregion
1432      RunAlgorithm(mctsSymbReg);
1433
1434      Console.WriteLine(mctsSymbReg.ExecutionTime);
1435      Assert.AreEqual(expectedNumberOfSolutions, ((IntValue)mctsSymbReg.Results["Iterations"].Value).Value);
1436    }
1437
1438
1439    // same as in SamplesUtil
1440    private void RunAlgorithm(IAlgorithm a) {
1441      var trigger = new EventWaitHandle(false, EventResetMode.ManualReset);
1442      Exception ex = null;
1443      a.Stopped += (src, e) => { trigger.Set(); };
1444      a.ExceptionOccurred += (src, e) => { ex = e.Value; trigger.Set(); };
1445      a.Prepare();
1446      a.Start();
1447      trigger.WaitOne();
1448
1449      Assert.AreEqual(ex, null);
1450    }
1451
1452  }
1453}
Note: See TracBrowser for help on using the repository browser.