Optimization.jl icon indicating copy to clipboard operation
Optimization.jl copied to clipboard

Support for scalar inputs

Open DanielVandH opened this issue 1 year ago • 1 comments

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.

DanielVandH avatar Jul 11 '22 15:07 DanielVandH

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).

ChrisRackauckas avatar Jul 12 '22 01:07 ChrisRackauckas

This doesn't seem to have enough usecase in my opinion and would add unnecessary complexity to code. Closing as won't fix.

Vaibhavdixit02 avatar Feb 23 '24 20:02 Vaibhavdixit02