/// <summary>
        /// This function computes the singular value decomposition of the trajectory matrix.
        /// This function only computes the singular values and the left singular vectors.
        /// </summary>
        /// <param name="singularValues">The output singular values of size L</param>
        /// <param name="leftSingularvectors">The output singular vectors of size L*L</param>
        public bool ComputeSvd(out Single[] singularValues, out Single[] leftSingularvectors)
        {
            Single[] covariance = new Single[_windowSize * _windowSize];
            Single[] sVal;
            Single[] sVec;
            singularValues      = new Single[_windowSize];
            leftSingularvectors = new Single[_windowSize * _windowSize];

            // Computing the covariance matrix of the trajectory matrix on the input series
            ComputeUnnormalizedTrajectoryCovarianceMat(covariance);

            // Computing the eigen decomposition of the covariance matrix
            //EigenUtils.EigenDecomposition(covariance, out sVal, out sVec);
            EigenUtils.MklSymmetricEigenDecomposition(covariance, _windowSize, out sVal, out sVec);

            var ind = new int[_windowSize];
            int i;

            for (i = 0; i < _windowSize; ++i)
            {
                ind[i] = i;
            }

            Array.Sort(ind, (a, b) => sVal[b].CompareTo(sVal[a]));
            for (i = 0; i < _windowSize; ++i)
            {
                singularValues[i] = sVal[ind[i]];
                Array.Copy(sVec, _windowSize * ind[i], leftSingularvectors, _windowSize * i, _windowSize);
            }

            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Computes the real and the complex roots of a real monic polynomial represented as:
        /// coefficients[0] + coefficients[1] * X + coefficients[2] * X^2 + ... + coefficients[n-1] * X^(n-1) + X^n
        /// by computing the eigenvalues of the Companion matrix. (https://en.wikipedia.org/wiki/Companion_matrix)
        /// </summary>
        /// <param name="coefficients">The monic polynomial coefficients in the ascending order</param>
        /// <param name="roots">The computed (complex) roots</param>
        /// <param name="roundOffDigits">The number decimal digits to keep after round-off</param>
        /// <param name="doublePrecision">The machine precision</param>
        /// <returns>A boolean flag indicating whether the algorithm was successful.</returns>
        public static bool FindPolynomialRoots(Double[] coefficients, ref Complex[] roots,
                                               int roundOffDigits = 6, Double doublePrecision = 2.22 * 1e-100)
        {
            Contracts.CheckParam(doublePrecision > 0, nameof(doublePrecision), "The double precision must be positive.");
            Contracts.CheckParam(Utils.Size(coefficients) >= 1, nameof(coefficients), "There must be at least one input coefficient.");

            int  i;
            int  n      = coefficients.Length;
            bool result = true;

            _tol = doublePrecision;

            if (Utils.Size(roots) < n)
            {
                roots = new Complex[n];
            }

            // Extracting the zero roots
            for (i = 0; i < n; ++i)
            {
                if (IsZero(coefficients[i]))
                {
                    roots[n - i - 1] = Complex.Zero;
                }
                else
                {
                    break;
                }
            }

            if (i == n) // All zero roots
            {
                return(true);
            }

            if (i == n - 1) // Handling the linear case
            {
                roots[0] = new Complex(-coefficients[i], 0);
            }
            else if (i == n - 2) // Handling the quadratic case
            {
                FindQuadraticRoots(coefficients[i + 1], coefficients[i], out roots[0], out roots[1]);
            }
            else // Handling higher-order cases by computing the eigenvalues of the Companion matrix
            {
                var coeff = coefficients;
                if (i > 0)
                {
                    coeff = new Double[n - i];
                    Array.Copy(coefficients, i, coeff, 0, n - i);
                }

                // REVIEW: the eigen decomposition of the companion matrix should be done using the FactorizedCompanionMatrix class
                // instead of MKL.
                //FactorizedCompanionMatrix companionMatrix = new FactorizedCompanionMatrix(coeff);
                //result = companionMatrix.ComputeEigenValues(ref roots);

                Double[] companionMatrix = null;
                var      realPart        = new Double[n - i];
                var      imaginaryPart   = new Double[n - i];
                var      dummy           = new Double[1];

                CreateFullCompanionMatrix(coeff, ref companionMatrix);
                var info = EigenUtils.Dhseqr(EigenUtils.Layout.ColMajor, EigenUtils.Job.EigenValues, EigenUtils.Compz.None,
                                             n - i, 1, n - i, companionMatrix, n - i, realPart, imaginaryPart, dummy, n - i);

                if (info != 0)
                {
                    return(false);
                }

                for (var j = 0; j < n - i; ++j)
                {
                    roots[j] = new Complex(realPart[j], imaginaryPart[j]);
                }
            }

            return(result);
        }