Example #1
0
        /// <summary>
        /// Computes the eigenvalues and eigenvectors of the matrix.
        /// </summary>
        /// <returns>A representation of the eigenvalues and eigenvectors of the matrix.</returns>
        /// <remarks>
        /// <para>For a generic vector v and matrix M, Mv = u will point in some direction with no particular relationship to v.
        /// The eigenvectors of a matrix M are vectors z that satisfy Mz = &#x3BB;z, i.e. multiplying an eigenvector by a
        /// matrix reproduces the same vector, up to a prortionality constant &#x3BB; called the eigenvalue.</para>
        /// <para>For v to be an eigenvector of M with eigenvalue &#x3BB;, (M - &#x3BB;I)z = 0. But for a matrix to
        /// anihilate any non-zero vector, that matrix must have determinant, so det(M - &#x3BB;I)=0. For a matrix of
        /// order N, this is an equation for the roots of a polynomial of order N. Since an order-N polynomial always has exactly
        /// N roots, an order-N matrix always has exactly N eigenvalues.</para>
        /// <para>Since a polynomial with real coefficients can still have complex roots, a real square matrix can nonetheless
        /// have complex eigenvalues (and correspondly complex eigenvectors). However, again like the complex roots of a real
        /// polynomial, such eigenvalues will always occurs in complex-conjugate pairs.</para>
        /// <para>Although the eigenvalue polynomial ensures that an order-N matrix has N eigenvalues, it can occur that there
        /// are not N corresponding independent eigenvectors. A matrix with fewer eigenvectors than eigenvalues is called
        /// defective. Like singularity, defectiveness represents a delecate balance between the elements of a matrix that can
        /// typically be disturbed by just an infinitesimal perturbation of elements. Because of round-off-error, then, floating-point
        /// algorithms cannot reliably identify defective matrices. Instead, this method will return a full set of eigenvectors,
        /// but some eigenvectors, corresponding to very nearly equal eigenvalues, will be very nearly parallel.</para>
        /// <para>While a generic square matrix can be defective, many subspecies of square matrices are guaranteed not to be.
        /// This includes Markov matrices, orthogonal matrices, and symmetric matrices.</para>
        /// <para>Determining the eigenvalues and eigenvectors of a matrix is an O(N<sup>3</sup>) operation. If you need only the
        /// eigenvalues of a matrix, the <see cref="Eigenvalues"/> method is more efficient.</para>
        /// </remarks>
        public ComplexEigensystem Eigensystem()
        {
            double[] aStore = MatrixAlgorithms.Copy(store, dimension, dimension);

            int[] perm = new int[dimension];
            for (int i = 0; i < perm.Length; i++)
            {
                perm[i] = i;
            }
            SquareMatrixAlgorithms.IsolateCheapEigenvalues(aStore, perm, dimension);
            double[] qStore = MatrixAlgorithms.AllocateStorage(dimension, dimension);
            for (int i = 0; i < perm.Length; i++)
            {
                MatrixAlgorithms.SetEntry(qStore, dimension, dimension, perm[i], i, 1.0);
            }
            //double[] qStore = SquareMatrixAlgorithms.CreateUnitMatrix(dimension);

            // Reduce the original matrix to Hessenberg form
            SquareMatrixAlgorithms.ReduceToHessenberg(aStore, qStore, dimension);

            // Reduce the Hessenberg matrix to real Schur form
            SquareMatrixAlgorithms.ReduceToRealSchurForm(aStore, qStore, dimension);

            //MatrixAlgorithms.PrintMatrix(aStore, dimension, dimension);

            //SquareMatrix A = new SquareMatrix(aStore, dimension);
            SquareMatrix Q = new SquareMatrix(qStore, dimension);

            Complex[] eigenvalues; Complex[][] eigenvectors;

            // Extract the eigenvalues and eigenvectors of the Schur form matrix
            SquareMatrixAlgorithms.SchurEigensystem(aStore, dimension, out eigenvalues, out eigenvectors);

            // transform eigenvectors of schur form into eigenvectors of original matrix
            // while we are at it, normalize so largest component has value 1
            for (int i = 0; i < dimension; i++)
            {
                Complex[] v    = new Complex[dimension];
                double    norm = 0.0;
                for (int j = 0; j < dimension; j++)
                {
                    for (int k = 0; k < dimension; k++)
                    {
                        v[j] += Q[j, k] * eigenvectors[i][k];
                    }
                    norm = Math.Max(norm, Math.Max(Math.Abs(v[j].Re), Math.Abs(v[j].Im)));
                }
                for (int j = 0; j < dimension; j++)
                {
                    v[j] = v[j] / norm;
                }
                eigenvectors[i] = v;
            }

            ComplexEigensystem eigensystem = new ComplexEigensystem(dimension, eigenvalues, eigenvectors);

            return(eigensystem);
        }
Example #2
0
 /// <summary>
 /// Initializes a new square matrix.
 /// </summary>
 /// <param name="dimension">The dimension of the matrix, which must be positive.</param>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="dimension"/> &lt; 1.</exception>
 public SquareMatrix(int dimension)
 {
     if (dimension < 1)
     {
         throw new ArgumentOutOfRangeException(nameof(dimension));
     }
     this.dimension = dimension;
     this.store     = MatrixAlgorithms.AllocateStorage(dimension, dimension, ref offset, ref rowStride, ref colStride);
 }
Example #3
0
 /// <summary>
 /// Initializes a new square matrix.
 /// </summary>
 /// <param name="dimension">The dimension of the matrix, which must be positive.</param>
 /// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="dimension"/> &lt; 1.</exception>
 public SquareMatrix(int dimension)
 {
     if (dimension < 1)
     {
         throw new ArgumentOutOfRangeException("dimension");
     }
     this.dimension = dimension;
     this.store     = MatrixAlgorithms.AllocateStorage(dimension, dimension);
 }
 public static double[] CreateUnitMatrix(int dimension)
 {
     double[] store = MatrixAlgorithms.AllocateStorage(dimension, dimension);
     for (int i = 0; i < dimension; i++)
     {
         store[dimension * i + i] = 1.0;
     }
     return(store);
 }
Example #5
0
        // initialization and storage

        /// <summary>
        /// Initializes a rectangular matrix with the given dimensions.
        /// </summary>
        /// <param name="rowCount">The number of rows.</param>
        /// <param name="columnCount">The number of columns.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="rowCount"/> or <paramref name="columnCount"/>
        /// is less than one.</exception>
        public RectangularMatrix(int rowCount, int columnCount)
        {
            if (rowCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }
            if (columnCount < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }
            rows  = rowCount;
            cols  = columnCount;
            store = MatrixAlgorithms.AllocateStorage(rows, cols, ref offset, ref rowStride, ref colStride);
        }
Example #6
0
 /// <summary>
 /// Initializes a rectangular matrix from the given 2D array.
 /// </summary>
 /// <param name="source">The source 2D array.</param>
 public RectangularMatrix(double[,] source)
 {
     if (source == null)
     {
         throw new ArgumentNullException(nameof(source));
     }
     rows  = source.GetLength(0);
     cols  = source.GetLength(1);
     store = MatrixAlgorithms.AllocateStorage(rows, cols, ref offset, ref rowStride, ref colStride);
     for (int r = 0; r < rows; r++)
     {
         for (int c = 0; c < cols; c++)
         {
             store[MatrixAlgorithms.GetIndex(rows, cols, r, c)] = source[r, c];
         }
     }
 }
Example #7
0
        // initialization and storage

        /// <summary>
        /// Initializes a rectangular matrix with the given dimensions.
        /// </summary>
        /// <param name="rowCount">The number of rows.</param>
        /// <param name="columnCount">The number of columns.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="rowCount"/> or <paramref name="columnCount"/>
        /// is less than one.</exception>
        public RectangularMatrix(int rowCount, int columnCount)
        {
            if (rowCount < 1)
            {
                throw new ArgumentOutOfRangeException("rowCount");
            }
            if (columnCount < 1)
            {
                throw new ArgumentOutOfRangeException("columnCount");
            }
            rows      = rowCount;
            cols      = columnCount;
            store     = MatrixAlgorithms.AllocateStorage(rows, cols);
            offset    = 0;
            rowStride = 1;
            colStride = rows;
        }
Example #8
0
 /// <summary>
 /// Initializes a new square matrix from the given 2D array.
 /// </summary>
 /// <param name="entries">The source 2D array.</param>
 /// <remarks><para>The entries are copied, so changes to <paramref name="entries"/> after the matrix is initialized do not affect matrix entries.</para></remarks>
 /// <exception cref="ArgumentNullException"><paramref name="entries"/> is <see langword="null"/>.</exception>
 /// <exception cref="DimensionMismatchException">The two dimensions of <paramref name="entries"/> are not equal.</exception>
 public SquareMatrix(double[,] entries)
 {
     if (entries == null)
     {
         throw new ArgumentNullException(nameof(entries));
     }
     if (entries.GetLength(0) != entries.GetLength(1))
     {
         throw new DimensionMismatchException();
     }
     this.dimension = entries.GetLength(0);
     this.store     = MatrixAlgorithms.AllocateStorage(dimension, dimension, ref offset, ref rowStride, ref colStride);
     for (int r = 0; r < dimension; r++)
     {
         for (int c = 0; c < dimension; c++)
         {
             this[r, c] = entries[r, c];
         }
     }
 }