protected override Matrix CalculateUpdate(int freeValuesCount, int xLength, Vector originalData, ConstraintRefContainer cons, Matrix n, Vector grad, Vector deltaX)
        {
            var gammatDotN          = new Vector(xLength);
            var firstSecond         = new Matrix(xLength, xLength);
            var deltaXDotGammatDotN = new Matrix(xLength, xLength);

            var gammatDotDeltaXt = new Matrix(xLength, xLength);
            var gradnew          = new Vector(xLength);

            for (var i = 0; i < freeValuesCount; i++)
            {
                gradnew[i] = cons.Grad(originalData, i);
            }

            Vector gamma  = gradnew - grad;
            double bottom = deltaX * gamma;

            //make sure that bottom is never 0
            if (bottom < 1e-9)
            {
                bottom = 1e-9;
            }

            for (var i = 0; i < xLength; i++)
            {
                gammatDotN[i] = 0;
                for (var j = 0; j < freeValuesCount; j++)
                {
                    gammatDotN[i] += gamma[j] * n[i, j];
                }
            }

            double gammatDotNDotGamma = gammatDotN * gamma;

            var firstTerm = 1 + gammatDotNDotGamma / bottom;

            for (var i = 0; i < freeValuesCount; i++)
            {
                for (var j = 0; j < freeValuesCount; j++)
                {
                    firstSecond[i, j]         = ((deltaX[j] * deltaX[i]) / bottom) * firstTerm;
                    deltaXDotGammatDotN[i, j] = deltaX[i] * gammatDotN[j];
                    gammatDotDeltaXt[i, j]    = gamma[i] * deltaX[j];
                }
            }

            Matrix nDotGammaDotDeltaXt = n * gammatDotDeltaXt;

            //Now calculate the BFGS update on N
            n = n + firstSecond - (deltaXDotGammatDotN + nDotGammaDotDeltaXt) * (1 / bottom);
            return(n);
        }
        protected override Matrix CalculateUpdate(int freeValuesCount, int xLength, Vector originalData, ConstraintRefContainer cons, Matrix n, Vector grad, Vector deltaX)
        {
            var firstTerm = new Matrix(xLength, xLength);

            var gradnew = new Vector(xLength);

            for (var i = 0; i < freeValuesCount; i++)
            {
                gradnew[i] = cons.Grad(originalData, i);
            }

            Vector gamma  = gradnew - grad;
            double bottom = deltaX * gamma;

            //make sure that bottom is never 0
            if (bottom < 1e-9)
            {
                bottom = 1e-9;
            }

            double gammatDotNDotGamma = 0.0;

            for (var i = 0; i < xLength; i++)
            {
                for (var j = 0; j < freeValuesCount; j++)
                {
                    gammatDotNDotGamma += gamma[j] * n[i, j] * gamma[i];
                }
            }

            if (gammatDotNDotGamma < 1e-9)
            {
                gammatDotNDotGamma = 1e-9;
            }

            var secondTerm = new Matrix(xLength, xLength);

            for (var i = 0; i < freeValuesCount; i++)
            {
                for (var j = 0; j < freeValuesCount; j++)
                {
                    firstTerm[i, j]  = (deltaX[i] * deltaX[j]) / bottom;
                    secondTerm[i, j] = n[i, j] * gamma[i] * gamma[j] * n[i, j] * (1 / gammatDotNDotGamma);
                }
            }

            //Now calculate the DFP update on N
            n = n + firstTerm - secondTerm;
            return(n);
        }
        public int SolveRef(ref Vector originalData, int freeValuesCount, ConstraintRefContainer cons, double isFine)
        {
            var xLength = originalData.Count;

            //Save the original parameters for later.
            var origSolution1 = new Vector(originalData);

            var convergence = isFine > 0.1 ? XconvergenceFine : XconvergenceRough;
            //Calculate Function at the starting point:
            var f0 = cons.Calc(originalData);

            if (f0 < SmallF)
            {
                return(0);
            }

            //Calculate the gradient at the starting point:

            var grad = new Vector(xLength); //The gradient vector (1xn)

            for (var j = 0; j < freeValuesCount; j++)
            {
                grad[j] = cons.Grad(originalData, j);
            }

            //Initialize N and calculate s
            var n = Matrix.Identity(xLength, xLength);

            var s    = -grad;
            var fnew = f0 + 1;

            var xold = new Vector(originalData); //Storage for the previous design variables

            /////////////////////////////////////////////////////////
            ////  Calculate first step
            /////////////////////////////////////////////////////////

            //Make the initial position alpha1
            double alpha1 = 0;

            ////Take a step of alpha=1 as alpha2
            double alpha2 = 1;

            double f1        = fnew;
            var    alphaStar = LineSearch(cons, xold, s, f1, alpha2, alpha1);

            originalData = xold + alphaStar * s;

            fnew = cons.Calc(originalData);

            /////////////////////////////////////
            // end of first step
            /////////////////////////////////////

            var deltaX  = new Vector(xLength);
            var gradnew = new Vector(xLength);

            double deltaXnorm = 1;

            var iterations = 1;

            deltaX = originalData - xold;
            while (deltaXnorm > convergence && fnew > SmallF && iterations < MaxIterations * xold.Count)
            {
                n = CalculateUpdate(freeValuesCount, xLength, originalData, cons, n, grad, deltaX);
                ////// line search + next steps /////
                for (var i = 0; i < freeValuesCount; i++)
                {
                    gradnew[i] = cons.Grad(originalData, i);
                }
                s = n * (-gradnew);

                //copy newest values to the xold
                xold      = originalData;
                f1        = fnew;
                alphaStar = LineSearch(cons, xold, s, f1, alpha2, alpha1);

                originalData = xold + alphaStar * s;
                fnew         = cons.Calc(originalData);

                deltaX     = originalData - xold;
                grad       = new Vector(gradnew);
                deltaXnorm = deltaX.Norm();
                iterations++;
            }

            // End of function
            double validSolution = isFine < 0.1 ? ValidSolutionFine : ValidSoltuionRough;

            if (fnew < validSolution)
            {
                return(0);
            }

            originalData = origSolution1;
            return(1);
        }