Class Schur<T extends MatrixMixin<T,?,?,?>,U>
- Type Parameters:
T
- The type of matrix to be decomposed.U
- The type for the internal storage data structure of the matrix to be decomposed.
- Direct Known Subclasses:
ComplexSchur
,RealSchur
An abstract base class for computing the Schur decomposition of a square matrix.
The Schur decomposition decomposes a given square matrix \( A \) into: \[ A = UTU^{H} \] where \( U \) is a unitary (or orthogonal for real matrices) matrix \( T \) is a quasi-upper triangular matrix known as the Schur form of \( A \). This means \( T \) is upper triangular except for possibly \( 2\times2 \) blocks along its diagonal, which correspond to complex conjugate pairs of eigenvalues.
The Schur decomposition proceeds by an iterative algorithm with possible random behavior. For reproducibility, constructors support specifying a seed for the pseudo-random number generator.
Usage:
The decomposition workflow typically follows these steps:- Instantiate a con concrete instance of
Schur
. - Call
Decomposition.decompose(MatrixMixin)
to perform the factorization. - Retrieve the resulting matrices using
getU()
andgetT()
.
Efficiency Considerations:
If eigenvectors are not required, settingcomputeU = false
may improve performance.
This class was inspired by code from the EJML library and the description of the Francis implicit double shifted QR algorithm from Fundamentals of Matrix Computations 3rd Edition by David S. Watkins.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionBalancer to apply a similarity transform to the matrix before the QR-algorithm is executed.protected boolean
Flag indicating if a check should be made during the decomposition that the working matrix contains only finite values.protected final boolean
Flag indicating if the orthogonal matrix \( U \) in the Schur decomposition should be computed.protected final int
Default number of iterations to apply before doing an exceptional shift.protected final int
Default factor for computing the maximum number of iterations to perform.protected int
Number of iterations to run without deflation before an exceptional shift is done.protected UnitaryDecomposition
<T, U> Decomposer to compute the Hessenburg decomposition as a setup step for the implicit double step QR algorithm.protected U
Stores the vector \( v \) in the Householder reflector \( P = I - \alpha vv^{T} \).protected int
The upper bound (exclusive) of the row/column indices of the block to reduce to Schur form.protected int
The lower bound (inclusive) of the row/column indices of the block to reduce to Schur form.protected int
Maximum number of iterations to run QR algorithm for.protected int
Factor for computing the maximum number of iterations to run the QR algorithm for.protected int
The total number of exceptional shifts that have been used during the decomposition.protected int
Stores the number of rows in the matrix being decomposed (after balancing).protected final RandomComplex
Random number generator to be used when computing a random exceptional shift.protected U
Stores the non-zero data of the first column of the shifted matrix \( \left(A- \rho _{1}I\right)\left(A-\rho _{2} I\right) \) where \( \rho _{1} \) and \( \rho _{2} \) are the two shifts.protected int
The number of iterations run in the QR algorithm without deflating or performing an exceptional shift.protected T
For storing the (possibly block) upper triangular matrix \( T \) in the Schur decomposition.protected U
Array for holding temporary values when computing the shifts.protected T
For storing the unitary \( U \) matrix in the Schur decomposition.protected U
An array for storing temporary values along the colum of a matrix when applying Householder reflectors.Fields inherited from class org.flag4j.linalg.decompositions.Decomposition
hasDecomposed
-
Constructor Summary
ConstructorsModifierConstructorDescriptionprotected
Schur
(boolean computeU, RandomComplex rng, UnitaryDecomposition<T, U> hess, Balancer<T> balancer) Creates a decomposer to compute the Schur decomposition for a real dense matrix. -
Method Summary
Modifier and TypeMethodDescriptionprotected abstract int
checkConvergence
(int workEnd) Checks for convergence of lower \( 2\times2 \) sub-matrix within working matrix to upper triangular or block upper triangular form.protected abstract void
checkFinite
(T src) Ensures thatsrc
only contains finite values.protected void
decomposeBase
(T src) Computes the Schur decomposition of the input matrix.enforceFinite
(boolean enforceFinite) Sets flag indicating if a check should be made to ensure the matrix being decomposed only contains finite values.getT()
Gets the upper, or possibly block-upper, triangular Schur matrix \( T \) from the Schur decompositiongetU()
Gets the unitary matrix \( U \) from the Schur decomposition containing the Schur vectors as its columns.protected abstract void
performDoubleShift
(int workEnd) Performs a full iteration of the Francis implicit double shifted QR algorithm (this includes the bulge chase).protected abstract void
performExceptionalShift
(int workEnd) Performs a full iteration of the single shifted QR algorithm (this includes the bulge chase) where the shift is chosen to be a random value with the same magnitude as the lower right element of the working matrix.setExceptionalThreshold
(int exceptionalThreshold) Sets the number of iterations of the QR algorithm to perform without deflation before performing a random shift.setMaxIterationFactor
(int maxIterationFactor) Specify maximum iteration factor for computing the total number of iterations to run the QR algorithm for when computing the decomposition.protected void
Performs basic setup and initializes data structures to be used in the decomposition.protected abstract void
Initializes temporary work arrays to be used in the decomposition.protected abstract void
Reverts the scaling and permutations applied during the balancing step to obtain the correct form.Methods inherited from class org.flag4j.linalg.decompositions.Decomposition
decompose, ensureHasDecomposed
-
Field Details
-
rng
Random number generator to be used when computing a random exceptional shift. -
DEFAULT_EXCEPTIONAL_ITERS
protected final int DEFAULT_EXCEPTIONAL_ITERSDefault number of iterations to apply before doing an exceptional shift.- See Also:
-
DEFAULT_MAX_ITERS_FACTOR
protected final int DEFAULT_MAX_ITERS_FACTORDefault factor for computing the maximum number of iterations to perform.- See Also:
-
T
For storing the (possibly block) upper triangular matrix \( T \) in the Schur decomposition. -
U
For storing the unitary \( U \) matrix in the Schur decomposition. -
hess
Decomposer to compute the Hessenburg decomposition as a setup step for the implicit double step QR algorithm. -
balancer
Balancer to apply a similarity transform to the matrix before the QR-algorithm is executed. This similarity transform consists of permuting rows/columns to isolate decoupled eigenvalues then scaling the rows and columns of the matrix
This is done to attempt to improve the conditioning of the eigen-problem.
-
iLow
protected int iLowThe lower bound (inclusive) of the row/column indices of the block to reduce to Schur form. -
iHigh
protected int iHighThe upper bound (exclusive) of the row/column indices of the block to reduce to Schur form. -
numRows
protected int numRowsStores the number of rows in the matrix being decomposed (after balancing). -
householderVector
Stores the vector \( v \) in the Householder reflector \( P = I - \alpha vv^{T} \). -
shiftCol
Stores the non-zero data of the first column of the shifted matrix \( \left(A- \rho _{1}I\right)\left(A-\rho _{2} I\right) \) where \( \rho _{1} \) and \( \rho _{2} \) are the two shifts. -
workArray
An array for storing temporary values along the colum of a matrix when applying Householder reflectors. This can help improve cache performance when applying the reflector. -
temp
Array for holding temporary values when computing the shifts. -
maxIterationsFactor
protected int maxIterationsFactorFactor for computing the maximum number of iterations to run the QR algorithm for. -
maxIterations
protected int maxIterationsMaximum number of iterations to run QR algorithm for. -
exceptionalThreshold
protected int exceptionalThresholdNumber of iterations to run without deflation before an exceptional shift is done. -
sinceLastExceptional
protected int sinceLastExceptionalThe number of iterations run in the QR algorithm without deflating or performing an exceptional shift. -
numExceptional
protected int numExceptionalThe total number of exceptional shifts that have been used during the decomposition. -
checkFinite
protected boolean checkFiniteFlag indicating if a check should be made during the decomposition that the working matrix contains only finite values. If true, an explicit check will be made and an exception will be thrown ifnon-finite
values are found. If false, no check will be made and the floating point arithmetic will carry on withinfinities
,negative-infinities
, andNaNs
present. -
computeU
protected final boolean computeUFlag indicating if the orthogonal matrix \( U \) in the Schur decomposition should be computed.- If
true
, \( U \) will be computed. - If
false
, \( U \) will not be computed. This may improve performance if \( U \) is not required.
- If
-
-
Constructor Details
-
Schur
protected Schur(boolean computeU, RandomComplex rng, UnitaryDecomposition<T, U> hess, Balancer<T> balancer) Creates a decomposer to compute the Schur decomposition for a real dense matrix.
If the \( U \) matrix is not needed, passing
computeU = false
may provide a performance improvement.- Parameters:
computeU
- Flag indicating if the orthogonal matrix \( U \) in the Schur decomposition should be computed.- If
true
, \( U \) will be computed. - If
false
, \( U \) will not be computed. This may improve performance if \( U \) is not required.
- If
rng
- Random number generator to use when performing random exceptional shifts.hess
- Decomposer to compute the Hessenburg decomposition as a setup step for the QR algorithm.balancer
- Balancer which balances the matrix as a preprocessing step to improve the conditioning of the eigenvalue problem.
-
-
Method Details
-
setExceptionalThreshold
Sets the number of iterations of the QR algorithm to perform without deflation before performing a random shift.
That is, if
exceptionalThreshold = 10
, then at most 10 iterations QR algorithm iterations will be performed. If, by the 10th iteration, no convergence has been detected which allows for deflation, then a QR algorithm iteration will be performed with a random (i.e. exceptional) shift.By default, the threshold is set to
DEFAULT_EXCEPTIONAL_ITERS
- Parameters:
exceptionalThreshold
- The new exceptional shift threshold. i.e. the number of iterations to perform without deflation before performing an iteration with random shifts.- Returns:
- A reference to this Schur decomposer.
- Throws:
IllegalArgumentException
- IfexceptionalThreshold
is not positive.
-
setMaxIterationFactor
Specify maximum iteration factor for computing the total number of iterations to run the QR algorithm for when computing the decomposition. The maximum number of iterations is computed as
maxIteration = maxIterationFactor * src.numRows;
If the algorithm does not converge within this limit, an exception will be thrown.By default, this is computed as
maxIterations = DEFAULT_MAX_ITERS_FACTOR * src.numRows;
wheresrc
is the matrix being decomposed (seeDEFAULT_MAX_ITERS_FACTOR
).- Parameters:
maxIterationFactor
- maximum iteration factor for use in computing the total maximum number of iterations to run the QR algorithm for.- Returns:
- A reference to this Schur decomposer.
- Throws:
IllegalArgumentException
- IfmaxIterationFactor
is not positive.
-
enforceFinite
Sets flag indicating if a check should be made to ensure the matrix being decomposed only contains finite values.
By default, this will be
false
.- Parameters:
enforceFinite
- Flag indicating if a check should be made to ensure matrices decomposed by this instance only contain finite values.- If
true
, an explicit check will be made. - If
false
, an explicit check will not be made.
- If
- Returns:
- A reference to this Schur decomposer.
-
getT
Gets the upper, or possibly block-upper, triangular Schur matrix \( T \) from the Schur decomposition- Returns:
- The \( T \) matrix from the Schur decomposition \( A=UTU^{H} \).
-
getU
Gets the unitary matrix \( U \) from the Schur decomposition containing the Schur vectors as its columns.- Returns:
- The \( U \) matrix from the Schur decomposition \( A=UTU^{H} \).
-
decomposeBase
Computes the Schur decomposition of the input matrix.
- Parameters:
src
- The source matrix to decompose.- Throws:
LinearAlgebraException
- If the decomposition does not converge within the specified number of max iterations.
-
setUp
Performs basic setup and initializes data structures to be used in the decomposition.- Parameters:
src
- The matrix to be decomposed.
-
unbalance
protected abstract void unbalance()Reverts the scaling and permutations applied during the balancing step to obtain the correct form.
Specifically, this method computes \[ \begin{align*} U :&= PDU \\ &= TU \end{align*} \] where \( P \) and \( D \) are the permutation and scaling matrices respectively from balancing.
-
setUpArrays
protected abstract void setUpArrays()Initializes temporary work arrays to be used in the decomposition. -
performExceptionalShift
protected abstract void performExceptionalShift(int workEnd) Performs a full iteration of the single shifted QR algorithm (this includes the bulge chase) where the shift is chosen to be a random value with the same magnitude as the lower right element of the working matrix. This can help the QR converge for certain pathological cases where the double shift algorithm oscillates or fails to converge for repeated eigenvalues.- Parameters:
workEnd
- The ending row (inclusive) of the current active working block.
-
performDoubleShift
protected abstract void performDoubleShift(int workEnd) Performs a full iteration of the Francis implicit double shifted QR algorithm (this includes the bulge chase).- Parameters:
workEnd
- The ending row (inclusive) of the current active working block.
-
checkConvergence
protected abstract int checkConvergence(int workEnd) Checks for convergence of lower \( 2\times2 \) sub-matrix within working matrix to upper triangular or block upper triangular form. If convergence is found, this will also zero out the values which have converged to near zero.- Parameters:
workEnd
- The ending row (inclusive) of the current active working block.- Returns:
- Returns the amount the working matrix size should be deflated. Will be zero if no convergence is detected, one if convergence to upper triangular form is detected and two if convergence to block upper triangular form is detected.
-
checkFinite
Ensures thatsrc
only contains finite values.- Parameters:
src
- Matrix of interest.- Throws:
IllegalArgumentException
- Ifsrc
does not contain only finite values.
-