LUdecompN_q
Updated 2024-03-06 21:00:22.677000
Syntax
SELECT * FROM [westclintech].[wct].[LUdecompN_q](
<@Matrix_RangeQuery, nvarchar(max),>)
Description
Use the table-value function LUdecompN_q to calculate the LU factorization of an N x N matrix A in 3rd normal form using partial pivoting. LUdecompN_q returns a lower triangular matrix L, an upper triangular matrix U, and a permutation matrix P such that,
LU = PA
For a 3 x 3 matrix this becomes:
P\times\begin{bmatrix}a_{11}&a_{12}&a_{13}\\a_{21}&a_{22}&a_{23}\\a_{31}&a_{32}&a_{33}\end{bmatrix}=\begin{bmatrix}l_{11}&0&0\\l_{21}&l_{22}&0\\l_{31}&l_{32}&l_{33}\end{bmatrix}\begin{bmatrix}u_{11}&u_{12}&u_{13}\\0&u_{22}&u_{23}\\0&0&u_{33}\end{bmatrix}
Arguments
@Matrix_RangeQuery
the SELECT statement, as text, used to determine the square (N x N) matrix to be used in this function. The SELECT statement specifies the column names from the table or view or can be used to enter the matrix values directly. Data returned from the @Matrix_RangeQuery select must be of the type float or of a type that implicitly converts to float.
Return Type
table
{"columns": [{"field": "colName", "headerName": "Name", "header": "name"}, {"field": "colDatatype", "headerName": "Type", "header": "type"}, {"field": "colDesc", "headerName": "Description", "header": "description", "minWidth": 1000}], "rows": [{"id": "d32666b6-a134-47c6-92aa-d3817d1959b4", "colName": "RowNum", "colDatatype": "int", "colDesc": "The zero-based row index for the matrix"}, {"id": "6e83d99f-9897-4ea5-93f0-7bc7a720f226", "colName": "ColNum", "colDatatype": "int", "colDesc": "The zero-based column index for the matrix"}, {"id": "c5236a14-b687-44b7-a64f-c2cd150d3d59", "colName": "ItemValue", "colDatatype": "float", "colDesc": "The value at RowNum, ColNum"}, {"id": "72290939-d4a8-465c-9653-2965db6730e2", "colName": "Type", "colDatatype": "nvarchar(4000)", "colDesc": "The pivot(P), lower triangular(L) or upper triangular (U) matrix type"}]}
Remarks
The number of columns in the matrix must be equal to the number of rows or an error will be returned.
Use the LUdecompN function for simpler queries.
Use LUdecomp_q for a table not in third-normal form.
The function returns an error if the array contains a non-numeric value.
The returned Type column contains 'L', 'U', or 'P'
Examples
In this example, we calculate the LU decomposition directly from the SELECT statement.
SELECT *
FROM wct.LUdecompN_q('
SELECT
*
FROM (VALUES
(0,0,0.002),
(0,1,1.231),
(0,2,2.471),
(1,0,1.196),
(1,1,3.165),
(1,2,2.54),
(2,0,1.475),
(2,1,4.271),
(2,2,2.142)
) m(r,c,x)');
This produces the following result.
{"columns":[{"field":"RowNum","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"ColNum","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Value","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Type"}],"rows":[{"RowNum":"0","ColNum":"0","Value":"1","Type":"L"},{"RowNum":"0","ColNum":"1","Value":"0","Type":"L"},{"RowNum":"0","ColNum":"2","Value":"0","Type":"L"},{"RowNum":"1","ColNum":"0","Value":"0.00167224080267559","Type":"L"},{"RowNum":"1","ColNum":"1","Value":"1","Type":"L"},{"RowNum":"1","ColNum":"2","Value":"0","Type":"L"},{"RowNum":"2","ColNum":"0","Value":"1.23327759197324","Type":"L"},{"RowNum":"2","ColNum":"1","Value":"0.299970803835884","Type":"L"},{"RowNum":"2","ColNum":"2","Value":"1","Type":"L"},{"RowNum":"0","ColNum":"0","Value":"1.196","Type":"U"},{"RowNum":"0","ColNum":"1","Value":"3.165","Type":"U"},{"RowNum":"0","ColNum":"2","Value":"2.54","Type":"U"},{"RowNum":"1","ColNum":"0","Value":"0","Type":"U"},{"RowNum":"1","ColNum":"1","Value":"1.22570735785953","Type":"U"},{"RowNum":"1","ColNum":"2","Value":"2.4667525083612","Type":"U"},{"RowNum":"2","ColNum":"0","Value":"0","Type":"U"},{"RowNum":"2","ColNum":"1","Value":"0","Type":"U"},{"RowNum":"2","ColNum":"2","Value":"-1.73047881640933","Type":"U"},{"RowNum":"0","ColNum":"0","Value":"0","Type":"P"},{"RowNum":"0","ColNum":"1","Value":"1","Type":"P"},{"RowNum":"0","ColNum":"2","Value":"0","Type":"P"},{"RowNum":"1","ColNum":"0","Value":"1","Type":"P"},{"RowNum":"1","ColNum":"1","Value":"0","Type":"P"},{"RowNum":"1","ColNum":"2","Value":"0","Type":"P"},{"RowNum":"2","ColNum":"0","Value":"0","Type":"P"},{"RowNum":"2","ColNum":"1","Value":"0","Type":"P"},{"RowNum":"2","ColNum":"2","Value":"1","Type":"P"}]}
Note that the results are returned in third-normal form. If we wanted to a more traditional (de-normalized) presentation of the results, we can us the PIVOT function.
SELECT Type,
[0],
[1],
[2]
FROM
(
SELECT *
FROM wct.LUdecompN_q('
SELECT
*
FROM (VALUES
(0,0,0.002),
(0,1,1.231),
(0,2,2.471),
(1,0,1.196),
(1,1,3.165),
(1,2,2.54),
(2,0,1.475),
(2,1,4.271),
(2,2,2.142)
) m(r,c,x)')
) d
PIVOT
(
SUM(Value)
FOR ColNum in ([0], [1], [2])
) p;
This produces the following result.
{"columns":[{"field":"Type"},{"field":"0","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"1","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"2","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"}],"rows":[{"0":"1","1":"0","2":"0","Type":"L"},{"0":"0.00167224080267559","1":"1","2":"0","Type":"L"},{"0":"1.23327759197324","1":"0.299970803835884","2":"1","Type":"L"},{"0":"0","1":"1","2":"0","Type":"P"},{"0":"1","1":"0","2":"0","Type":"P"},{"0":"0","1":"0","2":"1","Type":"P"},{"0":"1.196","1":"3.165","2":"2.54","Type":"U"},{"0":"0","1":"1.22570735785953","2":"2.4667525083612","Type":"U"},{"0":"0","1":"0","2":"-1.73047881640933","Type":"U"}]}
In this example, we demonstrate how to reconstruct the input matrix using the calculation P'LU.
SELECT k.*
FROM
(
SELECT Type as MatrixType,
wct.NMATRIX2STRING(RowNum, ColNum, Value) as Matrix
FROM wct.LUdecompN_q('
SELECT
*
FROM (VALUES
(0,0,0.002),
(0,1,1.231),
(0,2,2.471),
(1,0,1.196),
(1,1,3.165),
(1,2,2.54),
(2,0,1.475),
(2,1,4.271),
(2,2,2.142)
) m(r,c,x)')
GROUP BY Type
) p
PIVOT
(
MAX(Matrix)
FOR MatrixType IN (L, P, U)
) d
CROSS APPLY wct.MATRIX(wct.MATMULT(wct.TRANSPOSE(P), wct.MATMULT(L, U))) K;
This produces the following result.
{"columns":[{"field":"RowNum","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"ColNum","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"ItemValue","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"}],"rows":[{"RowNum":"0","ColNum":"0","ItemValue":"0.00200000000000001"},{"RowNum":"0","ColNum":"1","ItemValue":"1.231"},{"RowNum":"0","ColNum":"2","ItemValue":"2.471"},{"RowNum":"1","ColNum":"0","ItemValue":"1.196"},{"RowNum":"1","ColNum":"1","ItemValue":"3.165"},{"RowNum":"1","ColNum":"2","ItemValue":"2.54"},{"RowNum":"2","ColNum":"0","ItemValue":"1.475"},{"RowNum":"2","ColNum":"1","ItemValue":"4.27099999999998"},{"RowNum":"2","ColNum":"2","ItemValue":"2.14199999999999"}]}
This example demonstrates how to use the function by selecting data from a table.
SELECT *
INTO #A
FROM
(
VALUES
(0, 0, 0.002),
(0, 1, 1.231),
(0, 2, 2.471),
(1, 0, 1.196),
(1, 1, 3.165),
(1, 2, 2.54),
(2, 0, 1.475),
(2, 1, 4.271),
(2, 2, 2.142)
) m (r, c, x);
SELECT *
FROM wct.LUdecompN_q('SELECT r,c,x FROM #A');
This produces the following result.
RowNum ColNum Value Type
----------- ----------- ---------------------- ----
0 0 1 L
0 1 0 L
0 2 0 L
1 0 0.00167224080267559 L
1 1 1 L
1 2 0 L
2 0 1.23327759197324 L
2 1 0.299970803835884 L
2 2 1 L
0 0 1.196 U
0 1 3.165 U
0 2 2.54 U
1 0 0 U
1 1 1.22570735785953 U
1 2 2.4667525083612 U
2 0 0 U
2 1 0 U
2 2 -1.73047881640933 U
0 0 0 P
0 1 1 P
0 2 0 P
1 0 1 P
1 1 0 P
1 2 0 P
2 0 0 P
2 1 0 P
2 2 1 P
See Also
LU - LU factorization with partial pivoting
LUDECOMP - Calculate the LU factorization of an N x N matrix using partial pivoting.
LUDECOMP_Q - Calculate the LU factorization of an N x N matrix using partial pivoting.
LUDECOMPN - Calculate the LU factorization of an N x N matrix using partial pivoting.