diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 1a5824453..e0a9ec268 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -19,6 +19,7 @@ jobs: matrix: group: - Core + - OptimizationBase - OptimizationAuglag - OptimizationBBO - OptimizationCMAEvolutionStrategy @@ -45,7 +46,7 @@ jobs: - OptimizationPolyalgorithms - OptimizationNLPModels version: - - '1' + - '1.11' - 'lts' steps: - uses: actions/checkout@v4 @@ -57,10 +58,10 @@ jobs: cache-name: cache-artifacts with: path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + key: ${{ runner.os }}-test-${{ matrix.version }}-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- + ${{ runner.os }}-test-${{ matrix.version }}-${{ env.cache-name }}- + ${{ runner.os }}-test-${{ matrix.version }}- ${{ runner.os }}- - uses: julia-actions/julia-buildpkg@v1 - if: ${{ matrix.group == 'OptimizationQuadDIRECT' }} @@ -70,7 +71,7 @@ jobs: GROUP: ${{ matrix.group }} - uses: julia-actions/julia-processcoverage@v1 with: - directories: src,lib/OptimizationBBO/src,lib/OptimizationCMAEvolutionStrategy/src,lib/OptimizationEvolutionary/src,lib/OptimizationGCMAES/src,lib/OptimizationIpopt/src,lib/OptimizationMadNLP/src,lib/OptimizationManopt/src,lib/OptimizationMOI/src,lib/OptimizationMetaheuristics/src,lib/OptimizationMultistartOptimization/src,lib/OptimizationNLopt/src,lib/OptimizationNOMAD/src,lib/OptimizationOptimJL/src,lib/OptimizationOptimisers/src,lib/OptimizationPolyalgorithms/src,lib/OptimizationQuadDIRECT/src,lib/OptimizationSpeedMapping/src + directories: src,lib/OptimizationBase/src,lib/OptimizationBBO/src,lib/OptimizationCMAEvolutionStrategy/src,lib/OptimizationEvolutionary/src,lib/OptimizationGCMAES/src,lib/OptimizationIpopt/src,lib/OptimizationMadNLP/src,lib/OptimizationManopt/src,lib/OptimizationMOI/src,lib/OptimizationMetaheuristics/src,lib/OptimizationMultistartOptimization/src,lib/OptimizationNLopt/src,lib/OptimizationNOMAD/src,lib/OptimizationOptimJL/src,lib/OptimizationOptimisers/src,lib/OptimizationPolyalgorithms/src,lib/OptimizationQuadDIRECT/src,lib/OptimizationSpeedMapping/src - uses: codecov/codecov-action@v5 with: - file: lcov.info + files: lcov.info diff --git a/Project.toml b/Project.toml index 00af684ea..7bc2875ba 100644 --- a/Project.toml +++ b/Project.toml @@ -49,7 +49,7 @@ ModelingToolkit = "10.23" Mooncake = "0.4.138" Optim = ">= 1.4.1" Optimisers = ">= 0.2.5" -OptimizationBase = "3" +OptimizationBase = "4" OptimizationLBFGSB = "1" OptimizationMOI = "0.5" OptimizationOptimJL = "0.4" diff --git a/lib/OptimizationBase/Project.toml b/lib/OptimizationBase/Project.toml index b71b86852..4576abbf6 100644 --- a/lib/OptimizationBase/Project.toml +++ b/lib/OptimizationBase/Project.toml @@ -1,7 +1,7 @@ name = "OptimizationBase" uuid = "bca83a33-5cc9-4baa-983d-23429ab6bcbb" authors = ["Vaibhav Dixit and contributors"] -version = "3.3.1" +version = "4.0.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" @@ -55,7 +55,7 @@ ModelingToolkit = "10.23" PDMats = "0.11" Reexport = "1.2" ReverseDiff = "1.14" -SciMLBase = "2.104" +SciMLBase = "2.122" SparseConnectivityTracer = "0.6, 1" SparseMatrixColorings = "0.4" SymbolicAnalysis = "0.3" diff --git a/lib/OptimizationBase/src/OptimizationBase.jl b/lib/OptimizationBase/src/OptimizationBase.jl index 4849f74ae..230f5bca8 100644 --- a/lib/OptimizationBase/src/OptimizationBase.jl +++ b/lib/OptimizationBase/src/OptimizationBase.jl @@ -15,15 +15,10 @@ import SciMLBase: solve, init, solve!, __init, __solve, requireshessian, requiresconsjac, requiresconshess -supports_opt_cache_interface(alg) = false -@static if !hasmethod(SciMLBase.__solve, Tuple{OptimizationProblem, SciMLBase.AbstractOptimizationAlgorithm}) - include("solve.jl") -end - export ObjSense, MaxSense, MinSense export allowsbounds, requiresbounds, allowsconstraints, requiresconstraints, allowscallback, requiresgradient, requireshessian, - requiresconsjac, requiresconshess, supports_opt_cache_interface + requiresconsjac, requiresconshess using FastClosures @@ -36,6 +31,7 @@ const DEFAULT_DATA = Iterators.cycle((NullData(),)) Base.iterate(::NullData, i = 1) = nothing Base.length(::NullData) = 0 +include("solve.jl") include("adtypes.jl") include("symify.jl") include("cache.jl") diff --git a/lib/OptimizationBase/src/cache.jl b/lib/OptimizationBase/src/cache.jl index 9454e4f03..ec633283f 100644 --- a/lib/OptimizationBase/src/cache.jl +++ b/lib/OptimizationBase/src/cache.jl @@ -5,8 +5,11 @@ struct AnalysisResults{O, C} constraints::C end -struct OptimizationCache{F, RC, LB, UB, LC, UC, S, O, P, C, M} <: +struct OptimizationCache{ + O, IIP, F <: SciMLBase.AbstractOptimizationFunction{IIP}, + RC, LB, UB, LC, UC, S, P, C, M} <: SciMLBase.AbstractOptimizationCache + opt::O f::F reinit_cache::RC lb::LB @@ -14,7 +17,6 @@ struct OptimizationCache{F, RC, LB, UB, LC, UC, S, O, P, C, M} <: lcons::LC ucons::UC sense::S - opt::O progress::P callback::C manifold::M @@ -46,13 +48,13 @@ function OptimizationCache(prob::SciMLBase.OptimizationProblem, opt; prob.f.adtype isa AutoZygote) && (SciMLBase.requireshessian(opt) || SciMLBase.requiresconshess(opt) || SciMLBase.requireslagh(opt)) - @warn "The selected optimization algorithm requires second order derivatives, but `SecondOrder` ADtype was not provided. - So a `SecondOrder` with $(prob.f.adtype) for both inner and outer will be created, this can be suboptimal and not work in some cases so + @warn "The selected optimization algorithm requires second order derivatives, but `SecondOrder` ADtype was not provided. + So a `SecondOrder` with $(prob.f.adtype) for both inner and outer will be created, this can be suboptimal and not work in some cases so an explicit `SecondOrder` ADtype is recommended." elseif prob.f.adtype isa AutoZygote && (SciMLBase.requiresconshess(opt) || SciMLBase.requireslagh(opt) || SciMLBase.requireshessian(opt)) - @warn "The selected optimization algorithm requires second order derivatives, but `AutoZygote` ADtype was provided. + @warn "The selected optimization algorithm requires second order derivatives, but `AutoZygote` ADtype was provided. So a `SecondOrder` with `AutoZygote` for inner and `AutoForwardDiff` for outer will be created, for choosing another pair an explicit `SecondOrder` ADtype is recommended." end @@ -71,11 +73,10 @@ function OptimizationCache(prob::SciMLBase.OptimizationProblem, opt; cons_res = nothing end - return OptimizationCache(f, reinit_cache_passedon, prob.lb, prob.ub, prob.lcons, + return OptimizationCache(opt, f, reinit_cache_passedon, prob.lb, prob.ub, prob.lcons, prob.ucons, prob.sense, - opt, progress, callback, manifold, AnalysisResults(obj_res, cons_res), - merge((; maxiters, maxtime, abstol, reltol), - NamedTuple(kwargs))) + progress, callback, manifold, AnalysisResults(obj_res, cons_res), + merge((; maxiters, maxtime, abstol, reltol), NamedTuple(kwargs))) end function SciMLBase.__init(prob::SciMLBase.OptimizationProblem, opt; @@ -91,6 +92,8 @@ function SciMLBase.__init(prob::SciMLBase.OptimizationProblem, opt; kwargs...) end +SciMLBase.isinplace(::OptimizationCache{o, iip}) where {o, iip} = iip + # Wrapper for fields that may change in `reinit!(cache)` of a cache. mutable struct ReInitCache{uType, P} u0::uType diff --git a/lib/OptimizationBase/src/solve.jl b/lib/OptimizationBase/src/solve.jl index 273c32e38..cd1a80607 100644 --- a/lib/OptimizationBase/src/solve.jl +++ b/lib/OptimizationBase/src/solve.jl @@ -92,7 +92,7 @@ from NLopt for an example. The common local optimizer arguments are: """ function solve(prob::SciMLBase.OptimizationProblem, alg, args...; kwargs...)::SciMLBase.AbstractOptimizationSolution - if SciMLBase.supports_opt_cache_interface(alg) + if SciMLBase.has_init(alg) solve!(init(prob, alg, args...; kwargs...)) else if prob.u0 !== nothing && !isconcretetype(eltype(prob.u0)) diff --git a/lib/OptimizationManopt/test/runtests.jl b/lib/OptimizationManopt/test/runtests.jl index 3a1e276b7..9e22be677 100644 --- a/lib/OptimizationManopt/test/runtests.jl +++ b/lib/OptimizationManopt/test/runtests.jl @@ -166,7 +166,7 @@ R2 = Euclidean(2) opt = OptimizationManopt.TrustRegionsOptimizer() - #TODO: This autodiff currently provides a Hessian that seem to not procide a Hessian + #TODO: This autodiff currently provides a Hessian that seem to not provide a Hessian # TR Fails but also AD before that warns. So it passes _some_ hessian but a wrong one, even in format optprob = OptimizationFunction(rosenbrock, AutoForwardDiff()) prob = OptimizationProblem(optprob, x0, p; manifold = R2) @@ -187,4 +187,4 @@ R2 = Euclidean(2) #TODO: What is this? @test_throws SciMLBase.IncompatibleOptimizerError OptimizationBase.solve(prob_cons, opt) end -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index 2e1b7f39f..193d2c51b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,16 +14,19 @@ function activate_subpkg_env(subpkg) Pkg.instantiate() end -if GROUP == "All" || GROUP == "Core" - dev_subpkg("OptimizationOptimJL") - dev_subpkg("OptimizationOptimisers") - dev_subpkg("OptimizationMOI") -elseif GROUP == "GPU" || GROUP == "OptimizationPolyalgorithms" - dev_subpkg("OptimizationOptimJL") - dev_subpkg("OptimizationOptimisers") -elseif GROUP == "OptimizationNLPModels" - dev_subpkg("OptimizationOptimJL") - dev_subpkg("OptimizationMOI") +if VERSION < v"1.11" + if GROUP == "All" || GROUP == "Core" + dev_subpkg("OptimizationBase") + dev_subpkg("OptimizationOptimJL") + dev_subpkg("OptimizationOptimisers") + dev_subpkg("OptimizationMOI") + elseif GROUP == "GPU" || GROUP == "OptimizationPolyalgorithms" + dev_subpkg("OptimizationOptimJL") + dev_subpkg("OptimizationOptimisers") + elseif GROUP == "OptimizationNLPModels" + dev_subpkg("OptimizationOptimJL") + dev_subpkg("OptimizationMOI") + end end @time begin