rows() публичный Метод

public rows ( ) : int
Результат int
Пример #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_);
        }
Пример #2
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_);
            }
        }
Пример #3
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_);
            }
        }
Пример #4
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_);
                }
            }
        }
Пример #5
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);
        }
Пример #6
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);
        }
Пример #7
0
        public override Vector evolve(double t0, Vector x0, double dt, Vector dw)
        {
            /* predictor-corrector step to reduce discretization errors.
             *
             * Short - but slow - solution would be
             *
             * Array rnd_0     = stdDeviation(t0, x0, dt)*dw;
             * Array drift_0   = discretization_->drift(*this, t0, x0, dt);
             *
             * return apply(x0, ( drift_0 + discretization_
             *      ->drift(*this,t0,apply(x0, drift_0 + rnd_0),dt) )*0.5 + rnd_0);
             *
             * The following implementation does the same but is faster.
             */

            int    m   = nextIndexReset(t0);
            double sdt = Math.Sqrt(dt);

            Vector f          = new Vector(x0);
            Matrix diff       = lfmParam_.diffusion(t0, x0);
            Matrix covariance = lfmParam_.covariance(t0, x0);

            for (int k = m; k < size_; ++k)
            {
                double y = accrualPeriod_[k] * x0[k];
                m1[k] = y / (1 + y);

                double d = 0;
                m1.GetRange(m, k + 1 - m).ForEach(
                    (ii, vv) => d += vv *
                                     covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);
                d = (d - 0.5 * covariance[k, k]) * dt;

                double r = 0;
                diff.row(k).ForEach((kk, vv) => r += vv * dw[kk]);
                r *= sdt;

                double x = y * Math.Exp(d + r);
                m2[k] = x / (1 + x);

                double inner_product = 0;
                m2.GetRange(m, k + 1 - m).ForEach(
                    (ii, vv) => inner_product += vv *
                                                 covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);
                f[k] = x0[k] * Math.Exp(0.5 * (d + (inner_product - 0.5 * covariance[k, k]) * dt) + r);
            }

            return(f);
        }
Пример #8
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>();
        }
Пример #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");
                }
            }
        }
Пример #10
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;
                    }
                }
            }
        }
Пример #11
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]);
                        }
                    }
                }
            }
        }
Пример #12
0
        //! floating reference date, fixed market data
        public CapFloorTermVolSurface(int settlementDays,
                                      Calendar calendar,
                                      BusinessDayConvention bdc,
                                      List <Period> optionTenors,
                                      List <double> strikes,
                                      Matrix vols,
                                      DayCounter dc = null)
            : base(settlementDays, 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_    = new InitializedList <List <Handle <Quote> > >(vols.rows());
            vols_          = vols;

            checkInputs();
            initializeOptionDatesAndTimes();
            // fill dummy handles to allow generic handle-based computations later
            for (int i = 0; i < nOptionTenors_; ++i)
            {
                volHandles_[i] = new InitializedList <Handle <Quote> >(nStrikes_);
                for (int j = 0; j < nStrikes_; ++j)
                {
                    volHandles_[i][j] = new Handle <Quote>(new SimpleQuote(vols_[i, j]));
                }
            }
            interpolate();
        }
Пример #13
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();
        }
Пример #14
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;
            }
Пример #15
0
 public HypersphereCostFunction(Matrix targetMatrix, Vector targetVariance, bool lowerDiagonal) {
     size_ = targetMatrix.rows();
     lowerDiagonal_ = lowerDiagonal;
     targetMatrix_ = targetMatrix;
     targetVariance_ = targetVariance;
     currentRoot_ = new Matrix(size_, size_);
     tempMatrix_ = new Matrix(size_, size_);
     currentMatrix_ = new Matrix(size_, size_);
 }
Пример #16
0
 public HypersphereCostFunction(Matrix targetMatrix, Vector targetVariance, bool lowerDiagonal)
 {
     size_           = targetMatrix.rows();
     lowerDiagonal_  = lowerDiagonal;
     targetMatrix_   = targetMatrix;
     targetVariance_ = targetVariance;
     currentRoot_    = new Matrix(size_, size_);
     tempMatrix_     = new Matrix(size_, size_);
     currentMatrix_  = new Matrix(size_, size_);
 }
Пример #17
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);
        }
Пример #18
0
        public StochasticProcessArray(List<StochasticProcess1D> processes, Matrix correlation)
        {
            processes_ = processes;
            sqrtCorrelation_ = MatrixUtilitites.pseudoSqrt(correlation, MatrixUtilitites.SalvagingAlgorithm.Spectral);

            if (processes.Count == 0)
                throw new ApplicationException("no processes given");
            if(correlation.rows() != processes.Count)
                throw new ApplicationException("mismatch between number of processes and size of correlation matrix");
            for (int i=0; i<processes_.Count; i++)
                processes_[i].registerWith(update);
        }
Пример #19
0
        public StochasticProcessArray(List <StochasticProcess1D> processes, Matrix correlation)
        {
            processes_       = processes;
            sqrtCorrelation_ = MatrixUtilitites.pseudoSqrt(correlation, MatrixUtilitites.SalvagingAlgorithm.Spectral);

            Utils.QL_REQUIRE(processes.Count != 0, () => "no processes given");
            Utils.QL_REQUIRE(correlation.rows() == processes.Count, () =>
                             "mismatch between number of processes and size of correlation matrix");
            for (int i = 0; i < processes_.Count; i++)
            {
                processes_[i].registerWith(update);
            }
        }
Пример #20
0
        public override Vector evolve(double t0, Vector x0, double dt, Vector dw)
        {
            // predictor-corrector step to reduce discretization errors.

            int    m   = nextIndexReset(t0);
            double sdt = Math.Sqrt(dt);

            Vector f          = new Vector(x0);
            Matrix diff       = lfmParam_.diffusion(t0, x0);
            Matrix covariance = lfmParam_.covariance(t0, x0);

            for (int k = m; k < size_; ++k)
            {
                double y = accrualPeriod_[k] * x0[k];
                m1[k] = y / (1 + y);

                double d = 0;
                m1.GetRange(m, k + 1 - m).ForEach(
                    (ii, vv) => d += vv *
                                     covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);
                d = (d - 0.5 * covariance[k, k]) * dt;

                double r = 0;
                diff.row(k).ForEach((kk, vv) => r += vv * dw[kk]);
                r *= sdt;

                double x = y * Math.Exp(d + r);
                m2[k] = x / (1 + x);

                double inner_product = 0;
                m2.GetRange(m, k + 1 - m).ForEach(
                    (ii, vv) => inner_product += vv *
                                                 covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);
                f[k] = x0[k] * Math.Exp(0.5 * (d + (inner_product - 0.5 * covariance[k, k]) * dt) + r);
            }

            return(f);
        }
Пример #21
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;
        }
Пример #22
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);
        }
Пример #23
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);
        }
Пример #24
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);
        }
Пример #25
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");
        }
Пример #26
0
        public StochasticProcessArray(List <StochasticProcess1D> processes, Matrix correlation)
        {
            processes_       = processes;
            sqrtCorrelation_ = MatrixUtilitites.pseudoSqrt(correlation, MatrixUtilitites.SalvagingAlgorithm.Spectral);

            if (processes.Count == 0)
            {
                throw new ApplicationException("no processes given");
            }
            if (correlation.rows() != processes.Count)
            {
                throw new ApplicationException("mismatch between number of processes and size of correlation matrix");
            }
            for (int i = 0; i < processes_.Count; i++)
            {
                processes_[i].registerWith(update);
            }
        }
Пример #27
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_);
 }
Пример #28
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);
        }
Пример #29
0
        public override Vector drift(double t, Vector x)
        {
            Vector f          = new Vector(size_, 0.0);
            Matrix covariance = lfmParam_.covariance(t, x);
            int    m          = nextIndexReset(t);

            for (int k = m; k < size_; ++k)
            {
                m1[k] = accrualPeriod_[k] * x[k] / (1 + accrualPeriod_[k] * x[k]);
                double inner_product = 0;
                m1.GetRange(m, k + 1 - m).ForEach(
                    (ii, vv) => inner_product += vv *
                                                 covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);

                f[k] = inner_product - 0.5 * covariance[k, k];
            }
            return(f);
        }
Пример #30
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_);
 }
Пример #31
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);
        }
Пример #32
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;
                }
            }
        }
Пример #33
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);
        }
Пример #34
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);
        }
Пример #35
0
        // implementation of the Higham algorithm to find the nearest correlation matrix.
        private static Matrix highamImplementation(Matrix A, int maxIterations, double tolerance)
        {
            int    size = A.rows();
            Matrix R, Y = new Matrix(A), X = new Matrix(A), deltaS = new Matrix(size, size, 0.0);

            Matrix lastX = new Matrix(X);
            Matrix lastY = new Matrix(Y);

            for (int i = 0; i < maxIterations; ++i)
            {
                R      = Y - deltaS;
                X      = projectToPositiveSemidefiniteMatrix(R);
                deltaS = X - R;
                Y      = projectToUnitDiagonalMatrix(X);

                // convergence test
                if (Math.Max(normInf(X - lastX) / normInf(X),
                             Math.Max(normInf(Y - lastY) / normInf(Y),
                                      normInf(Y - X) / normInf(Y)))
                    <= tolerance)
                {
                    break;
                }
                lastX = X;
                lastY = Y;
            }

            // ensure we return a symmetric matrix
            for (int i = 0; i < size; ++i)
            {
                for (int j = 0; j < i; ++j)
                {
                    Y[i, j] = Y[j, i];
                }
            }

            return(Y);
        }
Пример #36
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 ) + ")" );

                    }
                 }
              }
               }
        }
Пример #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_);
        }
Пример #38
0
      public TqrEigenDecomposition(Vector diag, Vector sub, EigenVectorCalculation calc = EigenVectorCalculation.WithEigenVector,
                            ShiftStrategy strategy = ShiftStrategy.CloseEigenValue)
      {
         iter_ = 0;
         d_ = new Vector(diag);
         
         int row = calc == EigenVectorCalculation.WithEigenVector ? d_.size() :
            calc == EigenVectorCalculation.WithoutEigenVector ? 0 : 1;

         ev_ = new Matrix(row, d_.size(), 0.0);
         
         int n = diag.size();

         Utils.QL_REQUIRE( n == sub.size() + 1, () => "Wrong dimensions" );

         Vector e = new Vector(sub);

         int i;
         for (i=0; i < ev_.rows(); ++i) 
         {
            ev_[i,i] = 1.0;
         }

         for (int k=n-1; k >=1; --k) 
         {
            while (!offDiagIsZero(k, e)) 
            {
                int l = k;
                while (--l > 0 && !offDiagIsZero(l,e));
                iter_++;

                double q = d_[l];
                if (strategy != ShiftStrategy.NoShift) 
                {
                    // calculated eigenvalue of 2x2 sub matrix of
                    // [ d_[k-1] e_[k] ]
                    // [  e_[k]  d_[k] ]
                    // which is closer to d_[k+1].
                    // FLOATING_POINT_EXCEPTION
                    double t1 = Math.Sqrt(
                                          0.25*(d_[k]*d_[k] + d_[k-1]*d_[k-1])
                                          - 0.5*d_[k-1]*d_[k] + e[k]*e[k]);
                    double t2 = 0.5*(d_[k]+d_[k-1]);

                    double lambda = (Math.Abs(t2+t1 - d_[k]) < Math.Abs(t2-t1 - d_[k]))?
                                     t2+t1 : t2-t1;

                    if (strategy == ShiftStrategy.CloseEigenValue) 
                    {
                        q-=lambda;
                    } 
                    else 
                    {
                        q-=((k==n-1)? 1.25 : 1.0)*lambda;
                    }
                }

                // the QR transformation
                double sine = 1.0;
                double cosine = 1.0;
                double u = 0.0;

                bool recoverUnderflow = false;
                for (i=l+1; i <= k && !recoverUnderflow; ++i) 
                {
                    double h = cosine*e[i];
                    double p = sine*e[i];

                    e[i-1] = Math.Sqrt(p*p+q*q);
                    if (e[i-1] != 0.0) {
                        sine = p/e[i-1];
                        cosine = q/e[i-1];

                        double g = d_[i-1]-u;
                        double t = (d_[i]-g)*sine+2*cosine*h;

                        u = sine*t;
                        d_[i-1] = g + u;
                        q = cosine*t - h;

                        for (int j=0; j < ev_.rows(); ++j) 
                        {
                            double tmp = ev_[j,i-1];
                            ev_[j,i-1] = sine*ev_[j,i] + cosine*tmp;
                            ev_[j,i] = cosine*ev_[j,i] - sine*tmp;
                        }
                    } 
                    else 
                    {
                        // recover from underflow
                        d_[i-1] -= u;
                        e[l] = 0.0;
                        recoverUnderflow = true;
                    }
                }

                if (!recoverUnderflow) {
                    d_[k] -= u;
                    e[k] = q;
                    e[l] = 0.0;
                }
            }
        }

        // sort (eigenvalues, eigenvectors),
        // code taken from symmetricSchureDecomposition.cpp
        List<KeyValuePair<double, List<double> > > temp = new List<KeyValuePair<double,List<double>>>(n);
        List<double> eigenVector = new List<double>(ev_.rows());
        for (i=0; i<n; i++) 
        {
            if (ev_.rows() > 0)
                //std::copy(ev_.column_begin(i),ev_.column_end(i), eigenVector.begin());
                eigenVector = ev_.column(i) ;

            temp[i] = new KeyValuePair<double,List<double>>(d_[i], eigenVector);
        }
       
        //std::sort(temp.begin(), temp.end(), std::greater<std::pair<Real, std::vector<Real> > >());
        temp.Sort();

        // first element is positive
        for (i=0; i<n; i++) {
            d_[i] = temp[i].Key;
            double sign = 1.0;
            if (ev_.rows() > 0 && temp[i].Value[0]<0.0)
                sign = -1.0;
            for (int j=0; j<ev_.rows(); ++j) {
                ev_[j,i] = sign * temp[i].Value[j];
            }
        }

      }
Пример #39
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;
 } 
Пример #40
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;
        }
Пример #41
0
        // Optimization function for hypersphere and lower-diagonal algorithm
        private static Matrix hypersphereOptimize(Matrix targetMatrix, Matrix currentRoot, bool lowerDiagonal)
        {
            int i,j,k,size = targetMatrix.rows();
            Matrix result = new Matrix(currentRoot);
            Vector variance = new Vector(size);
            for (i=0; i<size; i++){
                variance[i]=Math.Sqrt(targetMatrix[i,i]);
            }
            if (lowerDiagonal) {
                Matrix approxMatrix = result*Matrix.transpose(result);
                result = MatrixUtilities.CholeskyDecomposition(approxMatrix, true);
                for (i=0; i<size; i++) {
                    for (j=0; j<size; j++) {
                        result[i,j]/=Math.Sqrt(approxMatrix[i,i]);
                    }
                }
            } else {
                for (i=0; i<size; i++) {
                    for (j=0; j<size; j++) {
                        result[i,j]/=variance[i];
                    }
                }
            }

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

            // hypersphere vector optimization

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

            for (i=0; i<size; i++) {
                for (j=0; j<size; j++) {
                    result[i,j]*=variance[i];
                }
            }
            return result;
        }
Пример #42
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;
 }
Пример #43
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;
        }
Пример #44
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;
        }
Пример #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 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;
        }
Пример #46
0
Файл: svd.cs Проект: 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;
                }
            }
        }
Пример #47
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;
 }
Пример #48
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;
        }
Пример #49
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);
 }
Пример #50
0
        // implementation of the Higham algorithm to find the nearest correlation matrix.
        private static Matrix highamImplementation(Matrix A, int maxIterations, double tolerance)
        {
            int size = A.rows();
            Matrix R, Y = new Matrix(A), X = new Matrix(A), deltaS = new Matrix(size, size, 0.0);

            Matrix lastX = new Matrix(X);
            Matrix lastY = new Matrix(Y);

            for (int i=0; i<maxIterations; ++i) {
                R = Y - deltaS;
                X = projectToPositiveSemidefiniteMatrix(R);
                deltaS = X - R;
                Y = projectToUnitDiagonalMatrix(X);

                // convergence test
                if (Math.Max(normInf(X-lastX)/normInf(X),
                        Math.Max(normInf(Y-lastY)/normInf(Y),
                                normInf(Y-X)/normInf(Y)))
                        <= tolerance)
                {
                    break;
                }
                lastX = X;
                lastY = Y;
            }

            // ensure we return a symmetric matrix
            for (int i=0; i<size; ++i)
                for (int j=0; j<i; ++j)
                    Y[i,j] = Y[j,i];

            return Y;
        }
Пример #51
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;
        }
Пример #52
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;
        }
Пример #53
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];
                }
            }
        }
Пример #54
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_);
        }