Skip to content

Commit d63707c

Browse files
Jutholkdvos
authored andcommitted
some final fixes
1 parent 5bef397 commit d63707c

4 files changed

Lines changed: 22 additions & 3 deletions

File tree

docs/src/user_interface/truncations.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,16 @@ When strategies are combined, only the values that satisfy all conditions are ke
127127
combined_trunc = truncrank(10) & trunctol(; atol = 1e-6);
128128
```
129129

130+
## Truncation Error
131+
132+
When using truncated decompositions such as [`svd_trunc`](@ref), [`eig_trunc`](@ref), or [`eigh_trunc`](@ref), an additional truncation error value is returned.
133+
This error is defined as the 2-norm of the discarded singular values or eigenvalues, providing a measure of the approximation quality.
134+
For `svd_trunc` and `eigh_trunc`, this corresponds to the 2-norm difference between the original and the truncated matrix.
135+
For the case of `eig_trunc`, this interpretation does not hold because the norm of the non-unitary matrix of eigenvectors and its inverse also influence the approximation quality.
136+
137+
138+
For example:
139+
```julia
140+
U, S, Vᴴ, ϵ = svd_trunc(A; trunc=truncrank(10))
141+
# ϵ is the 2-norm of the discarded singular values
142+
```

ext/MatrixAlgebraKitChainRulesCoreExt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ for eig in (:eig, :eigh)
113113
Ac = copy_input($eig_f, A)
114114
DV = $(eig_f!)(Ac, DV, alg.alg)
115115
DV′, ind = MatrixAlgebraKit.truncate($eig_t!, DV, alg.trunc)
116-
ϵ = compute_truncerr!(diagview(copy(DV[1])), ind)
116+
ϵ = compute_truncerr!(copy(diagview(DV[1])), ind)
117117
return (DV′..., ϵ), $(_make_eig_t_pb)(A, DV, ind)
118118
end
119119
function $(_make_eig_t_pb)(A, DV, ind)
@@ -157,7 +157,7 @@ function ChainRulesCore.rrule(::typeof(svd_trunc!), A, USVᴴ, alg::TruncatedAlg
157157
Ac = copy_input(svd_compact, A)
158158
USVᴴ = svd_compact!(Ac, USVᴴ, alg.alg)
159159
USVᴴ′, ind = MatrixAlgebraKit.truncate(svd_trunc!, USVᴴ, alg.trunc)
160-
ϵ = compute_truncerr!(diagview(copy(USVᴴ[2])), ind)
160+
ϵ = compute_truncerr!(copy(diagview(USVᴴ[2])), ind)
161161
return (USVᴴ′..., ϵ), _make_svd_trunc_pullback(A, USVᴴ, ind)
162162
end
163163
function _make_svd_trunc_pullback(A, USVᴴ, ind)

src/implementations/svd.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,12 @@ function svd_trunc!(A::AbstractMatrix, USVᴴ, alg::TruncatedAlgorithm{<:GPU_Ran
382382
_gpu_Xgesvdr!(A, S.diag, U, Vᴴ; alg.alg.kwargs...)
383383
# TODO: make this controllable using a `gaugefix` keyword argument
384384
gaugefix!(svd_trunc!, U, S, Vᴴ, size(A)...)
385-
return first(truncate(svd_trunc!, USVᴴ, alg.trunc))
385+
# TODO: make sure that truncation is based on maxrank, otherwise this might be wrong
386+
USVᴴtrunc, ind = truncate(svd_trunc!, (U, S, Vᴴ), alg.trunc)
387+
Strunc = diagview(USVᴴtrunc[2])
388+
# normal `compute_truncerr!` does not work here since `S` is not the full singular value spectrum
389+
ϵ = sqrt(norm(A)^2 - norm(Strunc)^2) # is there a more accurate way to do this?
390+
return USVᴴtrunc..., ϵ
386391
end
387392

388393
function MatrixAlgebraKit.svd_compact!(A::AbstractMatrix, USVᴴ, alg::GPU_SVDAlgorithm)

test/cuda/svd.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ end
106106
U1, S1, V1ᴴ, ϵ1 = @constinferred svd_trunc(A; alg, trunc = truncrank(r))
107107
@test length(S1.diag) == r
108108
@test opnorm(A - U1 * S1 * V1ᴴ) S₀[r + 1]
109+
@test norm(A - U1 * S1 * V1ᴴ) ϵ1
109110

110111
if !(alg isa CUSOLVER_Randomized)
111112
s = 1 + sqrt(eps(real(T)))

0 commit comments

Comments
 (0)