public void Subtract(double p, QuadraticModel Q)
 {
     f -= p * Q.f;
     for (int i = 0; i < g.Length; i++)
     {
         g[i] -= p * Q.g[i];
         for (int j = 0; j <= i; j++)
         {
             h[i][j] -= p * Q.h[i][j];
         }
     }
 }
        private void Initialize(MultiFunctor f, IReadOnlyList <double> x, double s)
        {
            // Allocate storage
            d = x.Count;
            int m = (d + 1) * (d + 2) / 2;

            origin = new double[d];
            points = new double[m][];
            for (int i = 0; i < m; i++)
            {
                points[i] = new double[d];
            }
            values      = new double[m];
            polynomials = new QuadraticModel[m];
            for (int i = 0; i < m; i++)
            {
                polynomials[i] = new QuadraticModel(d);
            }

            // Start with x as the origin.
            x.CopyTo(origin, 0);

            // The first interpolation point is the origin.
            x.CopyTo(points[0], 0);
            values[0] = f.Evaluate(points[0]);

            // Compute 2d more interpolation points one step along each axis.
            int k = 0;

            for (int i = 0; i < d; i++)
            {
                k++;
                x.CopyTo(points[k], 0);
                points[k][i] += s;
                double plusValue = f.Evaluate(points[k]);
                values[k] = plusValue;
                k++;
                x.CopyTo(points[k], 0);
                points[k][i] -= s;
                double minusValue = f.Evaluate(points[k]);
                values[k] = minusValue;
            }

            // Compute d(d+1)/2 more interpolation points at the corners.
            for (int i = 0; i < d; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    k++;
                    x.CopyTo(points[k], 0);
                    points[k][i] += s;
                    points[k][j] += s;
                    double cornerValue = f.Evaluate(points[k]);
                    values[k] = cornerValue;
                }
            }

            double s1 = 1.0 / s;
            double s2 = s1 * s1;

            // Compute the Lagrange polynomial for each point

            k = 0;

            for (int i = 0; i < d; i++)
            {
                k++;
                polynomials[2 * i + 1].g[i]    = 0.5 * s1;
                polynomials[2 * i + 1].h[i][i] = 0.5 * s2;
                k++;
                polynomials[2 * i + 2].g[i]    = -0.5 * s1;
                polynomials[2 * i + 2].h[i][i] = 0.5 * s2;
            }

            for (int i = 0; i < d; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    k++;
                    polynomials[k].h[i][j]          = s2;
                    polynomials[2 * i + 1].h[i][j] -= s2;
                    polynomials[2 * j + 1].h[i][j] -= s2;
                }
            }

            polynomials[0].f = 1.0;
            for (int l = 1; l < m; l++)
            {
                for (int i = 0; i < d; i++)
                {
                    polynomials[0].g[i] -= polynomials[l].g[i];
                    for (int j = 0; j <= i; j++)
                    {
                        polynomials[0].h[i][j] -= polynomials[l].h[i][j];
                    }
                }
            }

            // Compute the total interpolating polynomial.

            total = new QuadraticModel(d);
            for (int l = 0; l < m; l++)
            {
                total.f += values[l] * polynomials[l].f;
                for (int i = 0; i < d; i++)
                {
                    total.g[i] += values[l] * polynomials[l].g[i];
                    for (int j = 0; j <= i; j++)
                    {
                        total.h[i][j] += values[l] * polynomials[l].h[i][j];
                    }
                }
            }

            // Find the minimum point.

            minValueIndex = 0;
            for (int i = 1; i < m; i++)
            {
                if (values[i] < values[minValueIndex])
                {
                    minValueIndex = i;
                }
            }

            // move the origin to the minimum point
            double[] z = new double[d];
            for (int i = 0; i < z.Length; i++)
            {
                z[i] = points[minValueIndex][i] - origin[i];
            }
            ShiftOrigin(z);

            // compute badnesses
            //badnesses = new double[points.Length];
            //for (int i = 0; i < points.Length; i++) {
            //    badnesses[i] = ComputeBadressAbsolute(points[i], values[i]);
            //}
        }
 public void Subtract(double p, QuadraticModel Q)
 {
     f -= p * Q.f;
     for (int i = 0; i < g.Length; i++) {
         g[i] -= p * Q.g[i];
         for (int j = 0; j <= i; j++) {
             h[i][j] -= p * Q.h[i][j];
         }
     }
 }
        private void Initialize(MultiFunctor f, IList<double> x, double s)
        {
            // Allocate storage
            d = x.Count;
            int m = (d + 1) * (d + 2) / 2;
            origin = new double[d];
            points = new double[m][];
            for (int i = 0; i < m; i++) points[i] = new double[d];
            values = new double[m];
            polynomials = new QuadraticModel[m];
            for (int i = 0; i < m; i++) polynomials[i] = new QuadraticModel(d);

            // Start with x as the origin.
            x.CopyTo(origin, 0);

            // The first interpolation point is the origin.
            x.CopyTo(points[0], 0);
            values[0] = f.Evaluate(points[0]);

            // Compute 2d more interpolation points one step along each axis.
            int k = 0;
            for (int i = 0; i < d; i++) {
                k++;
                x.CopyTo(points[k], 0);
                points[k][i] += s;
                double plusValue = f.Evaluate(points[k]);
                values[k] = plusValue;
                k++;
                x.CopyTo(points[k], 0);
                points[k][i] -= s;
                double minusValue = f.Evaluate(points[k]);
                values[k] = minusValue;
            }

            // Compute d(d+1)/2 more interpolation points at the corners.
            for (int i = 0; i < d; i++) {
                for (int j = 0; j < i; j++) {
                    k++;
                    x.CopyTo(points[k], 0);
                    points[k][i] += s;
                    points[k][j] += s;
                    double cornerValue = f.Evaluate(points[k]);
                    values[k] = cornerValue;
                }
            }

            double s1 = 1.0 / s;
            double s2 = s1 * s1;

            // Compute the Lagrange polynomial for each point

            k = 0;

            for (int i = 0; i < d; i++) {
                k++;
                polynomials[2 * i + 1].g[i] = 0.5 * s1;
                polynomials[2 * i + 1].h[i][i] = 0.5 * s2;
                k++;
                polynomials[2 * i + 2].g[i] = -0.5 * s1;
                polynomials[2 * i + 2].h[i][i] = 0.5 * s2;
            }

            for (int i = 0; i < d; i++) {
                for (int j = 0; j < i; j++) {
                    k++;
                    polynomials[k].h[i][j] = s2;
                    polynomials[2 * i + 1].h[i][j] -= s2;
                    polynomials[2 * j + 1].h[i][j] -= s2;
                }
            }

            polynomials[0].f = 1.0;
            for (int l = 1; l < m; l++) {
                for (int i = 0; i < d; i++) {
                    polynomials[0].g[i] -= polynomials[l].g[i];
                    for (int j = 0; j <= i; j++) {
                        polynomials[0].h[i][j] -= polynomials[l].h[i][j];
                    }
                }
            }

            // Compute the total interpolating polynomial.

            total = new QuadraticModel(d);
            for (int l = 0; l < m; l++) {
                total.f += values[l] * polynomials[l].f;
                for (int i = 0; i < d; i++) {
                    total.g[i] += values[l] * polynomials[l].g[i];
                    for (int j = 0; j <= i; j++) {
                        total.h[i][j] += values[l] * polynomials[l].h[i][j];
                    }
                }
            }

            // Find the minimum point.

            minValueIndex = 0;
            for (int i = 1; i < m; i++) {
                if (values[i] < values[minValueIndex]) minValueIndex = i;
            }

            // move the origin to the minimum point
            double[] z = new double[d];
            for (int i = 0; i < z.Length; i++) z[i] = points[minValueIndex][i] - origin[i];
            ShiftOrigin(z);

            // compute badnesses
            //badnesses = new double[points.Length];
            //for (int i = 0; i < points.Length; i++) {
            //    badnesses[i] = ComputeBadressAbsolute(points[i], values[i]);
            //}
        }