public void FunctionTest()
        {
            double x = 0;
            double y = 0;

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

            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));
                }
            }
        }
        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 LambdaFunctionTest4()
        {
            double x = 0;
            double y = 0;
            double z = 0;

            Func<double> expected = () => -x * y + y * z;
            var actual = new QuadraticObjectiveFunction(() => -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 GoldfarbIdnani4()
        {
            // https://github.com/accord-net/framework/issues/171

            int n = 21;
            var Q = Matrix.Diagonal(n, 2.0);
            var d = Vector.Create(3132.0, 6264, 15660, 18792, 21924, 6264, 18792, 21924, 9396, 3132, 12528, 6264, 9396, 18792, 21924, 9396, 3132, 3132, 6264, 15660, 18792);

            int m = 44;

            var b = Vector.Create(
                703.999, -704.001,
                1267.999, -1268.001,
                1565.999, -1566.001,
                471.999, -472.001,
                1425.999, -1426.001, 
                -107.001,
                -1164.001, 
                -57.001,
                -311.001,
                -1433.001, 
                -0.001,
                -0.001, 
                -788.001, 
                -472.001, 
                -850.001, 
                -273.001, 
                -0.001, -0.001, -0.001, -0.001,
                -0.001, -0.001, -0.001, -0.001, -0.001, 
                -0.001, -0.001, -0.001, -0.001, -0.001, 
                -0.001, -0.001, -0.001, -0.001, -0.001, 
                -0.001, -0.001, -0.001, -0.001);

            var A = Matrix.Create(m, n, 
                 1.0, 1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0, 
                -1,  -1, -1, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0, 
                 0,   0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0, 
                 0,   0,  0,  0, -1, -1, -1, -1,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0, -1, -1, -1, -1, -1,  0,  0,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, -1, -1,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   1,  1,  1,  1,  1,  1,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  -1, -1, -1, -1, -1, -1,
                 0,   0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  
                 0,   0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  -1,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,   0, -1,  0,  0,  0,  0,
                 0,   0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,   0,  0,  0,  0,  0,  0,
                 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, -1,  0,  0,   0,  0,  0,  0,  0,  0,
                -1,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0, -1,  0,  0,  0,
                 0,   0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  -1, 0,   0,  0,  0,  0,  0,  0,
                 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);


            var solver = new GoldfarbIdnani(Q, d, A, b, 0);

            //for (int i = 0; i < solver.ConstraintTolerances.Length; i++)
            //    solver.ConstraintTolerances[i] = 1e-1;

            Assert.IsTrue(solver.Minimize());

            QuadraticObjectiveFunction f = new QuadraticObjectiveFunction(Q, d);
            f.Function(solver.Solution);

            var constraints = LinearConstraintCollection.FromMatrix(A, b, 0);

            double[] violation = constraints.Apply(x => x.GetViolation(solver.Solution));
        }