transpose() публичный статический Метод

public static transpose ( Matrix m ) : Matrix
m Matrix
Результат Matrix
Пример #1
0
        //! compute vector of derivatives of the least square function
        public void gradient(ref Vector grad_f, Vector x)
        {
            // size of target and function to fit vectors
            Vector target  = new Vector(lsp_.size());
            Vector fct2fit = new Vector(lsp_.size());
            // size of gradient matrix
            Matrix grad_fct2fit = new Matrix(lsp_.size(), x.size());

            // compute its values
            lsp_.targetValueAndGradient(x, ref grad_fct2fit, ref target, ref fct2fit);
            // do the difference
            Vector diff = target - fct2fit;

            // compute derivative
            grad_f = -2.0 * (Matrix.transpose(grad_fct2fit) * diff);
        }
Пример #2
0
        protected override void generateArguments()
        {
            double rho  = arguments_[0].value(0.0);
            double beta = arguments_[1].value(0.0);

            for (int i = 0; i < size_; ++i)
            {
                for (int j = i; j < size_; ++j)
                {
                    corrMatrix_[i, j]             = corrMatrix_[j, i]
                                                  = rho + (1 - rho) * Math.Exp(-beta * Math.Abs((double)i - (double)j));
                }
            }

            pseudoSqrt_ = MatrixUtilitites.rankReducedSqrt(corrMatrix_, factors_, 1.0, MatrixUtilitites.SalvagingAlgorithm.None);
            corrMatrix_ = pseudoSqrt_ * Matrix.transpose(pseudoSqrt_);
        }
Пример #3
0
        //! compute value and gradient of the least square function
        public double valueAndGradient(ref Vector grad_f, Vector x)
        {
            // size of target and function to fit vectors
            Vector target  = new Vector(lsp_.size());
            Vector fct2fit = new Vector(lsp_.size());
            // size of gradient matrix
            Matrix grad_fct2fit = new Matrix(lsp_.size(), x.size());

            // compute its values
            lsp_.targetValueAndGradient(x, ref grad_fct2fit, ref target, ref fct2fit);
            // do the difference
            Vector diff = target - fct2fit;

            // compute derivative
            grad_f = -2.0 * (Matrix.transpose(grad_fct2fit) * diff);
            // and compute the scalar product (square of the norm)
            return(Vector.DotProduct(diff, diff));
        }
Пример #4
0
        // Take a matrix and make all the eigenvalues non-negative
        private static Matrix projectToPositiveSemidefiniteMatrix(Matrix M)
        {
            int size = M.rows();

            Utils.QL_REQUIRE(size == M.columns(), () => "matrix not square");

            Matrix diagonal = new Matrix(size, size);
            SymmetricSchurDecomposition jd = new SymmetricSchurDecomposition(M);

            for (int i = 0; i < size; ++i)
            {
                diagonal[i, i] = Math.Max(jd.eigenvalues()[i], 0.0);
            }

            Matrix result = jd.eigenvectors() * diagonal * Matrix.transpose(jd.eigenvectors());

            return(result);
        }
Пример #5
0
        //! QR Solve

        /*! This implementation is based on MINPACK
         *  (<http://www.netlib.org/minpack>,
         *  <http://www.netlib.org/cephes/linalg.tgz>)
         *
         *  Given an m by n matrix A, an n by n diagonal matrix d,
         *  and an m-vector b, the problem is to determine an x which
         *  solves the system
         *
         *  A*x = b ,     d*x = 0 ,
         *
         *  in the least squares sense.
         *
         *  d is an input array of length n which must contain the
         *  diagonal elements of the matrix d.
         *
         *  See lmdiff.cpp for further details.
         */
        public static Vector qrSolve(Matrix a, Vector b, bool pivot = true, Vector d = null)
        {
            int m = a.rows();
            int n = a.columns();

            if (d == null)
            {
                d = new Vector();
            }
            Utils.QL_REQUIRE(b.Count == m, () => "dimensions of A and b don't match");
            Utils.QL_REQUIRE(d.Count == n || d.empty(), () => "dimensions of A and d don't match");

            Matrix q = new Matrix(m, n), r = new Matrix(n, n);

            List <int> lipvt = MatrixUtilities.qrDecomposition(a, ref q, ref r, pivot);
            List <int> ipvt  = new List <int>(n);

            ipvt = lipvt;

            //std::copy(lipvt.begin(), lipvt.end(), ipvt.get());

            Matrix aT = Matrix.transpose(a);
            Matrix rT = Matrix.transpose(r);

            Vector sdiag = new Vector(n);
            Vector wa    = new Vector(n);

            Vector ld = new Vector(n, 0.0);

            if (!d.empty())
            {
                ld = d;
                //std::copy(d.begin(), d.end(), ld.begin());
            }
            Vector x   = new Vector(n);
            Vector qtb = Matrix.transpose(q) * b;

            MINPACK.qrsolv(n, rT, n, ipvt, ld, qtb, x, sdiag, wa);

            return(x);
        }
Пример #6
0
        public Matrix jacFcn(int m, int n, Vector x, int iflag)
        {
            Vector xt = new Vector(x);
            Matrix fjac;

            // constraint handling needs some improvement in the future:
            // starting point should not be close to a constraint violation
            if (currentProblem_.constraint().test(xt))
            {
                Matrix tmp = new Matrix(m, n);
                currentProblem_.costFunction().jacobian(tmp, xt);
                Matrix tmpT = Matrix.transpose(tmp);
                fjac = new Matrix(tmpT);
            }
            else
            {
                Matrix tmpT = Matrix.transpose(initJacobian_);
                fjac = new Matrix(tmpT);
            }
            return(fjac);
        }
Пример #7
0
 public void updateInterpolators()
 {
     for (int k = 0; k < nLayers_; ++k)
     {
         transposedPoints_[k] = Matrix.transpose(points_[k]);
         Interpolation2D interpolation;
         if (k <= 4 && backwardFlat_)
         {
             interpolation = new BackwardflatLinearInterpolation(
                 optionTimes_, optionTimes_.Count,
                 swapLengths_, swapLengths_.Count,
                 transposedPoints_[k]);
         }
         else
         {
             interpolation = new BilinearInterpolation(
                 optionTimes_, optionTimes_.Count,
                 swapLengths_, swapLengths_.Count,
                 transposedPoints_[k]);
         }
         interpolators_[k] = new FlatExtrapolator2D(interpolation);
         interpolators_[k].enableExtrapolation();
     }
 }
Пример #8
0
            public override double value(Vector x)
            {
                int i, j, k;

                currentRoot_.fill(1);
                if (lowerDiagonal_)
                {
                    for (i = 0; i < size_; i++)
                    {
                        for (k = 0; k < size_; k++)
                        {
                            if (k > i)
                            {
                                currentRoot_[i, k] = 0;
                            }
                            else
                            {
                                for (j = 0; j <= k; j++)
                                {
                                    if (j == k && k != i)
                                    {
                                        currentRoot_[i, k] *= Math.Cos(x[i * (i - 1) / 2 + j]);
                                    }
                                    else if (j != i)
                                    {
                                        currentRoot_[i, k] *= Math.Sin(x[i * (i - 1) / 2 + j]);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    for (i = 0; i < size_; i++)
                    {
                        for (k = 0; k < size_; k++)
                        {
                            for (j = 0; j <= k; j++)
                            {
                                if (j == k && k != size_ - 1)
                                {
                                    currentRoot_[i, k] *= Math.Cos(x[j * size_ + i]);
                                }
                                else if (j != size_ - 1)
                                {
                                    currentRoot_[i, k] *= Math.Sin(x[j * size_ + i]);
                                }
                            }
                        }
                    }
                }
                double temp, error = 0;

                tempMatrix_    = Matrix.transpose(currentRoot_);
                currentMatrix_ = currentRoot_ * tempMatrix_;
                for (i = 0; i < size_; i++)
                {
                    for (j = 0; j < size_; j++)
                    {
                        temp   = currentMatrix_[i, j] * targetVariance_[i] * targetVariance_[j] - targetMatrix_[i, j];
                        error += temp * temp;
                    }
                }
                return(error);
            }
Пример #9
0
        // Optimization function for hypersphere and lower-diagonal algorithm
        private static Matrix hypersphereOptimize(Matrix targetMatrix, Matrix currentRoot, bool lowerDiagonal)
        {
            int    i, j, k, size = targetMatrix.rows();
            Matrix result   = new Matrix(currentRoot);
            Vector variance = new Vector(size);

            for (i = 0; i < size; i++)
            {
                variance[i] = Math.Sqrt(targetMatrix[i, i]);
            }
            if (lowerDiagonal)
            {
                Matrix approxMatrix = result * Matrix.transpose(result);
                result = MatrixUtilities.CholeskyDecomposition(approxMatrix, true);
                for (i = 0; i < size; i++)
                {
                    for (j = 0; j < size; j++)
                    {
                        result[i, j] /= Math.Sqrt(approxMatrix[i, i]);
                    }
                }
            }
            else
            {
                for (i = 0; i < size; i++)
                {
                    for (j = 0; j < size; j++)
                    {
                        result[i, j] /= variance[i];
                    }
                }
            }

            ConjugateGradient       optimize     = new ConjugateGradient();
            EndCriteria             endCriteria  = new EndCriteria(100, 10, 1e-8, 1e-8, 1e-8);
            HypersphereCostFunction costFunction = new HypersphereCostFunction(targetMatrix, variance, lowerDiagonal);
            NoConstraint            constraint   = new NoConstraint();

            // hypersphere vector optimization

            if (lowerDiagonal)
            {
                Vector       theta = new Vector(size * (size - 1) / 2);
                const double eps   = 1e-16;
                for (i = 1; i < size; i++)
                {
                    for (j = 0; j < i; j++)
                    {
                        theta[i * (i - 1) / 2 + j] = result[i, j];
                        if (theta[i * (i - 1) / 2 + j] > 1 - eps)
                        {
                            theta[i * (i - 1) / 2 + j] = 1 - eps;
                        }
                        if (theta[i * (i - 1) / 2 + j] < -1 + eps)
                        {
                            theta[i * (i - 1) / 2 + j] = -1 + eps;
                        }
                        for (k = 0; k < j; k++)
                        {
                            theta[i * (i - 1) / 2 + j] /= Math.Sin(theta[i * (i - 1) / 2 + k]);
                            if (theta[i * (i - 1) / 2 + j] > 1 - eps)
                            {
                                theta[i * (i - 1) / 2 + j] = 1 - eps;
                            }
                            if (theta[i * (i - 1) / 2 + j] < -1 + eps)
                            {
                                theta[i * (i - 1) / 2 + j] = -1 + eps;
                            }
                        }
                        theta[i * (i - 1) / 2 + j] = Math.Acos(theta[i * (i - 1) / 2 + j]);
                        if (j == i - 1)
                        {
                            if (result[i, i] < 0)
                            {
                                theta[i * (i - 1) / 2 + j] = -theta[i * (i - 1) / 2 + j];
                            }
                        }
                    }
                }
                Problem p = new Problem(costFunction, constraint, theta);
                optimize.minimize(p, endCriteria);
                theta = p.currentValue();
                result.fill(1);
                for (i = 0; i < size; i++)
                {
                    for (k = 0; k < size; k++)
                    {
                        if (k > i)
                        {
                            result[i, k] = 0;
                        }
                        else
                        {
                            for (j = 0; j <= k; j++)
                            {
                                if (j == k && k != i)
                                {
                                    result[i, k] *= Math.Cos(theta[i * (i - 1) / 2 + j]);
                                }
                                else if (j != i)
                                {
                                    result[i, k] *= Math.Sin(theta[i * (i - 1) / 2 + j]);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                Vector       theta = new Vector(size * (size - 1));
                const double eps   = 1e-16;
                for (i = 0; i < size; i++)
                {
                    for (j = 0; j < size - 1; j++)
                    {
                        theta[j * size + i] = result[i, j];
                        if (theta[j * size + i] > 1 - eps)
                        {
                            theta[j * size + i] = 1 - eps;
                        }
                        if (theta[j * size + i] < -1 + eps)
                        {
                            theta[j * size + i] = -1 + eps;
                        }
                        for (k = 0; k < j; k++)
                        {
                            theta[j * size + i] /= Math.Sin(theta[k * size + i]);
                            if (theta[j * size + i] > 1 - eps)
                            {
                                theta[j * size + i] = 1 - eps;
                            }
                            if (theta[j * size + i] < -1 + eps)
                            {
                                theta[j * size + i] = -1 + eps;
                            }
                        }
                        theta[j * size + i] = Math.Acos(theta[j * size + i]);
                        if (j == size - 2)
                        {
                            if (result[i, j + 1] < 0)
                            {
                                theta[j * size + i] = -theta[j * size + i];
                            }
                        }
                    }
                }
                Problem p = new Problem(costFunction, constraint, theta);
                optimize.minimize(p, endCriteria);
                theta = p.currentValue();
                result.fill(1);
                for (i = 0; i < size; i++)
                {
                    for (k = 0; k < size; k++)
                    {
                        for (j = 0; j <= k; j++)
                        {
                            if (j == k && k != size - 1)
                            {
                                result[i, k] *= Math.Cos(theta[j * size + i]);
                            }
                            else if (j != size - 1)
                            {
                                result[i, k] *= Math.Sin(theta[j * size + i]);
                            }
                        }
                    }
                }
            }

            for (i = 0; i < size; i++)
            {
                for (j = 0; j < size; j++)
                {
                    result[i, j] *= variance[i];
                }
            }
            return(result);
        }
Пример #10
0
 public Matrix correlation()
 {
     return(sqrtCorrelation_ * Matrix.transpose(sqrtCorrelation_));
 }
Пример #11
0
        public override Matrix covariance(double t0, Vector x0, double dt)
        {
            Matrix tmp = stdDeviation(t0, x0, dt);

            return(tmp * Matrix.transpose(tmp));
        }
Пример #12
0
        public SVD(Matrix M)
        {
            Matrix A;

            /* The implementation requires that rows > columns.
             * If this is not the case, we decompose M^T instead.
             * Swapping the resulting U and V gives the desired
             * result for M as
             *
             * M^T = U S V^T           (decomposition of M^T)
             *
             * M = (U S V^T)^T         (transpose)
             *
             * M = (V^T^T S^T U^T)     ((AB)^T = B^T A^T)
             *
             * M = V S U^T             (idempotence of transposition,
             *                          symmetry of diagonal matrix S)
             */

            if (M.rows() >= M.columns())
            {
                A          = new Matrix(M);
                transpose_ = false;
            }
            else
            {
                A          = Matrix.transpose(M);
                transpose_ = true;
            }

            m_ = A.rows();
            n_ = A.columns();

            // we're sure that m_ >= n_
            s_ = new Vector(n_);
            U_ = new Matrix(m_, n_);
            V_ = new Matrix(n_, n_);
            Vector e = new Vector(n_);
            Vector work = new Vector(m_);
            int    i, j, k;

            // Reduce A to bidiagonal form, storing the diagonal elements
            // in s and the super-diagonal elements in e.
            int nct = Math.Min(m_ - 1, n_);
            int nrt = Math.Max(0, n_ - 2);

            for (k = 0; k < Math.Max(nct, nrt); k++)
            {
                if (k < nct)
                {
                    // Compute the transformation for the k-th column and
                    // place the k-th diagonal in s[k].
                    // Compute 2-norm of k-th column without under/overflow.
                    s_[k] = 0;
                    for (i = k; i < m_; i++)
                    {
                        s_[k] = hypot(s_[k], A[i, k]);
                    }
                    if (s_[k] != 0.0)
                    {
                        if (A[k, k] < 0.0)
                        {
                            s_[k] = -s_[k];
                        }
                        for (i = k; i < m_; i++)
                        {
                            A[i, k] /= s_[k];
                        }
                        A[k, k] += 1.0;
                    }
                    s_[k] = -s_[k];
                }
                for (j = k + 1; j < n_; j++)
                {
                    if ((k < nct) && (s_[k] != 0.0))
                    {
                        // Apply the transformation.
                        double t = 0;
                        for (i = k; i < m_; i++)
                        {
                            t += A[i, k] * A[i, j];
                        }
                        t = -t / A[k, k];
                        for (i = k; i < m_; i++)
                        {
                            A[i, j] += t * A[i, k];
                        }
                    }

                    // Place the k-th row of A into e for the
                    // subsequent calculation of the row transformation.
                    e[j] = A[k, j];
                }
                if (k < nct)
                {
                    // Place the transformation in U for subsequent back multiplication.
                    for (i = k; i < m_; i++)
                    {
                        U_[i, k] = A[i, k];
                    }
                }
                if (k < nrt)
                {
                    // Compute the k-th row transformation and place the k-th super-diagonal in e[k].
                    // Compute 2-norm without under/overflow.
                    e[k] = 0;
                    for (i = k + 1; i < n_; i++)
                    {
                        e[k] = hypot(e[k], e[i]);
                    }
                    if (e[k] != 0.0)
                    {
                        if (e[k + 1] < 0.0)
                        {
                            e[k] = -e[k];
                        }
                        for (i = k + 1; i < n_; i++)
                        {
                            e[i] /= e[k];
                        }
                        e[k + 1] += 1.0;
                    }
                    e[k] = -e[k];
                    if ((k + 1 < m_) & (e[k] != 0.0))
                    {
                        // Apply the transformation.
                        for (i = k + 1; i < m_; i++)
                        {
                            work[i] = 0.0;
                        }
                        for (j = k + 1; j < n_; j++)
                        {
                            for (i = k + 1; i < m_; i++)
                            {
                                work[i] += e[j] * A[i, j];
                            }
                        }
                        for (j = k + 1; j < n_; j++)
                        {
                            double t = -e[j] / e[k + 1];
                            for (i = k + 1; i < m_; i++)
                            {
                                A[i, j] += t * work[i];
                            }
                        }
                    }

                    // Place the transformation in V for subsequent back multiplication.
                    for (i = k + 1; i < n_; i++)
                    {
                        V_[i, k] = e[i];
                    }
                }
            }

            // Set up the final bidiagonal matrix or order n.
            if (nct < n_)
            {
                s_[nct] = A[nct, nct];
            }
            if (nrt + 1 < n_)
            {
                e[nrt] = A[nrt, n_ - 1];
            }
            e[n_ - 1] = 0.0;

            // generate U
            for (j = nct; j < n_; j++)
            {
                for (i = 0; i < m_; i++)
                {
                    U_[i, j] = 0.0;
                }
                U_[j, j] = 1.0;
            }
            for (k = nct - 1; k >= 0; --k)
            {
                if (s_[k] != 0.0)
                {
                    for (j = k + 1; j < n_; ++j)
                    {
                        double t = 0;
                        for (i = k; i < m_; i++)
                        {
                            t += U_[i, k] * U_[i, j];
                        }
                        t = -t / U_[k, k];
                        for (i = k; i < m_; i++)
                        {
                            U_[i, j] += t * U_[i, k];
                        }
                    }
                    for (i = k; i < m_; i++)
                    {
                        U_[i, k] = -U_[i, k];
                    }
                    U_[k, k] = 1.0 + U_[k, k];
                    for (i = 0; i < k - 1; i++)
                    {
                        U_[i, k] = 0.0;
                    }
                }
                else
                {
                    for (i = 0; i < m_; i++)
                    {
                        U_[i, k] = 0.0;
                    }
                    U_[k, k] = 1.0;
                }
            }

            // generate V
            for (k = n_ - 1; k >= 0; --k)
            {
                if ((k < nrt) & (e[k] != 0.0))
                {
                    for (j = k + 1; j < n_; ++j)
                    {
                        double t = 0;
                        for (i = k + 1; i < n_; i++)
                        {
                            t += V_[i, k] * V_[i, j];
                        }
                        t = -t / V_[k + 1, k];
                        for (i = k + 1; i < n_; i++)
                        {
                            V_[i, j] += t * V_[i, k];
                        }
                    }
                }
                for (i = 0; i < n_; i++)
                {
                    V_[i, k] = 0.0;
                }
                V_[k, k] = 1.0;
            }

            // Main iteration loop for the singular values.
            int    p = n_, pp = p - 1;
            int    iter = 0;
            double eps  = Math.Pow(2.0, -52.0);

            while (p > 0)
            {
                int kase;

                // Here is where a test for too many iterations would go.

                // This section of the program inspects for
                // negligible elements in the s and e arrays.  On
                // completion the variables kase and k are set as follows.

                // kase = 1     if s(p) and e[k-1] are negligible and k<p
                // kase = 2     if s(k) is negligible and k<p
                // kase = 3     if e[k-1] is negligible, k<p, and
                //              s(k), ..., s(p) are not negligible (qr step).
                // kase = 4     if e(p-1) is negligible (convergence).

                for (k = p - 2; k >= -1; --k)
                {
                    if (k == -1)
                    {
                        break;
                    }
                    if (Math.Abs(e[k]) <= eps * (Math.Abs(s_[k]) + Math.Abs(s_[k + 1])))
                    {
                        e[k] = 0.0;
                        break;
                    }
                }
                if (k == p - 2)
                {
                    kase = 4;
                }
                else
                {
                    int ks;
                    for (ks = p - 1; ks >= k; --ks)
                    {
                        if (ks == k)
                        {
                            break;
                        }
                        double t = (ks != p ? Math.Abs(e[ks]) : 0) +
                                   (ks != k + 1 ? Math.Abs(e[ks - 1]) : 0);
                        if (Math.Abs(s_[ks]) <= eps * t)
                        {
                            s_[ks] = 0.0;
                            break;
                        }
                    }
                    if (ks == k)
                    {
                        kase = 3;
                    }
                    else if (ks == p - 1)
                    {
                        kase = 1;
                    }
                    else
                    {
                        kase = 2;
                        k    = ks;
                    }
                }
                k++;

                // Perform the task indicated by kase.
                switch (kase)
                {
                // Deflate negligible s(p).
                case 1: {
                    double f = e[p - 2];
                    e[p - 2] = 0.0;
                    for (j = p - 2; j >= k; --j)
                    {
                        double t  = hypot(s_[j], f);
                        double cs = s_[j] / t;
                        double sn = f / t;
                        s_[j] = t;
                        if (j != k)
                        {
                            f        = -sn * e[j - 1];
                            e[j - 1] = cs * e[j - 1];
                        }
                        for (i = 0; i < n_; i++)
                        {
                            t            = cs * V_[i, j] + sn * V_[i, p - 1];
                            V_[i, p - 1] = -sn * V_[i, j] + cs * V_[i, p - 1];
                            V_[i, j]     = t;
                        }
                    }
                }
                break;

                // Split at negligible s(k).
                case 2: {
                    double f = e[k - 1];
                    e[k - 1] = 0.0;
                    for (j = k; j < p; j++)
                    {
                        double t  = hypot(s_[j], f);
                        double cs = s_[j] / t;
                        double sn = f / t;
                        s_[j] = t;
                        f     = -sn * e[j];
                        e[j]  = cs * e[j];
                        for (i = 0; i < m_; i++)
                        {
                            t            = cs * U_[i, j] + sn * U_[i, k - 1];
                            U_[i, k - 1] = -sn * U_[i, j] + cs * U_[i, k - 1];
                            U_[i, j]     = t;
                        }
                    }
                }
                break;

                // Perform one qr step.
                case 3: {
                    // Calculate the shift.
                    double scale = Math.Max(
                        Math.Max(
                            Math.Max(
                                Math.Max(Math.Abs(s_[p - 1]),
                                         Math.Abs(s_[p - 2])),
                                Math.Abs(e[p - 2])),
                            Math.Abs(s_[k])),
                        Math.Abs(e[k]));
                    double sp    = s_[p - 1] / scale;
                    double spm1  = s_[p - 2] / scale;
                    double epm1  = e[p - 2] / scale;
                    double sk    = s_[k] / scale;
                    double ek    = e[k] / scale;
                    double b     = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2.0;
                    double c     = (sp * epm1) * (sp * epm1);
                    double shift = 0.0;
                    if ((b != 0.0) | (c != 0.0))
                    {
                        shift = Math.Sqrt(b * b + c);
                        if (b < 0.0)
                        {
                            shift = -shift;
                        }
                        shift = c / (b + shift);
                    }
                    double f = (sk + sp) * (sk - sp) + shift;
                    double g = sk * ek;

                    // Chase zeros.
                    for (j = k; j < p - 1; j++)
                    {
                        double t  = hypot(f, g);
                        double cs = f / t;
                        double sn = g / t;
                        if (j != k)
                        {
                            e[j - 1] = t;
                        }
                        f         = cs * s_[j] + sn * e[j];
                        e[j]      = cs * e[j] - sn * s_[j];
                        g         = sn * s_[j + 1];
                        s_[j + 1] = cs * s_[j + 1];
                        for (i = 0; i < n_; i++)
                        {
                            t            = cs * V_[i, j] + sn * V_[i, j + 1];
                            V_[i, j + 1] = -sn * V_[i, j] + cs * V_[i, j + 1];
                            V_[i, j]     = t;
                        }
                        t         = hypot(f, g);
                        cs        = f / t;
                        sn        = g / t;
                        s_[j]     = t;
                        f         = cs * e[j] + sn * s_[j + 1];
                        s_[j + 1] = -sn * e[j] + cs * s_[j + 1];
                        g         = sn * e[j + 1];
                        e[j + 1]  = cs * e[j + 1];
                        if (j < m_ - 1)
                        {
                            for (i = 0; i < m_; i++)
                            {
                                t            = cs * U_[i, j] + sn * U_[i, j + 1];
                                U_[i, j + 1] = -sn * U_[i, j] + cs * U_[i, j + 1];
                                U_[i, j]     = t;
                            }
                        }
                    }
                    e[p - 2] = f;
                    iter     = iter + 1;
                }
                break;

                // Convergence.
                case 4: {
                    // Make the singular values positive.
                    if (s_[k] <= 0.0)
                    {
                        s_[k] = (s_[k] < 0.0 ? -s_[k] : 0.0);
                        for (i = 0; i <= pp; i++)
                        {
                            V_[i, k] = -V_[i, k];
                        }
                    }

                    // Order the singular values.
                    while (k < pp)
                    {
                        if (s_[k] >= s_[k + 1])
                        {
                            break;
                        }
                        s_.swap(k, k + 1);
                        if (k < n_ - 1)
                        {
                            for (i = 0; i < n_; i++)
                            {
                                V_.swap(i, k, i, k + 1);
                            }
                        }
                        if (k < m_ - 1)
                        {
                            for (i = 0; i < m_; i++)
                            {
                                U_.swap(i, k, i, k + 1);
                            }
                        }
                        k++;
                    }
                    iter = 0;
                    --p;
                }
                break;
                }
            }
        }
Пример #13
0
        public LfmHullWhiteParameterization(
            LiborForwardModelProcess process,
            OptionletVolatilityStructure capletVol,
            Matrix correlation, int factors)
            : base(process.size(), factors)
        {
            diffusion_   = new Matrix(size_ - 1, factors_);
            fixingTimes_ = process.fixingTimes();

            Matrix sqrtCorr = new Matrix(size_ - 1, factors_, 1.0);

            if (correlation.empty())
            {
                if (!(factors_ == 1))
                {
                    throw new ApplicationException("correlation matrix must be given for " +
                                                   "multi factor models");
                }
            }
            else
            {
                if (!(correlation.rows() == size_ - 1 &&
                      correlation.rows() == correlation.columns()))
                {
                    throw new ApplicationException("wrong dimesion of the correlation matrix");
                }

                if (!(factors_ <= size_ - 1))
                {
                    throw new ApplicationException("too many factors for given LFM process");
                }

                Matrix tmpSqrtCorr = MatrixUtilitites.pseudoSqrt(correlation,
                                                                 MatrixUtilitites.SalvagingAlgorithm.Spectral);

                // reduce to n factor model
                // "Reconstructing a valid correlation matrix from invalid data"
                // (<http://www.quarchome.org/correlationmatrix.pdf>)
                for (int i = 0; i < size_ - 1; ++i)
                {
                    double d = 0;
                    tmpSqrtCorr.row(i).GetRange(0, factors_).ForEach((ii, vv) => d += vv * tmpSqrtCorr.row(i)[ii]);
                    //sqrtCorr.row(i).GetRange(0, factors_).ForEach((ii, vv) => sqrtCorr.row(i)[ii] = tmpSqrtCorr.row(i).GetRange(0, factors_)[ii] / Math.Sqrt(d));
                    for (int k = 0; k < factors_; ++k)
                    {
                        sqrtCorr[i, k] = tmpSqrtCorr.row(i).GetRange(0, factors_)[k] / Math.Sqrt(d);
                    }
                }
            }
            List <double> lambda      = new List <double>();
            DayCounter    dayCounter  = process.index().dayCounter();
            List <double> fixingTimes = process.fixingTimes();
            List <Date>   fixingDates = process.fixingDates();

            for (int i = 1; i < size_; ++i)
            {
                double cumVar = 0.0;
                for (int j = 1; j < i; ++j)
                {
                    cumVar += lambda[i - j - 1] * lambda[i - j - 1]
                              * (fixingTimes[j + 1] - fixingTimes[j]);
                }

                double vol = capletVol.volatility(fixingDates[i], 0.0, false);
                double var = vol * vol
                             * capletVol.dayCounter().yearFraction(fixingDates[0],
                                                                   fixingDates[i]);
                lambda.Add(Math.Sqrt((var - cumVar)
                                     / (fixingTimes[1] - fixingTimes[0])));
                for (int q = 0; q < factors_; ++q)
                {
                    diffusion_[i - 1, q] = sqrtCorr[i - 1, q] * lambda.Last();
                }
            }
            covariance_ = diffusion_ * Matrix.transpose(diffusion_);
        }
Пример #14
0
        public override void update()
        {
            Vector        tmp = new Vector(size_);
            List <double> dx  = new InitializedList <double>(size_ - 1),
                          S   = new InitializedList <double>(size_ - 1);

            for (int i = 0; i < size_ - 1; ++i)
            {
                dx[i] = xBegin_[i + 1] - xBegin_[i];
                S[i]  = (yBegin_[i + 1] - yBegin_[i]) / dx[i];
            }

            // first derivative approximation
            if (da_ == CubicInterpolation.DerivativeApprox.Spline)
            {
                TridiagonalOperator L = new TridiagonalOperator(size_);
                for (int i = 1; i < size_ - 1; ++i)
                {
                    L.setMidRow(i, dx[i], 2.0 * (dx[i] + dx[i - 1]), dx[i - 1]);
                    tmp[i] = 3.0 * (dx[i] * S[i - 1] + dx[i - 1] * S[i]);
                }

                // left boundary condition
                switch (leftType_)
                {
                case CubicInterpolation.BoundaryCondition.NotAKnot:
                    // ignoring end condition value
                    L.setFirstRow(dx[1] * (dx[1] + dx[0]), (dx[0] + dx[1]) * (dx[0] + dx[1]));
                    tmp[0] = S[0] * dx[1] * (2.0 * dx[1] + 3.0 * dx[0]) + S[1] * dx[0] * dx[0];
                    break;

                case CubicInterpolation.BoundaryCondition.FirstDerivative:
                    L.setFirstRow(1.0, 0.0);
                    tmp[0] = leftValue_;
                    break;

                case CubicInterpolation.BoundaryCondition.SecondDerivative:
                    L.setFirstRow(2.0, 1.0);
                    tmp[0] = 3.0 * S[0] - leftValue_ * dx[0] / 2.0;
                    break;

                case CubicInterpolation.BoundaryCondition.Periodic:
                    // ignoring end condition value
                    throw new NotImplementedException("this end condition is not implemented yet");

                case CubicInterpolation.BoundaryCondition.Lagrange:
                    L.setFirstRow(1.0, 0.0);
                    tmp[0] = cubicInterpolatingPolynomialDerivative(
                        this.xBegin_[0], this.xBegin_[1],
                        this.xBegin_[2], this.xBegin_[3],
                        this.yBegin_[0], this.yBegin_[1],
                        this.yBegin_[2], this.yBegin_[3],
                        this.xBegin_[0]);
                    break;

                default:
                    throw new ArgumentException("unknown end condition");
                }

                // right boundary condition
                switch (rightType_)
                {
                case CubicInterpolation.BoundaryCondition.NotAKnot:
                    // ignoring end condition value
                    L.setLastRow(-(dx[size_ - 2] + dx[size_ - 3]) * (dx[size_ - 2] + dx[size_ - 3]),
                                 -dx[size_ - 3] * (dx[size_ - 3] + dx[size_ - 2]));
                    tmp[size_ - 1] = -S[size_ - 3] * dx[size_ - 2] * dx[size_ - 2] -
                                     S[size_ - 2] * dx[size_ - 3] * (3.0 * dx[size_ - 2] + 2.0 * dx[size_ - 3]);
                    break;

                case CubicInterpolation.BoundaryCondition.FirstDerivative:
                    L.setLastRow(0.0, 1.0);
                    tmp[size_ - 1] = rightValue_;
                    break;

                case CubicInterpolation.BoundaryCondition.SecondDerivative:
                    L.setLastRow(1.0, 2.0);
                    tmp[size_ - 1] = 3.0 * S[size_ - 2] + rightValue_ * dx[size_ - 2] / 2.0;
                    break;

                case CubicInterpolation.BoundaryCondition.Periodic:
                    // ignoring end condition value
                    throw new NotImplementedException("this end condition is not implemented yet");

                case CubicInterpolation.BoundaryCondition.Lagrange:
                    L.setLastRow(0.0, 1.0);
                    tmp[size_ - 1] = cubicInterpolatingPolynomialDerivative(
                        this.xBegin_[size_ - 4], this.xBegin_[size_ - 3],
                        this.xBegin_[size_ - 2], this.xBegin_[size_ - 1],
                        this.yBegin_[size_ - 4], this.yBegin_[size_ - 3],
                        this.yBegin_[size_ - 2], this.yBegin_[size_ - 1],
                        this.xBegin_[size_ - 1]);
                    break;

                default:
                    throw new ArgumentException("unknown end condition");
                }

                // solve the system
                tmp = L.solveFor(tmp);
            }
            else if (da_ == CubicInterpolation.DerivativeApprox.SplineOM1)
            {
                Matrix T_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    T_[i, i]     = dx[i] / 6.0;
                    T_[i, i + 1] = (dx[i + 1] + dx[i]) / 3.0;
                    T_[i, i + 2] = dx[i + 1] / 6.0;
                }
                Matrix S_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    S_[i, i]     = 1.0 / dx[i];
                    S_[i, i + 1] = -(1.0 / dx[i + 1] + 1.0 / dx[i]);
                    S_[i, i + 2] = 1.0 / dx[i + 1];
                }
                Matrix Up_ = new Matrix(size_, 2, 0.0);
                Up_[0, 0]         = 1;
                Up_[size_ - 1, 1] = 1;
                Matrix Us_ = new Matrix(size_, size_ - 2, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    Us_[i + 1, i] = 1;
                }
                Matrix Z_ = Us_ * Matrix.inverse(T_ * Us_);
                Matrix I_ = new Matrix(size_, size_, 0.0);
                for (int i = 0; i < size_; ++i)
                {
                    I_[i, i] = 1;
                }
                Matrix V_ = (I_ - Z_ * T_) * Up_;
                Matrix W_ = Z_ * S_;
                Matrix Q_ = new Matrix(size_, size_, 0.0);
                Q_[0, 0] = 1.0 / (size_ - 1) * dx[0] * dx[0] * dx[0];
                Q_[0, 1] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[0] * dx[0] * dx[0];
                for (int i = 1; i < size_ - 1; ++i)
                {
                    Q_[i, i - 1] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[i - 1] * dx[i - 1] * dx[i - 1];
                    Q_[i, i]     = 1.0 / (size_ - 1) * dx[i] * dx[i] * dx[i] + 1.0 / (size_ - 1) * dx[i - 1] * dx[i - 1] * dx[i - 1];
                    Q_[i, i + 1] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[i] * dx[i] * dx[i];
                }
                Q_[size_ - 1, size_ - 2] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[size_ - 2] * dx[size_ - 2] * dx[size_ - 2];
                Q_[size_ - 1, size_ - 1] = 1.0 / (size_ - 1) * dx[size_ - 2] * dx[size_ - 2] * dx[size_ - 2];
                Matrix J_ = (I_ - V_ * Matrix.inverse(Matrix.transpose(V_) * Q_ * V_) * Matrix.transpose(V_) * Q_) * W_;
                Vector Y_ = new Vector(size_);
                for (int i = 0; i < size_; ++i)
                {
                    Y_[i] = this.yBegin_[i];
                }
                Vector D_ = J_ * Y_;
                for (int i = 0; i < size_ - 1; ++i)
                {
                    tmp[i] = (Y_[i + 1] - Y_[i]) / dx[i] - (2.0 * D_[i] + D_[i + 1]) * dx[i] / 6.0;
                }
                tmp[size_ - 1] = tmp[size_ - 2] + D_[size_ - 2] * dx[size_ - 2] + (D_[size_ - 1] - D_[size_ - 2]) * dx[size_ - 2] / 2.0;
            }
            else if (da_ == CubicInterpolation.DerivativeApprox.SplineOM2)
            {
                Matrix T_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    T_[i, i]     = dx[i] / 6.0;
                    T_[i, i + 1] = (dx[i] + dx[i + 1]) / 3.0;
                    T_[i, i + 2] = dx[i + 1] / 6.0;
                }
                Matrix S_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    S_[i, i]     = 1.0 / dx[i];
                    S_[i, i + 1] = -(1.0 / dx[i + 1] + 1.0 / dx[i]);
                    S_[i, i + 2] = 1.0 / dx[i + 1];
                }
                Matrix Up_ = new Matrix(size_, 2, 0.0);
                Up_[0, 0]         = 1;
                Up_[size_ - 1, 1] = 1;
                Matrix Us_ = new Matrix(size_, size_ - 2, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    Us_[i + 1, i] = 1;
                }
                Matrix Z_ = Us_ * Matrix.inverse(T_ * Us_);
                Matrix I_ = new Matrix(size_, size_, 0.0);
                for (int i = 0; i < size_; ++i)
                {
                    I_[i, i] = 1;
                }
                Matrix V_ = (I_ - Z_ * T_) * Up_;
                Matrix W_ = Z_ * S_;
                Matrix Q_ = new Matrix(size_, size_, 0.0);
                Q_[0, 0] = 1.0 / (size_ - 1) * dx[0];
                Q_[0, 1] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[0];
                for (int i = 1; i < size_ - 1; ++i)
                {
                    Q_[i, i - 1] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[i - 1];
                    Q_[i, i]     = 1.0 / (size_ - 1) * dx[i] + 1.0 / (size_ - 1) * dx[i - 1];
                    Q_[i, i + 1] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[i];
                }
                Q_[size_ - 1, size_ - 2] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[size_ - 2];
                Q_[size_ - 1, size_ - 1] = 1.0 / (size_ - 1) * dx[size_ - 2];
                Matrix J_ = (I_ - V_ * Matrix.inverse(Matrix.transpose(V_) * Q_ * V_) * Matrix.transpose(V_) * Q_) * W_;
                Vector Y_ = new Vector(size_);
                for (int i = 0; i < size_; ++i)
                {
                    Y_[i] = this.yBegin_[i];
                }
                Vector D_ = J_ * Y_;
                for (int i = 0; i < size_ - 1; ++i)
                {
                    tmp[i] = (Y_[i + 1] - Y_[i]) / dx[i] - (2.0 * D_[i] + D_[i + 1]) * dx[i] / 6.0;
                }
                tmp[size_ - 1] = tmp[size_ - 2] + D_[size_ - 2] * dx[size_ - 2] + (D_[size_ - 1] - D_[size_ - 2]) * dx[size_ - 2] / 2.0;
            }
            else
            {
                // local schemes
                if (size_ == 2)
                {
                    tmp[0] = tmp[1] = S[0];
                }
                else
                {
                    switch (da_)
                    {
                    case CubicInterpolation.DerivativeApprox.FourthOrder:
                        throw new NotImplementedException("FourthOrder not implemented yet");

                    case CubicInterpolation.DerivativeApprox.Parabolic:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            tmp[i] = (dx[i - 1] * S[i] + dx[i] * S[i - 1]) / (dx[i] + dx[i - 1]);
                        }
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] -
                                          dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;

                    case CubicInterpolation.DerivativeApprox.FritschButland:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            double Smin = Math.Min(S[i - 1], S[i]);
                            double Smax = Math.Max(S[i - 1], S[i]);
                            tmp[i] = 3.0 * Smin * Smax / (Smax + 2.0 * Smin);
                        }
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] -
                                          dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;

                    case CubicInterpolation.DerivativeApprox.Akima:
                        tmp[0] = (Math.Abs(S[1] - S[0]) * 2 * S[0] * S[1] +
                                  Math.Abs(2 * S[0] * S[1] - 4 * S[0] * S[0] * S[1]) * S[0]) /
                                 (Math.Abs(S[1] - S[0]) + Math.Abs(2 * S[0] * S[1] - 4 * S[0] * S[0] * S[1]));
                        tmp[1] = (Math.Abs(S[2] - S[1]) * S[0] + Math.Abs(S[0] - 2 * S[0] * S[1]) * S[1]) /
                                 (Math.Abs(S[2] - S[1]) + Math.Abs(S[0] - 2 * S[0] * S[1]));
                        for (int i = 2; i < size_ - 2; ++i)
                        {
                            if ((S[i - 2].IsEqual(S[i - 1])) && (S[i].IsNotEqual(S[i + 1])))
                            {
                                tmp[i] = S[i - 1];
                            }
                            else if ((S[i - 2].IsNotEqual(S[i - 1])) && (S[i].IsEqual(S[i + 1])))
                            {
                                tmp[i] = S[i];
                            }
                            else if (S[i].IsEqual(S[i - 1]))
                            {
                                tmp[i] = S[i];
                            }
                            else if ((S[i - 2].IsEqual(S[i - 1])) && (S[i - 1].IsNotEqual(S[i])) && (S[i].IsEqual(S[i + 1])))
                            {
                                tmp[i] = (S[i - 1] + S[i]) / 2.0;
                            }
                            else
                            {
                                tmp[i] = (Math.Abs(S[i + 1] - S[i]) * S[i - 1] + Math.Abs(S[i - 1] - S[i - 2]) * S[i]) /
                                         (Math.Abs(S[i + 1] - S[i]) + Math.Abs(S[i - 1] - S[i - 2]));
                            }
                        }
                        tmp[size_ - 2] = (Math.Abs(2 * S[size_ - 2] * S[size_ - 3] - S[size_ - 2]) * S[size_ - 3] +
                                          Math.Abs(S[size_ - 3] - S[size_ - 4]) * S[size_ - 2]) /
                                         (Math.Abs(2 * S[size_ - 2] * S[size_ - 3] - S[size_ - 2]) +
                                          Math.Abs(S[size_ - 3] - S[size_ - 4]));
                        tmp[size_ - 1] =
                            (Math.Abs(4 * S[size_ - 2] * S[size_ - 2] * S[size_ - 3] - 2 * S[size_ - 2] * S[size_ - 3]) *
                             S[size_ - 2] + Math.Abs(S[size_ - 2] - S[size_ - 3]) * 2 * S[size_ - 2] * S[size_ - 3]) /
                            (Math.Abs(4 * S[size_ - 2] * S[size_ - 2] * S[size_ - 3] - 2 * S[size_ - 2] * S[size_ - 3]) +
                             Math.Abs(S[size_ - 2] - S[size_ - 3]));
                        break;

                    case CubicInterpolation.DerivativeApprox.Kruger:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            if (S[i - 1] * S[i] < 0.0)
                            {
                                // slope changes sign at point
                                tmp[i] = 0.0;
                            }
                            else
                            {
                                // slope will be between the slopes of the adjacent
                                // straight lines and should approach zero if the
                                // slope of either line approaches zero
                                tmp[i] = 2.0 / (1.0 / S[i - 1] + 1.0 / S[i]);
                            }
                        }
                        // end points
                        tmp[0]         = (3.0 * S[0] - tmp[1]) / 2.0;
                        tmp[size_ - 1] = (3.0 * S[size_ - 2] - tmp[size_ - 2]) / 2.0;
                        break;

                    case CubicInterpolation.DerivativeApprox.Harmonic:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            double w1 = 2 * dx[i] + dx[i - 1];
                            double w2 = dx[i] + 2 * dx[i - 1];
                            if (S[i - 1] * S[i] <= 0.0)
                            {
                                // slope changes sign at point
                                tmp[i] = 0.0;
                            }
                            else
                            {
                                // weighted harmonic mean of S[i] and S[i-1] if they
                                // have the same sign; otherwise 0
                                tmp[i] = (w1 + w2) / (w1 / S[i - 1] + w2 / S[i]);
                            }
                        }
                        // end points [0]
                        tmp[0] = ((2 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[1] + dx[0]);
                        if (tmp[0] * S[0] < 0.0)
                        {
                            tmp[0] = 0;
                        }
                        else if (S[0] * S[1] < 0)
                        {
                            if (Math.Abs(tmp[0]) > Math.Abs(3 * S[0]))
                            {
                                tmp[0] = 3 * S[0];
                            }
                        }
                        // end points [n-1]
                        tmp[size_ - 1] = ((2 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 3] + dx[size_ - 2]);
                        if (tmp[size_ - 1] * S[size_ - 2] < 0.0)
                        {
                            tmp[size_ - 1] = 0;
                        }
                        else if (S[size_ - 2] * S[size_ - 3] < 0)
                        {
                            if (Math.Abs(tmp[size_ - 1]) > Math.Abs(3 * S[size_ - 2]))
                            {
                                tmp[size_ - 1] = 3 * S[size_ - 2];
                            }
                        }
                        break;

                    default:
                        throw new ArgumentException("unknown scheme");
                    }
                }
            }

            monotonicityAdjustments_.Erase();

            // Hyman monotonicity constrained filter
            if (monotonic_)
            {
                double correction;
                double pm, pu, pd, M;
                for (int i = 0; i < size_; ++i)
                {
                    if (i == 0)
                    {
                        if (tmp[i] * S[0] > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]),
                                                  Math.Abs(3.0 * S[0]));
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction.IsNotEqual(tmp[i]))
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                    else if (i == size_ - 1)
                    {
                        if (tmp[i] * S[size_ - 2] > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]), Math.Abs(3.0 * S[size_ - 2]));
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction.IsNotEqual(tmp[i]))
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                    else
                    {
                        pm = (S[i - 1] * dx[i] + S[i] * dx[i - 1]) /
                             (dx[i - 1] + dx[i]);
                        M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i - 1]), Math.Abs(S[i])),
                                           Math.Abs(pm));
                        if (i > 1)
                        {
                            if ((S[i - 1] - S[i - 2]) * (S[i] - S[i - 1]) > 0.0)
                            {
                                pd = (S[i - 1] * (2.0 * dx[i - 1] + dx[i - 2])
                                      - S[i - 2] * dx[i - 1]) /
                                     (dx[i - 2] + dx[i - 1]);
                                if (pm * pd > 0.0 && pm * (S[i - 1] - S[i - 2]) > 0.0)
                                {
                                    M = Math.Max(M, 1.5 * Math.Min(
                                                     Math.Abs(pm), Math.Abs(pd)));
                                }
                            }
                        }
                        if (i < size_ - 2)
                        {
                            if ((S[i] - S[i - 1]) * (S[i + 1] - S[i]) > 0.0)
                            {
                                pu = (S[i] * (2.0 * dx[i] + dx[i + 1]) - S[i + 1] * dx[i]) /
                                     (dx[i] + dx[i + 1]);
                                if (pm * pu > 0.0 && -pm * (S[i] - S[i - 1]) > 0.0)
                                {
                                    M = Math.Max(M, 1.5 * Math.Min(
                                                     Math.Abs(pm), Math.Abs(pu)));
                                }
                            }
                        }
                        if (tmp[i] * pm > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]), M);
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction.IsNotEqual(tmp[i]))
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                }
            }

            // cubic coefficients
            for (int i = 0; i < size_ - 1; ++i)
            {
                a_[i] = tmp[i];
                b_[i] = (3.0 * S[i] - tmp[i + 1] - 2.0 * tmp[i]) / dx[i];
                c_[i] = (tmp[i + 1] + tmp[i] - 2.0 * S[i]) / (dx[i] * dx[i]);
            }

            primitiveConst_[0] = 0.0;
            for (int i = 1; i < size_ - 1; ++i)
            {
                primitiveConst_[i] = primitiveConst_[i - 1]
                                     + dx[i - 1] *
                                     (yBegin_[i - 1] + dx[i - 1] *
                                      (a_[i - 1] / 2.0 + dx[i - 1] *
                                       (b_[i - 1] / 3.0 + dx[i - 1] * c_[i - 1] / 4.0)));
            }
        }
Пример #15
0
        //! QR decompoisition

        /*! This implementation is based on MINPACK
         *  (<http://www.netlib.org/minpack>,
         *  <http://www.netlib.org/cephes/linalg.tgz>)
         *
         *  This subroutine uses householder transformations with column
         *  pivoting (optional) to compute a qr factorization of the
         *  m by n matrix A. That is, qrfac determines an orthogonal
         *  matrix q, a permutation matrix p, and an upper trapezoidal
         *  matrix r with diagonal elements of nonincreasing magnitude,
         *  such that A*p = q*r.
         *
         *  Return value ipvt is an integer array of length n, which
         *  defines the permutation matrix p such that A*p = q*r.
         *  Column j of p is column ipvt(j) of the identity matrix.
         *
         *  See lmdiff.cpp for further details.
         */
        //public static List<int> qrDecomposition(Matrix A, Matrix q, Matrix r, bool pivot = true) {
        public static List <int> qrDecomposition(Matrix M, Matrix q, Matrix r, bool pivot)
        {
            Matrix mT = Matrix.transpose(M);
            int    m  = M.rows();
            int    n  = M.columns();

            List <int> lipvt = new InitializedList <int>(n);
            Vector     rdiag = new Vector(n);
            Vector     wa    = new Vector(n);

            MINPACK.qrfac(m, n, mT, 0, (pivot)?1:0, ref lipvt, n, ref rdiag, ref rdiag, wa);

            if (r.columns() != n || r.rows() != n)
            {
                r = new Matrix(n, n);
            }

            for (int i = 0; i < n; ++i)
            {
                //    std::fill(r.row_begin(i), r.row_begin(i)+i, 0.0);
                r[i, i] = rdiag[i];
                if (i < m)
                {
                    //        std::copy(mT.column_begin(i)+i+1, mT.column_end(i),
                    //                  r.row_begin(i)+i+1);
                }
                else
                {
                    //        std::fill(r.row_begin(i)+i+1, r.row_end(i), 0.0);
                }
            }

            if (q.rows() != m || q.columns() != n)
            {
                q = new Matrix(m, n);
            }

            Vector w = new Vector(m);
            //for (int k=0; k < m; ++k) {
            //    std::fill(w.begin(), w.end(), 0.0);
            //    w[k] = 1.0;

            //    for (int j=0; j < Math.Min(n, m); ++j) {
            //        double t3 = mT[j,j];
            //        if (t3 != 0.0) {
            //            double t
            //                = std::inner_product(mT.row_begin(j)+j, mT.row_end(j),
            //                                     w.begin()+j, 0.0)/t3;
            //            for (int i=j; i<m; ++i) {
            //                w[i]-=mT[j,i]*t;
            //            }
            //        }
            //        q[k,j] = w[j];
            //    }
            //    std::fill(q.row_begin(k) + Math.Min(n, m), q.row_end(k), 0.0);
            //}

            List <int> ipvt = new InitializedList <int>(n);

            //if (pivot) {
            //    std::copy(lipvt.get(), lipvt.get()+n, ipvt.begin());
            //}
            //else {
            //    for (int i=0; i < n; ++i)
            //        ipvt[i] = i;
            //}

            return(ipvt);
        }
Пример #16
0
        //! QR decompoisition

        /*! This implementation is based on MINPACK
         *  (<http://www.netlib.org/minpack>,
         *  <http://www.netlib.org/cephes/linalg.tgz>)
         *
         *  This subroutine uses householder transformations with column
         *  pivoting (optional) to compute a qr factorization of the
         *  m by n matrix A. That is, qrfac determines an orthogonal
         *  matrix q, a permutation matrix p, and an upper trapezoidal
         *  matrix r with diagonal elements of nonincreasing magnitude,
         *  such that A*p = q*r.
         *
         *  Return value ipvt is an integer array of length n, which
         *  defines the permutation matrix p such that A*p = q*r.
         *  Column j of p is column ipvt(j) of the identity matrix.
         *
         *  See lmdiff.cpp for further details.
         */
        //public static List<int> qrDecomposition(Matrix A, Matrix q, Matrix r, bool pivot = true) {
        public static List <int> qrDecomposition(Matrix M, ref Matrix q, ref Matrix r, bool pivot)
        {
            Matrix mT = Matrix.transpose(M);
            int    m  = M.rows();
            int    n  = M.columns();

            List <int> lipvt = new InitializedList <int>(n);
            Vector     rdiag = new Vector(n);
            Vector     wa    = new Vector(n);

            MINPACK.qrfac(m, n, mT, 0, (pivot)?1:0, ref lipvt, n, ref rdiag, ref rdiag, wa);

            if (r.columns() != n || r.rows() != n)
            {
                r = new Matrix(n, n);
            }

            for (int i = 0; i < n; ++i)
            {
                r[i, i] = rdiag[i];
                if (i < m)
                {
                    for (int j = i; j < mT.rows() - 1; j++)
                    {
                        r[i, j + 1] = mT[j + 1, i];
                    }
                }
            }

            if (q.rows() != m || q.columns() != n)
            {
                q = new Matrix(m, n);
            }

            Vector w = new Vector(m);

            for (int k = 0; k < m; ++k)
            {
                w.Erase();
                w[k] = 1.0;

                for (int j = 0; j < Math.Min(n, m); ++j)
                {
                    double t3 = mT[j, j];
                    if (t3 != 0.0)
                    {
                        double t = 0;
                        for (int kk = j; kk < mT.columns(); kk++)
                        {
                            t += (mT[j, kk] * w[kk]) / t3;
                        }

                        for (int i = j; i < m; ++i)
                        {
                            w[i] -= mT[j, i] * t;
                        }
                    }
                    q[k, j] = w[j];
                }
            }

            List <int> ipvt = new InitializedList <int>(n);

            if (pivot)
            {
                for (int i = 0; i < n; ++i)
                {
                    ipvt[i] = lipvt[i];
                }
            }
            else
            {
                for (int i = 0; i < n; ++i)
                {
                    ipvt[i] = i;
                }
            }

            return(ipvt);
        }