跳跃:期望float64,typeError的问题:在TypeSert中,预期的float64,forwarddiff.dual autodiff = true和exp()的问题

发布于 2025-01-25 01:48:05 字数 2274 浏览 2 评论 0原文

因此,我试图以最少的示例来根据我编写的更复杂的代码提出问题:

  1. 我遇到的一个巨大的常见错误是float64,而是forwarddiff.dual-偶然 - 有人可以给我一个提示。我总是确保避免使用此错误。我觉得每当我做一个新的优化问题时,我都必须重新发明方向盘以使其
  2. 显然无法自动化Julia Exp()函数?有人知道如何使它起作用吗?
  3. 我做了一个有限的总和以通过泰勒系列近似它。在我的一个功能中,如果我有20个术语,自动驾驶仪的工作还不够准确 - 所以我去了40个任期Autodiff现在不起作用 - 有人为此解决了吗?

任何建议将不胜感激!

using Cubature
    
    using Juniper
    using Ipopt
    using JuMP
    using LinearAlgebra 
    using Base.Threads
    using Cbc
    using DifferentialEquations
    using Trapz
    function mat_exp(x::AbstractVector{T},dim,num_terms,A) where T
    
        sum = zeros(Complex{T},(dim,dim))
        A[1,1] = A[1,1]*x[1]
        A[2,2] = A[2,2]*x[2]
    
       return exp(A)-1
    end
    
    function exp_approx_no_big(x::AbstractVector{T},dim,num_terms,A) where T
    
        sum = zeros(Complex{T},(dim,dim))
        A[1,1] = A[1,1]*x[1]
        A[2,2] = A[2,2]*x[2]
    
        for k=0:num_terms-1
        
        sum  = sum + (1.0/factorial(k))*A^k
        end
    
        return norm(sum)-1
    end
    function exp_approx_big(x::AbstractVector{T},dim,num_terms,A) where  T
    
        sum = zeros(Complex{T},(dim,dim))
        A[1,1] = A[1,1]*x[1]
        A[2,2] = A[2,2]*x[2]
    
        for k=0:num_terms-1
        
        sum  = sum + (1.0/factorial(big(k)))*A^k
        end
    
        return norm(sum)-1
    
    
    end
    
    
    
    
    optimizer = Juniper.Optimizer
    nl_solver= optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
    mip_solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0, "threads"=>nthreads())
    m = Model(optimizer_with_attributes(optimizer, "nl_solver"=>nl_solver, "mip_solver"=>mip_solver))
    
    @variable(m, 0.0<=x[1:2]<=1.0)
    dim=5
    A=zeros(Complex,(dim,dim))
    for k=1:dim
    A[k,k]=1.0
    end
    println(A)
    
    
    
    f(x...) = exp_approx_no_big(collect(x),dim,20,A)
    g(x...) = exp_approx_big(collect(x),dim,40,A)
    h(x...) = mat_exp(collect(x),dim,20,A)
    register(m, :f, 2, f; autodiff = true)
    @NLobjective(m, Min, f(x...))
    
    
    optimize!(m)
    
    
    println(JuMP.value.(x))
    println(JuMP.objective_value(m))
    println(JuMP.termination_status(m))
    
       

So I tried to make a minimum example to ask questions based on a more complicated piece of code I have written:

  1. A HUGE common error I'm getting is expecting float64 and instead got ForwardDiff.Dual - can someone give me a tip how in general I always make sure I avoid this bug. I feel like every time I do a new optimization problem I have to reinvent the wheel to try to make this go away
  2. Apparently you cannot autodiff the julia exp() function? Does anyone know how to make it work?
  3. A workaround is I did a finite sum to approximate it via the taylor series. In my one function if I had 20 terms the autodiff worked, but it wasn't accurate enough - so I went to 40 terms but then julia told me to do factorial(big(k)) and then when I try to do that with autodiff it doesn't work now - anyone have a fix for this?

Any advice would be greatly appreciated!

using Cubature
    
    using Juniper
    using Ipopt
    using JuMP
    using LinearAlgebra 
    using Base.Threads
    using Cbc
    using DifferentialEquations
    using Trapz
    function mat_exp(x::AbstractVector{T},dim,num_terms,A) where T
    
        sum = zeros(Complex{T},(dim,dim))
        A[1,1] = A[1,1]*x[1]
        A[2,2] = A[2,2]*x[2]
    
       return exp(A)-1
    end
    
    function exp_approx_no_big(x::AbstractVector{T},dim,num_terms,A) where T
    
        sum = zeros(Complex{T},(dim,dim))
        A[1,1] = A[1,1]*x[1]
        A[2,2] = A[2,2]*x[2]
    
        for k=0:num_terms-1
        
        sum  = sum + (1.0/factorial(k))*A^k
        end
    
        return norm(sum)-1
    end
    function exp_approx_big(x::AbstractVector{T},dim,num_terms,A) where  T
    
        sum = zeros(Complex{T},(dim,dim))
        A[1,1] = A[1,1]*x[1]
        A[2,2] = A[2,2]*x[2]
    
        for k=0:num_terms-1
        
        sum  = sum + (1.0/factorial(big(k)))*A^k
        end
    
        return norm(sum)-1
    
    
    end
    
    
    
    
    optimizer = Juniper.Optimizer
    nl_solver= optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
    mip_solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0, "threads"=>nthreads())
    m = Model(optimizer_with_attributes(optimizer, "nl_solver"=>nl_solver, "mip_solver"=>mip_solver))
    
    @variable(m, 0.0<=x[1:2]<=1.0)
    dim=5
    A=zeros(Complex,(dim,dim))
    for k=1:dim
    A[k,k]=1.0
    end
    println(A)
    
    
    
    f(x...) = exp_approx_no_big(collect(x),dim,20,A)
    g(x...) = exp_approx_big(collect(x),dim,40,A)
    h(x...) = mat_exp(collect(x),dim,20,A)
    register(m, :f, 2, f; autodiff = true)
    @NLobjective(m, Min, f(x...))
    
    
    optimize!(m)
    
    
    println(JuMP.value.(x))
    println(JuMP.objective_value(m))
    println(JuMP.termination_status(m))
    
       

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

断桥再见 2025-02-01 01:48:05

您的mat_exp函数有很多问题:

  • 它修改a就位,因此重复的调用不会执行您认为
  • 它返回exp(x) -1,是矩阵。跳转仅支持标量调用
  • 您可能的含义norm(EXP(x))-1
  • ,但前向diff不支持通过exp进行区分,
julia> using ForwardDiff

julia> function mat_exp(x::AbstractVector{T}) where {T}
           A = zeros(Complex{T}, (dim, dim))
           for k = 1:dim
               A[k, k] = one(T)
           end
           A[1, 1] = A[1, 1] * x[1]
           A[2, 2] = A[2, 2] * x[2]
           return norm(exp(A)) - one(T)
       end
mat_exp (generic function with 3 methods)

julia> ForwardDiff.gradient(mat_exp, [0.5, 0.5])
ERROR: MethodError: no method matching exp(::Matrix{Complex{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}})
Closest candidates are:
  exp(::StridedMatrix{var"#s832"} where var"#s832"<:Union{Float32, Float64, ComplexF32, ComplexF64}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/dense.jl:557
  exp(::StridedMatrix{var"#s832"} where var"#s832"<:Union{Integer, Complex{var"#s831"} where var"#s831"<:Integer}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/dense.jl:558
  exp(::Diagonal) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/diagonal.jl:603
  ...
Stacktrace:
 [1] mat_exp(x::Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}})
   @ Main ./REPL[34]:8
 [2] vector_mode_dual_eval!(f::typeof(mat_exp), cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}}, x::Vector{Float64})
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/apiutils.jl:37
 [3] vector_mode_gradient(f::typeof(mat_exp), x::Vector{Float64}, cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}})
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/gradient.jl:106
 [4] gradient(f::Function, x::Vector{Float64}, cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}}, ::Val{true})
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/gradient.jl:19
 [5] gradient(f::Function, x::Vector{Float64}, cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}}) (repeats 2 times)
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/gradient.jl:17
 [6] top-level scope
   @ REPL[35]:1

我也不知道为什么使用杜松,或安装了许多其他软件包。

如果您想对此进行讨论,请加入社区论坛: https:// usise.julialang.org/c/domain/opt/13 。 (对于来回而言,这比StackoverFlow要好得多。)有人可能有建议,但我不知道朱莉娅(Julia)中的广告工具可以通过矩阵指数分化。

There are quite a few problems with your mat_exp function:

  • It modifies A in-place, so repeated calls will not do what you think
  • It returns exp(x) - 1, which is a matrix. JuMP only supports scalar calls
  • You probably meant norm(exp(x)) - 1
  • But ForwardDiff doesn't support differentiating through exp
julia> using ForwardDiff

julia> function mat_exp(x::AbstractVector{T}) where {T}
           A = zeros(Complex{T}, (dim, dim))
           for k = 1:dim
               A[k, k] = one(T)
           end
           A[1, 1] = A[1, 1] * x[1]
           A[2, 2] = A[2, 2] * x[2]
           return norm(exp(A)) - one(T)
       end
mat_exp (generic function with 3 methods)

julia> ForwardDiff.gradient(mat_exp, [0.5, 0.5])
ERROR: MethodError: no method matching exp(::Matrix{Complex{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}})
Closest candidates are:
  exp(::StridedMatrix{var"#s832"} where var"#s832"<:Union{Float32, Float64, ComplexF32, ComplexF64}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/dense.jl:557
  exp(::StridedMatrix{var"#s832"} where var"#s832"<:Union{Integer, Complex{var"#s831"} where var"#s831"<:Integer}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/dense.jl:558
  exp(::Diagonal) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/diagonal.jl:603
  ...
Stacktrace:
 [1] mat_exp(x::Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}})
   @ Main ./REPL[34]:8
 [2] vector_mode_dual_eval!(f::typeof(mat_exp), cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}}, x::Vector{Float64})
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/apiutils.jl:37
 [3] vector_mode_gradient(f::typeof(mat_exp), x::Vector{Float64}, cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}})
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/gradient.jl:106
 [4] gradient(f::Function, x::Vector{Float64}, cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}}, ::Val{true})
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/gradient.jl:19
 [5] gradient(f::Function, x::Vector{Float64}, cfg::ForwardDiff.GradientConfig{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2, Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(mat_exp), Float64}, Float64, 2}}}) (repeats 2 times)
   @ ForwardDiff ~/.julia/packages/ForwardDiff/jJIvy/src/gradient.jl:17
 [6] top-level scope
   @ REPL[35]:1

I also don't know why you're using Juniper, or that you have a bunch of other packages installed.

If you want to have a discussion on this, come join the community forum: https://discourse.julialang.org/c/domain/opt/13. (It's much better for back-and-forth than stackoverflow.) Someone might have suggestions, but I don't know of an AD tool in Julia that can differentiate through a matrix exponential.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文