Function Repository Resource:

OrderedSchurDecomposition

Source Notebook

Compute the ordered Schur decomposition of a matrix

Contributed by: Jan Mangaldan

ResourceFunction["OrderedSchurDecomposition"][m]

yields the ordered Schur decomposition for a numerical matrix m, given as a list {q,t} where q is an orthonormal matrix and t is a block upper‐triangular matrix.

ResourceFunction["OrderedSchurDecomposition"][{m,a}]

gives the generalized Schur decomposition of the matrix pencil {m,a}, where m and a are numerical matrices.

Details and Options

ResourceFunction["OrderedSchurDecomposition"] is similar to the built-in SchurDecomposition, except that the diagonal blocks in t are sorted according to a specified order.
The matrix m must be square.
The original matrix m is equal to q.t.ConjugateTranspose[q].
In ResourceFunction["OrderedSchurDecomposition"][{m,a}], the matrices m and a must be square, and have the same size.
ResourceFunction["OrderedSchurDecomposition"][{m,a}] yields a list of matrices {q,s,p,t} where q and p are orthonormal matrices, and s and t are upper‐triangular matrices, such that m is given by q.s.ConjugateTranspose[p], and a is given by q.t.ConjugateTranspose[p].
ResourceFunction["OrderedSchurDecomposition"] has the following options and settings:
"Criteria""Magnitude"criterion used for ordering diagonal elements in the triangular factor
"Order""Decreasing"whether to sort in increasing or decreasing order
PivotingFalsewhether to perform pivoting
RealBlockDiagonalFormTruewhether to use real blocks instead of complex values for real matrices
The option "Criteria" can be set to any of the following:
"Magnitude"sort diagonal elements by magnitude
"RealPart"sort diagonal elements by their real parts
"AbsRealPart"sort diagonal elements by the absolute values of their real parts
"AbsImaginaryPart"sort diagonal elements by the absolute values of their imaginary parts
The option "Order" can be set to any of the following:
"Decreasing"sort in decreasing order
"Increasing"sort in increasing order
With the setting PivotingTrue, ResourceFunction["OrderedSchurDecomposition"] yields a list {q,t,d} where d is a permuted diagonal matrix such that m.d is equal to d.q.t.ConjugateTranspose[q].
For real-valued matrices m, setting the option RealBlockDiagonalFormFalse allows complex values on the diagonal of the t matrix.

Examples

Basic Examples (2) 

The ordered Schur decomposition of a real matrix:

In[1]:=
MatrixForm /@ ResourceFunction[
  "OrderedSchurDecomposition"][{{1.1, 2.2, 3.25}, {0.76, 4.6, 5}, {0.1, 0.1, 6.1}}]
Out[1]=

Compare with the result of SchurDecomposition:

In[2]:=
MatrixForm /@ SchurDecomposition[{{1.1, 2.2, 3.25}, {0.76, 4.6, 5}, {0.1, 0.1, 6.1}}]
Out[2]=

Scope (3) 

A 4×4 matrix with real entries:

In[3]:=
m = \!\(\*
TagBox[
RowBox[{"(", "", GridBox[{
{"3", "1", "2", "5"},
{"2", "1", "3", "7"},
{"3", "1", "2", "4"},
{"4", "1", "3", "2"}
},
GridBoxAlignment->{"Columns" -> {{Center}}, "Rows" -> {{Baseline}}},
GridBoxSpacings->{"Columns" -> {
Offset[
           0.27999999999999997`], {
Offset[0.7]}, 
Offset[0.27999999999999997`]}, "Rows" -> {
Offset[0.2], {
Offset[0.4]}, 
Offset[0.2]}}], "", ")"}],
Function[BoxForm`e$, 
MatrixForm[BoxForm`e$]]]\);

Compute the ordered Schur decomposition with machine precision, with the diagonal elements sorted in decreasing order of magnitude:

In[4]:=
ResourceFunction["OrderedSchurDecomposition"][N[m]] // Map[MatrixForm]
Out[4]=

Compute the ordered Schur decomposition with 24-digit arbitrary precision:

In[5]:=
ResourceFunction["OrderedSchurDecomposition"][N[m, 24]]
Out[5]=

Sort the diagonal elements by their real parts, in increasing order:

In[6]:=
ResourceFunction["OrderedSchurDecomposition"][N[m], "Criteria" -> "RealPart", "Order" -> "Increasing"] // Map[MatrixForm]
Out[6]=

A 3×3 matrix with complex entries:

In[7]:=
m = ( {
    {-17., 3. + 4. I, 2.},
    {-3., 0.3 - I, 0.65 - 0.71 I},
    {1. + 0.13 I, 0., 5.}
   } );

Ordered Schur decomposition of a complex matrix, with the diagonal elements sorted in decreasing order of magnitude:

In[8]:=
ResourceFunction["OrderedSchurDecomposition"][m] // Map[MatrixForm]
Out[8]=

Sort the diagonal elements by the magnitude of their imaginary parts, in increasing order:

In[9]:=
ResourceFunction["OrderedSchurDecomposition"][m, "Criteria" -> "AbsImaginaryPart", "Order" -> "Increasing"] // Map[MatrixForm]
Out[9]=

Compute the ordered generalized Schur decomposition for a matrix pencil:

In[10]:=
ResourceFunction["OrderedSchurDecomposition"][N@{( {
      {1, 7, 3},
      {2, 9, 12},
      {5, 22, 7}
     } ), ( {
      {1, 2, 3},
      {13, 6, 4},
      {1, 8, 15}
     } )}] // Map[MatrixForm]
Out[10]=

Use a different ordering:

In[11]:=
ResourceFunction["OrderedSchurDecomposition"][N@{( {
      {1, 7, 3},
      {2, 9, 12},
      {5, 22, 7}
     } ), ( {
      {1, 2, 3},
      {13, 6, 4},
      {1, 8, 15}
     } )}, "Criteria" -> "RealPart", "Order" -> "Increasing"] // Map[MatrixForm]
Out[11]=

Options (13) 

Criteria (4) 

m is a matrix with complex eigenvalues:

In[12]:=
m = {{-5, -4, -11, -9, 10}, {6, 5, 11, 9, -10}, {-2, 2, -6, -4, 9}, {2, -2, 2, 2, -7}, {-2, 2, -7, -5, 9}};
Eigenvalues[N[m]]
Out[13]=

Sort the diagonal elements by their magnitude in decreasing order:

In[14]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], "Criteria" -> "Magnitude", RealBlockDiagonalForm -> False];
In[15]:=
MatrixForm[Chop[t]]
Out[15]=

Sort the diagonal elements by their real parts in decreasing order:

In[16]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], "Criteria" -> "RealPart", RealBlockDiagonalForm -> False];
In[17]:=
MatrixForm[Chop[t]]
Out[17]=

Sort the diagonal elements by the magnitude of their imaginary parts:

In[18]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], "Criteria" -> "AbsImaginaryPart", RealBlockDiagonalForm -> False];
In[19]:=
MatrixForm[Chop[t]]
Out[19]=

Order (3) 

m is a matrix with positive eigenvalues:

In[20]:=
m = {{4, 5, 4, 1}, {3, 5, 4, 1}, {0, 4, 4, 1}, {0, 0, 3, 1}};
Eigenvalues[N[m]]
Out[21]=

Sort the diagonal elements in decreasing order:

In[22]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], "Order" -> "Decreasing"];
In[23]:=
MatrixForm[Chop[t]]
Out[23]=

Sort the diagonal elements in increasing order:

In[24]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], "Order" -> "Increasing"];
In[25]:=
MatrixForm[MatrixForm[Chop[t]]]
Out[25]=

Pivoting (3) 

m is a 3×3 matrix:

In[26]:=
m = {{1., 100., 1.*^4}, {0.01, 1., 100.}, {1.*^-4, 0.01, 1.}};

With PivotingTrue, an extra matrix that represents the scaling and permutation is returned:

In[27]:=
{q, t, d} = ResourceFunction["OrderedSchurDecomposition"][m, Pivoting -> True]
Out[27]=
In[28]:=
Map[MatrixForm, %]
Out[28]=

Verify that m.d is equal to d.q.t.ConjugateTranspose[q]:

In[29]:=
Chop[m . d - d . q . t . ConjugateTranspose[q]]
Out[29]=

RealBlockDiagonalForm (3) 

m is a matrix with two real and two complex eigenvalues:

In[30]:=
m = {{1, 0, -1, 1}, {2, 0, -1, 2}, {1, 1, -1, 1}, {-1, 1, 0, 0}};
Eigenvalues[m]
Out[31]=

With RealBlockDiagonalFormFalse, the result is complex upper triangular:

In[32]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], RealBlockDiagonalForm -> False];
In[33]:=
MatrixForm[Chop[t]]
Out[33]=

With RealBlockDiagonalFormTrue, there are real 2×2 blocks along the diagonal:

In[34]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][N[m], RealBlockDiagonalForm -> True];
In[35]:=
MatrixForm[Chop[t]]
Out[35]=

Properties and Relations (2) 

m is a matrix with two real and two complex eigenvalues:

In[36]:=
m = N[{{0, 1, 0, 0}, {0, 0, -2, 0}, {0, 0, 0, 3}, {-4, 0, 0, 0}}];
Eigenvalues[m] // Chop
Out[37]=

Find the ordered Schur decomposition of m:

In[38]:=
{q, t} = ResourceFunction["OrderedSchurDecomposition"][m]
Out[38]=

The real eigenvalues appear on the diagonal of t, the complex as a 2×2 block:

In[39]:=
MatrixForm[t]
Out[39]=

Verify that m is equal to q.t.ConjugateTranspose[q]:

In[40]:=
Chop[m - q . t . ConjugateTranspose[q]]
Out[40]=

A matrix pencil:

In[41]:=
{m, a} = N[{( {
      {5, 6, -5},
      {4, -3, 3},
      {3, -2, 3}
     } ), ( {
      {16, -6, 5},
      {5, -6, 16},
      {3, -5, 6}
     } )}];

Find the ordered generalized Schur decomposition:

In[42]:=
{q, s, p, t} = ResourceFunction["OrderedSchurDecomposition"][{m, a}]
Out[42]=

Verify that m is given by q.s.ConjugateTranspose[p]:

In[43]:=
Chop[m - q . s . ConjugateTranspose[p]]
Out[43]=

Verify that a is given by q.t.ConjugateTranspose[p]:

In[44]:=
Chop[a - q . t . ConjugateTranspose[p]]
Out[44]=

Version History

  • 1.0.0 – 07 February 2022

Related Resources

License Information