A new classIncrementalSVDBrand : IncrementalSVD has been added which exactly follows Brand's fast algorithm. It mostly follows IncrementalSVDFastUpdate, but has some modifications:
Moved computeBasis from buildIncrementalSVD to getSpatialBasis. This is because we do not need to compute the basis while updating the SVD. We only need to compute the basis when we try to get its value.
Added the re-orthogonalization of the projection error vector before being appended in buildIncrementalSVD. This guarantees the orthogonality of d_U down to the machine precision. (Gram-Schmidt alone does not guarantee the orthogonality down to the machine precision, but doing Gram-Schmidt twice does. See https://doi.org/10.1016/j.camwa.2005.08.009)
Added the re-orthogonalization of d_Up and d_W in addNewSample. d_U is also being orthogonalized: although this will not be called since d_U is guaranteed to be orthonormal, it was not omitted just in case.
An additional test case has been added to unit_test/test_IncrementalSVDBrand to verify the revised version of the incremental SVD. It appends unit vectors to the incremental SVD object then checks if the computed basis and the singular values are either 0 or 1.
Finally, a bug in IncrementalSVD::buildIncrementalSVD has been fixed. Computing the norm of the projection error as
k = sqrt(u.u - 2.0*l.l + basisl.basisl)
should be avoided since this results in the catastrophic cancellation. It will lead to the incorrect estimate of the linear dependence of the new snapshot vector. Instead, one should compute it as
A new class
IncrementalSVDBrand : IncrementalSVD
has been added which exactly follows Brand's fast algorithm. It mostly followsIncrementalSVDFastUpdate
, but has some modifications:computeBasis
frombuildIncrementalSVD
togetSpatialBasis
. This is because we do not need to compute the basis while updating the SVD. We only need to compute the basis when we try to get its value.buildIncrementalSVD
. This guarantees the orthogonality ofd_U
down to the machine precision. (Gram-Schmidt alone does not guarantee the orthogonality down to the machine precision, but doing Gram-Schmidt twice does. See https://doi.org/10.1016/j.camwa.2005.08.009)d_Up
andd_W
inaddNewSample
.d_U
is also being orthogonalized: although this will not be called sinced_U
is guaranteed to be orthonormal, it was not omitted just in case.An additional test case has been added to
unit_test/test_IncrementalSVDBrand
to verify the revised version of the incremental SVD. It appends unit vectors to the incremental SVD object then checks if the computed basis and the singular values are either 0 or 1.Finally, a bug in
IncrementalSVD::buildIncrementalSVD
has been fixed. Computing the norm of the projection error ask = sqrt(u.u - 2.0*l.l + basisl.basisl)
should be avoided since this results in the catastrophic cancellation. It will lead to the incorrect estimate of the linear dependence of the new snapshot vector. Instead, one should compute it as
k = sqrt((u-basisl).(u-basisl)),
which remains double-precision.