From 5ed8cd9dc3f71c984440874d9de773b6fc28a3f7 Mon Sep 17 00:00:00 2001 From: Robert Feldt Date: Sun, 12 Apr 2020 11:34:23 +0200 Subject: [PATCH] fixed shutdown methods and added test shutting down optimization from callback function --- Manifest.toml | 259 +++++++++++++++++++++++++++++++ src/opt_controller.jl | 16 +- src/optimizer.jl | 4 +- test/test_toplevel_bboptimize.jl | 13 ++ 4 files changed, 287 insertions(+), 5 deletions(-) create mode 100644 Manifest.toml diff --git a/Manifest.toml b/Manifest.toml new file mode 100644 index 00000000..f9a8684f --- /dev/null +++ b/Manifest.toml @@ -0,0 +1,259 @@ +# This file is machine-generated - editing it directly is not advised + +[[Arpack]] +deps = ["Arpack_jll", "Libdl", "LinearAlgebra"] +git-tree-sha1 = "2ff92b71ba1747c5fdd541f8fc87736d82f40ec9" +uuid = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97" +version = "0.4.0" + +[[Arpack_jll]] +deps = ["Libdl", "OpenBLAS_jll", "Pkg"] +git-tree-sha1 = "e214a9b9bd1b4e1b4f15b22c0994862b66af7ff7" +uuid = "68821587-b530-5797-8361-c406ea357684" +version = "3.5.0+3" + +[[Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[CPUTime]] +git-tree-sha1 = "2dcc50ea6a0a1ef6440d6eecd0fe3813e5671f45" +uuid = "a9c8d775-2e2e-55fc-8582-045d282d599e" +version = "1.0.0" + +[[Compat]] +deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] +git-tree-sha1 = "0198d18b28c093bef39872a22f1a897218a925f5" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "3.8.0" + +[[CompilerSupportLibraries_jll]] +deps = ["Libdl", "Pkg"] +git-tree-sha1 = "7c4f882c41faa72118841185afc58a2eb00ef612" +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "0.3.3+0" + +[[DataAPI]] +git-tree-sha1 = "674b67f344687a88310213ddfa8a2b3c76cc4252" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.1.0" + +[[DataStructures]] +deps = ["InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "73eb18320fe3ba58790c8b8f6f89420f0a622773" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.17.11" + +[[Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[DelimitedFiles]] +deps = ["Mmap"] +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" + +[[Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[Distributions]] +deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns"] +git-tree-sha1 = "c4ed10355637fcb0725dc6a27060f74df24f13cd" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.23.2" + +[[FillArrays]] +deps = ["LinearAlgebra", "Random", "SparseArrays"] +git-tree-sha1 = "51cc2f9bc4eb9c6c0e81ec2f779d1085583cc956" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "0.8.7" + +[[HTTP]] +deps = ["Base64", "Dates", "IniFile", "MbedTLS", "Sockets"] +git-tree-sha1 = "cd60d9a575d3b70c026d7e714212fd4ecf86b4bb" +uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" +version = "0.8.13" + +[[IniFile]] +deps = ["Test"] +git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8" +uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f" +version = "0.5.0" + +[[InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "b34d7cef7b337321e97d22242c3c2b91f476748e" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.0" + +[[LibGit2]] +deps = ["Printf"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[LinearAlgebra]] +deps = ["Libdl"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"] +git-tree-sha1 = "a9e2221f06b42f56052f43ad7edecb01d0ef5ab4" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.0.1" + +[[MbedTLS_jll]] +deps = ["Libdl", "Pkg"] +git-tree-sha1 = "066a4467008745eed36dad973ceb66405785a621" +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.16.0+1" + +[[Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "de0a5ce9e5289f27df672ffabef4d1e5861247d5" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "0.4.3" + +[[Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[OpenBLAS_jll]] +deps = ["CompilerSupportLibraries_jll", "Libdl", "Pkg"] +git-tree-sha1 = "2ee3e636e94b9fd95fa8364d5cba2e20dae16609" +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.9+2" + +[[OpenSpecFun_jll]] +deps = ["CompilerSupportLibraries_jll", "Libdl", "Pkg"] +git-tree-sha1 = "d51c416559217d974a1113522d5919235ae67a87" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.3+3" + +[[OrderedCollections]] +deps = ["Random", "Serialization", "Test"] +git-tree-sha1 = "c4c13474d23c60d20a67b217f1d7f22a40edf8f1" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.1.0" + +[[PDMats]] +deps = ["Arpack", "LinearAlgebra", "SparseArrays", "SuiteSparse", "Test"] +git-tree-sha1 = "2fc6f50ddd959e462f0a2dbc802ddf2a539c6e35" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.9.12" + +[[Parsers]] +deps = ["Dates", "Test"] +git-tree-sha1 = "75d07cb840c300084634b4991761886d0d762724" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "1.0.1" + +[[Pkg]] +deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" + +[[Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "dc84e810393cfc6294248c9032a9cdacc14a3db4" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.3.1" + +[[REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[Random]] +deps = ["Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "86c5647b565873641538d8f812c04e4c9dbeb370" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.6.1" + +[[Rmath_jll]] +deps = ["Libdl", "Pkg"] +git-tree-sha1 = "1660f8fefbf5ab9c67560513131d4e933012fc4b" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.2.2+0" + +[[SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" + +[[Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + +[[Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[SortingAlgorithms]] +deps = ["DataStructures", "Random", "Test"] +git-tree-sha1 = "03f5898c9959f8115e30bc7226ada7d0df554ddd" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "0.3.1" + +[[SparseArrays]] +deps = ["LinearAlgebra", "Random"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[SpatialIndexing]] +deps = ["Printf", "Random", "Test"] +git-tree-sha1 = "7bc6fc5c363aae476ec2c8bc527aef104b90c779" +uuid = "d4ead438-fe20-5cc5-a293-4fd39a41b74c" +version = "0.1.2" + +[[SpecialFunctions]] +deps = ["OpenSpecFun_jll"] +git-tree-sha1 = "e19b98acb182567bcb7b75bb5d9eedf3a3b5ec6c" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "0.10.0" + +[[Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[StatsBase]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics"] +git-tree-sha1 = "a6102b1f364befdb05746f386b67c6b7e3262c45" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.33.0" + +[[StatsFuns]] +deps = ["Rmath", "SpecialFunctions"] +git-tree-sha1 = "f290ddd5fdedeadd10e961eb3f4d3340f09d030a" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "0.9.4" + +[[SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[Test]] +deps = ["Distributed", "InteractiveUtils", "Logging", "Random"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" diff --git a/src/opt_controller.jl b/src/opt_controller.jl index f83cfd2d..f26a860f 100644 --- a/src/opt_controller.jl +++ b/src/opt_controller.jl @@ -42,7 +42,7 @@ mutable struct OptRunController{O<:Optimizer, E<:Evaluator} max_steps_without_fevals::Int # stop optimization if no func evals in this many steps (indicates a converged/degenerate search) max_steps_without_progress::Int # stop optimization if no improvement in this many steps (indicates a converged/degenerate search) max_time::Float64 # maximal time, 0 to ignore - + min_delta_fitness_tol::Float64 # minimal difference between current best fitness and second-best one fitness_tol::Float64 # minimal difference between current best fitness and the known optmimum @@ -61,6 +61,7 @@ mutable struct OptRunController{O<:Optimizer, E<:Evaluator} last_callback_time::Float64 # last time callback function was called stop_reason::String # the reason for algorithm termination, empty if it's not terminated + shutdown::Bool # shutdown optimization run iff true end """ @@ -90,7 +91,7 @@ function OptRunController(optimizer::O, evaluator::E, params) where {O<:Optimize :CallbackFunction, :CallbackInterval, :MaxSteps, :MaxFuncEvals, :MaxNumStepsWithoutFuncEvals, :MaxStepsWithoutProgress, :MaxTime, :MinDeltaFitnessTolerance, :FitnessTolerance]]..., - 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, -1.0, "") + 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, -1.0, "", false) end # stepping optimizer has it's own evaluator, get a reference @@ -188,6 +189,10 @@ function elapsed_time(ctrl::OptRunController) end function check_stop_condition(ctrl::OptRunController) + if ctrl.shutdown + return "Run explicitly stopped via shutdown method" + end + if ctrl.max_time > 0 && elapsed_time(ctrl) > ctrl.max_time return "Max time ($(ctrl.max_time) s) reached" end @@ -270,12 +275,17 @@ setup_optimizer!(ctrl::OptRunController{<:SteppingOptimizer}) = setup_optimizer!(ctrl::OptRunController{<:AskTellOptimizer}) = setup!(ctrl.optimizer, ctrl.evaluator) -shutdown_optimizer!(ctrl::OptRunController{<:SteppingOptimizer}) = +shutdown!(ctrl::OptRunController) = ctrl.shutdown = true + +function shutdown_optimizer!(ctrl::OptRunController{<:SteppingOptimizer}) shutdown!(ctrl.optimizer) + shutdown!(ctrl) +end function shutdown_optimizer!(ctrl::OptRunController{<:AskTellOptimizer}) shutdown!(ctrl.optimizer) shutdown!(ctrl.evaluator) + shutdown!(ctrl) end """ diff --git a/src/optimizer.jl b/src/optimizer.jl index 27ebff0b..1f8190d2 100644 --- a/src/optimizer.jl +++ b/src/optimizer.jl @@ -91,11 +91,11 @@ function setup!(o::SteppingOptimizer) end function setup!(o::AskTellOptimizer, evaluator::Evaluator) - # Do nothing, override if you need to setup prior to the optimization loop + # Do nothing, override if optimizer needs specific setup prior to the optimization loop end function shutdown!(o::Optimizer) - # Do nothing, override if you need to setup prior to the optimization loop + # Do nothing, override if optimizer needs specific shutdown end shutdown!(o::SteppingOptimizer) = diff --git a/test/test_toplevel_bboptimize.jl b/test/test_toplevel_bboptimize.jl index 01728e27..fd39e215 100644 --- a/test/test_toplevel_bboptimize.jl +++ b/test/test_toplevel_bboptimize.jl @@ -234,4 +234,17 @@ res = bboptimize(CallableObjective1(); SearchRange = [(-2.0, 3.0), (-4.0, 5.0)]) @test best_candidate(res) ≈ zeros(2) atol = 1e-5 end + + @testset "explicit termination via shutdown method" begin + cb = function (oc) + if best_fitness(oc) < 50.0 + BlackBoxOptim.shutdown_optimizer!(oc) + end + end + res = bboptimize(rosenbrock; SearchRange = (-5.0, 5.0), NumDimensions = 2, + PopulationSize = 10, TraceMode = :silent, MaxFuncEvals = 1000, + CallbackFunction = cb, CallbackInterval = 0.0) + reason = BlackBoxOptim.stop_reason(res) + @test occursin("stopped", reason) && occursin("shutdown method", reason) + end end