diff --git a/src/algorithms/common.jl b/src/algorithms/common.jl index 2ef51bb6..2b9b738b 100644 --- a/src/algorithms/common.jl +++ b/src/algorithms/common.jl @@ -184,6 +184,22 @@ An abstract type that stores optimization result. """ abstract type AbstractResult end +""" + restore_input! + Some fields of `AbstractResult` should be flattened after optimization, use this method whenever before returning it to frontend +""" +function restore_input!(r::AbstractResult, unflatten) + if :minimizer in fieldnames(typeof(r)) + @set! r.minimizer = unflatten(r.minimizer) + end + if :initial_x in fieldnames(typeof(r)) + @set! r.initial_x = unflatten(r.initial_x) + end + return r +end + + + """ GenericResult @@ -212,6 +228,7 @@ end abstract type AbstractModel end + """ ``` optimize( @@ -224,6 +241,7 @@ optimize( callback::Function = plot_trace ? LazyPlottingCallback() : NoCallback(), kwargs..., ) + ``` Optimizes `model` using the algorithm `optimizer`, e.g. an instance of [`MMA87`](@ref) or [`MMA02`](@ref). `x0` is the initial solution. The keyword arguments are: @@ -237,7 +255,7 @@ Optimizes `model` using the algorithm `optimizer`, e.g. an instance of [`MMA87`] function optimize(model::AbstractModel, optimizer::AbstractOptimizer, x0, args...; kwargs...) _model, _x0, unflatten = tovecmodel(model, x0) r = optimize(_model, optimizer, _x0, args...; kwargs...) - return @set r.minimizer = unflatten(r.minimizer) + return restore_input!(r, unflatten) end """ @@ -246,7 +264,7 @@ end function optimize(model::AbstractModel, optimizer::AbstractOptimizer, args...; kwargs...) _model, _, unflatten = tovecmodel(model) r = optimize(_model, optimizer, args...; kwargs...) - return @set r.minimizer = unflatten(r.minimizer) + return restore_input!(r, unflatten) end """ diff --git a/test/mma.jl b/test/mma.jl index 164873bb..ebf38f14 100755 --- a/test/mma.jl +++ b/test/mma.jl @@ -98,3 +98,36 @@ end @test norm(r.minimizer - [1/3, 8/27]) < 1e-6 end end + +# Test unflatten minimizer and initial_x +@testset "Unflatten initial_x" begin + function _f((x, _)) + sqrt(x[2]) + end + function _g((x, _), a, b) + (a*x[1] + b)^3 - x[2] + end + + _options = MMAOptions( + tol = Tolerance(kkt = 1e-6, f = 0.0), + s_init = 0.1, + maxiter = 1 + ) + + m = Model(_f) + addvar!(m, [(0.0, 0.0), (0.0, 0.0)], [(10.0, Inf), (10.0, Inf)]) + + function eqc1(x) + _g(x, 2, 0) + end + function eqc2(x) + _g(x, -1, 1) + end + add_ineq_constraint!(m, eqc1) + add_ineq_constraint!(m, eqc2) + + x0 = [(0.0, 0.0), (0.0, 0.0)] + r = Nonconvex.optimize(m, MMA02(), x0, options = _options, convcriteria = KKTCriteria()) + @test size(r.minimizer) == (2,) + @test size(r.initial_x) == (2,) +end