diff --git a/lib/OptimizationBBO/Project.toml b/lib/OptimizationBBO/Project.toml index 7977ee438..8deb4617f 100644 --- a/lib/OptimizationBBO/Project.toml +++ b/lib/OptimizationBBO/Project.toml @@ -1,7 +1,7 @@ name = "OptimizationBBO" uuid = "3e6eede4-6085-4f62-9a71-46d9bc1eb92b" authors = ["Vaibhav Dixit and contributors"] -version = "0.4.0" +version = "0.4.1" [deps] BlackBoxOptim = "a134a8b2-14d6-55f6-9291-3336d3ab0209" diff --git a/lib/OptimizationBBO/src/OptimizationBBO.jl b/lib/OptimizationBBO/src/OptimizationBBO.jl index f0d3d6f33..0e203de62 100644 --- a/lib/OptimizationBBO/src/OptimizationBBO.jl +++ b/lib/OptimizationBBO/src/OptimizationBBO.jl @@ -83,6 +83,13 @@ function __map_optimizer_args(prob::Optimization.OptimizationCache, opt::BBO; return mapped_args end +# single objective +map_objective(obj) = obj +# multiobjective +function map_objective(obj::BlackBoxOptim.IndexedTupleFitness) + obj.orig +end + function SciMLBase.__solve(cache::Optimization.OptimizationCache{ F, RC, @@ -109,20 +116,19 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ P, C } - local x, cur, state - function _cb(trace) if cache.callback === Optimization.DEFAULT_CALLBACK cb_call = false else n_steps = BlackBoxOptim.num_steps(trace) curr_u = decompose_trace(trace, cache.progress) + objective = map_objective(BlackBoxOptim.best_fitness(trace)) opt_state = Optimization.OptimizationState(; iter = n_steps, u = curr_u, - objective = x[1], + objective, original = trace) - cb_call = cache.callback(opt_state, x...) + cb_call = cache.callback(opt_state, objective) end if !(cb_call isa Bool) @@ -139,13 +145,7 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ maxtime = Optimization._check_and_convert_maxtime(cache.solver_args.maxtime) _loss = function (θ) - if isa(cache.f, MultiObjectiveOptimizationFunction) - x = (cache.f(θ, cache.p),) - return x[1] - else - x = cache.f(θ, cache.p) - return first(x) - end + cache.f(θ, cache.p) end opt_args = __map_optimizer_args(cache, cache.opt; @@ -157,8 +157,6 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ opt_setup = BlackBoxOptim.bbsetup(_loss; opt_args...) - t0 = time() - if isnothing(cache.u0) opt_res = BlackBoxOptim.bboptimize(opt_setup) else @@ -170,13 +168,11 @@ function SciMLBase.__solve(cache::Optimization.OptimizationCache{ Base.@logmsg(Base.LogLevel(-1), "", progress=1, _id=:OptimizationBBO) end - t1 = time() - # Use the improved convert function opt_ret = Optimization.deduce_retcode(opt_res.stop_reason) stats = Optimization.OptimizationStats(; iterations = opt_res.iterations, - time = t1 - t0, + time = opt_res.elapsed_time, fevals = opt_res.f_calls) SciMLBase.build_solution(cache, cache.opt, BlackBoxOptim.best_candidate(opt_res), diff --git a/lib/OptimizationBBO/test/runtests.jl b/lib/OptimizationBBO/test/runtests.jl index e5215fee8..1295465fc 100644 --- a/lib/OptimizationBBO/test/runtests.jl +++ b/lib/OptimizationBBO/test/runtests.jl @@ -26,13 +26,20 @@ using Test @test 10 * sol.objective < l1 fitness_progress_history = [] + fitness_progress_history_orig = [] + loss_history = [] function cb(state, fitness) - push!(fitness_progress_history, [state.u, fitness]) + push!(fitness_progress_history, state.objective) + push!(fitness_progress_history_orig, BlackBoxOptim.best_fitness(state.original)) + push!(loss_history, fitness) return false end sol = solve(prob, BBO_adaptive_de_rand_1_bin_radiuslimited(), callback = cb) # println(fitness_progress_history) @test !isempty(fitness_progress_history) + fp1 = fitness_progress_history[1] + fp2 = fitness_progress_history_orig[1] + @test fp2 == fp1 == loss_history[1] @test_logs begin (Base.LogLevel(-1), "loss: 0.0") @@ -77,6 +84,39 @@ using Test @test sol_1.objective[2]≈1.7763568e-15 atol=1e-3 end + @testset "Sphere and Rastrigin Functions with callback" begin + function multi_obj_func_1(x, p) + f1 = sum(x .^ 2) # Sphere function + f2 = sum(x .^ 2 .- 10 .* cos.(2π .* x) .+ 10) # Rastrigin function + return (f1, f2) + end + + fitness_progress_history = [] + fitness_progress_history_orig = [] + function cb(state, fitness) + push!(fitness_progress_history, state.objective) + push!(fitness_progress_history_orig, + BlackBoxOptim.best_fitness(state.original)) + return false + end + + mof_1 = MultiObjectiveOptimizationFunction(multi_obj_func_1) + prob_1 = Optimization.OptimizationProblem(mof_1, u0; lb = lb, ub = ub) + sol_1 = solve(prob_1, opt, NumDimensions = 2, + FitnessScheme = ParetoFitnessScheme{2}(is_minimizing = true), + callback = cb) + + fp1 = fitness_progress_history[1] + fp2 = fitness_progress_history_orig[1] + @test fp2.orig == fp1 + @test length(fp1) == 2 + + @test sol_1 ≠ nothing + println("Solution for Sphere and Rastrigin: ", sol_1) + @test sol_1.objective[1]≈6.9905986e-18 atol=1e-3 + @test sol_1.objective[2]≈1.7763568e-15 atol=1e-3 + end + # Test 2: Rosenbrock and Ackley Functions @testset "Rosenbrock and Ackley Functions" begin function multi_obj_func_2(x, p) diff --git a/lib/OptimizationMOI/Project.toml b/lib/OptimizationMOI/Project.toml index 18ae43ec1..5a5031c82 100644 --- a/lib/OptimizationMOI/Project.toml +++ b/lib/OptimizationMOI/Project.toml @@ -1,7 +1,7 @@ name = "OptimizationMOI" uuid = "fd9f6733-72f4-499f-8506-86b2bdd0dea1" authors = ["Vaibhav Dixit and contributors"] -version = "0.5.2" +version = "0.5.3" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/lib/OptimizationMOI/src/nlp.jl b/lib/OptimizationMOI/src/nlp.jl index 24301e29a..099a8c70a 100644 --- a/lib/OptimizationMOI/src/nlp.jl +++ b/lib/OptimizationMOI/src/nlp.jl @@ -559,7 +559,19 @@ function SciMLBase.__solve(cache::MOIOptimizationNLPCache) minimum = NaN opt_ret = SciMLBase.ReturnCode.Default end - stats = Optimization.OptimizationStats() + + # check if the solver supports BarrierIterations + iterations = try + MOI.get(opt_setup, MOI.BarrierIterations()) + catch e + if !(e isa MOI.GetAttributeNotAllowed) + rethrow(e) + end + 0 + end + + stats = Optimization.OptimizationStats(; time = MOI.get(opt_setup, MOI.SolveTimeSec()), + iterations) return SciMLBase.build_solution(cache, cache.opt, minimizer, diff --git a/lib/OptimizationMOI/test/runtests.jl b/lib/OptimizationMOI/test/runtests.jl index f1002b3f0..649facb01 100644 --- a/lib/OptimizationMOI/test/runtests.jl +++ b/lib/OptimizationMOI/test/runtests.jl @@ -77,7 +77,7 @@ end # cache interface cache = init(prob, Ipopt.Optimizer()) sol = solve!(cache) - @test 10 * sol.minimum < l1 + @test 10 * sol.objective < l1 optprob = OptimizationFunction(rosenbrock, Optimization.AutoZygote()) prob = OptimizationProblem(optprob, x0, _p; sense = Optimization.MinSense) @@ -88,16 +88,30 @@ end sol = solve(prob, opt) #test reuse of optimizer @test 10 * sol.objective < l1 + # test stats + @test sol.stats.time > 0 + @test sol.stats.iterations > 0 + sol = solve(prob, OptimizationMOI.MOI.OptimizerWithAttributes(Ipopt.Optimizer, "max_cpu_time" => 60.0)) @test 10 * sol.objective < l1 + # test stats with AbstractBridgeOptimizer + sol = solve(prob, + OptimizationMOI.MOI.OptimizerWithAttributes(Ipopt.Optimizer, + "max_cpu_time" => 60.0, "max_iter" => 5)) + + @test 60 > sol.stats.time > 0 + @test sol.stats.iterations == 5 + sol = solve(prob, OptimizationMOI.MOI.OptimizerWithAttributes(NLopt.Optimizer, "algorithm" => :LN_BOBYQA)) @test 10 * sol.objective < l1 + @test sol.stats.time > 0 + sol = solve(prob, OptimizationMOI.MOI.OptimizerWithAttributes(NLopt.Optimizer, "algorithm" => :LD_LBFGS)) @@ -161,6 +175,7 @@ end res = solve(optprob, minlp_solver) @test res.u == [0.0, 0.0, 1.0, 0.0] @test res.objective == -4.0 + @test res.stats.time > 0 end @testset "Integer Domain" begin diff --git a/lib/OptimizationNOMAD/Project.toml b/lib/OptimizationNOMAD/Project.toml index 86fe4f839..17e16f1fe 100644 --- a/lib/OptimizationNOMAD/Project.toml +++ b/lib/OptimizationNOMAD/Project.toml @@ -1,7 +1,7 @@ name = "OptimizationNOMAD" uuid = "2cab0595-8222-4775-b714-9828e6a9e01b" authors = ["Vaibhav Dixit and contributors"] -version = "0.3.0" +version = "0.3.1" [deps] Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba" @@ -10,7 +10,7 @@ Reexport = "189a3867-3050-52da-a836-e630ba90ab69" [compat] julia = "1" -NOMAD = "2" +NOMAD = "2.4.1" Optimization = "4" Reexport = "1.2"