4.4 Block Matrix Manipulation

By block matrices we mean matrices with noncommuting entries.

The Mathematica convention for handling vectors is tricky.

   v={{1,2,4}}

is a 1×3 matrix or a row vector

   v={{1},{2},{4}}

is a 3×1 matrix or a column vector

   v={1,2,4}

is a vector but NOT A MATRIX. Indeed whether it is a row or column vector depends on the context. DON’T USE IT. Always remember to use TWO curly brackets on your vectors or there will probably be trouble.

As of NCAlgebra version 3.2 one can handle block matrix manipulation two different ways. One is the old way as described below where you use the command MatMult[A, B] to multiply block matrices A and B and tpMat[A] to take transposes. The other way is much more pleasing though still a little risky. First you use the NCGuts[] with the Options NCStrongProduct1 True to change ** to make block matrices multiply corectly. Further invoke the Option NCStrongProduct2 True to strengthen the power of **. Now one does not have to use MatMult and tpMat; just use ** and tp instead it recognizes matrix sizes and multiplies correctly.

4.4.1 MatMult[x, y, ]

Aliases: MM
Description: MatMult multiplies matrices. The Mathematica code executed for MatMult[x,y] is Inner[ NonCommutativeMultiply, x, y, Plus];
Arguments: x is a block matrix, and y is a block matrix.
Comments / Limitations: MatMult can take any number of input parameters. For example, MatMult[a, b, c, d] will give the same result as MatMult[a, MatMult[b, MatMult[c, d]] ].

4.4.2 ajMat[u]

Aliases: None
Description: ajMat[u] returns the transpose of the block matrix u. The Mathematica code is Transpose[Map[aj[#]&,u, 2]];
Arguments: u is a block m × n matrix.
Comments / Limitations: None

4.4.3 coMat[u]

Aliases: None
Description: coMat[u] returns the transpose of the block matrix u. The Mathematica code is [Map[co[#]&,u, 2]];
Arguments: u is a block m × n matrix
Comments / Limitations: None

4.4.4 tpMat[u]

Aliases: None
Description: tpMat[u] returns the transpose of the block matrix u. The Mathematica is Transpose[Map[tp[#]&,u, 2]];
Arguments: u is a block m × n matrix
Comments / Limitations: None

4.4.5 NCMToMatMult[expr]

Aliases: None
Description: Sometimes one develops an expression in which ** occurs between matrices. This command takes all ** and converts them to MatMult. The Mathematica code executed is expr//.NonCommutativeMultiply MatMult;
Arguments: expr is an algebraic expression. This and its inverse (TimesToNCM) are important in manipulating block matrices. One can use
expr ∕∕.N onCommutativeM    ultiply → M  atM ult
instead of this command, since that is all that this command amounts to.
Comments / Limitations: None

4.4.6 TimesToNCM[expr]

Aliases: TTNCM
Description: The Mathematica code executed is expr∕.Times NonCommutativeMultiply
Arguments: expr is an algebraic expression.
Comments / Limitations: It changes commutative multiplication (Times) to NonCommutative multiplication.

4.4.7 Special Operations with Block Matrices

In 1999, we produced commands for LU decomposition and Cholesky decomposition of an inversion of matrices with noncommutative entries. These replace older commands GaussElimination[X] and invMat2[mat] for 2 × 2 block matrices which are no longer documented. The next 6 commands do that.

4.4.8 NCLDUDecomposition[aMatrix, Options]

Aliases: None.
Description: NCLDUDecomposition[X] yields the LDU decomposition for a square matrix X. It returns a list of four elements, namely L,D,U, and P such that PXPT = LDU. The first element is the lower triangular matrix L, the second element is the diagonal matrix D, the third element is the upper triangular matrix U, and the fourth is the permutation matrix P (the identity is returned if no permutation is needed). As an option, it may also return a list of the permutations used at each step of the LDU factorization as a fifth element.

Suppose X is given by X = {{a,b, 0},{0,c,d},{a, 0,d}}. The command
{lo,di,up, P }=  N CLDU   Decomposition[X]
returns matrices, which in MatrixForm are:

    (                     )                (                           )
       1        0       0                     a  0          0
lo = (  0        1       0 )           di = (  0  c          0          )
       1  - b * *inv[c] 1                     0  0  d + b * *inv[c] * *d
     (                            )       (           )
        1  inv[a] * *b     0                 1  0  0
up = (  0      1       inv[c] * *d )  P = (  0  1  0  )
        0      0           1                 0  0  1

As matrix X is 3×3, one can provide 2 permutation matrices. Let those permutations be given by l1 = {3, 2, 1} and l2 = {1, 3, 2}, that means:

      (          )         (          )
         0  0  1              1  0  0
P 1 = (  0  1  0 )   P 2 = (  0  0  1 )
         1  0  0              0  1  0

just as in NCPermutationMatrix. The command

{lo,di,up, P}=  N CLDU   Decomposition[X,   P ermutation  →  {l1, l2}]
returns matrices, which in MatrixForm are:

     (            )                        (              )
        1   0   0                             d  0    0
lo = (  0   1   0 )                   di = (  0  a    0   )
     (  1  - 1  1                 )        (  0  0  b +) c
        1  inv[d] * *a      0                 0  0  1
     (  0       1       inv[a] * *b )       (  1  0  0 )
up =                                  P  =               = P2 P1
        0       0           1                 0  1  0

It can be checked that PT lo di up P = X:

M atM  ult[T ranspose[P ],lo, di,up, P ] = {{a, b,0},{0,c,d}, {a,0,d}}
Arguments: X is a square matrix n by n. The default Options are:
{Permutation False, CheckDecomposition False,
NCSimplifyPivots False, StopAutoPermutation False,
ReturnPermutation False, Stop2by2Pivoting False }. If permutation matrices are to be given, they should be provided as Permutation → {l1, l2, ⋅⋅⋅, ln}, where each li is a list of integers (see the command NCPermutationMatrix[]). If CheckDecomposition is set to True, the function checks if PXPT is identical to LDU. Where P = P1P2⋅⋅⋅Pn, and each Pi is the permutation matrix associated with each li.

Often a prospective pivot will appear to be nonzero in Mathematica even though it reduces to zero. To ensure we are not pivoting with a convoluted form of zero, we simplify the pivot at each step. By default, NCLDUDecomposition converts the pivot from non-commutative to commutative and then simplifies the expression. If the commutative form of the pivot simplifies to zero, Mathematica scrolls down the diagonal looking for a pivot which does not simplify to zero. If all the diagonal entries simplify to zero utilizing the CommuteEverything[] command, the process is repeated using NCSimplifyRational.
This strategy is incorporated for two main reasons. One is that for large matrices it is much faster. Secondly, NCSimplifyRational does not always completely simplify complicated expressions. Setting NCSimplifyPivots True bypasses CommuteEverything and immediately applies
NCSimplifyRational to each pivot. NCLDUDecomposition will automatically pivot if the current pivot at a particular iteration is zero. If the user utilized the Permutation option, then the permutation designated will be temporarily disregarded. However, NCLDUDecomposition will try and use the given permutation list for the next step. In this way,
NCLDUDecomposition follows the user permutation as closely as possible. If StopAutoPermutation True, then NCLDUDecomposition will not automatically pivot and will strictly adhere to the user’s permutation, attempting to divide by zero if need be. This will allow the user to determine which permutations are not possible. Because NCLDUDecomposition will automatically pivot when necessary by default, the ReturnPermutation was created so that the permutation used in the decomposition can be returned to the user for further analysis if set to True.
To explain the last option it is somewhat necessary for the user to have an idea of how the pivoting strategy works. The permutations used are always symmetrically applied. Because of this, we can only place other diagonal elements in the (1,1) position. However, it is possible to place any off diagonal element in the (2,1) position. Thus our strategy is to pivot only with diagonal elements if possible. If all the diagonal elements are zero, then a permutation matrix is used to place a nonzero entry in the (2,1) position which will automaticaly place a nonzero entry in the (1,2) position if the matrix is symmetric. Then, instead of using the (1,1) entry as a pivot, the 2×2 submatrix starting in the (1,1) position is used as a block pivot. This has the effect of creating an LDU decomposition where D is a block diagonal matrix with 1×1 and 2×2 blocks along the diagonal. (Note: The pivots are precisely the diagonal entries of D.) Setting Stop2by2Pivoting True will halt 2 × 2 block pivoting, returning instead, the remaining undecomposed block with zeros along the diagonal as a final block diagonal entry.
Comments / Limitations: NCLDUDecomposition automatically assumes invertible any expressions (pivot) it needs to be invertible. Also, the 2 × 2 pivoting strategy assumes that the matrix is symmetric in that it only ensures that the (2,1) entry is nonzero (assuming by symmetry that the (1,2) is also zero). The pivoting strategy chooses its pivots based upon the smallest leaf count invoking the Mathematica command LeafCount[]. It will choose the smallest nonzero diagonal element basing size upon the leaf count. This strategy is incorporated in an attempt to find the simplest LDU factorization possible. If a 2 × 2 pivot is used and ReturnPermutation is set to True then at the end of the permutation list returned will be the string 2by2 permutation.

4.4.9 NCAllPermutationLDU[aMatrix]

Aliases: None.
Description: NCAllPermutationLDU[aMatrix] returns the LDU decomposition of a matrix for all possible permutations. The code cycles through all possible permutations and calls NCLDUDecomposition for each one.
Arguments: aMatrix is a square matrix. The default options for NCAllPermutationLDU are: PermutationSelection False, CheckDecomposition False, NCSimplifyPivots False, StopAutoPermutation False, ReturnPermutation False, Stop2by2Pivoting False. All of these options have the same effect as in NCLDUDecomposition, except for PermutationSelection. PermutationSelection should be a list of numbers between 1 and the number of possible permutations. NCAllPermutationLDU will use this list to choose the permutations from its canonical list to decompose the matrix using NCLDUDecomposition. For example, PermutationSelection can be {1,,n}.
Comments / Limitations: The output is a list of all successful outputs from NCLDUDecomposition. Note that some permutations may lead to a zero pivot in the process of doing the LDU decomposition. In that case, the LDU decomposition is not well defined, actually in Mathematica one gets a lot of signs, but this output will not be included in the list of successful outputs.

4.4.10 NCInverse[aSquareMatrix]

Aliases: None.
Description: NCInverse[m] gives a symbolic inverse of a matrix with noncommutative entries.
Arguments: m is an n × n matrix with noncommutative entries.
Comments / Limitations: This command is primarily used symbolically and is not guarenteed to work for any specific examples. Usually the elements of the inverse matrix (m-1) are huge expressions. We recommend using NCSimplifyRational[NCInverse[m]] to improve the formula you get. In some cases, NCSimplifyRational[m-1m] does not provide the identity matrix, even though it does equal the identity matrix. The formula we use for NCInverse[] comes from the LDU decomposition. Thus in principle it depends on the order chosen for pivoting even if the inverse of a matrix is unique.

4.4.11 NCPermutationMatrix[aListOfIntegers]

Aliases: None.
Description: NCPermutationMatrix[aListOfIntegers] returns the permutation matrix associated with the list of integers. It is just the identity matrix with its columns re-ordered.
Arguments: aListOfIntegers is an encoding which specifies where the 1’s occur in each column. e.g., aListOfintegers = {2, 4, 3, 1} represents the permutation matrix
     ⌊             ⌋
       0   0  0  1
P  = || 1   0  0  0 ||
     ⌈ 0   0  1  0 ⌉
       0   1  0  0

Comments / Limitations: None.

4.4.12 NCMatrixToPermutation[aMatrix]

Aliases: None.
Description: NCMatrixToPermutation[aMatrix] returns the permutation associated with the permutation matrix, aMatrix. Basically, it is the inverse of NCPermutationMatrix.
Arguments: aMatrix must be matrix whose columns (or rows) can be permuted to yield the identity matrix. In other words, aMatrix must be a permutation matrix. For example, if m = {{0, 0, 0, 1},{1, 0, 0, 0},{0, 0, 1, 0},{0, 1, 0, 0}}, then NCPermutationMatrix[m] gives {2, 4, 3, 1}.
Comments / Limitations: None.

4.4.13 NCCheckPermutation[SizeOfMatrix, aListOfPermutations]

Aliases: None.
Description: If aListOfPermutations is consistent with the matrix size, SizeOfMatrix, then the output is valid permutation list. If not, the output is not valid permutation list.
Arguments: The size of a square matrix (an integer) and a list of permutations.
Comments / Limitations: If the SizeOfMatrix is n, then aListOfPermutations must be a list of n - 1 permutations of the integers 1 through n. Since this command is generally called within the context of NCLDUDecomposition the list of permutations must correspond to a list that can be used within the command.

4.4.14 Diag[aMatrix]

Aliases: None.
Description: Returns the elements of the diagonal of a matrix.
Arguments: None.
Comments / Limitations: The code is Flatten[MapIndexed[Part,m]].

4.4.15 Cascade[P, K]

Aliases: None
Description: Cascade[P,K] is the composition of P, K as is found is systems engineering.
Arguments: P is a 2×2 block matrix. K is a symbol.
Comments / Limitations: frequency response functions grow from this.

4.4.16 Chain[P]

Aliases: None
Description: Chain[P] returns the chain matrix arising from P as is found in systems engineering.
Arguments: P is a block 2×2 matrix.
Comments / Limitations: Chain[ ] assumes appropriate matrices are invertible.

4.4.17 Redheffer[P]

Aliases: None
Description: Redheffer[P] gives the inverse of chain.
Redheffer[Chain[P]] = P = Chain[Redheffer[P]].
Arguments: P is a block 2 × 2 matrix.
Comments / Limitations: Redheffer[P] assumes the invertiblity of the entries of P.

4.4.18 DilationHalmos[x]

Aliases: None
Description: DilationHalmos[x] gives block 2 × 2 matrix which is the Halmos dilation of x
Arguments: x is a symbol
Comments / Limitations: u = DilationHalmos[x] has the property u is unitary, that is, MatMult[u,tpMat[u]] == IdentityMatrix[2] and MatMult[tpMat[u],u] == IdentityMatrix[2].

4.4.19 SchurComplementTop[M]

Aliases: None
Description: SchurComplementTop[M] returns the Shur Complement of the top diagonal entry of a block 2 × 2 matrix M.
Arguments: M is a block 2 × 2 matrix.
Comments / Limitations: Assumes invertibility of a diagonal entry.

4.4.20 SchurComplementBtm[M]

Aliases: None
Description: SchurComplementBtm[M] returns the ShurComplement of the bottom diagonal entry of a block 2 × 2 matrix M.
Arguments: M is a block 2 × 2 matrix.
Comments / Limitations: Assumes invertibility of a diagonal entry.