Pinv and autodiff error

Hi, I’m getting the following error in the following MWE:

(I’m aware that I could implement Moore-Penrose by hand to circumvent the issue; I’d rather not do this, as I’m trying to understand why exactly I get this error here).

MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{typeof(f), Float64}, Float64, 1})
using Optim, LinearAlgebra

function f(x::AbstractVector{T}) where T <: Real
    n = length(x)
    KXX = Matrix{Real}(undef, n, n)
    for i = 1:n
        for j = i:n
            KXX[i, j] = x[i] * x[j]
            KXX[j, i] = KXX[i, j]
        end
    end
    return sum(pinv(KXX)) + sum(x .^2)
end

x_opt_NM = optimize(f, [0.])
display(x_opt_NM)

x_opt = optimize(f, [0.], Newton(); autodiff = :forward)
display(x_opt)

I’m failing to see where it tries to make something into a Float. (Note that the problem persists for higher dimensional problems, just replace [0.] by zeros(d) for some choice d)

I’m not sure I see why this doesn’t work either, but I suspect it has something to do with Real not being a concrete type and a broadcast inside pinv making a concrete array. Using the actual type of the argument does work:

function f(x::AbstractVector{T}) where T <: Real
    n = length(x)
    KXX = Matrix{T}(undef, n, n) # Use the actual type here
    for i = 1:n
        for j = i:n
            KXX[i, j] = x[i] * x[j]
            KXX[j, i] = KXX[i, j]
        end
    end
    return sum(pinv(KXX)) + sum(x .^2)
end

Or, even less restrictive:

function f2(x)
    n = length(x)
    KXX = similar(x, (n,n))
    for i = 1:n
        for j = i:n
            KXX[i, j] = x[i] * x[j]
            KXX[j, i] = KXX[i, j]
        end
    end
    return sum(pinv(KXX)) + sum(x .^2)
end
1 Like

Thank you for pointing that out! There’s probably a good reason why this is the case, but it is certainly a bit counterintuitive to me at present! I’ll make the necessary changes to my code then!