Beispiel #1
0
        /// <summary>
        /// Extract sub matrix.
        /// </summary>
        /// <param name="i1">Start row.</param>
        /// <param name="i2">End row.</param>
        /// <param name="j1">Start column.</param>
        /// <param name="j2">End column.</param>
        /// <returns></returns>
        public MatrixQ Extract(int i1, int i2, int j1, int j2)
        {
            if (i2 < i1 || j2 < j1 || i1 <= 0 || j2 <= 0 || i2 > rowCount || j2 > columnCount)
            throw new ArgumentException("Index exceeds matrix dimension.");

              MatrixQ B = new MatrixQ(i2 - i1 + 1, j2 - j1 + 1);

              for (int i = i1; i <= i2; i++)
            for (int j = j1; j <= j2; j++)
              B[i - i1 + 1, j - j1 + 1] = this[i, j];

              return B;
        }
Beispiel #2
0
        /// <summary>
        /// Returns the shortest path between two given vertices i and j as
        /// int array.
        /// </summary>
        /// <param name="P">Path matrix as returned from Floyd().</param>
        /// <param name="i">One-based index of start vertex.</param>
        /// <param name="j">One-based index of end vertex.</param>
        /// <returns></returns>
        public static ArrayList FloydPath(MatrixQ P, int i, int j)
        {
            if (!P.IsSquare())
            throw new ArgumentException("Path matrix must be square.");
              else if (!P.IsReal())
            throw new ArgumentException("Adjacence matrices are expected to be real.");

              ArrayList path = new ArrayList();
              path.Add(i);

              //int borderliner = 0;
              //int n = P.Size()[0] + 1; // shortest path cannot have more than n vertices!

              while (P[i, j] != 0) {
            i = Convert.ToInt32(P[i, j]);
            path.Add(i);

            //borderliner++;

            //if (borderliner == n)
            //    throw new FormatException("P was not a Floyd path matrix.");
              }

              path.Add(j);

              return path;
        }
Beispiel #3
0
        public static MatrixQ HorizontalConcat(MatrixQ[] A)
        {
            if (A == null)
            throw new ArgumentNullException();
              else if (A.Length == 1)
            return A[0];
              else {
            MatrixQ C = HorizontalConcat(A[0], A[1]);

            for (int i = 2; i < A.Length; i++) {
              C = HorizontalConcat(C, A[i]);
            }

            return C;
              }
        }
Beispiel #4
0
        /// <summary>
        /// Generates diagonal matrix
        /// </summary>
        /// <param name="diag_vector">column vector containing the diag elements</param>
        /// <returns></returns>
        public static MatrixQ Diag(MatrixQ diag_vector)
        {
            int dim = diag_vector.VectorLength();

              if (dim == 0)
            throw new ArgumentException("diag_vector must be 1xN or Nx1");

              MatrixQ M = new MatrixQ(dim, dim);

              for (int i = 1; i <= dim; i++) {
            M[i, i] = diag_vector[i];
              }

              return M;
        }
Beispiel #5
0
        /// <summary>
        /// Implements the dot product of two vectors.
        /// </summary>
        /// <param name="v">Row or column vector.</param>
        /// <param name="w">Row or column vector.</param>
        /// <returns>Dot product.</returns>
        public static Complex Dot(MatrixQ v, MatrixQ w)
        {
            int m = v.VectorLength();
              int n = w.VectorLength();

              if (m == 0 || n == 0)
            throw new ArgumentException("Arguments need to be vectors.");
              else if (m != n)
            throw new ArgumentException("Vectors must be of the same length.");

              Complex buf = Complex.Zero;

              for (int i = 1; i <= m; i++) {
            buf += v[i] * w[i];
              }

              return buf;
        }
Beispiel #6
0
        public static MatrixQ operator *(Complex x, MatrixQ A)
        {
            MatrixQ B = new MatrixQ(A.RowCount, A.ColumnCount);

              for (int i = 1; i <= A.RowCount; i++) {
            for (int j = 1; j <= A.ColumnCount; j++) {
              B[i, j] = A[i, j] * x;
            }
              }

              return B;
        }
Beispiel #7
0
        /// <summary>
        /// Creates m by n chessboard matrix with interchangнng ones and zeros.
        /// 
        /// </summary>        
        /// <param name="n">Number of columns.</param>
        /// <param name="even">Indicates, if matrix entry (1,1) equals zero.</param>
        /// <returns></returns>
        public static MatrixQ ChessboardMatrix(int n, bool even)
        {
            MatrixQ M = new MatrixQ(n);

              if (even)
            for (int i = 1; i <= n; i++)
              for (int j = 1; j <= n; j++)
            M[i, j] = KroneckerDelta((i + j) % 2, 0);
              else
            for (int i = 1; i <= n; i++)
              for (int j = 1; j <= n; j++)
            M[i, j] = KroneckerDelta((i + j) % 2, 1);

              return M;
        }
Beispiel #8
0
        /// <summary>
        /// Inserts row at specified index.
        /// </summary>
        /// <param name="row">Vector to insert</param>
        /// <param name="i">One-based index at which to insert</param>
        public void InsertRow(MatrixQ row, int i)
        {
            int size = row.VectorLength();

              if (size == 0)
            throw new InvalidOperationException("Row must be a vector of length > 0.");

              if (i <= 0)
            throw new ArgumentException("Row index must be positive.");

              if (i > rowCount)
            this[i, size] = Complex.Zero;

              else if (size > columnCount) {
            this[i, size] = Complex.Zero;
            rowCount++;
              }
              else
            rowCount++;

              Values.Insert(--i, new ArrayList(size));
              //Debug.WriteLine(Values.Count.ToString());

              for (int k = 1; k <= size; k++) {
            ((ArrayList)Values[i]).Add(row[k]);
              }

              // fill w/ zeros if vector row is too short
              for (int k = size; k < columnCount; k++) {
            ((ArrayList)Values[i]).Add(Complex.Zero);
              }
        }
Beispiel #9
0
        /// <summary>
        /// Gram-Schmidtian orthogonalization of an m by n matrix A, such that
        /// {Q, R} is returned, where A = QR, Q is m by n and orthogonal, R is
        /// n by n and upper triangular matrix.
        /// </summary>
        /// <returns></returns>
        public MatrixQ[] QRGramSchmidt()
        {
            int m = rowCount;
              int n = columnCount;

              MatrixQ A = this.Clone();

              MatrixQ Q = new MatrixQ(m, n);
              MatrixQ R = new MatrixQ(n, n);

              // the first column of Q equals the first column of this matrix
              for (int i = 1; i <= m; i++)
            Q[i, 1] = A[i, 1];

              R[1, 1] = Complex.One;

              for (int k = 1; k <= n; k++) {
            R[k, k] = new Complex(A.Column(k).Norm());

            for (int i = 1; i <= m; i++)
              Q[i, k] = A[i, k] / R[k, k];

            for (int j = k + 1; j <= n; j++) {
              R[k, j] = Dot(Q.Column(k), A.Column(j));

              for (int i = 1; i <= m; i++)
            A[i, j] = A[i, j] - Q[i, k] * R[k, j];
            }
              }

              return new MatrixQ[] { Q, R };
        }
Beispiel #10
0
 /// <summary>
 /// Inserts a sub matrix M at row i and column j.
 /// </summary>
 /// <param name="i">One-based row number to insert.</param>
 /// <param name="j">One-based column number to insert.</param>
 /// <param name="M">Sub matrix to insert.</param>
 public void Insert(int i, int j, MatrixQ M)
 {
     for (int m = 1; m <= M.rowCount; m++)
     for (int n = 1; n <= M.columnCount; n++)
       this[i + m - 1, j + n - 1] = M[m, n];
 }
Beispiel #11
0
        /// <summary>
        /// Inserts column at specified index.
        /// </summary>
        /// <param name="col">Vector to insert</param>
        /// <param name="j">One-based index at which to insert</param>
        public void InsertColumn(MatrixQ col, int j)
        {
            int size = col.VectorLength();

              if (size == 0)
            throw new InvalidOperationException("Row must be a vector of length > 0.");

              if (j <= 0)
            throw new ArgumentException("Row index must be positive.");

              if (j > columnCount) {
            this[size, j] = Complex.Zero;
              }
              else
            columnCount++;

              if (size > rowCount) {
            this[size, j] = Complex.Zero;
              }

              j--;

              for (int k = 0; k < size; k++) {
            ((ArrayList)Values[k]).Insert(j, col[k + 1]);
              }

              // fill w/ zeros if vector col too short
              for (int k = size; k < rowCount; k++) {
            ((ArrayList)Values[k]).Insert(j, 0);
              }
        }
Beispiel #12
0
        /// <summary>
        /// Performs Hessenberg-Householder reduction, where {H, Q}
        /// is returned, with H Hessenbergian, Q orthogonal and H = Q'AQ.
        /// </summary>
        /// <returns></returns>
        public MatrixQ[] HessenbergHouseholder()
        {
            //throw new NotImplementedException("Still buggy!");

              if (!this.IsSquare())
            throw new InvalidOperationException("Cannot perform Hessenberg Householder decomposition of non-square matrix.");

              int n = rowCount;
              MatrixQ Q = Identity(n);
              MatrixQ H = this.Clone();
              MatrixQ I, N, R, P;
              MatrixQ[] vbeta = new MatrixQ[2];
              int m;

              // don't try to understand from the code alone.
              // this is pure magic to me - mathematics, reborn as code.
              for (int k = 1; k <= n - 2; k++) {
            vbeta = HouseholderVector(H.Extract(k + 1, n, k, k));
            I = Identity(k);
            N = Zeros(k, n - k);

            m = vbeta[0].VectorLength();
            R = Identity(m) - vbeta[1][1, 1] * vbeta[0] * vbeta[0].Transpose();

            H.Insert(k + 1, k, R * H.Extract(k + 1, n, k, n));
            H.Insert(1, k + 1, H.Extract(1, n, k + 1, n) * R);

            P = BlockMatrix(I, N, N.Transpose(), R);

            Q = Q * P;
              }

              return new MatrixQ[] { H, Q };
        }
Beispiel #13
0
        /// <summary>
        /// Performs forward insertion for regular lower triangular matrix
        /// and right side b, such that the solution is saved right within b.
        /// The matrix is not changed.
        /// </summary>
        /// <param name="b">Vector of height n, if matrix is n by n.</param>
        public void ForwardInsertion(MatrixQ b)
        {
            if (!this.IsLowerTriangular())
            throw new InvalidOperationException("Cannot perform forward insertion for matrix not being lower triangular.");

              if (/*this.Determinant*/this.DiagProd() == 0)
            throw new InvalidOperationException("Warning: Matrix is nearly singular.");

              int n = rowCount;

              if (b.VectorLength() != n)
            throw new ArgumentException("Parameter must vector of the same height as matrix.");

              for (int j = 1; j <= n - 1; j++) {
            b[j] /= this[j, j];

            for (int i = 1; i <= n - j; i++)
              b[j + i] -= b[j] * this[j + i, j];
              }

              b[n] /= this[n, n];
        }
Beispiel #14
0
        /// <summary>
        /// Extracts upper trapeze matrix of this matrix.
        /// </summary>
        /// <returns></returns>
        public MatrixQ ExtractUpperTrapeze()
        {
            MatrixQ buf = new MatrixQ(rowCount, columnCount);

              for (int i = 1; i <= rowCount; i++) {
            for (int j = i; j <= columnCount; j++) {
              buf[i, j] = this[i, j];
            }
              }

              return buf;
        }
Beispiel #15
0
        /// <summary>
        /// Givens product. Internal use for QRGivens.
        /// </summary>
        /// <param name="c"></param>
        /// <param name="s"></param>
        /// <param name="n"></param>
        /// <returns></returns>
        private MatrixQ GivProd(MatrixQ c, MatrixQ s, int n)
        {
            int n1 = n - 1;
              int n2 = n - 2;

              MatrixQ Q = Eye(n);
              Q[n1, n1] = c[n1];
              Q[n, n] = c[n1];
              Q[n1, n] = s[n1];
              Q[n, n1] = -s[n1];

              for (int k = n2; k >= 1; k--) {
            int k1 = k + 1;
            Q[k, k] = c[k];
            Q[k1, k] = -s[k];
            MatrixQ q = Q.Extract(k1, k1, k1, n);
            Q.Insert(k, k1, s[k] * q);
            Q.Insert(k1, k1, c[k] * q);
              }

              return Q;
        }
Beispiel #16
0
        /// <summary>
        /// Executes the QR iteration.
        /// </summary>
        /// <param name="max_iterations"></param>
        /// <returns></returns>
        public MatrixQ QRIterationBasic(int max_iterations)
        {
            if (!this.IsReal())
            throw new InvalidOperationException("Basic QR iteration is possible only for real matrices.");

              MatrixQ T = this.Clone();
              MatrixQ[] QR = new MatrixQ[2];

              for (int i = 0; i < max_iterations; i++) {
            QR = T.QRGramSchmidt();
            T = QR[1] * QR[0];
              }

              return T;
        }
Beispiel #17
0
        public static MatrixQ operator *(MatrixQ A, MatrixQ B)
        {
            if (A.ColumnCount != B.RowCount)
            throw new ArgumentException("Inner matrix dimensions must agree.");

              MatrixQ C = new MatrixQ(A.RowCount, B.ColumnCount);

              for (int i = 1; i <= A.RowCount; i++) {
            for (int j = 1; j <= B.ColumnCount; j++) {
              C[i, j] = Dot(A.Row(i), B.Column(j));
            }
              }

              return C;
        }
Beispiel #18
0
        /// <summary>
        /// Returns the matrix of the real parts of the entries of this matrix.
        /// </summary>
        /// <returns></returns>
        public MatrixQ Re()
        {
            MatrixQ M = new MatrixQ(rowCount, columnCount);

              for (int i = 1; i <= rowCount; i++)
            for (int j = 1; j <= columnCount; j++)
              M[i, j] = new Complex(this[i, j].Re);

              return M;
        }
Beispiel #19
0
        /// <summary>
        /// Constructs block matrix [A, B; C, D].
        /// </summary>
        /// <param name="A">Upper left sub matrix.</param>
        /// <param name="B">Upper right sub matrix.</param>
        /// <param name="C">Lower left sub matrix.</param>
        /// <param name="D">Lower right sub matrix.</param>
        /// <returns></returns>
        public static MatrixQ BlockMatrix(MatrixQ A, MatrixQ B, MatrixQ C, MatrixQ D)
        {
            if (A.RowCount != B.RowCount || C.RowCount != D.RowCount
              || A.ColumnCount != C.ColumnCount || B.ColumnCount != D.ColumnCount)
            throw new ArgumentException("Matrix dimensions must agree.");

              MatrixQ R = new MatrixQ(A.RowCount + C.RowCount, A.ColumnCount + B.ColumnCount);

              for (int i = 1; i <= R.rowCount; i++)
            for (int j = 1; j <= R.columnCount; j++)
              if (i <= A.RowCount) {
            if (j <= A.ColumnCount)
              R[i, j] = A[i, j];
            else
              R[i, j] = B[i, j - A.ColumnCount];
              }
              else {
            if (j <= C.ColumnCount)
              R[i, j] = C[i - A.RowCount, j];
            else
              R[i, j] = D[i - A.RowCount, j - C.ColumnCount];
              }

              return R;
        }
Beispiel #20
0
        /// <summary>
        /// Retrieves row with one-based index i.
        /// </summary>
        /// <param name="i"></param>
        /// <returns>i-th row...</returns>
        public MatrixQ Row(int i)
        {
            if (i <= 0 || i > rowCount)
            throw new ArgumentException("Index exceed matrix dimension.");

              //return (new Matrix((Complex[])((ArrayList)Values[i - 1]).ToArray(typeof(Complex)))).Transpose();

              MatrixQ buf = new MatrixQ(columnCount, 1);

              for (int j = 1; j <= this.columnCount; j++) {
            buf[j] = this[i, j];
              }

              return buf;
        }
Beispiel #21
0
        /// <summary>
        /// Performs depth-first search for a graph given by its adjacence matrix.
        /// </summary>
        /// <param name="adjacence_matrix">A[i,j] = 0 or +infty, if there is no edge from i to j; any non-zero value otherwise.</param>
        /// <param name="root">The vertex to begin the search.</param>
        /// <returns>Adjacence matrix of the computed spanning tree.</returns>
        public static MatrixQ DFS(MatrixQ adjacence_matrix, int root)
        {
            if (!adjacence_matrix.IsSquare())
            throw new ArgumentException("Adjacence matrices are expected to be square.");
              else if (!adjacence_matrix.IsReal())
            throw new ArgumentException("Adjacence matrices are expected to be real.");

              int n = adjacence_matrix.RowCount;

              if (root < 1 || root > n)
            throw new ArgumentException("Root must be a vertex of the graph, e.i. in {1, ..., n}.");

              MatrixQ spanTree = new MatrixQ(n);

              bool[] marked = new bool[n + 1];

              Stack todo = new Stack();
              todo.Push(root);
              marked[root] = true;

              // adajacence lists for each vertex
              ArrayList[] A = new ArrayList[n + 1];

              for (int i = 1; i <= n; i++) {
            A[i] = new ArrayList();

            for (int j = 1; j <= n; j++)
              if (adjacence_matrix[i, j].Re != 0 && adjacence_matrix[i, j].Im != double.PositiveInfinity)
            A[i].Add(j);
              }

              int v, w;

              while (todo.Count > 0) {
            v = (int)todo.Peek();

            if (A[v].Count > 0) {
              w = (int)A[v][0];

              if (!marked[w]) {
            marked[w] = true; // mark w
            spanTree[v, w].Re = 1; // mark vw
            todo.Push(w); // one more to search
              }

              A[v].RemoveAt(0);
            }
            else
              todo.Pop();
              }

              return spanTree;
        }
Beispiel #22
0
        /// <summary>
        /// Splits matrix into its row vectors.
        /// </summary>
        /// <returns>Array of row vectors.</returns>
        public MatrixQ[] RowVectorize()
        {
            MatrixQ[] buf = new MatrixQ[rowCount];

              for (int i = 1; i <= buf.Length; i++) {
            buf[i] = this.Row(i);
              }

              return buf;
        }
Beispiel #23
0
        /// <summary>
        /// Generates diagonal matrix
        /// </summary>
        /// <param name="diag_vector">column vector containing the diag elements</param>
        /// <returns></returns>
        public static MatrixQ Diag(MatrixQ diag_vector, int offset)
        {
            int dim = diag_vector.VectorLength();

              if (dim == 0)
            throw new ArgumentException("diag_vector must be 1xN or Nx1.");

              //if (Math.Abs(offset) >= dim)
              //    throw new ArgumentException("Absolute value of offset must be less than length of diag_vector.");

              MatrixQ M = new MatrixQ(dim + Math.Abs(offset), dim + Math.Abs(offset));
              dim = M.RowCount;

              if (offset >= 0) {
            for (int i = 1; i <= dim - offset; i++) {
              M[i, i + offset] = diag_vector[i];
            }
              }
              else {
            for (int i = 1; i <= dim + offset; i++) {
              M[i - offset, i] = diag_vector[i];
            }
              }

              return M;
        }
Beispiel #24
0
 /// <summary>
 /// Solves equation this*x = b via conjugate gradient method.
 /// </summary>
 /// <param name="b"></param>
 /// <returns></returns>
 public MatrixQ SolveCG(MatrixQ b)
 {
     throw new NotImplementedException("Still buggy!");
 }
Beispiel #25
0
        /// <summary>
        /// Computes all shortest distance between any vertices in a given graph.
        /// </summary>
        /// <param name="adjacence_matrix">Square adjacence matrix. The main diagonal
        /// is expected to consist of zeros, any non-existing edges should be marked
        /// positive infinity.</param>
        /// <returns>Two matrices D and P, where D[u,v] holds the distance of the shortest
        /// path between u and v, and P[u,v] holds the shortcut vertex on the way from
        /// u to v.</returns>
        public static MatrixQ[] Floyd(MatrixQ adjacence_matrix)
        {
            if (!adjacence_matrix.IsSquare())
            throw new ArgumentException("Expected square matrix.");
              else if (!adjacence_matrix.IsReal())
            throw new ArgumentException("Adjacence matrices are expected to be real.");

              int n = adjacence_matrix.RowCount;

              MatrixQ D = adjacence_matrix.Clone(); // distance matrix
              MatrixQ P = new MatrixQ(n);

              double buf;

              for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
              for (int j = 1; j <= n; j++) {
            buf = D[i, k].Re + D[k, j].Re;
            if (buf < D[i, j].Re) {
              D[i, j].Re = buf;
              P[i, j].Re = k;
            }
              }

              return new MatrixQ[] { D, P };
        }
Beispiel #26
0
        /// <summary>
        /// Swaps each matrix entry A[i, j] with A[j, i].
        /// </summary>
        /// <returns>A transposed matrix.</returns>
        public MatrixQ Transpose()
        {
            MatrixQ M = new MatrixQ(columnCount, rowCount);

              for (int i = 1; i <= columnCount; i++) {
            for (int j = 1; j <= rowCount; j++) {
              M[i, j] = this[j, i];
            }
              }

              return M;
        }
Beispiel #27
0
        public static MatrixQ HorizontalConcat(MatrixQ A, MatrixQ B)
        {
            MatrixQ C = A.Row(1);

              for (int i = 2; i <= A.RowCount; i++) {
            C.InsertRow(A.Row(i), i);
              }

              for (int i = 1; i <= B.RowCount; i++) {
            C.InsertRow(B.Row(i), C.RowCount + 1);
              }

              return C;
        }
Beispiel #28
0
        /// <summary>
        /// Computes the Householder vector.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        private static MatrixQ[] HouseholderVector(MatrixQ x)
        {
            //throw new NotImplementedException("Supposingly buggy!");

              //if (!x.IsReal())
              //    throw new ArgumentException("Cannot compute housholder vector of non-real vector.");

              int n = x.VectorLength();

              if (n == 0)
            throw new InvalidOperationException("Expected vector as argument.");

              MatrixQ y = x / x.Norm();
              MatrixQ buf = y.Extract(2, n, 1, 1);
              Complex s = Dot(buf, buf);

              MatrixQ v = Zeros(n, 1);
              v[1] = Complex.One;

              v.Insert(2, 1, buf);

              double beta = 0;

              if (s != 0) {
            Complex mu = Complex.Sqrt(y[1] * y[1] + s);
            if (y[1].Re <= 0)
              v[1] = y[1] - mu;
            else
              v[1] = -s / (y[1] + mu);

            beta = 2 * v[1].Re * v[1].Re / (s.Re + v[1].Re * v[1].Re);
            v = v / v[1];
              }

              return new MatrixQ[] { v, new MatrixQ(beta) };
        }
Beispiel #29
0
        /// <summary>
        /// Creates m by n matrix filled with ones.
        /// </summary>
        /// <param name="m">Number of rows.</param>
        /// <param name="n">Number of columns.</param>
        /// <returns>m by n matrix filled with ones.</returns>        
        public static MatrixQ Ones(int m, int n)
        {
            MatrixQ M = new MatrixQ(m, n);

              for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
              ((ArrayList)M.Values[i])[j] = Complex.One;
            }
              }

              return M;
        }
Beispiel #30
0
        /// <summary>
        /// Extracts main diagonal vector of the matrix as a column vector.
        /// </summary>
        /// <returns></returns>
        public MatrixQ DiagVector()
        {
            if (!this.IsSquare())
            throw new InvalidOperationException("Cannot get diagonal of non-square matrix.");

              MatrixQ v = new MatrixQ(this.columnCount, 1);

              for (int i = 1; i <= this.columnCount; i++) {
            v[i] = this[i, i];
              }

              return v;
        }