public void OperatorCompositionTest(string string1, string string2, double weight1, double weight2)
        {
            double x = 0;
            double y = 0;
            double z = 0;

            var actual1 = new QuadraticObjectiveFunction(string1);
            var actual2 = new QuadraticObjectiveFunction(string2);
            var actual  = (weight1 * actual1) + (weight2 * actual2);

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        x = (i - 5) / 10.0;
                        y = (j - 5) / 10.0;
                        z = (k - 5) / 10.0;

                        var arg = new[] { x, y, z }.First(actual1.NumberOfVariables);

                        double a = actual.Function(arg);
                        double e = (weight1 * actual1.Function(arg)) + (weight2 * actual2.Function(arg));

                        Assert.AreEqual(e, a, 1e-10);
                        Assert.IsFalse(double.IsNaN(a));
                        Assert.IsFalse(double.IsNaN(e));
                    }
                }
            }
        }
        public void OperatorScalingTest2(string string1, double scalar)
        {
            double x = 0;
            double y = 0;
            double z = 0;

            var actual1 = new QuadraticObjectiveFunction(string1);
            var actual  = actual1 * scalar;

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        x = (i - 5) / 10.0;
                        y = (j - 5) / 10.0;
                        z = (k - 5) / 10.0;

                        var arg = new[] { x, y, z }.First(actual1.NumberOfVariables);

                        double a = actual.Function(arg);
                        double e = actual1.Function(arg) * scalar;

                        Assert.AreEqual(e, a, 1e-10);
                        Assert.IsFalse(double.IsNaN(a));
                        Assert.IsFalse(double.IsNaN(e));
                    }
                }
            }
        }
        public void OperatorCompositionDocumentation()
        {
            #region doc_example
            // The quadratic objective function supports the notion
            // of vector addition and scalar multiplication. That is,
            // QP programs can be linearly combined to create new QP
            // problems. This idea can be useful when composing
            // objective functions.
            var f1 = new QuadraticObjectiveFunction("2x² + 4y² - 2xy + 6");
            var f2 = new QuadraticObjectiveFunction("3x² - 4y² + 6xy + 3x + 2y");

            // Suppose we have the functions:
            //      f₁(x,y) = 2x² - 2xy + 4y² + 6
            //      f₂(x,y) = 3x² + 6xy - 4y² + 3x + 2y
            //
            // Then we can create a new function - f(x,y) - defined as
            // some linear combination of f₁ and f₂. e.g.
            //      f(x,y) = {f₁ + 2f₂}(x,y)
            //
            // In code, we can write this:
            QuadraticObjectiveFunction f = f1 + (2 * f2); // 8x² -4y² +10xy +6x +4y +6

            // And now we can test our new objective function:
            double[] x = { 1, 2 };

            double result1 = f1.Function(x);
            double result2 = f2.Function(x);

            double result = f.Function(x);          // should be 32
            double check  = result1 + 2 * result2;  // should be the same
            #endregion

            Assert.AreEqual(result, check);
        }
        public void LambdaFunctionTest5()
        {
            double x = 0;
            double y = 0;
            double z = 0;

            Func <double> expected = () => 2 * y * x - x * y + y * z;
            var           actual   = new QuadraticObjectiveFunction(() => 2 * y * x - x * y + y * z);

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        x = (i - 5) / 10.0;
                        y = (j - 5) / 10.0;
                        z = (k - 5) / 10.0;

                        double a = actual.Function(new[] { x, y, z });
                        double e = expected();

                        Assert.AreEqual(e, a, 1e-10);
                        Assert.IsFalse(Double.IsNaN(a));
                        Assert.IsFalse(Double.IsNaN(e));
                    }
                }
            }
        }
        public void FunctionTest2()
        {
            double x = 0;
            double y = 0;
            double z = 0;

            Func <double> expected = () => - 2 * x * x + x * y - y * y - 10 * x * z + z * z;
            var           actual   = new QuadraticObjectiveFunction("-2x² + xy - y² - 10xz + z²");

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        x = (i - 5) / 10.0;
                        y = (j - 5) / 10.0;
                        z = (k - 5) / 10.0;

                        double a = actual.Function(new[] { x, y, z });
                        double e = expected();

                        Assert.AreEqual(e, a, 1e-10);
                        Assert.IsFalse(double.IsNaN(a));
                        Assert.IsFalse(double.IsNaN(e));
                    }
                }
            }
        }
        public void NonSymmetricSelfCorrectsTest()
        {
            double x = 0, y = 0;
            var    f1 = new QuadraticObjectiveFunction(() => - 2 * x * x + x * y - y * y - 3 * y * x);
            var    f2 = new QuadraticObjectiveFunction("-2x² + xy - y² - 3yx");

            var correct = new QuadraticObjectiveFunction("-2x² + xy - y² - 3yx");

            double[] arg = { 3, 7 };

            double result1  = f1.Function(arg);
            double result2  = f2.Function(arg);
            double expected = correct.Function(arg);

            Assert.AreEqual(expected, result1);
            Assert.AreEqual(expected, result2);
        }
        public void LambdaFunctionTest3()
        {
            double x = 0;

            Func <double> expected = () => x * x + 1;
            var           actual   = new QuadraticObjectiveFunction(() => x * x + 1);

            for (int i = 0; i < 10; i++)
            {
                x = (i - 5) / 10.0;

                double a = actual.Function(new[] { x });
                double e = expected();

                Assert.AreEqual(e, a, 1e-10);
                Assert.IsFalse(Double.IsNaN(a));
                Assert.IsFalse(Double.IsNaN(e));
            }
        }
        public void LambdaFunctionTest()
        {
            double x = 0;
            double y = 0;

            Func <double> expected = () => - 2 * x * x + x * y - y * y + 5 * y;
            var           actual   = new QuadraticObjectiveFunction(() => - 2 * x * x + x * y - y * y + 5 * y);

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    x = (i - 5) / 10.0;
                    y = (j - 5) / 10.0;

                    double a = actual.Function(new[] { x, y });
                    double e = expected();

                    Assert.AreEqual(e, a, 1e-10);
                    Assert.IsFalse(double.IsNaN(a));
                    Assert.IsFalse(double.IsNaN(e));
                }
            }
        }