columns() public method

public columns ( ) : int
return int
Exemplo n.º 1
0
        //! floating reference date, fixed market data
        public SwaptionVolatilityMatrix(
            Calendar calendar,
            BusinessDayConvention bdc,
            List <Period> optionTenors,
            List <Period> swapTenors,
            Matrix vols,
            DayCounter dayCounter)

            : base(optionTenors, swapTenors, 0, calendar, bdc, dayCounter)
        {
            volHandles_   = new InitializedList <List <Handle <Quote> > >(vols.rows());
            volatilities_ = new Matrix(vols.rows(), vols.columns());
            checkInputs(vols.rows(), vols.columns());

            // fill dummy handles to allow generic handle-based
            // computations later on
            for (int i = 0; i < vols.rows(); ++i)
            {
                volHandles_[i] = new InitializedList <Handle <Quote> >(vols.columns());
                for (int j = 0; j < vols.columns(); ++j)
                {
                    volHandles_[i][j] = new Handle <Quote>((new
                                                            SimpleQuote(vols[i, j])));
                }
            }

            interpolation_ =
                new BilinearInterpolation(swapLengths_, swapLengths_.Count,
                                          optionTimes_, optionTimes_.Count,
                                          volatilities_);
        }
Exemplo n.º 2
0
        public static void normalizePseudoRoot(Matrix matrix, Matrix pseudo)
        {
            int size = matrix.rows();

            if (size != pseudo.rows())
            {
                throw new Exception("matrix/pseudo mismatch: matrix rows are " + size +
                                    " while pseudo rows are " + pseudo.columns());
            }
            int pseudoCols = pseudo.columns();

            // row normalization
            for (int i = 0; i < size; ++i)
            {
                double norm = 0.0;
                for (int j = 0; j < pseudoCols; ++j)
                {
                    norm += pseudo[i, j] * pseudo[i, j];
                }
                if (norm > 0.0)
                {
                    double normAdj = Math.Sqrt(matrix[i, i] / norm);
                    for (int j = 0; j < pseudoCols; ++j)
                    {
                        pseudo[i, j] *= normAdj;
                    }
                }
            }
        }
Exemplo n.º 3
0
        //! fixed reference date, floating market data
        public SwaptionVolatilityMatrix(
            Date referenceDate,
            Calendar calendar,
            BusinessDayConvention bdc,
            List <Period> optionTenors,
            List <Period> swapTenors,
            List <List <Handle <Quote> > > vols,
            DayCounter dayCounter,
            bool flatExtrapolation       = false,
            VolatilityType type          = VolatilityType.ShiftedLognormal,
            List <List <double> > shifts = null)
            : base(optionTenors, swapTenors, referenceDate, calendar, bdc, dayCounter)
        {
            volHandles_     = vols;
            shiftValues_    = shifts;
            volatilities_   = new Matrix(vols.Count, vols.First().Count);
            shifts_         = new Matrix(vols.Count, vols.First().Count, 0.0);
            volatilityType_ = type;
            checkInputs(volatilities_.rows(), volatilities_.columns(), shifts_.rows(), shifts_.columns());
            registerWithMarketData();

            // fill dummy handles to allow generic handle-based
            if (shiftValues_ == null)
            {
                shiftValues_ = new InitializedList <List <double> >(volatilities_.rows());
                for (int i = 0; i < volatilities_.rows(); ++i)
                {
                    shiftValues_[i] = new InitializedList <double>(volatilities_.columns());
                    for (int j = 0; j < volatilities_.columns(); ++j)
                    {
                        shiftValues_[i][j] = shifts_.rows() > 0 ? shifts_[i, j] : 0.0;
                    }
                }
            }

            if (flatExtrapolation)
            {
                interpolation_ = new FlatExtrapolator2D(new BilinearInterpolation(
                                                            swapLengths_, swapLengths_.Count,
                                                            optionTimes_, optionTimes_.Count, volatilities_));

                interpolationShifts_ = new FlatExtrapolator2D(new BilinearInterpolation(
                                                                  swapLengths_, swapLengths_.Count,
                                                                  optionTimes_, optionTimes_.Count, shifts_));
            }
            else
            {
                interpolation_ = new BilinearInterpolation(
                    swapLengths_, swapLengths_.Count,
                    optionTimes_, optionTimes_.Count,
                    volatilities_);

                interpolationShifts_ = new BilinearInterpolation(
                    swapLengths_, swapLengths_.Count,
                    optionTimes_, optionTimes_.Count,
                    shifts_);
            }
        }
Exemplo n.º 4
0
        //! floating reference date, fixed market data
        public SwaptionVolatilityMatrix(
            Calendar calendar,
            BusinessDayConvention bdc,
            List <Period> optionTenors,
            List <Period> swapTenors,
            Matrix vols,
            DayCounter dayCounter,
            bool flatExtrapolation = false,
            VolatilityType type    = VolatilityType.ShiftedLognormal,
            Matrix shifts          = null)

            : base(optionTenors, swapTenors, 0, calendar, bdc, dayCounter)
        {
            volHandles_     = new InitializedList <List <Handle <Quote> > >(vols.rows());
            shiftValues_    = new InitializedList <List <double> >(vols.rows());
            volatilities_   = new Matrix(vols.rows(), vols.columns());
            shifts_         = shifts ?? new Matrix(vols.rows(), vols.columns(), 0.0);
            volatilityType_ = type;
            checkInputs(volatilities_.rows(), volatilities_.columns(), shifts_.rows(), shifts_.columns());

            // fill dummy handles to allow generic handle-based
            // computations later on
            for (int i = 0; i < vols.rows(); ++i)
            {
                volHandles_[i]  = new InitializedList <Handle <Quote> >(vols.columns());
                shiftValues_[i] = new InitializedList <double>(vols.columns());
                for (int j = 0; j < vols.columns(); ++j)
                {
                    volHandles_[i][j] = new Handle <Quote>((new
                                                            SimpleQuote(vols[i, j])));
                }
            }

            if (flatExtrapolation)
            {
                interpolation_ = new FlatExtrapolator2D(new BilinearInterpolation(
                                                            swapLengths_, swapLengths_.Count,
                                                            optionTimes_, optionTimes_.Count, volatilities_));

                interpolationShifts_ = new FlatExtrapolator2D(new BilinearInterpolation(
                                                                  swapLengths_, swapLengths_.Count,
                                                                  optionTimes_, optionTimes_.Count, shifts_));
            }
            else
            {
                interpolation_ = new BilinearInterpolation(
                    swapLengths_, swapLengths_.Count,
                    optionTimes_, optionTimes_.Count,
                    volatilities_);

                interpolationShifts_ = new BilinearInterpolation(
                    swapLengths_, swapLengths_.Count,
                    optionTimes_, optionTimes_.Count,
                    shifts_);
            }
        }
Exemplo n.º 5
0
        /// Build matrices ///

        /// Forward moneyness ///
        public void matricesBuildingForwardMoneyness()
        {
            double discount_ = 0.0;

            for (int j = 0; j < fwMoneynessGrid_.columns(); j++)
            {
                for (int i = 0; i < fwMoneynessGrid_.rows(); i++)
                {
                    discount_ = dividendTS_.link.discount(times_[i], true) / riskFreeTS_.link.discount(times_[i], true);
                    fwMoneynessGrid_[i, j] = strikes_[j] / (spot_ * discount_);
                }
            }
        }
Exemplo n.º 6
0
        public static Matrix transpose(Matrix m)
        {
            Matrix result = new Matrix(m.columns(), m.rows());

            for (int i = 0; i < m.rows(); i++)
            {
                for (int j = 0; j < m.columns(); j++)
                {
                    result[j, i] = m[i, j];
                }
            }
            return(result);
        }
Exemplo n.º 7
0
        public BlackVarianceSurface(Date referenceDate,
                                    Calendar calendar,
                                    List <Date> dates,
                                    List <double> strikes,
                                    Matrix blackVolMatrix,
                                    DayCounter dayCounter,
                                    Extrapolation lowerExtrapolation = Extrapolation.InterpolatorDefaultExtrapolation,
                                    Extrapolation upperExtrapolation = Extrapolation.InterpolatorDefaultExtrapolation)
            : base(referenceDate, calendar)
        {
            dayCounter_         = dayCounter;
            maxDate_            = dates.Last();
            strikes_            = strikes;
            lowerExtrapolation_ = lowerExtrapolation;
            upperExtrapolation_ = upperExtrapolation;
            dates_        = dates;
            volatilities_ = blackVolMatrix;

            Utils.QL_REQUIRE(dates.Count == blackVolMatrix.columns(), () =>
                             "mismatch between date vector and vol matrix colums");
            Utils.QL_REQUIRE(strikes_.Count == blackVolMatrix.rows(), () =>
                             "mismatch between money-strike vector and vol matrix rows");
            Utils.QL_REQUIRE(dates[0] >= referenceDate, () =>
                             "cannot have dates[0] < referenceDate");

            int i, j;

            times_     = new InitializedList <double>(dates.Count + 1);
            times_[0]  = 0.0;
            variances_ = new Matrix(strikes_.Count, dates.Count + 1);
            for (i = 0; i < blackVolMatrix.rows(); i++)
            {
                variances_[i, 0] = 0.0;
            }
            for (j = 1; j <= blackVolMatrix.columns(); j++)
            {
                times_[j] = timeFromReference(dates[j - 1]);
                Utils.QL_REQUIRE(times_[j] > times_[j - 1],
                                 () => "dates must be sorted unique!");
                for (i = 0; i < blackVolMatrix.rows(); i++)
                {
                    variances_[i, j] = times_[j] * blackVolMatrix[i, j - 1] * blackVolMatrix[i, j - 1];
                }
            }

            // default: bilinear interpolation
            setInterpolation <Bilinear>();
        }
Exemplo n.º 8
0
        //! fixed reference date, floating market data
        public CapFloorTermVolSurface(Date settlementDate,
                                      Calendar calendar,
                                      BusinessDayConvention bdc,
                                      List <Period> optionTenors,
                                      List <double> strikes,
                                      List <List <Handle <Quote> > > vols,
                                      DayCounter dc = null)
            : base(settlementDate, calendar, bdc, dc ?? new Actual365Fixed())
        {
            nOptionTenors_ = optionTenors.Count;
            optionTenors_  = optionTenors;
            optionDates_   = new InitializedList <Date>(nOptionTenors_);
            optionTimes_   = new InitializedList <double>(nOptionTenors_);
            nStrikes_      = strikes.Count;
            strikes_       = strikes;
            volHandles_    = vols;
            vols_          = new Matrix(vols.Count, vols[0].Count);

            checkInputs();
            initializeOptionDatesAndTimes();
            for (int i = 0; i < nOptionTenors_; ++i)
            {
                Utils.QL_REQUIRE(volHandles_[i].Count == nStrikes_, () =>
                                 (i + 1) + " row of vol handles has size " + volHandles_[i].Count + " instead of " + nStrikes_);
            }
            registerWithMarketData();
            for (int i = 0; i < vols_.rows(); ++i)
            {
                for (int j = 0; j < vols_.columns(); ++j)
                {
                    vols_[i, j] = volHandles_[i][j].link.value();
                }
            }
            interpolate();
        }
Exemplo n.º 9
0
        private void checkSurface()
        {
            Utils.QL_REQUIRE(times_.Count == localVolMatrix_.columns(),
                             () => "mismatch between date vector and vol matrix colums");
            for (int i = 0; i < strikes_.Count; ++i)
            {
                Utils.QL_REQUIRE(strikes_[i].Count == localVolMatrix_.rows(),
                                 () => "mismatch between money-strike vector and "
                                 + "vol matrix rows");
            }

            for (int j = 1; j < times_.Count; j++)
            {
                Utils.QL_REQUIRE(times_[j] > times_[j - 1],
                                 () => "dates must be sorted unique!");
            }

            for (int i = 0; i < strikes_.Count; ++i)
            {
                for (int j = 1; j < strikes_[i].Count; j++)
                {
                    Utils.QL_REQUIRE(strikes_[i][j] >= strikes_[i][j - 1],
                                     () => "strikes must be sorted");
                }
            }
        }
Exemplo n.º 10
0
        public void matricesBuildingB()
        {
            int k = 0;

            for (int j = 0; j < B_.columns(); j++)
            {
                for (int i = 0; i < B_.rows(); i++)
                {
                    if ((i == j) && (i < strikes_.Count + 2))
                    {
                        B_[i, i] = 1.0;
                    }
                    if ((j >= strikes_.Count - 1) && (i >= strikes_.Count + 2))
                    {
                        if (i == j)
                        {
                            k        = i - strikesSpline_[0].Count;
                            B_[i, i] = lambda_ * (1.0 / 3) * (strikesSpline_[0][k + 2] - strikesSpline_[0][k]);
                        }
                        if ((i == j + 1) || (i + 1 == j))
                        {
                            k        = i - strikesSpline_[0].Count;
                            B_[i, j] = lambda_ * (1.0 / 6) * (strikesSpline_[0][k + 1] - strikesSpline_[0][k]);
                        }
                    }
                }
            }
        }
Exemplo n.º 11
0
            public void setLayer(int i, Matrix x)
            {
                Utils.QL_REQUIRE(i < nLayers_, () => "Cube::setLayer: incompatible number of layer ");
                Utils.QL_REQUIRE(x.rows() == optionTimes_.Count, () => "Cube::setLayer: incompatible size 1");
                Utils.QL_REQUIRE(x.columns() == swapLengths_.Count, () => "Cube::setLayer: incompatible size 2");

                points_[i] = x;
            }
Exemplo n.º 12
0
        public static void normalizePseudoRoot(Matrix matrix, Matrix pseudo) {
            int size = matrix.rows();
            if (size != pseudo.rows())
                throw new ApplicationException("matrix/pseudo mismatch: matrix rows are " + size +
                       " while pseudo rows are " + pseudo.columns());
            int pseudoCols = pseudo.columns();

            // row normalization
            for (int i=0; i<size; ++i) {
                double norm = 0.0;
                for (int j=0; j<pseudoCols; ++j)
                    norm += pseudo[i,j]*pseudo[i,j];
                if (norm>0.0) {
                    double normAdj = Math.Sqrt(matrix[i,i]/norm);
                    for (int j=0; j<pseudoCols; ++j)
                        pseudo[i,j] *= normAdj;
                }
            }
        }
Exemplo n.º 13
0
        public static Matrix CholeskyDecomposition(Matrix S, bool flexible)
        {
            int i, j, size = S.rows();

            if (size != S.columns())
            {
                throw new ApplicationException("input matrix is not a square matrix");
            }
            #if QL_EXTRA_SAFETY_CHECKS
            for (i = 0; i < S.rows(); i++)
            {
                for (j = 0; j < i; j++)
                {
                    QL_REQUIRE(S[i][j] == S[j][i], () =>
                               "input matrix is not symmetric");
                }
            }
            #endif

            Matrix result = new Matrix(size, size, 0.0);
            double sum;
            for (i = 0; i < size; i++)
            {
                for (j = i; j < size; j++)
                {
                    sum = S[i, j];
                    for (int k = 0; k <= i - 1; k++)
                    {
                        sum -= result[i, k] * result[j, k];
                    }
                    if (i == j)
                    {
                        if (!(flexible || sum > 0.0))
                        {
                            throw new ApplicationException("input matrix is not positive definite");
                        }
                        // To handle positive semi-definite matrices take the
                        // square root of sum if positive, else zero.
                        result[i, i] = Math.Sqrt(Math.Max(sum, 0.0));
                    }
                    else
                    {
                        // With positive semi-definite matrices is possible
                        // to have result[i][i]==0.0
                        // In this case sum happens to be zero as well
                        result[j, i] = (sum == 0.0 ? 0.0 : sum / result[i, i]);
                    }
                }
            }
            return(result);
        }
Exemplo n.º 14
0
        public override Matrix stdDeviation(double t0, Vector x0, double dt)
        {
            Matrix tmp = sqrtCorrelation_;

            for (int i = 0; i < size(); ++i)
            {
                double sigma = processes_[i].stdDeviation(t0, x0[i], dt);
                for (int j = 0; j < tmp.columns(); j++)
                {
                    tmp[i, j] *= sigma;
                }
            }
            return(tmp);
        }
Exemplo n.º 15
0
        public override Matrix diffusion(double t, Vector x)
        {
            Matrix tmp = sqrtCorrelation_;

            for (int i = 0; i < size(); ++i)
            {
                double sigma = processes_[i].diffusion(t, x[i]);
                for (int j = 0; j < tmp.columns(); j++)
                {
                    tmp[i, j] *= sigma;
                }
            }
            return(tmp);
        }
Exemplo n.º 16
0
        // Take a matrix and make all the diagonal entries 1.
        private static Matrix projectToUnitDiagonalMatrix(Matrix M)
        {
            int size = M.rows();

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

            Matrix result = new Matrix(M);

            for (int i = 0; i < size; ++i)
            {
                result[i, i] = 1.0;
            }

            return(result);
        }
Exemplo n.º 17
0
        /*! \relates Matrix */
        public static Matrix operator *(Matrix m1, Matrix m2)
        {
            Utils.QL_REQUIRE(m1.columns() == m2.rows(), () => "matrices with different sizes (" +
                             m1.rows() + "x" + m1.columns() + ", " +
                             m2.rows() + "x" + m2.columns() + ") cannot be multiplied");
            Matrix result = new Matrix(m1.rows(), m2.columns());

            for (int i = 0; i < result.rows(); i++)
            {
                for (int j = 0; j < result.columns(); j++)
                {
                    result[i, j] = m1.row(i) * m2.column(j);
                }
            }
            return(result);
        }
Exemplo n.º 18
0
        // Matrix infinity norm. See Golub and van Loan (2.3.10) or
        // <http://en.wikipedia.org/wiki/Matrix_norm>
        private static double normInf(Matrix M)
        {
            int    rows = M.rows();
            int    cols = M.columns();
            double norm = 0.0;

            for (int i = 0; i < rows; ++i)
            {
                double colSum = 0.0;
                for (int j = 0; j < cols; ++j)
                {
                    colSum += Math.Abs(M[i, j]);
                }
                norm = Math.Max(norm, colSum);
            }
            return(norm);
        }
Exemplo n.º 19
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);
        }
Exemplo n.º 20
0
        public KernelInterpolation2DImpl(List <double> xBegin, int size, List <double> yBegin, int ySize,
                                         Matrix zData, Kernel kernel)
            : base(xBegin, size, yBegin, ySize, zData)
        {
            xSize_    = size;
            ySize_    = yBegin.Count;
            xySize_   = xSize_ * ySize_;
            invPrec_  = 1.0e-10;
            alphaVec_ = new Vector(xySize_);
            yVec_     = new Vector(xySize_);
            M_        = new Matrix(xySize_, xySize_);
            kernel_   = kernel;

            Utils.QL_REQUIRE(zData.rows() == xSize_, () =>
                             "Z value matrix has wrong number of rows");
            Utils.QL_REQUIRE(zData.columns() == ySize_, () =>
                             "Z value matrix has wrong number of columns");
        }
Exemplo n.º 21
0
 //! fixed reference date, floating market data
 public SwaptionVolatilityMatrix(
     Date referenceDate,
     Calendar calendar,
     BusinessDayConvention bdc,
     List <Period> optionTenors,
     List <Period> swapTenors,
     List <List <Handle <Quote> > > vols,
     DayCounter dayCounter)
     : base(optionTenors, swapTenors, referenceDate, calendar, bdc, dayCounter)
 {
     volHandles_   = vols;
     volatilities_ = new Matrix(vols.Count, vols.First().Count);
     checkInputs(volatilities_.rows(), volatilities_.columns());
     registerWithMarketData();
     interpolation_ = new BilinearInterpolation(swapLengths_, swapLengths_.Count,
                                                optionTimes_, optionTimes_.Count,
                                                volatilities_);
 }
Exemplo n.º 22
0
        // Take a matrix and make all the diagonal entries 1.
        private static Matrix projectToUnitDiagonalMatrix(Matrix M)
        {
            int size = M.rows();

            if (size != M.columns())
            {
                throw new Exception("matrix not square");
            }

            Matrix result = new Matrix(M);

            for (int i = 0; i < size; ++i)
            {
                result[i, i] = 1.0;
            }

            return(result);
        }
Exemplo n.º 23
0
 //! floating reference date, floating market data
 public SwaptionVolatilityMatrix(
     Calendar calendar,
     BusinessDayConvention bdc,
     List<Period> optionTenors,
     List<Period> swapTenors,
     List<List<Handle<Quote> > > vols,
     DayCounter dayCounter)
     : base(optionTenors, swapTenors, 0, calendar, bdc, dayCounter)
 {
     volHandles_=vols;
     volatilities_ = new Matrix(vols.Count, vols.First().Count );
     checkInputs(volatilities_.rows(), volatilities_.columns());
     registerWithMarketData();
     interpolation_ =
     new BilinearInterpolation(swapLengths_, swapLengths_.Count,
     optionTimes_, optionTimes_.Count,
     volatilities_);
 }
Exemplo n.º 24
0
        /*! \relates Matrix */
        public static Matrix operator *(Matrix m1, Matrix m2)
        {
            if (!(m1.columns() == m2.rows()))
            {
                throw new Exception("matrices with different sizes (" +
                                    m1.rows() + "x" + m1.columns() + ", " +
                                    m2.rows() + "x" + m2.columns() + ") cannot be multiplied");
            }
            Matrix result = new Matrix(m1.rows(), m2.columns());

            for (int i = 0; i < result.rows(); i++)
            {
                for (int j = 0; j < result.columns(); j++)
                {
                    result[i, j] = m1.row(i) * m2.column(j);
                }
            }
            return(result);
        }
Exemplo n.º 25
0
        public static Matrix inverse(Matrix m)
        {
            Utils.QL_REQUIRE(m.rows() == m.columns(), () => "matrix is not square");
            int    n      = m.rows();
            Matrix result = new Matrix(n, n);

            for (int i = 0; i < n; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    result[i, j] = m[i, j];
                }
            }

            Matrix lum;

            int[] perm;
            decompose(m, out lum, out perm);

            double[] b = new double[n];
            for (int i = 0; i < n; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    if (i == perm[j])
                    {
                        b[j] = 1.0;
                    }
                    else
                    {
                        b[j] = 0.0;
                    }
                }

                double[] x = Helper(lum, b); //
                for (int j = 0; j < n; ++j)
                {
                    result[j, i] = x[j];
                }
            }
            return(result);
        }
Exemplo n.º 26
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);
        }
Exemplo n.º 27
0
        public static Matrix CholeskyDecomposition(Matrix S, bool flexible)
        {
            int i, j, size = S.rows();

            if(size != S.columns())
                throw new ApplicationException("input matrix is not a square matrix");
            #if QL_EXTRA_SAFETY_CHECKS
            for (i=0; i<S.rows(); i++)
                for (j=0; j<i; j++)
                    QL_REQUIRE(S[i][j] == S[j][i],
                               "input matrix is not symmetric");
            #endif

            Matrix result = new Matrix(size, size, 0.0);
            double sum;
            for (i=0; i<size; i++) {
                for (j=i; j<size; j++) {
                    sum = S[i,j];
                    for (int k=0; k<=i-1; k++) {
                        sum -= result[i,k]*result[j,k];
                    }
                    if (i == j) {
                        if (!(flexible || sum > 0.0))
                            throw new ApplicationException("input matrix is not positive definite");
                        // To handle positive semi-definite matrices take the
                        // square root of sum if positive, else zero.
                        result[i,i] = Math.Sqrt(Math.Max(sum, 0.0));
                    } else {
                        // With positive semi-definite matrices is possible
                        // to have result[i][i]==0.0
                        // In this case sum happens to be zero as well
                        result[j,i] = (sum==0.0 ? 0.0 : sum/result[i,i]);
                    }
                }
            }
            return result;
        }
Exemplo n.º 28
0
        /// A and B ///
        public void matricesBuildingA()
        {
            int k = 0;

            for (int j = 0; j < A_.columns(); j++)
            {
                for (int i = 0; i < A_.rows(); i++)
                {
                    if (i >= strikes_.Count + 1)
                    {
                        if (i == j + strikes_.Count + 1)
                        {
                            k        = i - strikesSpline_[0].Count + 1;
                            A_[i, j] = -(1.0 / 3) * (strikesSpline_[0][k + 2] - strikesSpline_[0][k]);
                        }
                        if ((i == j + strikes_.Count + 1 + 1) || (i + 1 == j + strikes_.Count + 1))
                        {
                            k        = i - strikesSpline_[0].Count + 1;
                            A_[i, j] = -(1.0 / 6) * (strikesSpline_[0][k + 1] - strikesSpline_[0][k]);
                        }
                    }
                }
            }
        }
Exemplo n.º 29
0
        LiborForwardModelProcess makeProcess(Matrix volaComp)
        {
            int factors = (volaComp.empty() ? 1 : volaComp.columns());

            IborIndex index = makeIndex();
            LiborForwardModelProcess process= new LiborForwardModelProcess(len, index,null);

            LfmCovarianceParameterization fct=new LfmHullWhiteParameterization(
                                                    process,
                                                    makeCapVolCurve(Settings.evaluationDate()),
                                                    volaComp * Matrix.transpose(volaComp), factors);

            process.setCovarParam(fct);

            return process;
        }
Exemplo n.º 30
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;
        }
Exemplo n.º 31
0
        protected CPICapFloorTermPriceSurface(double nominal,
                                              double baseRate, // avoids an uncontrolled crash if index has no TS
                                              Period observationLag,
                                              Calendar cal,    // calendar in index may not be useful
                                              BusinessDayConvention bdc,
                                              DayCounter dc,
                                              Handle <ZeroInflationIndex> zii,
                                              Handle <YieldTermStructure> yts,
                                              List <double> cStrikes,
                                              List <double> fStrikes,
                                              List <Period> cfMaturities,
                                              Matrix cPrice,
                                              Matrix fPrice)
            : base(0, cal, baseRate, observationLag, zii.link.frequency(), zii.link.interpolated(), yts, dc)
        {
            zii_          = zii;
            cStrikes_     = cStrikes;
            fStrikes_     = fStrikes;
            cfMaturities_ = cfMaturities;
            cPrice_       = cPrice;
            fPrice_       = fPrice;
            nominal_      = nominal;
            bdc_          = bdc;

            // does the index have a TS?
            Utils.QL_REQUIRE(!zii_.link.zeroInflationTermStructure().empty(), () => "ZITS missing from index");
            Utils.QL_REQUIRE(!nominalTermStructure().empty(), () => "nominal TS missing");

            // data consistency checking, enough data?
            Utils.QL_REQUIRE(fStrikes_.Count > 1, () => "not enough floor strikes");
            Utils.QL_REQUIRE(cStrikes_.Count > 1, () => "not enough cap strikes");
            Utils.QL_REQUIRE(cfMaturities_.Count > 1, () => "not enough maturities");
            Utils.QL_REQUIRE(fStrikes_.Count == fPrice.rows(), () => "floor strikes vs floor price rows not equal");
            Utils.QL_REQUIRE(cStrikes_.Count == cPrice.rows(), () => "cap strikes vs cap price rows not equal");
            Utils.QL_REQUIRE(cfMaturities_.Count == fPrice.columns(), () => "maturities vs floor price columns not equal");
            Utils.QL_REQUIRE(cfMaturities_.Count == cPrice.columns(), () => "maturities vs cap price columns not equal");

            // data has correct properties (positive, monotonic)?
            for (int j = 0; j < cfMaturities_.Count; j++)
            {
                Utils.QL_REQUIRE(cfMaturities[j] > new Period(0, TimeUnit.Days), () => "non-positive maturities");
                if (j > 0)
                {
                    Utils.QL_REQUIRE(cfMaturities[j] > cfMaturities[j - 1], () => "non-increasing maturities");
                }
                for (int i = 0; i < fPrice_.rows(); i++)
                {
                    Utils.QL_REQUIRE(fPrice_[i, j] > 0.0, () => "non-positive floor price: " + fPrice_[i, j]);
                    if (i > 0)
                    {
                        Utils.QL_REQUIRE(fPrice_[i, j] >= fPrice_[i - 1, j], () => "non-increasing floor prices");
                    }
                }
                for (int i = 0; i < cPrice_.rows(); i++)
                {
                    Utils.QL_REQUIRE(cPrice_[i, j] > 0.0, () => "non-positive cap price: " + cPrice_[i, j]);
                    if (i > 0)
                    {
                        Utils.QL_REQUIRE(cPrice_[i, j] <= cPrice_[i - 1, j], () => "non-decreasing cap prices: "
                                         + cPrice_[i, j] + " then " + cPrice_[i - 1, j]);
                    }
                }
            }


            // Get the set of strikes, noting that repeats, overlaps are
            // expected between caps and floors but that no overlap in the
            // output is allowed so no repeats or overlaps are used
            cfStrikes_ = new List <double>();
            for (int i = 0; i < fStrikes_.Count; i++)
            {
                cfStrikes_.Add(fStrikes[i]);
            }
            double eps        = 0.0000001;
            double maxFstrike = fStrikes_.Last();

            for (int i = 0; i < cStrikes_.Count; i++)
            {
                double k = cStrikes[i];
                if (k > maxFstrike + eps)
                {
                    cfStrikes_.Add(k);
                }
            }

            // final consistency checking
            Utils.QL_REQUIRE(cfStrikes_.Count > 2, () => "overall not enough strikes");
            for (int i = 1; i < cfStrikes_.Count; i++)
            {
                Utils.QL_REQUIRE(cfStrikes_[i] > cfStrikes_[i - 1], () => "cfStrikes not increasing");
            }
        }
Exemplo n.º 32
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;
        }
Exemplo n.º 33
0
        //! Returns the pseudo square root of a real symmetric matrix
        /*! Given a matrix \f$ M \f$, the result \f$ S \f$ is defined
            as the matrix such that \f$ S S^T = M. \f$
            If the matrix is not positive semi definite, it can
            return an approximation of the pseudo square root
            using a (user selected) salvaging algorithm.

            For more information see: "The most general methodology to create
            a valid correlation matrix for risk management and option pricing
            purposes", by R. Rebonato and P. Jдckel.
            The Journal of Risk, 2(2), Winter 1999/2000
            http://www.rebonato.com/correlationmatrix.pdf

            Revised and extended in "Monte Carlo Methods in Finance",
            by Peter Jдckel, Chapter 6.

            \pre the given matrix must be symmetric.

            \relates Matrix

            \warning Higham algorithm only works for correlation matrices.

            \test
            - the correctness of the results is tested by reproducing
              known good data.
            - the correctness of the results is tested by checking
              returned values against numerical calculations.
        */
        public static Matrix pseudoSqrt(Matrix matrix, SalvagingAlgorithm sa)
        {
            int size = matrix.rows();

            #if QL_EXTRA_SAFETY_CHECKS
            checkSymmetry(matrix);
            #else
            if (size != matrix.columns())
                throw new ApplicationException("non square matrix: " + size + " rows, " + matrix.columns() + " columns");
            #endif

            // spectral (a.k.a Principal Component) analysis
            SymmetricSchurDecomposition jd = new SymmetricSchurDecomposition(matrix);
            Matrix diagonal = new Matrix(size, size, 0.0);

            // salvaging algorithm
            Matrix result = new Matrix(size, size);
            bool negative;
            switch (sa) {
                case SalvagingAlgorithm.None:
                    // eigenvalues are sorted in decreasing order
                    if (!(jd.eigenvalues()[size-1]>=-1e-16))
                        throw new ApplicationException("negative eigenvalue(s) (" + jd.eigenvalues()[size-1] + ")");
                    result = MatrixUtilities.CholeskyDecomposition(matrix, true);
                    break;

                case SalvagingAlgorithm.Spectral:
                    // negative eigenvalues set to zero
                    for (int i=0; i<size; i++)
                        diagonal[i,i] = Math.Sqrt(Math.Max(jd.eigenvalues()[i], 0.0));

                    result = jd.eigenvectors() * diagonal;
                    normalizePseudoRoot(matrix, result);
                    break;

                case SalvagingAlgorithm.Hypersphere:
                    // negative eigenvalues set to zero
                    negative=false;
                    for (int i=0; i<size; ++i){
                        diagonal[i,i] = Math.Sqrt(Math.Max(jd.eigenvalues()[i], 0.0));
                        if (jd.eigenvalues()[i]<0.0) negative=true;
                    }
                    result = jd.eigenvectors() * diagonal;
                    normalizePseudoRoot(matrix, result);

                    if (negative)
                        result = hypersphereOptimize(matrix, result, false);
                    break;

                case SalvagingAlgorithm.LowerDiagonal:
                    // negative eigenvalues set to zero
                    negative=false;
                    for (int i=0; i<size; ++i){
                        diagonal[i,i] = Math.Sqrt(Math.Max(jd.eigenvalues()[i], 0.0));
                        if (jd.eigenvalues()[i]<0.0) negative=true;
                    }
                    result = jd.eigenvectors() * diagonal;

                    normalizePseudoRoot(matrix, result);

                    if (negative)
                        result = hypersphereOptimize(matrix, result, true);
                    break;

                case SalvagingAlgorithm.Higham:
                    int maxIterations = 40;
                    double tol = 1e-6;
                    result = highamImplementation(matrix, maxIterations, tol);
                    result = MatrixUtilities.CholeskyDecomposition(result, true);
                    break;

                default:
                    throw new ApplicationException("unknown salvaging algorithm");
            }

            return result;
        }
Exemplo n.º 34
0
        // Take a matrix and make all the diagonal entries 1.
        private static Matrix projectToUnitDiagonalMatrix(Matrix M)
        {
            int size = M.rows();
            if (size != M.columns())
                throw new ApplicationException("matrix not square");

            Matrix result = new Matrix(M);
            for (int i=0; i<size; ++i)
                result[i,i] = 1.0;

            return result;
        }
Exemplo n.º 35
0
Arquivo: svd.cs Projeto: vdt/QLNet
        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;
                }
            }
        }
Exemplo n.º 36
0
        //[TestMethod()]
        public void testQRDecomposition()
        {
            //BOOST_MESSAGE("Testing QR decomposition...");

            setup();

            double tol = 1.0e-12;
            Matrix[] testMatrices = { M1, M2, I,
                                      M3, Matrix.transpose(M3), M4, Matrix.transpose(M4), M5 };

            for (int j = 0; j < testMatrices.Length; j++) {
                Matrix Q = new Matrix(), R = new Matrix();
                bool pivot = true;
                Matrix A = testMatrices[j];
                List<int> ipvt = MatrixUtilities.qrDecomposition(A, Q, R, pivot);

                Matrix P = new Matrix(A.columns(), A.columns(), 0.0);

                // reverse column pivoting
                for (int i=0; i < P.columns(); ++i) {
                    P[ipvt[i],i] = 1.0;
                }

                if (norm(Q*R - A*P) > tol)
                    Assert.Fail("Q*R does not match matrix A*P (norm = "
                               + norm(Q*R-A*P) + ")");

                pivot = false;
                MatrixUtilities.qrDecomposition(A, Q, R, pivot);

                if (norm(Q*R - A) > tol)
                    Assert.Fail("Q*R does not match matrix A (norm = "
                               + norm(Q*R-A) + ")");
            }
        }
Exemplo n.º 37
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_);
        }
Exemplo n.º 38
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_);
        }
Exemplo n.º 39
0
        public static Matrix rankReducedSqrt(Matrix matrix,
                                             int maxRank,
                                             double componentRetainedPercentage,
                                             SalvagingAlgorithm sa)
        {
            int size = matrix.rows();

            #if QL_EXTRA_SAFETY_CHECKS
                checkSymmetry(matrix);
            #else
            if (size != matrix.columns())
                throw new ApplicationException("non square matrix: " + size + " rows, " + matrix.columns() + " columns");
            #endif

            if (!(componentRetainedPercentage > 0.0))
                throw new ApplicationException("no eigenvalues retained");

            if (!(componentRetainedPercentage <= 1.0))
                throw new ApplicationException("percentage to be retained > 100%");

            if (!(maxRank >= 1))
                throw new ApplicationException("max rank required < 1");

            // spectral (a.k.a Principal Component) analysis
            SymmetricSchurDecomposition jd = new SymmetricSchurDecomposition(matrix);
            Vector eigenValues = jd.eigenvalues();

            // salvaging algorithm
            switch (sa)
            {
                case SalvagingAlgorithm.None:
                    // eigenvalues are sorted in decreasing order
                    if (!(eigenValues[size - 1] >= -1e-16))
                        throw new ApplicationException("negative eigenvalue(s) (" + eigenValues[size - 1] + ")");
                    break;
                case SalvagingAlgorithm.Spectral:
                    // negative eigenvalues set to zero
                    for (int i = 0; i < size; ++i)
                        eigenValues[i] = Math.Max(eigenValues[i], 0.0);
                    break;
                case SalvagingAlgorithm.Higham:
                    {
                        int maxIterations = 40;
                        double tolerance = 1e-6;
                        Matrix adjustedMatrix = highamImplementation(matrix, maxIterations, tolerance);
                        jd = new SymmetricSchurDecomposition(adjustedMatrix);
                        eigenValues = jd.eigenvalues();
                    }
                    break;
                default:
                    throw new ApplicationException("unknown or invalid salvaging algorithm");

            }

            // factor reduction
            /*std::accumulate(eigenValues.begin(),
                              eigenValues.end(), 0.0);*/
            double accumulate = 0;
            eigenValues.ForEach((ii, vv) => accumulate += eigenValues[ii]);
            double enough = componentRetainedPercentage * accumulate;

            if (componentRetainedPercentage == 1.0)
            {
                // numerical glitches might cause some factors to be discarded
                enough *= 1.1;
            }
            // retain at least one factor
            double components = eigenValues[0];
            int retainedFactors = 1;
            for (int i = 1; components < enough && i < size; ++i)
            {
                components += eigenValues[i];
                retainedFactors++;
            }
            // output is granted to have a rank<=maxRank
            retainedFactors = Math.Min(retainedFactors, maxRank);

            Matrix diagonal = new Matrix(size, retainedFactors, 0.0);
            for (int i = 0; i < retainedFactors; ++i)
                diagonal[i, i] = Math.Sqrt(eigenValues[i]);
            Matrix result = jd.eigenvectors() * diagonal;

            normalizePseudoRoot(matrix, result);
            return result;
        }
Exemplo n.º 40
0
 // Matrix infinity norm. See Golub and van Loan (2.3.10) or
 // <http://en.wikipedia.org/wiki/Matrix_norm>
 private static double normInf(Matrix M)
 {
     int rows = M.rows();
     int cols = M.columns();
     double norm = 0.0;
     for (int i=0; i<rows; ++i) {
         double colSum = 0.0;
         for (int j=0; j<cols; ++j)
             colSum += Math.Abs(M[i,j]);
         norm = Math.Max(norm, colSum);
     }
     return norm;
 }
Exemplo n.º 41
0
        // Take a matrix and make all the eigenvalues non-negative
        private static Matrix projectToPositiveSemidefiniteMatrix(Matrix M)
        {
            int size = M.rows();
            if (size != M.columns())
                throw new ApplicationException("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;
        }
Exemplo n.º 42
0
        //! floating reference date, fixed market data
        public SwaptionVolatilityMatrix(
            Calendar calendar,
            BusinessDayConvention bdc,
            List<Period> optionTenors,
            List<Period> swapTenors,
            Matrix vols,
            DayCounter dayCounter)
            : base(optionTenors, swapTenors, 0, calendar, bdc, dayCounter)
        {
            volHandles_ = new InitializedList<List<Handle<Quote>>>(vols.rows());
            volatilities_ = new Matrix(vols.rows(), vols.columns());
            checkInputs(vols.rows(), vols.columns());

            // fill dummy handles to allow generic handle-based
            // computations later on
            for (int i=0; i<vols.rows(); ++i) {
                volHandles_[i] = new InitializedList<Handle<Quote>>(vols.columns());
                for (int j=0; j<vols.columns(); ++j)
                    volHandles_[i][j] = new Handle<Quote>((new
                        SimpleQuote(vols[i,j])));
            }

            interpolation_ =
            new BilinearInterpolation(swapLengths_, swapLengths_.Count,
            optionTimes_, optionTimes_.Count,
            volatilities_);
        }
Exemplo n.º 43
0
 public static Matrix transpose(Matrix m) {
     Matrix result = new Matrix(m.columns(),m.rows());
     for (int i=0; i<m.rows(); i++)
         for (int j=0; j<m.columns();j++)
             result[j,i] = m[i,j];
     return result;
 }
Exemplo n.º 44
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;
        }
Exemplo n.º 45
0
        //! Returns the pseudo square root of a real symmetric matrix

        /*! Given a matrix \f$ M \f$, the result \f$ S \f$ is defined
         *  as the matrix such that \f$ S S^T = M. \f$
         *  If the matrix is not positive semi definite, it can
         *  return an approximation of the pseudo square root
         *  using a (user selected) salvaging algorithm.
         *
         *  For more information see: "The most general methodology to create
         *  a valid correlation matrix for risk management and option pricing
         *  purposes", by R. Rebonato and P. Jдckel.
         *  The Journal of Risk, 2(2), Winter 1999/2000
         *  http://www.rebonato.com/correlationmatrix.pdf
         *
         *  Revised and extended in "Monte Carlo Methods in Finance",
         *  by Peter Jдckel, Chapter 6.
         *
         *  \pre the given matrix must be symmetric.
         *
         *  \relates Matrix
         *
         *  \warning Higham algorithm only works for correlation matrices.
         *
         *  \test
         *  - the correctness of the results is tested by reproducing
         *    known good data.
         *  - the correctness of the results is tested by checking
         *    returned values against numerical calculations.
         */
        public static Matrix pseudoSqrt(Matrix matrix, SalvagingAlgorithm sa)
        {
            int size = matrix.rows();

            #if QL_EXTRA_SAFETY_CHECKS
            checkSymmetry(matrix);
            #else
            if (size != matrix.columns())
            {
                throw new Exception("non square matrix: " + size + " rows, " + matrix.columns() + " columns");
            }
            #endif

            // spectral (a.k.a Principal Component) analysis
            SymmetricSchurDecomposition jd = new SymmetricSchurDecomposition(matrix);
            Matrix diagonal = new Matrix(size, size, 0.0);

            // salvaging algorithm
            Matrix result = new Matrix(size, size);
            bool   negative;
            switch (sa)
            {
            case SalvagingAlgorithm.None:
                // eigenvalues are sorted in decreasing order
                if (!(jd.eigenvalues()[size - 1] >= -1e-16))
                {
                    throw new Exception("negative eigenvalue(s) (" + jd.eigenvalues()[size - 1] + ")");
                }
                result = MatrixUtilities.CholeskyDecomposition(matrix, true);
                break;

            case SalvagingAlgorithm.Spectral:
                // negative eigenvalues set to zero
                for (int i = 0; i < size; i++)
                {
                    diagonal[i, i] = Math.Sqrt(Math.Max(jd.eigenvalues()[i], 0.0));
                }

                result = jd.eigenvectors() * diagonal;
                normalizePseudoRoot(matrix, result);
                break;

            case SalvagingAlgorithm.Hypersphere:
                // negative eigenvalues set to zero
                negative = false;
                for (int i = 0; i < size; ++i)
                {
                    diagonal[i, i] = Math.Sqrt(Math.Max(jd.eigenvalues()[i], 0.0));
                    if (jd.eigenvalues()[i] < 0.0)
                    {
                        negative = true;
                    }
                }
                result = jd.eigenvectors() * diagonal;
                normalizePseudoRoot(matrix, result);

                if (negative)
                {
                    result = hypersphereOptimize(matrix, result, false);
                }
                break;

            case SalvagingAlgorithm.LowerDiagonal:
                // negative eigenvalues set to zero
                negative = false;
                for (int i = 0; i < size; ++i)
                {
                    diagonal[i, i] = Math.Sqrt(Math.Max(jd.eigenvalues()[i], 0.0));
                    if (jd.eigenvalues()[i] < 0.0)
                    {
                        negative = true;
                    }
                }
                result = jd.eigenvectors() * diagonal;

                normalizePseudoRoot(matrix, result);

                if (negative)
                {
                    result = hypersphereOptimize(matrix, result, true);
                }
                break;

            case SalvagingAlgorithm.Higham:
                int    maxIterations = 40;
                double tol           = 1e-6;
                result = highamImplementation(matrix, maxIterations, tol);
                result = MatrixUtilities.CholeskyDecomposition(result, true);
                break;

            default:
                throw new Exception("unknown salvaging algorithm");
            }

            return(result);
        }
Exemplo n.º 46
0
 double norm(Matrix m)
 {
     double sum = 0.0;
     for (int i=0; i<m.rows(); i++)
         for (int j=0; j<m.columns(); j++)
             sum += m[i,j]*m[i,j];
     return Math.Sqrt(sum);
 }
Exemplo n.º 47
0
        public static Matrix rankReducedSqrt(Matrix matrix,
                                             int maxRank,
                                             double componentRetainedPercentage,
                                             SalvagingAlgorithm sa)
        {
            int size = matrix.rows();

            #if QL_EXTRA_SAFETY_CHECKS
            checkSymmetry(matrix);
            #else
            if (size != matrix.columns())
            {
                throw new Exception("non square matrix: " + size + " rows, " + matrix.columns() + " columns");
            }
            #endif

            if (!(componentRetainedPercentage > 0.0))
            {
                throw new Exception("no eigenvalues retained");
            }

            if (!(componentRetainedPercentage <= 1.0))
            {
                throw new Exception("percentage to be retained > 100%");
            }

            if (!(maxRank >= 1))
            {
                throw new Exception("max rank required < 1");
            }

            // spectral (a.k.a Principal Component) analysis
            SymmetricSchurDecomposition jd = new SymmetricSchurDecomposition(matrix);
            Vector eigenValues             = jd.eigenvalues();

            // salvaging algorithm
            switch (sa)
            {
            case SalvagingAlgorithm.None:
                // eigenvalues are sorted in decreasing order
                if (!(eigenValues[size - 1] >= -1e-16))
                {
                    throw new Exception("negative eigenvalue(s) (" + eigenValues[size - 1] + ")");
                }
                break;

            case SalvagingAlgorithm.Spectral:
                // negative eigenvalues set to zero
                for (int i = 0; i < size; ++i)
                {
                    eigenValues[i] = Math.Max(eigenValues[i], 0.0);
                }
                break;

            case SalvagingAlgorithm.Higham:
            {
                int    maxIterations  = 40;
                double tolerance      = 1e-6;
                Matrix adjustedMatrix = highamImplementation(matrix, maxIterations, tolerance);
                jd          = new SymmetricSchurDecomposition(adjustedMatrix);
                eigenValues = jd.eigenvalues();
            }
            break;

            default:
                throw new Exception("unknown or invalid salvaging algorithm");
            }

            // factor reduction

            /*std::accumulate(eigenValues.begin(),
             *                eigenValues.end(), 0.0);*/
            double accumulate = 0;
            eigenValues.ForEach((ii, vv) => accumulate += eigenValues[ii]);
            double enough = componentRetainedPercentage * accumulate;

            if (componentRetainedPercentage == 1.0)
            {
                // numerical glitches might cause some factors to be discarded
                enough *= 1.1;
            }
            // retain at least one factor
            double components      = eigenValues[0];
            int    retainedFactors = 1;
            for (int i = 1; components < enough && i < size; ++i)
            {
                components += eigenValues[i];
                retainedFactors++;
            }
            // output is granted to have a rank<=maxRank
            retainedFactors = Math.Min(retainedFactors, maxRank);

            Matrix diagonal = new Matrix(size, retainedFactors, 0.0);
            for (int i = 0; i < retainedFactors; ++i)
            {
                diagonal[i, i] = Math.Sqrt(eigenValues[i]);
            }
            Matrix result = jd.eigenvectors() * diagonal;

            normalizePseudoRoot(matrix, result);
            return(result);
        }
Exemplo n.º 48
0
        public void testQRSolve()
        {
            // Testing QR solve...
               setup();

               double tol = 1.0e-12;
               MersenneTwisterUniformRng rng = new MersenneTwisterUniformRng( 1234 );
               Matrix bigM = new Matrix( 50, 100, 0.0 );
               for ( int i = 0; i < Math.Min( bigM.rows(), bigM.columns() ); ++i )
               {
              bigM[i, i] = i + 1.0;
               }
               Matrix[] testMatrices = { M1, M2, M3, Matrix.transpose(M3),
                                    M4, Matrix.transpose(M4), M5, I, M7, bigM, Matrix.transpose(bigM) };

               for ( int j = 0; j < testMatrices.Length; j++ )
               {
              Matrix A = testMatrices[j];
              Vector b = new Vector( A.rows() );

              for ( int k = 0; k < 10; ++k )
              {
                 for ( int i = 0; i < b.Count; ++i )
                 {
                    b[i] = rng.next().value;
                 }
                 Vector x = MatrixUtilities.qrSolve( A, b, true );

                 if ( A.columns() >= A.rows() )
                 {
                    if ( norm( A * x - b ) > tol )
                       Assert.Fail( "A*x does not match vector b (norm = "
                                  + norm( A * x - b ) + ")" );
                 }
                 else
                 {
                    // use the SVD to calculate the reference values
                    int n = A.columns();
                    Vector xr = new Vector( n, 0.0 );

                    SVD svd = new SVD( A );
                    Matrix V = svd.V();
                    Matrix U = svd.U();
                    Vector w = svd.singularValues();
                    double threshold = n * Const.QL_EPSILON;

                    for ( int i = 0; i < n; ++i )
                    {
                       if ( w[i] > threshold )
                       {
                          double u = 0;
                          int zero = 0;
                          for ( int kk = 0; kk < U.rows(); kk++ )
                             u += ( U[kk, i] * b[zero++] ) / w[i];

                          for ( int jj = 0; jj < n; ++jj )
                          {
                             xr[jj] += u * V[jj, i];
                          }
                       }
                    }

                    if ( norm( xr - x ) > tol )
                    {
                       Assert.Fail( "least square solution does not match (norm = "
                                  + norm( x - xr ) + ")" );

                    }
                 }
              }
               }
        }
Exemplo n.º 49
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;
                }
            }
        }
Exemplo n.º 50
0
 /*! \relates Matrix */
 public static Matrix operator *(Matrix m1, Matrix m2) {
     if (!(m1.columns() == m2.rows()))
         throw new ApplicationException("matrices with different sizes (" +
                m1.rows() + "x" + m1.columns() + ", " +
                m2.rows() + "x" + m2.columns() + ") cannot be multiplied");
     Matrix result = new Matrix(m1.rows(), m2.columns());
     for (int i = 0; i < result.rows(); i++)
         for (int j = 0; j < result.columns(); j++)
             result[i, j] = m1.row(i) * m2.column(j);
     return result;
 } 
Exemplo n.º 51
0
        /*! \pre s must be symmetric */
        public SymmetricSchurDecomposition(Matrix s) {
            diagonal_ = new Vector(s.rows());
            eigenVectors_ = new Matrix(s.rows(), s.columns(), 0.0);

            if (!(s.rows() > 0 && s.columns() > 0)) 
                throw new ApplicationException( "null matrix given");
            if (s.rows()!=s.columns()) 
                throw new ApplicationException( "input matrix must be square");

            int size = s.rows();
            for (int q=0; q<size; q++) {
                diagonal_[q] = s[q,q];
                eigenVectors_[q,q] = 1.0;
            }
            Matrix ss = new Matrix(s);

            Vector tmpDiag = new Vector(diagonal_);
            Vector tmpAccumulate = new Vector(size, 0.0);
            double threshold, epsPrec = 1e-15;
            bool keeplooping = true;
            int maxIterations = 100, ite = 1;
            do {
                //main loop
                double sum = 0;
                for (int a=0; a<size-1; a++) {
                    for (int b=a+1; b<size; b++) {
                        sum += Math.Abs(ss[a,b]);
                    }
                }

                if (sum==0) {
                    keeplooping = false;
                } else {
                    /* To speed up computation a threshold is introduced to
                       make sure it is worthy to perform the Jacobi rotation
                    */
                    if (ite<5) threshold = 0.2*sum/(size*size);
                    else       threshold = 0.0;

                    int j, k, l;
                    for (j=0; j<size-1; j++) {
                        for (k=j+1; k<size; k++) {
                            double sine, rho, cosin, heig, tang, beta;
                            double smll = Math.Abs(ss[j,k]);
                            if(ite> 5 &&
                               smll<epsPrec*Math.Abs(diagonal_[j]) &&
                               smll<epsPrec*Math.Abs(diagonal_[k])) {
                                    ss[j,k] = 0;
                            } else if (Math.Abs(ss[j,k])>threshold) {
                                heig = diagonal_[k]-diagonal_[j];
                                if (smll<epsPrec*Math.Abs(heig)) {
                                    tang = ss[j,k]/heig;
                                } else {
                                    beta = 0.5*heig/ss[j,k];
                                    tang = 1.0/(Math.Abs(beta)+
                                        Math.Sqrt(1+beta*beta));
                                    if (beta<0)
                                        tang = -tang;
                                }
                                cosin = 1/Math.Sqrt(1+tang*tang);
                                sine = tang*cosin;
                                rho = sine/(1+cosin);
                                heig = tang*ss[j,k];
                                tmpAccumulate[j] -= heig;
                                tmpAccumulate[k] += heig;
                                diagonal_[j] -= heig;
                                diagonal_[k] += heig;
                                ss[j,k] = 0.0;
                                for (l=0; l+1<=j; l++)
                                    jacobiRotate_(ss, rho, sine, l, j, l, k);
                                for (l=j+1; l<=k-1; l++)
                                    jacobiRotate_(ss, rho, sine, j, l, l, k);
                                for (l=k+1; l<size; l++)
                                    jacobiRotate_(ss, rho, sine, j, l, k, l);
                                for (l=0;   l<size; l++)
                                    jacobiRotate_(eigenVectors_,
                                                      rho, sine, l, j, l, k);
                            }
                        }
                    }
                    for (k=0; k<size; k++) {
                        tmpDiag[k] += tmpAccumulate[k];
                        diagonal_[k] = tmpDiag[k];
                        tmpAccumulate[k] = 0.0;
                    }
                }
            } while (++ite<=maxIterations && keeplooping);

            if(!(ite<=maxIterations))
                throw new ApplicationException("Too many iterations (" + maxIterations + ") reached");


            // sort (eigenvalues, eigenvectors)
            List<KeyValuePair<double, Vector>> temp = new InitializedList<KeyValuePair<double, Vector>>(size);
            int row, col;
            for (col=0; col<size; col++) {
                Vector eigenVector = new Vector(size);
                eigenVectors_.column(col).ForEach((ii, xx) => eigenVector[ii] = xx);
                temp[col] = new KeyValuePair<double,Vector>(diagonal_[col], eigenVector);
            }
            // sort descending: std::greater
            temp.Sort((x, y) => y.Key.CompareTo(x.Key));
            double maxEv = temp[0].Key;
            for (col=0; col<size; col++) {
                // check for round-off errors
                diagonal_[col] = (Math.Abs(temp[col].Key/maxEv)<1e-16 ? 0.0 : temp[col].Key);
                double sign = 1.0;
                if (temp[col].Value[0]<0.0)
                    sign = -1.0;
                for (row=0; row<size; row++) {
                    eigenVectors_[row,col] = sign * temp[col].Value[row];
                }
            }
        }