Optimization.jl
Optimization.jl copied to clipboard
Support for scalar inputs
There is currently no (little? Haven't tried all the solvers) support for scalar inputs, e.g.
julia> f = (u, p) -> u^2; u0 = 0.0; prob = OptimizationProblem(f, u0);
julia> optf = OptimizationFunction(f, Optimization.AutoForwardDiff());
julia> prob=OptimizationProblem(optf,u0,p);
julia> solve(prob, BFGS())
ERROR: MethodError: no method matching fill!(::Float64, ::Float64)
Closest candidates are:
fill!(::Union{LinearAlgebra.Hermitian{T, S}, LinearAlgebra.Symmetric{T, S}} where {T, S}, ::Any) at C:\Users\licer\AppData\Local\Programs\Julia-1.8.0-rc1\share\julia\stdlib\v1.8\LinearAlgebra\src\symmetric.jl:305
fill!(::Union{LinearAlgebra.Bidiagonal, LinearAlgebra.Diagonal, LinearAlgebra.SymTridiagonal, LinearAlgebra.Tridiagonal}, ::Any) at C:\Users\licer\AppData\Local\Programs\Julia-1.8.0-rc1\share\julia\stdlib\v1.8\LinearAlgebra\src\special.jl:365
fill!(::Union{SparseArrays.AbstractSparseMatrixCSC, SparseArrays.SparseVector}, ::Any) at C:\Users\licer\AppData\Local\Programs\Julia-1.8.0-rc1\share\julia\stdlib\v1.8\SparseArrays\src\sparsevector.jl:2099
...
Stacktrace:
[1] x_of_nans(x::Float64, Tf::Type{Float64})
@ NLSolversBase C:\Users\licer\.julia\packages\NLSolversBase\cfJrN\src\NLSolversBase.jl:60
[2] alloc_DF(x::Float64, F::Float64)
@ NLSolversBase C:\Users\licer\.julia\packages\NLSolversBase\cfJrN\src\objective_types\abstract.jl:22
[3] ___solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, var"#19#20", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Float64, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::BFGS{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Nothing, Nothing, Flat}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}; callback::Function, maxiters::Nothing, maxtime::Nothing, abstol::Nothing, reltol::Nothing, progress::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ OptimizationOptimJL C:\Users\licer\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:137
[4] ___solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, var"#19#20", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Float64, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::BFGS{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Nothing, Nothing, Flat}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}})
@ OptimizationOptimJL C:\Users\licer\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:59
[5] __solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, var"#19#20", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Float64, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::BFGS{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Nothing, Nothing, Flat}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ OptimizationOptimJL C:\Users\licer\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:56
[6] __solve(prob::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, var"#19#20", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Float64, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, opt::BFGS{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Nothing, Nothing, Flat}, data::Base.Iterators.Cycle{Tuple{Optimization.NullData}}) (repeats 2 times)
@ OptimizationOptimJL C:\Users\licer\.julia\packages\OptimizationOptimJL\fdrJg\src\OptimizationOptimJL.jl:40
[7] solve(::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, var"#19#20", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Float64, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::BFGS{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Nothing, Nothing, Flat}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ SciMLBase C:\Users\licer\.julia\packages\SciMLBase\IJbT7\src\solve.jl:71
[8] solve(::OptimizationProblem{true, OptimizationFunction{true, Optimization.AutoForwardDiff{nothing}, var"#19#20", Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Float64, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::BFGS{LineSearches.InitialStatic{Float64}, LineSearches.HagerZhang{Float64, Base.RefValue{Bool}}, Nothing, Nothing, Flat})
@ SciMLBase C:\Users\licer\.julia\packages\SciMLBase\IJbT7\src\solve.jl:70
[9] top-level scope
@ REPL[49]:1
An obvious solution is to simply put everything into a 1-vector:
julia> f = (u, p) -> u[1]^2; u0 = [0.0]; prob = OptimizationProblem(f, u0);
julia> optf = OptimizationFunction(f, Optimization.AutoForwardDiff());
julia> prob=OptimizationProblem(optf,u0,p);
julia> solve(prob, BFGS())
u: 1-element Vector{Float64}:
0.0
It might be nice to somehow do this automatically, for example defining a method for ::Number
and taking u0 =[u0]
and _f = (u, p) -> f(u[1], p)
. I don't imagine it's so simple to support scalar inputs directly though since most of the packages seem to require vectors.
We do this in Sundials, so we could do it here. It can be done in the instantiate_function
part where u0
can be checked if it's scalar, and then a trait for allows_scalar_state(alg)
can be checked, and if it's not allowed the wrapping can be done automatically (with unwrapping done on the solution object).
This doesn't seem to have enough usecase in my opinion and would add unnecessary complexity to code. Closing as won't fix.