SciML / Optimization.jl

Mathematical Optimization in Julia. Local, global, gradient-based and derivative-free. Linear, Quadratic, Convex, Mixed-Integer, and Nonlinear Optimization in one simple, fast, and differentiable interface.
https://docs.sciml.ai/Optimization/stable/
MIT License
711 stars 79 forks source link

`solve` not type-inferrable #556

Open sethaxen opened 1 year ago

sethaxen commented 1 year ago

Before v3.13.1, which implemented init, calling solve(prob, optimizer) was type-inferrable, but with v3.13.1, it became non-type-inferrable.

julia> using Optimization, OptimizationOptimJL, Test

julia> f(x, p) = sum(abs2, x)/2;

julia> fun = OptimizationFunction(f);

julia> prob = OptimizationProblem(fun, randn(3));

julia> optimizer = NelderMead();

julia> @inferred solve(prob, optimizer)

on v3.13.0:

u: 3-element Vector{Float64}:
 -9.550802798460414e-5
  8.410929885505606e-5
  3.509039964423626e-5

on v3.13.1 and master:

ERROR: return type SciMLBase.OptimizationSolution{Float64, 1, Vector{Float64}, OptimizationOptimJL.OptimJLOptimizationCache{OptimizationFunction{true, SciMLBase.NoAD, typeof(f), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Optimization.ReInitCache{Vector{Float64}, SciMLBase.NullParameters}, Nothing, Nothing, Nothing, Nothing, Nothing, NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}, Base.Iterators.Cycle{Tuple{Optimization.NullData}}, Bool, OptimizationOptimJL.var"#5#7"}, NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}, Float64, Optim.MultivariateOptimizationResults{NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}, Vector{Float64}, Float64, Float64, Vector{OptimizationState{Float64, NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}}}, Bool, NamedTuple{(:f_limit_reached, :g_limit_reached, :h_limit_reached, :time_limit, :callback, :f_increased), NTuple{6, Bool}}}, Float64, Nothing} does not match inferred return type SciMLBase.OptimizationSolution{_A, _B, _C, OptimizationOptimJL.OptimJLOptimizationCache{OptimizationFunction{true, SciMLBase.NoAD, typeof(f), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Optimization.ReInitCache{Vector{Float64}, SciMLBase.NullParameters}, Nothing, Nothing, Nothing, Nothing, Nothing, NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}, Base.Iterators.Cycle{Tuple{Optimization.NullData}}, Bool, OptimizationOptimJL.var"#5#7"}, _D, _E, _F, Float64, Nothing} where {_A, _B, _C, _D, _E, _F}
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] top-level scope
   @ REPL[8]:1
sethaxen commented 1 year ago

@ValentinKaisermayer I think this type-noninferrability may have been introduced in #406 . Is this something that can be fixed?

Vaibhavdixit02 commented 1 year ago

@sethaxen thanks for the issue. I plan to prioritize this, have been stuck at getting the CI to pass on #553 hence the delay.

Vaibhavdixit02 commented 1 year ago

We had an update to the caching after #406 in #536 also. Did you git bisect to find #406 as the point where it started showing up?

sethaxen commented 1 year ago

git bisect starting with c67d6301b128d567ea9233481f0d86b8342869fe as a good commit terminates with #406, but the above code fails then with a different error:

julia> @inferred solve(prob, optimizer)
ERROR: MethodError: Cannot `convert` an object of type Nothing to an object of type SciMLBase.AbstractOptimizationCache

Closest candidates are:
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:64

Stacktrace:
 [1] init(::OptimizationProblem{true, OptimizationFunction{true, SciMLBase.NoAD, typeof(f), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, SciMLBase.NullParameters, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ SciMLBase ~/.julia/packages/SciMLBase/s9wrq/src/solve.jl:149
 [2] init(::OptimizationProblem{true, OptimizationFunction{true, SciMLBase.NoAD, typeof(f), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, SciMLBase.NullParameters, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters})
   @ SciMLBase ~/.julia/packages/SciMLBase/s9wrq/src/solve.jl:146
 [3] solve(::OptimizationProblem{true, OptimizationFunction{true, SciMLBase.NoAD, typeof(f), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, SciMLBase.NullParameters, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ SciMLBase ~/.julia/packages/SciMLBase/s9wrq/src/solve.jl:83
 [4] solve(::OptimizationProblem{true, OptimizationFunction{true, SciMLBase.NoAD, typeof(f), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED_NO_TIME), Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}, Vector{Float64}, SciMLBase.NullParameters, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, ::NelderMead{Optim.AffineSimplexer, Optim.AdaptiveParameters})
   @ SciMLBase ~/.julia/packages/SciMLBase/s9wrq/src/solve.jl:80
 [5] top-level scope
   @ REPL[8]:1
Vaibhavdixit02 commented 1 year ago

I made some attempts on this but haven't been successful yet. The parametric types in OptimizationSolution for some fields are not inferred which doesn't make sense immediately.