поэтому я написал минимальный пример, чтобы показать, что я пытаюсь сделать. В основном я хочу решить проблему оптимизации с несколькими переменными. Когда я пытаюсь сделать это в JuMP, у меня возникают проблемы с тем, что моя функция obj не может принимать объект forwardDiff.
Я посмотрел здесь: и, похоже, это связано с сигнатурой функции :Ограничение сигнатур функций при использовании ForwardDiff в Julia. Я сделал это в своей функции obj, а для страховки сделал это и в своей подфункции, но все равно получаю ошибку
LoadError: MethodError: no method matching Float64(::ForwardDiff.Dual{ForwardDiff.Tag{JuMP.var"#110#112"{typeof(my_fun)},Float64},Float64,2})
Closest candidates are:
Float64(::Real, ::RoundingMode) where T<:AbstractFloat at rounding.jl:200
Float64(::T) where T<:Number at boot.jl:715
Float64(::Int8) at float.jl:60
Это все еще не работает. Я чувствую, что основная часть кода у меня правильная, просто происходит какая-то странная вещь, которую мне нужно очистить, чтобы автодифференциация работала...
Какие-либо предложения?
using JuMP
using Ipopt
using LinearAlgebra
function obj(x::Array{<:Real,1})
println(x)
x1 = x[1]
x2 = x[2]
eye= Matrix{Float64}(I, 4, 4)
obj_val = tr(eye-kron(mat_fun(x1),mat_fun(x2)))
println(obj_val)
return obj_val
end
function mat_fun(var::T) where {T<:Real}
eye= Matrix{Float64}(I, 2, 2)
eye[2,2]=var
return eye
end
m = Model(Ipopt.Optimizer)
my_fun(x...) = obj(collect(x))
@variable(m, 0<=x[1:2]<=2.0*pi)
register(m, :my_fun, 2, my_fun; autodiff = true)
@NLobjective(m, Min, my_fun(x...))
optimize!(m)
# retrieve the objective value, corresponding x values and the status
println(JuMP.value.(x))
println(JuMP.objective_value(m))
println(JuMP.termination_status(m))
Я нашел проблему: в моем mat_fun тип возврата должен был быть «Настоящим», чтобы он распространялся. До этого был Float64, что не соответствовало тому факту, что я думаю, что все типы должны быть реальными с автодифференцированием. Несмотря на то, что Float64 явно является Real, похоже, что наследование не сохраняется, т.е. вы должны убедиться, что все, что возвращается и вводится, имеет тип Real.
using JuMP
using Ipopt
using LinearAlgebra
function obj(x::AbstractVector{T}) where {T<:Real}
println(x)
x1 = x[1]
x2 = x[2]
eye= Matrix{Float64}(I, 4, 4)
obj_val = tr(eye-kron(mat_fun(x1),mat_fun(x2)))
#println(obj_val)
return obj_val
end
function mat_fun(var::T) where {T<:Real}
eye= zeros(Real,(2,2))
eye[2,2]=var
return eye
end
m = Model(Ipopt.Optimizer)
my_fun(x...) = obj(collect(x))
@variable(m, 0<=x[1:2]<=2.0*pi)
register(m, :my_fun, 2, my_fun; autodiff = true)
@NLobjective(m, Min, my_fun(x...))
optimize!(m)
# retrieve the objective value, corresponding x values and the status
println(JuMP.value.(x))
println(JuMP.objective_value(m))
println(JuMP.termination_status(m))
Используйте вместо этого
function obj(x::Vector{T}) where {T}
println(x)
x1 = x[1]
x2 = x[2]
eye= Matrix{T}(I, 4, 4)
obj_val = tr(eye-kron(mat_fun(x1),mat_fun(x2)))
println(obj_val)
return obj_val
end
function mat_fun(var::T) where {T}
eye= Matrix{T}(I, 2, 2)
eye[2,2]=var
return eye
end
По сути, везде, где вы видите Float64
, замените его типом входящего аргумента.
Вы можете использовать T вместо Real