Main Content

svdappend

Revise SVD after appending data

Since R2023b

Description

[U1,S1,V1] = svdappend(U,S,V,D), where A = U*S*V' is an existing singular value decomposition (SVD), calculates the SVD of [A D] without explicitly forming A or [A D]. The results are equivalent, up to round-off error, to [U1,S1,V1] = svd([A D],"econ","vector").

example

[U1,S1,V1] = svdappend(U,S,V,D,Name=Value) additionally specifies options using one or more name-value arguments. For example, svdappend(U,S,V,D,Shape="rows") specifies that D contains new rows to append, and the revised SVD is for [A; D].

example

Examples

collapse all

Calculate the SVD of a 5-by-5 random matrix, and then calculate the revised SVD with three additional columns.

Create a 5-by-5 random matrix and calculate the SVD.

A = rand(5);
[U,S,V] = svd(A)
U = 5×5

   -0.2475   -0.5600    0.4131    0.5759    0.3504
   -0.3542   -0.5207   -0.7577   -0.0111   -0.1707
   -0.4641    0.6013   -0.1679    0.6063   -0.1652
   -0.5475   -0.1183    0.4755   -0.3314   -0.5919
   -0.5460    0.1992   -0.0298   -0.4369    0.6859

S = 5×5

    3.3129         0         0         0         0
         0    0.9431         0         0         0
         0         0    0.8358         0         0
         0         0         0    0.4837         0
         0         0         0         0    0.0198

V = 5×5

   -0.4307   -0.8839    0.0530   -0.0884    0.1503
   -0.4309    0.2207    0.1961   -0.7322   -0.4370
   -0.4617    0.0890   -0.7467    0.3098   -0.3539
   -0.4730    0.3701   -0.0798   -0.1023    0.7890
   -0.4380    0.1585    0.6283    0.5913   -0.1968

Create a 5-by-3 matrix containing three new columns of data, and then calculate the revised SVD.

D = rand(5,3);
[U1,S1,V1] = svdappend(U,S,V,D)
U1 = 5×5

    0.3616    0.6757   -0.4056    0.3016    0.3966
    0.4066    0.2922    0.8635    0.0546   -0.0270
    0.4272   -0.3990   -0.1227    0.7092   -0.3745
    0.5707    0.0815   -0.2734   -0.6000   -0.4826
    0.4424   -0.5406    0.0091   -0.2075    0.6848

S1 = 5×1

    3.7334
    1.3862
    0.8863
    0.6852
    0.4189

V1 = 8×5

    0.4066    0.3586    0.2168   -0.4290    0.5809
    0.3631   -0.3711   -0.1345   -0.4995    0.0597
    0.3995   -0.2777    0.5995    0.4701   -0.0200
    0.3993   -0.4331   -0.0153    0.0597   -0.0557
    0.3878   -0.1270   -0.6640    0.1470   -0.1071
    0.3197    0.3849    0.1225    0.1730   -0.1565
    0.1221    0.2360   -0.3436    0.5301    0.5243
    0.3410    0.4990   -0.0366   -0.0964   -0.5870

Calculate the SVD of a 6-by-6 random matrix, and then calculate the revised SVD with four additional rows. Use the MaxRank and WindowSize name-value arguments to control the calculation and size of the output.

Create a 6-by-6 random matrix and calculate the SVD.

A = rand(6);
[U,S,V] = svd(A)
U = 6×6

   -0.4758   -0.0015   -0.4257    0.6098   -0.4496   -0.1358
   -0.4440   -0.4208   -0.1279   -0.2969    0.3761   -0.6163
   -0.4229    0.2502    0.2709   -0.5781   -0.5923   -0.0053
   -0.2832   -0.4610    0.7395    0.3449    0.0073    0.2035
   -0.3375   -0.2843   -0.3978   -0.2476    0.1740    0.7453
   -0.4510    0.6834    0.1544    0.1598    0.5247    0.0695

S = 6×6

    3.5693         0         0         0         0         0
         0    1.2230         0         0         0         0
         0         0    1.0101         0         0         0
         0         0         0    0.6166         0         0
         0         0         0         0    0.4062         0
         0         0         0         0         0    0.0390

V = 6×6

   -0.3809   -0.7234    0.0105    0.5327    0.1649   -0.1430
   -0.4327    0.1494    0.8629   -0.1576    0.1404    0.0352
   -0.4497    0.3557   -0.1725    0.1099   -0.4108   -0.6787
   -0.5038    0.1141   -0.4450   -0.3723    0.6261    0.0674
   -0.3875   -0.3141   -0.1275   -0.3898   -0.6244    0.4394
   -0.2478    0.4650   -0.1059    0.6235   -0.0496    0.5657

Create a 4-by-6 matrix containing four new rows of data, and then calculate the revised SVD. Specify Shape="rows" to append the data in D as rows.

D = rand(4,6);
[U1,S1,V1] = svdappend(U,S,V,D,Shape="rows")
U1 = 10×6

    0.3909    0.0593   -0.3501   -0.2543    0.2971    0.6734
    0.3588    0.2925   -0.2515    0.3982    0.1097   -0.3212
    0.3429   -0.3027    0.1746    0.3867   -0.2745    0.3894
    0.2353    0.4938    0.5672    0.2279   -0.0616    0.0268
    0.2715    0.1703   -0.4510    0.2314    0.0597   -0.1402
    0.3767   -0.5450    0.2275   -0.2637    0.1615   -0.2770
    0.3299    0.1748   -0.1556   -0.4787   -0.7600   -0.1485
    0.2389   -0.1394   -0.1109   -0.0742    0.2814   -0.4153
    0.2908    0.3004    0.3953   -0.3542    0.3391    0.0045
    0.2818   -0.3305    0.1186    0.3035   -0.1384    0.0052

S1 = 6×1

    4.3460
    1.3335
    1.1287
    1.0049
    0.5681
    0.4734

V1 = 6×6

    0.3915    0.8486    0.0006   -0.1502    0.3210   -0.0307
    0.4490   -0.1113    0.8111    0.2481   -0.1583   -0.2038
    0.4156   -0.3870   -0.0439    0.0599    0.5980    0.5608
    0.4960   -0.2554   -0.4951    0.1048    0.0576   -0.6552
    0.3582    0.1589   -0.3070    0.3938   -0.6290    0.4489
    0.3132   -0.1649    0.0298   -0.8638   -0.3396    0.1108

Specify MaxRank=5 to impose a limit on the number of singular values in S2 and the number of singular vectors in U2 and V2. After calculating the revised SVD, svdappend truncates the smallest singular values and associated singular vectors until the limit is satisfied. These results are similar to U1, S1, and V1, but the smallest singular value and associated singular vectors are truncated.

[U2,S2,V2] = svdappend(U,S,V,D,Shape="rows",MaxRank=5)
U2 = 10×5

    0.3909    0.0593   -0.3501   -0.2543    0.2971
    0.3588    0.2925   -0.2515    0.3982    0.1097
    0.3429   -0.3027    0.1746    0.3867   -0.2745
    0.2353    0.4938    0.5672    0.2279   -0.0616
    0.2715    0.1703   -0.4510    0.2314    0.0597
    0.3767   -0.5450    0.2275   -0.2637    0.1615
    0.3299    0.1748   -0.1556   -0.4787   -0.7600
    0.2389   -0.1394   -0.1109   -0.0742    0.2814
    0.2908    0.3004    0.3953   -0.3542    0.3391
    0.2818   -0.3305    0.1186    0.3035   -0.1384

S2 = 5×1

    4.3460
    1.3335
    1.1287
    1.0049
    0.5681

V2 = 6×5

    0.3915    0.8486    0.0006   -0.1502    0.3210
    0.4490   -0.1113    0.8111    0.2481   -0.1583
    0.4156   -0.3870   -0.0439    0.0599    0.5980
    0.4960   -0.2554   -0.4951    0.1048    0.0576
    0.3582    0.1589   -0.3070    0.3938   -0.6290
    0.3132   -0.1649    0.0298   -0.8638   -0.3396

Specify WindowSize=5 to instead discard some of the old rows of data before calculating the revised SVD. Because you specified four new rows of data, this calculation uses those rows and one old row to calculate the revised SVD. Therefore, the results are different than U2, S2, and V2, even though both calculations return five singular values.

[U3,S3,V3] = svdappend(U,S,V,D,Shape="rows",WindowSize=5)
U3 = 5×5

    0.5744    0.4555   -0.1212   -0.5750   -0.3424
    0.4696   -0.5545    0.6641   -0.0052   -0.1761
    0.3423    0.1068    0.0897   -0.1393    0.9187
    0.4155   -0.5223   -0.7285    0.1546    0.0005
    0.3997    0.4482    0.0745    0.7912   -0.0883

S3 = 5×1

    3.0549
    1.0150
    0.6496
    0.4210
    0.3188

V3 = 6×5

    0.2944   -0.7761   -0.3257    0.1669    0.4170
    0.5009    0.1933   -0.4472    0.3182   -0.4043
    0.4010    0.4166   -0.3378   -0.0369    0.1463
    0.4957    0.2692    0.4236   -0.1555    0.5918
    0.2325   -0.1051    0.5839    0.6846   -0.2150
    0.4494   -0.3212    0.2439   -0.6138   -0.4948

Calculate the SVD of a 6-by-6 test matrix, and then calculate the revised SVD with two additional columns. Use the AbsoluteTolerance and RelativeTolerance name-value arguments to filter out small singular values and their associated singular vectors.

Create a 6-by-6 test matrix that has only one large singular value using the gallery function. Calculate the SVD.

rng default
A = gallery("randsvd",6,[],1);
[U,S,V] = svd(A,"vector")
U = 6×6

   -0.5231    0.4398   -0.2661   -0.0608   -0.0294    0.6765
   -0.1183   -0.2117    0.7924   -0.1320    0.4046    0.3636
    0.2745   -0.2283   -0.1911   -0.8821   -0.1331    0.2005
   -0.4983   -0.5383   -0.4065   -0.0453    0.5131   -0.1770
   -0.6224    0.0395    0.3152   -0.2965   -0.4881   -0.4308
    0.0372    0.6468    0.0153   -0.3329    0.5623   -0.3912

S = 6×1

    1.0000
    0.0000
    0.0000
    0.0000
    0.0000
    0.0000

V = 6×6

   -0.2745    0.5572   -0.1389   -0.6956   -0.1745    0.2839
    0.0787    0.4188    0.3088    0.5010   -0.6452    0.2363
   -0.0477   -0.2451    0.6644   -0.4136   -0.3366   -0.4602
    0.5721    0.5285   -0.1578   -0.0377    0.0885   -0.5994
   -0.5411   -0.0578   -0.5104    0.1651   -0.4039   -0.5030
    0.5442   -0.4141   -0.3981   -0.2557   -0.5187    0.1987

Create a 6-by-2 matrix containing two new columns of data, and then calculate the revised SVD. The vector of singular values S1 now contains three large singular values.

D = rand(6,2);
[U1,S1,V1] = svdappend(U,S,V,D)
U1 = 6×6

    0.5419   -0.0980   -0.2440   -0.2845   -0.3320   -0.6679
    0.4939    0.4285    0.2632    0.6155    0.3072   -0.1732
    0.0935    0.4736    0.6259   -0.4188   -0.4163    0.1630
    0.4448   -0.2781    0.1769   -0.4897    0.6326    0.2311
    0.4456   -0.4660    0.0556    0.3207   -0.4706    0.5069
    0.2395    0.5366   -0.6672   -0.1491   -0.0193    0.4324

S1 = 6×1

    2.1458
    0.6808
    0.3284
    0.0000
    0.0000
    0.0000

V1 = 8×6

    0.1031   -0.2335   -0.1009   -0.2977   -0.7510   -0.0757
   -0.0296    0.0670    0.0289    0.5449   -0.4660   -0.4599
    0.0179   -0.0406   -0.0175    0.5849   -0.2703    0.6476
   -0.2149    0.4866    0.2103   -0.1370   -0.1525    0.4882
    0.2033   -0.4603   -0.1989   -0.3399   -0.1447    0.3425
   -0.2045    0.4630    0.2001   -0.3716   -0.3186   -0.0876
    0.6506    0.5247   -0.5490   -0.0000    0.0000    0.0000
    0.6599   -0.0330    0.7506    0.0000   -0.0000   -0.0000

Now, perform the same calculation but specify AbsoluteTolerance=1e-6 to filter out any singular values smaller than that threshold.

[U2,S2,V2] = svdappend(U,S,V,D,AbsoluteTolerance=1e-6)
U2 = 6×3

    0.5419   -0.0980   -0.2440
    0.4939    0.4285    0.2632
    0.0935    0.4736    0.6259
    0.4448   -0.2781    0.1769
    0.4456   -0.4660    0.0556
    0.2395    0.5366   -0.6672

S2 = 3×1

    2.1458
    0.6808
    0.3284

V2 = 8×3

    0.1031   -0.2335   -0.1009
   -0.0296    0.0670    0.0289
    0.0179   -0.0406   -0.0175
   -0.2149    0.4866    0.2103
    0.2033   -0.4603   -0.1989
   -0.2045    0.4630    0.2001
    0.6506    0.5247   -0.5490
    0.6599   -0.0330    0.7506

Alternatively, specify RelativeTolerance=0.3 to filter out singular values smaller than 30% of the largest singular value. While the absolute tolerance can be any number, the relative tolerance is a value from 0 to 1 indicating how small a singular value can be relative to the largest singular value.

[U3,S3,V3] = svdappend(U,S,V,D,RelativeTolerance=0.3)
U3 = 6×2

    0.5419   -0.0980
    0.4939    0.4285
    0.0935    0.4736
    0.4448   -0.2781
    0.4456   -0.4660
    0.2395    0.5366

S3 = 2×1

    2.1458
    0.6808

V3 = 8×2

    0.1031   -0.2335
   -0.0296    0.0670
    0.0179   -0.0406
   -0.2149    0.4866
    0.2033   -0.4603
   -0.2045    0.4630
    0.6506    0.5247
    0.6599   -0.0330

Input Arguments

collapse all

Existing SVD factors, specified as matrices. U, S, and V can be SVD factors of any shape calculated by one of these functions:

How you should recombine the SVD factors differs depending on whether the singular values are returned as a vector or matrix, and whether the decomposition is complete, economy size, or truncated. For example, if S is a vector returned as part of a complete decomposition of a square matrix A, then A = (U.*S')*V'.

Example: [U,S,V] = svd(A)

Example: [U,S,V] = svd(A,"vector")

Example: [U,S,V] = svd(A,"econ")

Example: [U,S,V] = svd(A,"econ","vector")

Example: [U,S,V] = svds(A,5)

Example: [U,S,V] = svdsketch(A,1e-5)

Data Types: single | double
Complex Number Support: Yes

New columns or rows to append, specified as a vector or matrix. Use the Shape name-value argument to specify whether D contains columns or rows of data to append. By default, svdappend appends D as new columns of data.

When U, S, and V are nonempty and D has a different data type than those factors, svdappend casts D to be the same data type.

Data Types: single | double
Complex Number Support: Yes

Name-Value Arguments

Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the argument name and Value is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Example: [U1,S1,V1] = svdappend(U,S,V,D,Shape="rows",WindowSize=10)

Shape of data in D, specified as "columns" or "rows". If the value is "columns", the revised SVD is for [A D]. If the value is "rows", the revised SVD is for [A; D]. Neither [A D] nor [A; D] are explicitly formed.

Example: [U1,S1,V1] = svdappend(U,S,V,D,Shape="rows")

Maximum number of columns or rows to compute the SVD, specified as a positive integer scalar. WindowSize controls the memory consumption of the algorithm. The function appends new data and discards the oldest data (starting with the first column or row) to satisfy WindowSize before computing the revised SVD. By default, svdappend does not discard data.

Example: [U1,S1,V1] = svdappend(U,S,V,D,WindowSize=50)

Absolute tolerance for singular values and vectors, specified as a nonnegative real scalar. The function truncates singular values in S1 less than or equal to AbsoluteTolerance. Corresponding singular vectors in U1 and V1 are also truncated. By default, svdappend does not truncate the outputs.

Each of the name-value arguments AbsoluteTolerance, RelativeTolerance, and MaxRank result in a specific rank for the revised SVD. svdappend truncates the revised SVD based on the minimum rank from all specified arguments.

Example: [U1,S1,V1] = svdappend(U,S,V,D,AbsoluteTolerance=1e-6)

Data Types: single | double

Relative tolerance for singular values and vectors, specified as a real scalar in the range [0 1]. The function truncates singular values in S1 less than or equal to RelativeTolerance*S1(1). Corresponding singular vectors in U1 and V1 are also truncated. By default, svdappend does not truncate the outputs.

Each of the name-value arguments AbsoluteTolerance, RelativeTolerance, and MaxRank result in a specific rank for the revised SVD. svdappend truncates the revised SVD based on the minimum rank from all specified arguments.

Example: [U1,S1,V1] = svdappend(U,S,V,D,RelativeTolerance=0.3)

Data Types: single | double

Maximum rank of the revised SVD, specified as a positive integer scalar. MaxRank imposes a limit on the number of singular values in S1 and the number of singular vectors in U1 and V1. By default, there is no limit to the rank.

Each of the name-value arguments AbsoluteTolerance, RelativeTolerance, and MaxRank result in a specific rank for the revised SVD. svdappend truncates the revised SVD based on the minimum rank from all specified arguments.

Example: [U1,S1,V1] = svdappend(U,S,V,D,MaxRank=25)

Data Types: single | double

Output Arguments

collapse all

Revised singular vectors, returned as matrices.

  • If Shape="columns", then (U1.*S1')*V1' is equivalent to [U*S*V' D] up to round-off error, ignoring truncation.

  • If Shape="rows", then (U1.*S1')*V1' is equivalent to [U*S*V'; D] up to round-off error, ignoring truncation.

  • Each of the name-value arguments AbsoluteTolerance, RelativeTolerance, and MaxRank result in a specific rank for the revised SVD. Use these arguments to truncate singular values and vectors to control the rank of U1*diag(S1)*V1'.

Different machines and releases of MATLAB® can produce different singular vectors that are still numerically accurate. Corresponding columns in U1 and V1 can flip their signs, since this change does not affect the value of the expression U1*S1*V1'.

Revised singular values, returned as a column vector. Use diag(S1) to create a diagonal matrix of singular values from S1.

Version History

Introduced in R2023b