private void btnSimplify_Click(object sender, EventArgs e)
        {
            var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
            var simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);

            UpdateModel(simplifiedExpressionTree);
        }
        public static ISymbolicRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData, string modelStructure, int maxIterations)
        {
            var parser     = new InfixExpressionParser();
            var tree       = parser.Parse(modelStructure);
            var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();

            if (!SymbolicRegressionConstantOptimizationEvaluator.CanOptimizeConstants(tree))
            {
                throw new ArgumentException("The optimizer does not support the specified model structure.");
            }

            var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();

            SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices,
                                                                              applyLinearScaling: false, maxIterations: maxIterations,
                                                                              updateVariableWeights: false, updateConstantsInTree: true);


            var scaledModel = new SymbolicRegressionModel(problemData.TargetVariable, tree, (ISymbolicDataAnalysisExpressionTreeInterpreter)interpreter.Clone());

            scaledModel.Scale(problemData);
            SymbolicRegressionSolution solution = new SymbolicRegressionSolution(scaledModel, (IRegressionProblemData)problemData.Clone());

            solution.Model.Name = "Regression Model";
            solution.Name       = "Regression Solution";
            return(solution);
        }
        public void SimplifierAxiomsTest()
        {
            SymbolicExpressionImporter importer = new SymbolicExpressionImporter();
            SymbolicDataAnalysisExpressionTreeSimplifier simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
            SymbolicExpressionTreeStringFormatter        formatter  = new SymbolicExpressionTreeStringFormatter();

            #region single argument arithmetics
            {
                var actualTree   = simplifier.Simplify(importer.Import("(+ 1.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(+ (variable 2.0 a))"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(- 1.0)"));
                var expectedTree = importer.Import("-1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(- (variable 2.0 a))"));
                var expectedTree = importer.Import("(variable -2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(* 2.0)"));
                var expectedTree = importer.Import("2.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(* (variable 2.0 a))"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(/ 2.0)"));
                var expectedTree = importer.Import("0.5");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(/ (variable 2.0 a))"));
                var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region aggregation of constants into factors
            {
                var actualTree   = simplifier.Simplify(importer.Import("(* 2.0 (variable 2.0 a))"));
                var expectedTree = importer.Import("(variable 4.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(/ (variable 2.0 a) 2.0)"));
                var expectedTree = importer.Import("(variable 1.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(/ (variable 2.0 a) (* 2.0 2.0))"));
                var expectedTree = importer.Import("(variable 0.5 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region constant and variable folding
            {
                var actualTree   = simplifier.Simplify(importer.Import("(+ 1.0 2.0)"));
                var expectedTree = importer.Import("3.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(+ (variable 2.0 a) (variable 2.0 a))"));
                var expectedTree = importer.Import("(variable 4.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(- (variable 2.0 a) (variable 1.0 a))"));
                var expectedTree = importer.Import("(variable 1.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(* (variable 2.0 a) (variable 2.0 a))"));
                var expectedTree = importer.Import("(* (* (variable 1.0 a) (variable 1.0 a)) 4.0)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                var actualTree   = simplifier.Simplify(importer.Import("(/ (variable 1.0 a) (variable 2.0 a))"));
                var expectedTree = importer.Import("0.5");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region logarithm rules
            {
                // cancellation
                var actualTree   = simplifier.Simplify(importer.Import("(log (exp (variable 2.0 a)))"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // must not transform logs in this way as we do not know wether both variables are positive
                var actualTree   = simplifier.Simplify(importer.Import("(log (* (variable 1.0 a) (variable 1.0 b)))"));
                var expectedTree = importer.Import("(log (* (variable 1.0 a) (variable 1.0 b)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // must not transform logs in this way as we do not know wether both variables are positive
                var actualTree   = simplifier.Simplify(importer.Import("(log (/ (variable 1.0 a) (variable 1.0 b)))"));
                var expectedTree = importer.Import("(log (/ (variable 1.0 a) (variable 1.0 b)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region exponentiation rules
            {
                // cancellation
                var actualTree   = simplifier.Simplify(importer.Import("(exp (log (variable 2.0 a)))"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // exp transformation
                var actualTree   = simplifier.Simplify(importer.Import("(exp (+ (variable 2.0 a) (variable 3.0 b)))"));
                var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (variable 3.0 b)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // exp transformation
                var actualTree   = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (variable 3.0 b)))"));
                var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (variable -3.0 b)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // exp transformation
                var actualTree   = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (* (variable 3.0 b) (variable 4.0 c))))"));
                var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (variable 1.0 c) -12.0)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // exp transformation
                var actualTree   = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (* (variable 3.0 b) (cos (variable 4.0 c)))))"));
                var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (cos (variable 4.0 c)) -3.0)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region power rules
            {
                // cancellation
                var actualTree   = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) 0.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // fixed point
                var actualTree   = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) 1.0)"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // inversion fixed point
                var actualTree   = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) -1.0)"));
                var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // inversion
                var actualTree   = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) -2.0)"));
                var expectedTree = importer.Import("(/ 1.0 (pow (variable 2.0 a) 2.0))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // constant folding
                var actualTree   = simplifier.Simplify(importer.Import("(pow 3.0 2.0)"));
                var expectedTree = importer.Import("9.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region root rules
            {
                // cancellation
                var actualTree   = simplifier.Simplify(importer.Import("(root (variable 2.0 a) 0.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // fixed point
                var actualTree   = simplifier.Simplify(importer.Import("(root (variable 2.0 a) 1.0)"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // inversion fixed point
                var actualTree   = simplifier.Simplify(importer.Import("(root (variable 2.0 a) -1.0)"));
                var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // inversion
                var actualTree   = simplifier.Simplify(importer.Import("(root (variable 2.0 a) -2.0)"));
                var expectedTree = importer.Import("(/ 1.0 (root (variable 2.0 a) 2.0))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // constant folding
                var actualTree   = simplifier.Simplify(importer.Import("(root 9.0 2.0)"));
                var expectedTree = importer.Import("3.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region boolean operations
            {
                // always true and
                var actualTree   = simplifier.Simplify(importer.Import("(and 1.0 2.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // always false and
                var actualTree   = simplifier.Simplify(importer.Import("(and 1.0 -2.0)"));
                var expectedTree = importer.Import("-1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // always true or
                var actualTree   = simplifier.Simplify(importer.Import("(or -1.0 2.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // always false or
                var actualTree   = simplifier.Simplify(importer.Import("(or -1.0 -2.0)"));
                var expectedTree = importer.Import("-1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // constant not
                var actualTree   = simplifier.Simplify(importer.Import("(not -2.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // constant not
                var actualTree   = simplifier.Simplify(importer.Import("(not 2.0)"));
                var expectedTree = importer.Import("-1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // constant not
                var actualTree   = simplifier.Simplify(importer.Import("(not 0.0)"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // nested nots
                var actualTree   = simplifier.Simplify(importer.Import("(not (not 1.0))"));
                var expectedTree = importer.Import("1.0");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // not of non-Boolean argument
                var actualTree   = simplifier.Simplify(importer.Import("(not (variable 1.0 a))"));
                var expectedTree = importer.Import("(not (> (variable 1.0 a) 0.0))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // not Boolean argument
                var actualTree   = simplifier.Simplify(importer.Import("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))"));
                var expectedTree = importer.Import("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
            #region conditionals
            {
                // always false
                var actualTree   = simplifier.Simplify(importer.Import("(if -1.0 (variable 2.0 a) (variable 3.0 a))"));
                var expectedTree = importer.Import("(variable 3.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // always true
                var actualTree   = simplifier.Simplify(importer.Import("(if 1.0 (variable 2.0 a) (variable 3.0 a))"));
                var expectedTree = importer.Import("(variable 2.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // always false (0.0)
                var actualTree   = simplifier.Simplify(importer.Import("(if 0.0 (variable 2.0 a) (variable 3.0 a))"));
                var expectedTree = importer.Import("(variable 3.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // complex constant condition (always false)
                var actualTree   = simplifier.Simplify(importer.Import("(if (* 1.0 -2.0) (variable 2.0 a) (variable 3.0 a))"));
                var expectedTree = importer.Import("(variable 3.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // complex constant condition (always false)
                var actualTree   = simplifier.Simplify(importer.Import("(if (/ (variable 1.0 a) (variable -2.0 a)) (variable 2.0 a) (variable 3.0 a))"));
                var expectedTree = importer.Import("(variable 3.0 a)");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            {
                // insertion of relational operator
                var actualTree   = simplifier.Simplify(importer.Import("(if (variable 1.0 a) (variable 2.0 a) (variable 3.0 a))"));
                var expectedTree = importer.Import("(if (> (variable 1.0 a) 0.0) (variable 2.0 a) (variable 3.0 a))");
                Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
            }
            #endregion
        }
 private void btnSimplify_Click(object sender, EventArgs e) {
   var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
   var simplifiedExpressionTree = simplifier.Simplify(Content.Model.SymbolicExpressionTree);
   UpdateModel(simplifiedExpressionTree);
 }