Exemple #1
0
        /// <summary>
        /// Computes the eigenvalues for an N-by-N real nonsymmetric matrix A.
        /// </summary>
        /// <param name="A">N-by-N real nonsymmetric matrix A.</param>
        /// <returns>The eigenvalues.</returns>
        public ComplexMatrix GetEigenvalues(Matrix A)
        {
            if (this._dgeev == null)
            {
                this._dgeev = new DGEEV();
            }

            this.CheckDimensions(A);


            Matrix ACopy = A.Clone();

            double[] ACopyData    = ACopy.Data;
            Matrix   RealEVectors = new Matrix(1, 1);

            double[]      EigenVectsData = RealEVectors.Data;
            ComplexMatrix EigenVals      = new ComplexMatrix(A.RowCount, 1);

            double[] REigVal = new double[A.RowCount];
            double[] IEigVal = new double[A.RowCount];

            //double[] EigenValsData = EigenVals.Data;
            int Info = 0;

            double[] VL = new double[A.RowCount];

            double[] Work  = new double[1];
            int      LWork = -1;

            //Calculamos LWORK
            _dgeev.Run("N", "N", A.RowCount, ref ACopyData, 0, ACopy.RowCount, ref REigVal, 0, ref IEigVal, 0, ref VL, 0, 1, ref EigenVectsData, 0, A.RowCount, ref Work, 0, LWork, ref Info);

            LWork = Convert.ToInt32(Work[0]);
            if (LWork > 0)
            {
                Work = new double[LWork];
                _dgeev.Run("N", "N", A.RowCount, ref ACopyData, 0, ACopy.RowCount, ref REigVal, 0, ref IEigVal, 0, ref VL, 0, 1, ref EigenVectsData, 0, A.RowCount, ref Work, 0, LWork, ref Info);
            }
            else
            {
                //Error
            }


            #region Error
            //= 0:  successful exit
            //.LT. 0:  if INFO = -i, the i-th argument had an illegal value.
            //.GT. 0:  if INFO = i, the QR algorithm failed to compute all the
            // eigenvalues, and no eigenvectors have been computed;
            // elements i+1:N of WR and WI contain eigenvalues which
            // have converged.

            if (Info < 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value");
            }
            else if (Info > 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new Exception("The QR algorithm failed to compute all the eigenvalues.");
            }

            #endregion


            for (int i = 0; i < EigenVals.RowCount; i++)
            {
                EigenVals[i, 0] = new Complex(REigVal[i], IEigVal[i]);
            }


            return(EigenVals);
        }
        /// <summary>
        ///Computes the singular value decomposition (SVD) of a real
        /// M-by-N matrix A.
        /// The SVD is written
        /// A = U * S * transpose(V)
        /// </summary>
        /// <param name="A">The A matrix.</param>
        /// <param name="S">The diagonal elements of S are the singular values of A.</param>
        /// <param name="U">The U matrix, U is an M-by-M orthogonal matrix</param>
        /// <param name="VT">the transpose(V), V is an N-by-N orthogonal matrix.</param>
        public void ComputeSVD(Matrix A, out Matrix S, out Matrix U, out Matrix VT)
        {
            if (this._dgesvd == null)
            {
                this._dgesvd = new DGESVD();
            }

            Matrix ACopy = A.Clone();

            double[] ACopyData = ACopy.Data;
            S = new Matrix(A.RowCount, A.ColumnCount);     // A is MxN, S is  MxN
            double[] SingularValuesData = new double[Math.Min(A.RowCount, A.ColumnCount)];
            U = new Matrix(A.RowCount, A.RowCount);        // A is MxN, U is  MxM
            double[] UData = U.Data;
            VT = new Matrix(A.ColumnCount, A.ColumnCount); // A is MxN, V is  NxN
            double[] VTData = VT.Data;

            double[] Work  = new double[1];
            int      LWork = -1;
            int      Info  = 0;

            //Calculamos LWORK
            this._dgesvd.Run("A", "A", A.RowCount, A.ColumnCount, ref ACopyData, 0, A.RowCount, ref SingularValuesData, 0, ref UData, 0, U.RowCount, ref VTData, 0, VT.RowCount, ref Work, 0, LWork, ref Info);

            LWork = Convert.ToInt32(Work[0]);
            if (LWork > 0)
            {
                Work = new double[LWork];
                _dgesvd.Run("A", "A", A.RowCount, A.ColumnCount, ref ACopyData, 0, A.RowCount, ref SingularValuesData, 0, ref UData, 0, U.RowCount, ref VTData, 0, VT.RowCount, ref Work, 0, LWork, ref Info);
            }
            else
            {
                //Error
            }

            #region Error
            // <param name="INFO">
            // (output) INTEGER
            // = 0:  successful exit.
            // .LT. 0:  if INFO = -i, the i-th argument had an illegal value.
            // .GT. 0:  if DBDSQR did not converge, INFO specifies how many
            // superdiagonals of an intermediate bidiagonal form B
            // did not converge to zero. See the description of WORK
            // above for details.

            if (Info < 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value");
            }
            else if (Info > 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new Exception("DBDSQR did not converge.");
            }

            #endregion

            for (int i = 0; i < SingularValuesData.Length; i++)
            {
                S[i, i] = SingularValuesData[i];
            }
        }
        /// <summary>
        /// Computes the minimum-norm solution to a real linear least squares problem: minimize 2-norm(|| A*X - B||)
        /// using the singular value decomposition (SVD) of A.
        /// The matrix A can be rank-deficient.
        /// </summary>
        /// <param name="A">The A matrix.</param>
        /// <param name="B">The matrix containing the right-hand side of the linear system.</param>
        /// <param name="rcond">
        /// rcond is used to determine the effective rank of A.
        /// Singular values S(i) .LE. rcond*S(1) are treated as zero.
        /// </param>
        /// <returns>A matrix containing the solution.</returns>
        public Matrix SVDdcSolve(Matrix A, Matrix B, double rcond)
        {
            if (this._dgelsd == null)
            {
                this._dgelsd = new DGELSD();
            }

            Matrix AClon = A.Clone();

            double[] AClonData = AClon.Data;
            Matrix   ClonB     = new Matrix(Math.Max(A.RowCount, A.ColumnCount), B.ColumnCount);

            double[] ClonData = ClonB.Data;

            for (int j = 0; j < ClonB.ColumnCount; j++)
            {
                for (int i = 0; i < B.RowCount; i++)
                {
                    ClonB[i, j] = B[i, j];
                }
            }

            // (output) DOUBLE PRECISION array, dimension (min(M,N))
            //The singular values of A in decreasing order.
            //The condition number of A in the 2-norm = S(1)/S(min(m,n)).
            double[] S = new double[Math.Min(A.RowCount, A.ColumnCount)];

            //// (input) DOUBLE PRECISION
            //// RCOND is used to determine the effective rank of A.
            //// Singular values S(i) .LE. RCOND*S(1) are treated as zero.
            //// If RCOND .LT. 0, machine precision is used instead.
            //double RCond = -1.0;
            // (output) INTEGER
            // The effective rank of A, i.e., the number of singular values
            // which are greater than RCOND*S(1).
            int Rank = 0;
            int Info = 0;

            //int LWork
            double[] Work   = new double[1];
            int      LWork  = -1;
            int      LIWork = this.CalculateLIWORK(A.RowCount, A.ColumnCount);

            int[] IWork = new int[LIWork];

            //Calculamos LWORK ideal
            this._dgelsd.Run(A.RowCount, A.ColumnCount, B.ColumnCount, ref AClonData, 0, A.RowCount, ref ClonData, 0, ClonB.RowCount, ref S, 0, rcond, ref Rank, ref Work, 0, LWork, ref IWork, 0, ref Info);
            LWork = Convert.ToInt32(Work[0]);
            if (LWork > 0)
            {
                Work = new double[LWork];
                this._dgelsd.Run(A.RowCount, A.ColumnCount, B.ColumnCount, ref AClonData, 0, A.RowCount, ref ClonData, 0, ClonB.RowCount, ref S, 0, rcond, ref Rank, ref Work, 0, LWork, ref IWork, 0, ref Info);
            }
            else
            {
                //Error
            }


            #region Error
            // = 0:  successful exit
            // .LT. 0:  if INFO = -i, the i-th argument had an illegal value.
            // .GT. 0:  the algorithm for computing the SVD failed to converge;
            // if INFO = i, i off-diagonal elements of an intermediate
            // bidiagonal form did not converge to zero.
            if (Info < 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value");
            }
            else if (Info > 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new Exception("The algorithm for computing the SVD failed to converge.");
            }

            #endregion



            Matrix Solution = new Matrix(A.ColumnCount, B.ColumnCount);

            for (int j = 0; j < Solution.ColumnCount; j++)
            {
                for (int i = 0; i < Solution.RowCount; i++)
                {
                    Solution[i, j] = ClonB[i, j];
                }
            }

            return(Solution);
        }
        //public Matrix Solve(Matrix A, Matrix B)
        //{
        //    return this.SVDdcSolve(A, B);
        //}

        //public Matrix Solve(Matrix A, Matrix B, LLSMethod method)
        //{
        //    switch (method)
        //    {
        //        case LLSMethod.QRorLQ:
        //            return this.QRorLQSolve(A, B);
        //            break;
        //        case LLSMethod.COF:
        //            return this.COFSolve(A, B);
        //            break;
        //        case LLSMethod.SVD:
        //            return this.SVDdcSolve(A, B);
        //            break;
        //    }
        //}

        #endregion

        #region Private Metods

        #region QR or LQ factorization



        /// <summary>
        /// Solves overdetermined or underdetermined real linear systems
        /// involving an M-by-N matrix A, using a QR or LQ
        /// factorization of A.  It is assumed that A has full rank.
        /// </summary>
        /// <param name="A">The A matrix.</param>
        /// <param name="B">The matrix containing the right-hand side of the linear system.</param>
        /// <returns>A matrix containing the solution.</returns>
        public Matrix QRorLQSolve(Matrix A, Matrix B)
        {
            if (this._dgels == null)
            {
                this._dgels = new DGELS();
            }

            Matrix AClon = A.Clone();

            double[] AClonData = AClon.Data;

            Matrix ClonB = new Matrix(Math.Max(A.RowCount, A.ColumnCount), B.ColumnCount);

            double[] ClonData = ClonB.Data;

            for (int j = 0; j < ClonB.ColumnCount; j++)
            {
                for (int i = 0; i < B.RowCount; i++)
                {
                    ClonB[i, j] = B[i, j];
                }
            }


            int Info = 0;

            //int LWork
            double[] Work  = new double[1];
            int      LWork = -1;

            //Calculamos LWORK ideal
            _dgels.Run("N", A.RowCount, A.ColumnCount, B.ColumnCount, ref AClonData, 0, A.RowCount, ref ClonData, 0, ClonB.RowCount, ref Work, 0, LWork, ref Info);
            LWork = Convert.ToInt32(Work[0]);
            if (LWork > 0)
            {
                Work = new double[LWork];
                _dgels.Run("N", A.RowCount, A.ColumnCount, B.ColumnCount, ref AClonData, 0, A.RowCount, ref ClonData, 0, ClonB.RowCount, ref Work, 0, LWork, ref Info);
            }
            else
            {
                //Error
            }


            #region Error
            // = 0:  successful exit
            // .LT. 0:  if INFO = -i, the i-th argument had an illegal value
            // .GT. 0:  if INFO =  i, the i-th diagonal element of the
            // triangular factor of A is zero, so that A does not have
            // full rank; the least squares solution could not be
            // computed.
            if (Info < 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value");
            }
            else if (Info > 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new Exception("The matrix A does not have full rank; the least squares solution could not be computed. You can use SVDSolve or SVDdcSolve");
            }

            #endregion

            Matrix Solution = new Matrix(A.ColumnCount, B.ColumnCount);

            for (int j = 0; j < Solution.ColumnCount; j++)
            {
                for (int i = 0; i < Solution.RowCount; i++)
                {
                    Solution[i, j] = ClonB[i, j];
                }
            }

            return(Solution);
        }
        /// <summary>
        /// Computes the minimum-norm solution to a real linear least squares problem: minimize 2-norm(|| A*X - B||)
        /// using a complete orthogonal factorization of A.
        /// The matrix A can be rank-deficient.
        /// </summary>
        /// <param name="A">The A matrix.</param>
        /// <param name="B">The matrix containing the right-hand side of the linear system.</param>
        /// <param name="rcond">
        /// The parameter rcond is used to determine the effective rank of A, which
        /// is defined as the order of the largest leading triangular
        /// submatrix R11 in the QR factorization with pivoting of A,
        /// whose estimated condition number .LT. 1/rcond.
        /// </param>
        /// <returns>A matrix containing the solution.</returns>
        public Matrix COFSolve(Matrix A, Matrix B, double rcond)
        {
            if (this._dgelsy == null)
            {
                this._dgelsy = new DGELSY();
            }

            Matrix AClon = A.Clone();

            double[] AClonData = AClon.Data;

            Matrix ClonB = new Matrix(Math.Max(A.RowCount, A.ColumnCount), B.ColumnCount);

            double[] ClonData = ClonB.Data;

            for (int j = 0; j < ClonB.ColumnCount; j++)
            {
                for (int i = 0; i < B.RowCount; i++)
                {
                    ClonB[i, j] = B[i, j];
                }
            }

            int Info = 0;

            //int LWork
            double[] Work = new double[1];
            int[]    JPVT = new int[A.ColumnCount];

            int RANK  = 1;
            int LWork = -1;

            //Calculamos LWORK ideal
            this._dgelsy.Run(A.RowCount, A.ColumnCount, B.ColumnCount, ref AClonData, 0, A.RowCount, ref ClonData, 0, ClonB.RowCount, ref JPVT, 0, rcond, ref RANK, ref Work, 0, LWork, ref Info);
            LWork = Convert.ToInt32(Work[0]);
            if (LWork > 0)
            {
                Work = new double[LWork];
                this._dgelsy.Run(A.RowCount, A.ColumnCount, B.ColumnCount, ref AClonData, 0, A.RowCount, ref ClonData, 0, ClonB.RowCount, ref JPVT, 0, rcond, ref RANK, ref Work, 0, LWork, ref Info);
            }
            else
            {
                //Error
            }


            #region Error
            //  INFO    (output) INTEGER
            //  = 0: successful exit
            //  < 0: If INFO = -i, the i-th argument had an illegal value.
            //
            if (Info < 0)
            {
                string infoSTg = Math.Abs(Info).ToString();
                throw new ArgumentException("the " + infoSTg + " -th argument had an illegal value");
            }
            else if (Info > 0)
            {
                //Aqui no se espqcifica nungun error, asi que en principio este valor no es posible, de cualquier forma se lo
                //pongo por si las dudas
                string infoSTg = Math.Abs(Info).ToString();
                throw new Exception("Error The algorithm ... ");
            }
            #endregion

            Matrix Solution = new Matrix(A.ColumnCount, B.ColumnCount);

            for (int j = 0; j < Solution.ColumnCount; j++)
            {
                for (int i = 0; i < Solution.RowCount; i++)
                {
                    Solution[i, j] = ClonB[i, j];
                }
            }

            return(Solution);
        }