#region License Information /* HeuristicLab * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Problems.DataAnalysis; using HeuristicLab.Problems.DataAnalysis.Symbolic; using HeuristicLab.Problems.DataAnalysis.Symbolic.ConstantsOptimization; using HeuristicLab.Problems.DataAnalysis.Symbolic.Regression; using HeuristicLab.Problems.Instances.DataAnalysis; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace UnitTests { [TestClass] public class ConstantsOptimizationTests { private static readonly int seed = 1234; public static void CompareConstantsOptimizationResults(IRegressionProblemData problemData, ISymbolicExpressionTree tree) { var applyLinearScaling = true; var old_optimizedTree = (ISymbolicExpressionTree)tree.Clone(); var old_result = SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants( new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), old_optimizedTree, problemData, problemData.TrainingIndices, applyLinearScaling, maxIterations: 10); var new_optimizedTree = (ISymbolicExpressionTree)tree.Clone(); var new_result = LMConstantsOptimizer.OptimizeConstants(new_optimizedTree, problemData.Dataset, problemData.TargetVariable, problemData.TrainingIndices, applyLinearScaling, maxIterations: 10); // extract constants var old_constants = Util.ExtractConstants(old_optimizedTree, applyLinearScaling); var new_constants = Util.ExtractConstants(new_optimizedTree, applyLinearScaling); { // consistency with old ConstOpt style var initalR2 = SymbolicRegressionSingleObjectivePearsonRSquaredEvaluator.Calculate( new SymbolicDataAnalysisExpressionTreeLinearInterpreter(), tree, double.MinValue, double.MaxValue, problemData, problemData.TrainingIndices, applyLinearScaling); // LMConstantsOptimizer returns 0 if optimization was not successful if (initalR2 - new_result > 0.001) { new_result = initalR2; new_constants = old_constants; } } //check R² values Assert.AreEqual(old_result, new_result, 1E-6); //check numeric values of constants for (int i = 0; i < old_constants.Length; i++) { if (old_constants[i] == 0) { Assert.AreEqual(old_constants[i], new_constants[i], 1E-8); // check absolute error } else { Assert.AreEqual(0.0, 1.0 - new_constants[i] / old_constants[i], 1E-6); // check percentual error } } } [TestMethod] [TestCategory("Problems.DataAnalysis.Symbolic.Regression")] [TestProperty("Time", "short")] public void ConstantsOptimizationTest_Nguyen01() { var problemData = new NguyenFunctionOne(seed).GenerateRegressionData(); var modelTemplate = "({0})* CUBE(X) + ({1}) * SQR(X) + ({2}) * X"; string modelString; object[] constants; ISymbolicExpressionTree modelTree; constants = new object[] { 1.0, 2.0, 3.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 5.0, -2.0, 500.362 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { -6987.25, 1, -888 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); } [TestMethod] [TestCategory("Problems.DataAnalysis.Symbolic.Regression")] [TestProperty("Time", "short")] public void ConstantsOptimizationTest_Nguyen03() { var problemData = new NguyenFunctionThree(seed).GenerateRegressionData(); var modelTemplate = "({0})* X*X*X*X*X + ({1}) * X*X*X*X + ({2}) * X*X*X + ({3}) * X*X + ({4}) * X + {5}"; string modelString; object[] constants; ISymbolicExpressionTree modelTree; constants = new object[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 5.0, -2.0, 500.362, -5646, 0.0001, 1234 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { -6987.25, 1, -888, +888, -1, 6987.25, 0, 25 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); } [TestMethod] [TestCategory("Problems.DataAnalysis.Symbolic.Regression")] [TestProperty("Time", "short")] public void ConstantsOptimizationTest_Nguyen05() { var problemData = new NguyenFunctionFive(seed).GenerateRegressionData(); var modelTemplate = "({0}) * SIN(({1})*X*X) * COS(({2})*X) + ({3})"; string modelString; object[] constants; ISymbolicExpressionTree modelTree; constants = new object[] { 1.0, 2.0, 3.0, 4.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 5.0, -2.0, -3.0, 5.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 0.5, 1, 1, 3 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); } [TestMethod] [TestCategory("Problems.DataAnalysis.Symbolic.Regression")] [TestProperty("Time", "short")] public void ConstantsOptimizationTest_Nguyen07() { var problemData = new NguyenFunctionSeven(seed).GenerateRegressionData(); var modelTemplate = "({0}) * LOG(({1})*X + ({2})) + ({3}) * LOG(({4})*X*X + ({5})) + ({6})"; string modelString; object[] constants; ISymbolicExpressionTree modelTree; constants = new object[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 5.0, 2.0, 500.362, -5646, 0.0001, 1234, 421 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); // This test fails not because of a problem in ConstOpt but because of the code in // OnlinePearsonsRCalculator // double xVar = sxCalculator.PopulationVariance; // double yVar = syCalculator.PopulationVariance; // if (xVar.IsAlmost(0.0) || yVar.IsAlmost(0.0)) { // return 0.0; // } else { ... // PopulationVariance might become close to zero, but the result of cov / (sqrt(xvar) * sqrt(yvar) might still be correct. // Currently, we just return 0. Which means that we reset optimized constants to initial values CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { -6987.25, 1, 888, +888, -1, 6987.25, 0, 25 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); } [TestMethod] [TestCategory("Problems.DataAnalysis.Symbolic.Regression")] [TestProperty("Time", "short")] public void ConstantsOptimizationTest_Nguyen08() { var problemData = new NguyenFunctionEight(seed).GenerateRegressionData(); var modelTemplate = "({0})* SQRT(({1}) * X) + ({2})"; string modelString; object[] constants; ISymbolicExpressionTree modelTree; constants = new object[] { 1.0, 2.0, 3.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 5.0, 20.0, -500.362 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { -6987.25, 1, -888 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); } [TestMethod] [TestCategory("Problems.DataAnalysis.Symbolic.Regression")] [TestProperty("Time", "short")] public void ConstantsOptimizationTest_Keijzer05() { var problemData = new KeijzerFunctionFive(seed).GenerateRegressionData(); var modelTemplate = "( ({0}) * X * Z ) / ( (({1}) * X + ({2})) * ({3}) * SQR(Y) ) + ({4})"; string modelString; object[] constants; ISymbolicExpressionTree modelTree; constants = new object[] { 1.0, 2.0, 3.0, 4.0, 5.0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { 5.0, -2.0, 500.362, -5646, 0.0001 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); constants = new object[] { -6987.25, 1, -888, +888, -1, 6987.25, 0 }; modelString = string.Format(modelTemplate, constants); modelTree = new InfixExpressionParser().Parse(modelString); CompareConstantsOptimizationResults(problemData, modelTree); } [TestInitialize] public void InitEnvironment() { System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; } } }