Skip to content

SVD pullback of rank-deficient matrix #150

@lkdvos

Description

@lkdvos

I encountered a DimensionMismatch error during the backward pass of an optimization loop involving SVD truncation on $U(1)$ symmetric tensors. I think this issue occurs when the distribution of bond dimensions across different charge sectors changes between the forward pass and the backward pullback. As I don't want to fixed the sectors, I really need this function maybe.

ERROR: LoadError: DimensionMismatch: 
Stacktrace:
  [1] svd_pullback!(ΔA::Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, A::Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, USVᴴ::Tuple{Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, Diagonal{Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}}, Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}}, ΔUSVᴴ::Vector{Any}, ind::BitVector; tol::Float64, rank_atol::Float64, degeneracy_atol::Float64, gauge_atol::Float64)
    @ MatrixAlgebraKit ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/pullbacks/svd.jl:51
  [2] svd_pullback!(ΔA::Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, A::Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, USVᴴ::Tuple{Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}, Diagonal{Float64, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}}, Base.ReshapedArray{Float64, 2, SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}, Tuple{}}}, ΔUSVᴴ::Vector{Any}, ind::BitVector)
    @ MatrixAlgebraKit ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/pullbacks/svd.jl:24

Originally posted by @Ryo-wtnb11 in #101

I investigated this issue in a bit more detail and can distill the problem to the following MWE:

using Zygote, MatrixAlgebraKit

# generate a rank-deficient matrix
A = zeros(3, 3)
rand!(@view(A[1:2, 1:2]))

# dummy function to derive
function f(A)
    U, S, Vh = svd_compact(A)
    return tr(U * S * Vh)
end

Zygote.gradient(f, A)
ERROR: DimensionMismatch: 
Stacktrace:
  [1] svd_pullback!(ΔA::Matrix{…}, A::Matrix{…}, USVᴴ::Tuple{…}, ΔUSVᴴ::Vector{…}, ind::Colon; tol::Float64, rank_atol::Float64, degeneracy_atol::Float64, gauge_atol::Float64)
    @ MatrixAlgebraKit ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/pullbacks/svd.jl:51
  [2] svd_pullback!
    @ ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/pullbacks/svd.jl:24 [inlined]
  [3] svd_pullback!(ΔA::Matrix{…}, A::Matrix{…}, USVᴴ::Tuple{…}, ΔUSVᴴ::Vector{…})
    @ MatrixAlgebraKit ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/pullbacks/svd.jl:24

I think I have an idea of what is going on, I am pretty sure I can bypass the error but I'm not entirely sure everything will still be correct.
The main point is that we are currently checking that we are not keeping more singular values than the numerical rank of the matri.
This happens when indU or indV has more entries than the rank, throwing a DimensionMismatch for that (which is clearly not the most informative message either...).

In principle I might be able to alter the implementation to ignore that, but I'm not entirely sure if that is mathematically allowed, since this is basically one large degenerate subspace (nullspace) and I don't know if this would be correctly taking that into account.

@Jutho, I don't know if you have more insight into this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions