Logo

SQL Server SVdecomp Function

Updated 2023-10-17 15:39:32.457000

Description

Use the table-valued function SVdecomp to calculate the economy-sized singular value decomposition of an m-x-n matrix A*.* SVdecomp returns an m-x-n orthogonal matrix U, an n-x-n orthogonal matrix V and an n-x-n diagonal matrix W such that,

    A = UWVT

Syntax

SELECT * FROM [westclintech].[wct].[SVdecomp](
  <@Matrix_RangeQuery, nvarchar(max),>
 ,<@Is3N, bit,>)

Arguments

@Matrix_RangeQuery

the SELECT statement, as text, used to return the input matrix for 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.

@Is3N

a bit value identifying the form for the resultant table returned by @Matrix_RangeQuery. Enter 'True' for a resultant table in 3rd normal form. Enter 'False' for a de-normalized table in 'spreadsheet' form.

Return Type

table

colNamecolDatatypecolDesc
RowNumintThe zero-based row index for the matrix
ColNumintThe zero-based column index for the matrix
ValuefloatThe value at RowNum, ColNum
Typenvarchar(4000)The U, V, or W matrix

Remarks

If @Is3N is NULL then @Is3N = 'False'.

Use SVD for a matrix stored as a string.

[Type] is either 'U', 'V' or 'W'.

The function returns an error if the matrix contains a non-numeric value.

Examples

In this example @Matrix_RangeQuery returns the matrix from a derived table embodied in the statement. The matrix is in spreadsheet form.

SELECT *
FROM wct.SVDECOMP(
                     'SELECT
       *
   FROM (
       VALUES
           (1,2,3,4)
          ,(2,3,4,5)
          ,(3,4,5,6)
          ,(4,5,6,7)
       )n(x1,x2,x3,x4)',
                     'False'
                 );

This produces the following result.

RowNumColNumValueType
000.314721188083371U
01-0.775210019137647U
02-0.287437287650082U
030.466240072997124U
100.427472435994882U
11-0.342443158005239U
120.730764549218788U
13-0.407410325844917U
200.540223683906393U
210.0903237031271687U
22-0.599217235487328U
23-0.583899567301538U
300.652974931817905U
310.523090564259578U
320.155889973918623U
330.525069820149331U
000.314721188083371V
010.775210019137647V
020.547722557505166V
030V
100.427472435994883V
110.342443158005239V
12-0.730296743340221V
13-0.408248290463864V
200.540223683906394V
21-0.0903237031271688V
22-0.182574185835056V
230.816496580927726V
300.652974931817905V
31-0.523090564259577V
320.365148371670111V
33-0.408248290463863V
0017.1651513899117W
010W
020W
030W
100W
111.16515138991168W
120W
130W
200W
210W
221.05167369421319E-16W
230W
300W
310W
320W
331.01544874061251E-16W

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. Also note that we can use * to select all the columns.

SELECT Type,
       [0],
       [1],
       [2],
       [3]
FROM
(
    SELECT *
    FROM wct.SVDECOMP(
                         'SELECT
          *
       FROM (
          VALUES
               (1,2,3,4)
              ,(2,3,4,5)
              ,(3,4,5,6)
              ,(4,5,6,7)
          )n(x1,x2,x3,x4)',
                         'False'
                     )
) d
PIVOT
(
    sum(Value)
    for ColNum in ([0], [1], [2], [3])
) as P;

This produces the following result.

Type0123
U0.314721188083371-0.775210019137647-0.2874372876500820.466240072997124
U0.427472435994882-0.3424431580052390.730764549218788-0.407410325844917
U0.5402236839063930.0903237031271687-0.599217235487328-0.583899567301538
U0.6529749318179050.5230905642595780.1558899739186230.525069820149331
V0.3147211880833710.7752100191376470.5477225575051660
V0.4274724359948830.342443158005239-0.730296743340221-0.408248290463864
V0.540223683906394-0.0903237031271688-0.1825741858350560.816496580927726
V0.652974931817905-0.5230905642595770.365148371670111-0.408248290463863
W17.1651513899117000
W01.1651513899116800
W001.05167369421319E-160
W0001.01544874061251E-16

In this example we show how to select data from a table. This will return the same results as our first example.

--store data in #a
SELECT *
INTO #A
FROM
(
    VALUES
        (1, 2, 3, 4),
        (2, 3, 4, 5),
        (3, 4, 5, 6),
        (4, 5, 6, 7)
) n (x1, x2, x3, x4);
--Select the data from #a
SELECT *
FROM wct.SVdecomp('SELECT * FROM #A', 'False');

For data in 3rd normal form, the function expects 3 columns in the resultant table; row number, column number, and the value.

--put data into #B
SELECT *
INTO #B
FROM
(
    VALUES
        (0, 0, 1),
        (0, 1, 2),
        (0, 2, 3),
        (0, 3, 4),
        (1, 0, 2),
        (1, 1, 3),
        (1, 2, 4),
        (1, 3, 5),
        (2, 0, 3),
        (2, 1, 4),
        (2, 2, 5),
        (2, 3, 6),
        (3, 0, 4),
        (3, 1, 5),
        (3, 2, 6),
        (3, 3, 7)
) n (rownum, colnum, ItemValue);
--Select the data from #B
SELECT *
FROM wct.SVdecomp('SELECT * FROM #B', 'True');

In this example, we demonstrate how to reconstruct that input matrix using the calculation UWV'.

SELECT k.*
FROM
(
    SELECT Type as MatrixType,
           wct.NMATRIX2STRING(RowNum, ColNum, Value) as Matrix
    FROM wct.SVdecomp('SELECT * FROM #B', 'True')
    GROUP BY Type
) p
PIVOT
(
    MAX(Matrix)
    FOR MatrixType IN (U, W, V)
) d
    CROSS APPLY wct.MATRIX(wct.MATMULT(wct.MATMULT(U, W), wct.TRANSPOSE(V))) K;

This produces the following result.

RowNumColNumItemValue
001
012
023
034
102
113.00000000000001
124
135
203
214.00000000000001
225
236
304
315.00000000000001
326.00000000000001
337.00000000000001

See Also

SVD - Economy-sized singular value decomposition using a formatted matrix as input

QRDECOMP - Decompose a de-normalized N x N matrix A into the product of an upper triangular matrix R and an orthogonal matrix Q, such that A = QR.

LUDECOMP - Calculate the LU factorization of an N x N matrix using partial pivoting.