SciML / DataDrivenDiffEq.jl

Data driven modeling and automated discovery of dynamical systems for the SciML Scientific Machine Learning organization
https://docs.sciml.ai/DataDrivenDiffEq/stable/
MIT License
402 stars 56 forks source link

truncated_svd() is unable to handle complex matrices #367

Open clairevalva opened 2 years ago

clairevalva commented 2 years ago

truncated_svd appears to be unable to handle complex matrices (both with the method of truncation by explicit rank or tolerance). The following code which uses truncated_svd() via DMDSVD() fails.

using DataDrivenDiffEq
freq1 = 2
freq2 = 3
freq3 = 11

dt = 0.1
t = 0:dt:30

x = exp.(1im*freq1*t);
y = exp.(1im*freq2*t);
z = exp.(1im*freq3*t);

X = hcat(x,y,z)';

problem = DiscreteDataDrivenProblem(X, t);
res = solve(problem, DMDSVD());

with errors:

 [1] min(x::Float64, y::ComplexF64)
   @ Base ./operators.jl:433
 [2] truncated_svd(A::Matrix{ComplexF64}, truncation::Float64)
   @ DataDrivenDiffEq ~/.julia/packages/DataDrivenDiffEq/s9jl3/src/koopman/algorithms.jl:3
AlCap23 commented 2 years ago

Currently, we assume(d) the input is Real.

A quick fix would be to compare the magnitude and truncation:

function truncated_svd(A::AbstractMatrix{T}, truncation::Real) where T <: Number
    truncation = min(norm(convert(T, truncation)), norm(one(T)))
    U, S, V = svd(A)
    r = vec(S .> truncation*maximum(S))
    U = U[:, r]
    S = S[r]
    V = V[:, r]
    return U, S, V
end
ChrisRackauckas commented 2 years ago

We should probably throw an error message much sooner then that makes it clear that complex isn't supported here.

clairevalva commented 2 years ago

An error sooner would be nice :) (But at least for the case of DMDSVD, there is no particular reason intrinsic to the algorithm itself that requires real input.)