Schur Decomposition
schur.Rd
The Schur decomposition of a (real, square) matrix \(A\) is
$$A = U S U'$$
where \(U\) is an orthogonal matrix and S
is
upper quasi-triangular with 1-by-1 and 2-by-2 blocks on the diagonal.
The 2-by-2 blocks correspond to the complex eigenvalues of \(A\).
Usage
schur(A, select = NULL, tol = sqrt(.Machine$double.eps))
Arguments
- A
square, non-empty, real matrix.
- select
If non NULL, then the Schur decomposition is reordered such that the selected cluster of eigenvalues appear in the leading diagonal blocks of the quasi-triangular matrix \(S\). See the details below.
- tol
tolerance used to decide whether the target eigenvalues match the eigenvalues of \(A\). See the details below.
Value
List with components U
, S
, lambda
and k
,
where lambda
contains the (computed) eigenvalues of \(A\) and
k
indicates how many eigenvalues have been selected (put to the top).
Details
The optional parameter select
determines which eigenvalues, respectively
1-by-1 and 2-by-2 blocks, should be put to the top of the matrix \(S\).
select='iuc'
: Select the eigenvalues with moduli less than one (inside the unit circle).select='ouc'
: Select the eigenvalues with moduli greater than one (outside the unit circle).select='lhf'
: Select the eigenvalues with a negative imaginary part (left half plane).select='rhf'
: Select the eigenvalues with a positive imaginary part (right half plane).select='real'
: Select the real eigenvalues.select='cplx'
: Select the complex eigenvalues.select
is a (complex) vector of eigenvalues. The function checks whether the "target eigenvalues", i.e. the entries ofselect
, match the eigenvalues of the matrix \(A\). In addition the procedure also makes sure that complex eigenvalues are selected in complex conjugated pairs.
The function schur
is simply a wrapper for qz.dgees
and qz.dtrsen
.
Examples
# generate a "random" 6-by-6 matrix A
m = 6
set.seed(1532)
A = matrix(stats::rnorm(m*m, sd = 0.5), nrow = m, ncol = m)
set.seed(NULL)
# compute the Schur decomposition of A (and its eigenvalues)
out = schur(A)
lambda = out$lambda # eigenvalues of A
# check A = U S U'
all.equal(A, out$U %*% out$S %*% t(out$U))
#> [1] TRUE
print(out$S)
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] -1.258119 0.16047666 0.11317140 0.8606362 -0.003078162 0.6654092
#> [2,] 0.000000 -0.07298067 -1.88015298 -0.6360467 0.070634280 -0.3670152
#> [3,] 0.000000 0.43391617 -0.07298067 -0.2158021 0.295439282 -0.2451203
#> [4,] 0.000000 0.00000000 0.00000000 0.7667058 1.205338328 0.7751998
#> [5,] 0.000000 0.00000000 0.00000000 -0.5427939 0.766705822 0.2745867
#> [6,] 0.000000 0.00000000 0.00000000 0.0000000 0.000000000 0.5968981
print(lambda)
#> [1] -1.2581190+0.0000000i -0.0729807+0.9032324i -0.0729807-0.9032324i
#> [4] 0.7667058+0.8088574i 0.7667058-0.8088574i 0.5968981+0.0000000i
# compute an "ordered" Schur decomposition where the eigenvalues
# inside the unit circle are put to the top of S:
out = schur(A, 'iuc')
print(out$S)
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] -0.07298067 0.44125325 -0.3372971 -0.1346907 0.17508505 -0.03645365
#> [2,] -1.84889014 -0.07298067 -0.2813143 0.4372502 -0.08687296 0.50003336
#> [3,] 0.00000000 0.00000000 0.5968981 -0.8305954 0.25520954 -0.64478335
#> [4,] 0.00000000 0.00000000 0.0000000 -1.2581190 0.21109806 -0.56034950
#> [5,] 0.00000000 0.00000000 0.0000000 0.0000000 0.76670582 0.45519124
#> [6,] 0.00000000 0.00000000 0.0000000 0.0000000 -1.43730860 0.76670582
print(out$k) # three eigenvalues are inside the unit circle.
#> [1] 3
print(out$lambda)
#> [1] -0.0729807+0.9032324i -0.0729807-0.9032324i 0.5968981+0.0000000i
#> [4] -1.2581190+0.0000000i 0.7667058+0.8088574i 0.7667058-0.8088574i
# compute an "ordered" Schur decomposition where the eigenvalues
# lambda[5] and lambda[6] apear in the top. Note that
# lambda[5] is complex and hence the procedure also selects
# the conjugate of lambda[5]:
out = schur(A, lambda[c(6,5)])
print(out$S)
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] 0.7667058 0.5359624 -0.2917256 -0.4321118 -0.03373457 0.07288711
#> [2,] -1.2207018 0.7667058 1.0416001 -0.6797241 -0.61359022 -0.43178545
#> [3,] 0.0000000 0.0000000 0.5968981 -0.5021335 0.46948321 0.19968389
#> [4,] 0.0000000 0.0000000 0.0000000 -1.2581190 -0.26080155 -0.25951666
#> [5,] 0.0000000 0.0000000 0.0000000 0.0000000 -0.07298067 0.46503579
#> [6,] 0.0000000 0.0000000 0.0000000 0.0000000 -1.75433548 -0.07298067
print(out$k) # three eigenvalues have been selected
#> [1] 3
print(out$lambda)
#> [1] 0.7667058+0.8088574i 0.7667058-0.8088574i 0.5968981+0.0000000i
#> [4] -1.2581190+0.0000000i -0.0729807+0.9032324i -0.0729807-0.9032324i
if (FALSE) {
# If the "target" eigenvalues do not match the eigenvalues of A
# then "schur" throws an error:
out = schur(A, select = lambda[1:3]+ 1)
}