Exemplo n.º 1
0
        private static double[] GenerateFirstColumn(double[] aStore, int dimension, int a, int n, double sum, double product)
        {
            // compute the first column of M = (A - \lambda I) (A - \lambda^* I) = A^2 - 2 Re(\lambda) + |\lambda|^2 I
            // where 2 Re(\lambda) = sum of approximate eigenvalues, |\lambda|^2 = product of approximate eigenvalues
            // since A is Hessenberg, this has only three entries

            // first get the relevant A entries, which for the first column are from the leading Hesenberg entries

            int    b   = a + 1;
            int    c   = a + 2;
            double Aaa = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, a);
            double Aab = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, b);
            double Aba = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, b, a);
            double Abb = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, b, b);
            double Acb = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, c, b);

            // Aba should not be zero, or the problem would have been reduced
            Debug.Assert(Aba != 0.0);

            // use these entries and the sum and product of eigenvalues of get first column

            double[] u = new double[3];
            u[0] = Aaa * (Aaa - sum) + Aba * Aab + product;
            u[1] = Aba * (Aaa + Abb - sum);
            u[2] = Aba * Acb;

            return(u);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Gets or sets an entry of the matrix.
 /// </summary>
 /// <param name="r">The (zero-based) row number.</param>
 /// <param name="c">The (zero-based) column number.</param>
 /// <returns>The value of the specified matrix entry M<sub>r c</sub>.</returns>
 public override double this[int r, int c] {
     get {
         if ((r < 0) || (r >= dimension))
         {
             throw new ArgumentOutOfRangeException("r");
         }
         if ((c < 0) || (c >= dimension))
         {
             throw new ArgumentOutOfRangeException("c");
         }
         return(MatrixAlgorithms.GetEntry(store, dimension, dimension, r, c));
     }
     set {
         if ((r < 0) || (r >= dimension))
         {
             throw new ArgumentOutOfRangeException("r");
         }
         if ((c < 0) || (c >= dimension))
         {
             throw new ArgumentOutOfRangeException("c");
         }
         if (IsReadOnly)
         {
             throw new InvalidOperationException();
         }
         MatrixAlgorithms.SetEntry(store, dimension, dimension, r, c, value);
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Computes the determinant of the original matrix.
        /// </summary>
        /// <returns>det A</returns>
        public double Determinant()
        {
            double det = 1.0;

            for (int i = 0; i < dimension; i++)
            {
                det *= MatrixAlgorithms.GetEntry(rStore, dimension, dimension, i, i);
            }
            return(det);
        }
Exemplo n.º 4
0
        // v is assumed to

        private static void CompleteEigenvector(double[] aStore, int n, Complex[] v, Complex e, int i, int j)
        {
            while (j >= 0)
            {
                if ((j == 0) || (MatrixAlgorithms.GetEntry(aStore, n, n, j, j - 1) == 0.0))
                {
                    Complex t = 0.0;
                    for (int k = j + 1; k <= i; k++)
                    {
                        t += MatrixAlgorithms.GetEntry(aStore, n, n, j, k) * v[k];
                        //t += a[j, k] * v[k];
                    }

                    if (t == 0.0)
                    {
                        // this branch exists to avoid undefined 0.0 / 0.0
                        v[j] = 0.0;
                    }
                    else
                    {
                        //v[j] = t / (e - a[j, j]);
                        v[j] = t / (e - MatrixAlgorithms.GetEntry(aStore, n, n, j, j));
                    }

                    j--;
                }
                else
                {
                    Complex t1 = 0.0;
                    Complex t2 = 0.0;
                    for (int k = j + 1; k <= i; k++)
                    {
                        t1 -= MatrixAlgorithms.GetEntry(aStore, n, n, j - 1, k) * v[k];
                        t2 -= MatrixAlgorithms.GetEntry(aStore, n, n, j, k) * v[k];
                        //t1 -= a[j - 1, k] * v[k];
                        //t2 -= a[j, k] * v[k];
                    }
                    TwoByTwoSystem(
                        MatrixAlgorithms.GetEntry(aStore, n, n, j - 1, j - 1) - e,
                        MatrixAlgorithms.GetEntry(aStore, n, n, j - 1, j),
                        MatrixAlgorithms.GetEntry(aStore, n, n, j, j - 1),
                        MatrixAlgorithms.GetEntry(aStore, n, n, j, j) - e,
                        ref t1, ref t2
                        );
                    //TwoByTwoSystem(a[j - 1, j - 1] - e, a[j - 1, j], a[j, j - 1], a[j, j] - e, ref t1, ref t2);
                    v[j - 1] = t1;
                    v[j]     = t2;

                    j -= 2;
                }
            }
        }
Exemplo n.º 5
0
        public static void SchurEigensystem(double[] aStore, int n, out Complex[] eigenvalues, out Complex[][] eigenvectors)
        {
            eigenvalues  = new Complex[n];
            eigenvectors = new Complex[n][];

            int i = n - 1;

            while (i >= 0)
            {
                // find the eigenvector corresponding to the ith eigenvalue

                if ((i == 0) || (MatrixAlgorithms.GetEntry(aStore, n, n, i, i - 1) == 0.0))
                {
                    // We have no sub-diagonal element on the ith row. Since
                    //  (XXXXX) ( X )   ( X )
                    //  (XXXXX) ( X )   ( X )
                    //  (  aXX) ( 1 ) = ( a )
                    //  (   XX) ( 0 )   ( 0 )
                    //  (   XX) ( 0 )   ( 0 )
                    // a vector with v[i] = 1, v[j > i] = 0, and v[j < i] properly chosen will be an eigenvector.

                    // the eigenvalue is the ith diagonal element
                    double e = MatrixAlgorithms.GetEntry(aStore, n, n, i, i);

                    // we take the ith component of the eigenvector to be one; higher components must be zero
                    Complex[] v = new Complex[n];
                    v[i] = 1.0;

                    CompleteEigenvector(aStore, n, v, e, i, i - 1);
                    //WriteTransformedEigenvector(i, e, v, n, Q);
                    eigenvectors[i] = v;
                    eigenvalues[i]  = e;

                    i--;
                }
                else
                {
                    // We have a 2x2 sub-block
                    //   ( X X X )
                    //   (  [X X])
                    //   (  [X X])
                    // Find its eigenvalues

                    Complex e1, e2;
                    TwoByTwoEigenvalues(
                        MatrixAlgorithms.GetEntry(aStore, n, n, i - 1, i - 1),
                        MatrixAlgorithms.GetEntry(aStore, n, n, i - 1, i),
                        MatrixAlgorithms.GetEntry(aStore, n, n, i, i - 1),
                        MatrixAlgorithms.GetEntry(aStore, n, n, i, i),
                        out e1, out e2
                        );
                    //TwoByTwoEigenvalues(a[i - 1, i - 1], a[i - 1, i], a[i, i - 1], a[i, i], out e1, out e2);

                    // For each eigenvalue, compute the trailing eigenvector components and then the remaining components.
                    // For the trailing components, since
                    //   (a11 a12) ( v1 ) = \lambda ( v1 )
                    //   (a21 a22) ( v2 )           ( v2 )
                    // It follows that
                    //   v1 = (\lambda - a22) / a21 * v2
                    // and we normalize by choosing v2 = 1. Since we are only here if a21 != 0, there is no danger of
                    // dividing by zero, but there may well be a danger that (\lambda - a22) looses significant
                    // precision due to cancelation.

                    Complex[] v = new Complex[n];
                    v[i] = 1.0;
                    //v[i - 1] = (e1 - a[i, i]) / a[i, i - 1];
                    v[i - 1] = (e1 - MatrixAlgorithms.GetEntry(aStore, n, n, i, i)) / MatrixAlgorithms.GetEntry(aStore, n, n, i, i - 1);
                    CompleteEigenvector(aStore, n, v, e1, i, i - 2);
                    //WriteTransformedEigenvector(i, e1, v, n, Q);
                    eigenvectors[i] = v;
                    eigenvalues[i]  = e1;

                    v    = new Complex[n];
                    v[i] = 1.0;
                    //v[i - 1] = (e2 - a[i, i]) / a[i, i - 1];
                    v[i - 1] = (e2 - MatrixAlgorithms.GetEntry(aStore, n, n, i, i)) / MatrixAlgorithms.GetEntry(aStore, n, n, i, i - 1);
                    CompleteEigenvector(aStore, n, v, e2, i, i - 2);
                    //WriteTransformedEigenvector(i - 1, e2, v, n, Q);
                    eigenvectors[i - 1] = v;
                    eigenvalues[i - 1]  = e2;

                    i -= 2;
                }
            }
        }
Exemplo n.º 6
0
        // inverts the matrix in place
        // the in-place-ness makes this a bit confusing

        public static void GaussJordanInvert(double[] store, int dimension)
        {
            // keep track of row exchanges
            int[] ps = new int[dimension];

            // iterate over dimensions
            for (int k = 0; k < dimension; k++)
            {
                // look for a pivot in the kth column on any lower row
                int    p = k;
                double q = MatrixAlgorithms.GetEntry(store, dimension, dimension, k, k);

                for (int r = k + 1; r < dimension; r++)
                {
                    double s = MatrixAlgorithms.GetEntry(store, dimension, dimension, r, k);
                    if (Math.Abs(s) > Math.Abs(q))
                    {
                        p = r;
                        q = s;
                    }
                }
                ps[k] = p;

                // if no non-zero pivot is found, the matrix is singular and cannot be inverted
                if (q == 0.0)
                {
                    throw new DivideByZeroException();
                }

                // if the best pivot was on a lower row, swap it into the kth row
                if (p != k)
                {
                    Blas1.dSwap(store, k, dimension, store, p, dimension, dimension);
                }

                // divide the pivot row by the pivot element, so the diagonal element becomes unity
                MatrixAlgorithms.SetEntry(store, dimension, dimension, k, k, 1.0);
                Blas1.dScal(1.0 / q, store, k, dimension, dimension);

                // add factors to the pivot row to zero all off-diagonal elements in the kth column
                for (int r = 0; r < dimension; r++)
                {
                    if (r == k)
                    {
                        continue;
                    }
                    double a = MatrixAlgorithms.GetEntry(store, dimension, dimension, r, k);
                    MatrixAlgorithms.SetEntry(store, dimension, dimension, r, k, 0.0);
                    Blas1.dAxpy(-a, store, k, dimension, store, r, dimension, dimension);
                }
            }

            // unscramble exchanges
            for (int k = dimension - 1; k >= 0; k--)
            {
                int p = ps[k];
                if (p != k)
                {
                    Blas1.dSwap(store, dimension * p, 1, store, dimension * k, 1, dimension);
                }
            }
        }
Exemplo n.º 7
0
        public static Complex[] ExtractEigenvalues(double[] aStore, double[] qStore, int dimension)
        {
            int count = 0;

            // keep track of extracted eigenvalues
            Complex[] lambdas = new Complex[dimension];

            double sum_old = Double.PositiveInfinity;

            int n = dimension - 1;

            while (n >= 0)
            {
                //Write(aStore, dimension, dimension);

                // find the lowest decoupled, unreduced block
                int    a   = n;
                double sum = 0.0;
                while (a > 0)
                {
                    double f = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, a)) +
                               Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a - 1, a - 1));
                    double e = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, a - 1);
                    if ((f + e) == f)
                    {
                        MatrixAlgorithms.SetEntry(aStore, dimension, dimension, a, a - 1, 0.0);
                        break;
                    }
                    sum += Math.Abs(e);
                    a--;
                }

                /*
                 * Console.WriteLine("count = {0}", count);
                 * double[] qt = MatrixAlgorithms.Transpose(qStore, dimension, dimension);
                 * double[] qa = MatrixAlgorithms.Multiply(qStore, dimension, dimension, aStore, dimension, dimension);
                 * double[] qaqt = MatrixAlgorithms.Multiply(qa, dimension, dimension, qt, dimension, dimension);
                 * MatrixAlgorithms.PrintMatrix(qaqt, dimension, dimension);
                 */

                // check for maximum numbers of iterations without finding an eigenvalue
                if (count > 32)
                {
                    throw new NonconvergenceException();
                }

                // we are working between a and n, and our block is at least 3 wide

                // reduce if possible, otherwise do a iteration step

                if (a == n)
                {
                    // 1 X 1 block isolated
                    lambdas[a] = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, a);
                    n         -= 1;
                    count      = 0;
                    sum_old    = Double.PositiveInfinity;
                }
                else if (a == (n - 1))
                {
                    // 2 X 2 block isolated
                    double Aaa = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, a);
                    double Aba = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a + 1, a);
                    double Aab = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a, a + 1);
                    double Abb = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, a + 1, a + 1);
                    // eigenvalues are given by the quadratic formula
                    //   e = \frac{a_11 + a22}{2} \pm q
                    // descriminant q^2 = ( \frac{a_11 - a_22}{2} )^2 + a_21 a_1
                    double c  = (Aaa + Abb) / 2.0;
                    double d  = Aaa * Abb - Aba * Aab;
                    double q2 = c * c - d;
                    if (q2 >= 0.0)
                    {
                        // eigenvalues are real

                        double q = Math.Sqrt(q2);
                        if (c >= 0.0)
                        {
                            lambdas[a] = c + q;
                        }
                        else
                        {
                            lambdas[a] = c - q;
                        }
                        // i tried to do this as c + Math.Sign(c) * q, but when c = 0, Math.Sign(c) = 0, not 1
                        lambdas[a + 1] = d / lambdas[a];

                        /*
                         * double sn, cn;
                         * TwoByTwoSchur(ref Aaa, ref Aab, ref Aba, ref Abb, out sn, out cn);
                         * MatrixAlgorithms.SetEntry(aStore, dimension, dimension, a, a, Aaa);
                         * MatrixAlgorithms.SetEntry(aStore, dimension, dimension, a, a + 1, Aab);
                         * MatrixAlgorithms.SetEntry(aStore, dimension, dimension, a + 1, a, Aba);
                         * MatrixAlgorithms.SetEntry(aStore, dimension, dimension, a + 1, a + 1, Abb);
                         *
                         * // Multiply A from left by the rotation matrix R
                         * for (int cc = a + 2; cc < dimension; cc++) {
                         *  int i = MatrixAlgorithms.GetIndex(dimension, dimension, a, cc);
                         *  int j = MatrixAlgorithms.GetIndex(dimension, dimension, a + 1, cc);
                         *  double t = aStore[i];
                         *  aStore[i] = cn * t + sn * aStore[j];
                         *  aStore[j] = cn * aStore[j] - sn * t;
                         * }
                         * // Multiply A from the right by R^T
                         * for (int rr = 0; rr < a; rr++) {
                         *  int i = MatrixAlgorithms.GetIndex(dimension, dimension, rr, a);
                         *  int j = MatrixAlgorithms.GetIndex(dimension, dimension, rr, a + 1);
                         *  double t = aStore[i];
                         *  aStore[i] = cn * t + sn * aStore[j];
                         *  aStore[j] = cn * aStore[j] - sn * t;
                         * }
                         * // Multiply Q^T from the left by R
                         * if (qStore != null) {
                         *  for (int cc = 0; cc < dimension; cc++) {
                         *      int i = MatrixAlgorithms.GetIndex(dimension, dimension, a, cc);
                         *      int j = MatrixAlgorithms.GetIndex(dimension, dimension, a + 1, cc);
                         *      double t = qStore[i];
                         *      qStore[i] = cn * t + sn * qStore[j];
                         *      qStore[j] = cn * qStore[j] - sn * t;
                         *  }
                         * }
                         *
                         * lambdas[a] = Aaa;
                         * lambdas[a + 1] = Abb;
                         */
                    }
                    else
                    {
                        double q = Math.Sqrt(-q2);
                        lambdas[a]     = new Complex(c, q);
                        lambdas[a + 1] = new Complex(c, -q);
                    }

                    n      -= 2;
                    count   = 0;
                    sum_old = Double.PositiveInfinity;
                }
                else
                {
                    // use the lower-left 2 X 2 matrix to generate an approximate eigenvalue pair

                    int    m   = n - 1;
                    double Amm = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, m, m);
                    double Amn = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, m, n);
                    double Anm = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n, m);
                    double Ann = MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n, n);

                    // the trace of this 2 X 2 matrix is the sum of its eigenvalues, and its determinate is their product

                    double tr  = Amm + Ann;
                    double det = Amm * Ann - Amn * Anm;

                    // ad hoc shift
                    if ((count == 8) || (count == 16) || (count == 24))
                    {
                        double w = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n, n - 1)) +
                                   Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, m, m - 1));
                        tr  = 2.0 * w;
                        det = w * w;
                    }

                    FrancisTwoStep(aStore, qStore, dimension, a, n, tr, det);
                    sum_old = sum;
                    count++;
                }
            }

            return(lambdas);
        }
Exemplo n.º 8
0
        // EIGENVALUE ALGORITHMS

        //

        public static Complex[] ReduceToRealSchurForm(double[] aStore, double[] qStore, int dimension)
        {
            // keep track of eigenvalues
            Complex[] eigenvalues = new Complex[dimension];

            // keep track of interations
            int count = 0;

            // isolate the upper and lower boundaries of the curent subproblem
            // p is the upper index, n the lower index

            int n = dimension - 1;

            while (n >= 0)
            {
                // move up the matrix from endpoint n, looking for subdiagonal elements negligible compared to the neighboring diagonal elements
                // if we find one, that reduces the problem to the submatrix between p and n
                int p = n;
                while (p > 0)
                {
                    double d = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p, p)) + Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p - 1, p - 1));
                    double e = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p, p - 1));

                    if (d + e == d)
                    {
                        //  double f = d * Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p, p) - MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p - 1, p - 1));
                        //  double g = e * Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p - 1, p));

                        //  if (f + g == f) {
                        MatrixAlgorithms.SetEntry(aStore, dimension, dimension, p, p - 1, 0.0);
                        break;
                        //  }
                    }

                    p--;
                }

                /*
                 * if (p == n) {
                 *  // one eigenvalue
                 *  // reduce n and re-set count
                 * } else {
                 *  // compute m, matrix elements
                 *  // reduce n and re-set count
                 *  if (p == m) {
                 *      // two eigenvalues
                 *  } else {
                 *      // do step
                 *  }
                 * }
                 */

                //Print(a, dimension, p, n);

                // get the (indexes for) the entries in the trailing 2x2 matrix
                int m    = n - 1;
                int ammi = MatrixAlgorithms.GetIndex(dimension, dimension, m, m);
                int amni = MatrixAlgorithms.GetIndex(dimension, dimension, m, n);
                int anmi = MatrixAlgorithms.GetIndex(dimension, dimension, n, m);
                int anni = MatrixAlgorithms.GetIndex(dimension, dimension, n, n);

                if (n - p > 1)
                {
                    count++;
                    if (count > 32)
                    {
                        throw new NonconvergenceException();
                    }

                    double tr  = aStore[ammi] + aStore[anni];
                    double det = aStore[ammi] * aStore[anni] - aStore[amni] * aStore[anmi];

                    // ad hoc shift
                    if ((count == 8) || (count == 16) || (count == 24))
                    {
                        double w = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n, n - 1)) +
                                   Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n - 1, n - 2));
                        tr  = 2.0 * w;
                        det = w * w;
                    }

                    FrancisTwoStep(aStore, qStore, dimension, p, n, tr, det);
                }
                else
                {
                    if (p == n)
                    {
                        eigenvalues[n] = aStore[anni];
                    }
                    else if (p == m)
                    {
                        double sn, cn;
                        TwoByTwoRealSchur(ref aStore[ammi], ref aStore[amni], ref aStore[anmi], ref aStore[anni], out sn, out cn, out eigenvalues[m], out eigenvalues[n]);

                        // Multiply A from left by the rotation matrix R
                        for (int cc = p + 2; cc < dimension; cc++)
                        {
                            int    i = MatrixAlgorithms.GetIndex(dimension, dimension, p, cc);
                            int    j = MatrixAlgorithms.GetIndex(dimension, dimension, p + 1, cc);
                            double t = aStore[i];
                            aStore[i] = cn * t + sn * aStore[j];
                            aStore[j] = cn * aStore[j] - sn * t;
                        }
                        // Multiply A from the right by R^T
                        for (int rr = 0; rr < p; rr++)
                        {
                            int    i = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p);
                            int    j = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p + 1);
                            double t = aStore[i];
                            aStore[i] = cn * t + sn * aStore[j];
                            aStore[j] = cn * aStore[j] - sn * t;
                        }
                        // Multiply Q^T from the left by R
                        if (qStore != null)
                        {
                            for (int rr = 0; rr < dimension; rr++)
                            {
                                int    i = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p);
                                int    j = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p + 1);
                                double t = qStore[i];
                                qStore[i] = cn * t + sn * qStore[j];
                                qStore[j] = cn * qStore[j] - sn * t;
                            }
                        }
                    }

                    n     = p - 1;
                    count = 0;
                }
            }

            return(eigenvalues);
        }