From a8c0f641797566a48addf6ec5641f5cf74688023 Mon Sep 17 00:00:00 2001 From: rodrigosgr Date: Wed, 22 Apr 2020 17:22:45 -0300 Subject: [PATCH 1/3] =?UTF-8?q?vers=C3=A3o=20para=20rodar=20o=20CUTEst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SQP.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/SQP.jl b/src/SQP.jl index 4181882..20c5797 100644 --- a/src/SQP.jl +++ b/src/SQP.jl @@ -18,7 +18,7 @@ function sqp(nlp :: AbstractNLPModel; cons_tol :: Real = 1e-8, max_iter :: Int = 1000, max_time :: Float64 = 30.0, - relax_param :: Float64 = 0.5, + relax_param :: Float64 = 0.6, trust_reg :: Float64 = 3.0, μ0 :: Float64 = 1.0) @@ -45,8 +45,8 @@ function sqp(nlp :: AbstractNLPModel; cx = cons(nlp, x) - nlp.meta.ucon gx = grad(nlp, x) A = jac(nlp, x) - W = Symmetric(hess(nlp, x, y = y), :L) - Z = nullspace(A) + W = Symmetric(hess(nlp, x, y), :L) + Z = nullspace(Matrix(A)) norm_cx = norm(cx) tr = TrustRegion(trust_reg) ρ = 0.0 @@ -102,14 +102,14 @@ function sqp(nlp :: AbstractNLPModel; μ_plus = max(μ0, μ_bar, norm(y)) end - ϕ(x) = obj(nlp, x) + μ_plus * norm(cons(nlp, x)) - nlp_aux = ADNLPModel(ϕ, x) + #ϕ(x) = obj(nlp, x) + μ_plus * norm(cons(nlp, x)) + #nlp_aux = ADNLPModel(ϕ, x) ϕx = fx + μ_plus * norm_cx ϕn = next_f + μ_plus * next_norm_c - Δm = μ * vpred - upred + Δm = μ * vpred - upred - ared, pred = aredpred(nlp_aux, ϕn, ϕx, Δm, next_x, d, dot(d, grad(nlp_aux,x))) - ρ = ared / pred + ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, dot(d, gx) - μ_plus * norm_cx) + ρ = (ared + tol) / (pred + tol) set_property!(tr, :ratio, ρ) if acceptable(tr) @@ -120,8 +120,8 @@ function sqp(nlp :: AbstractNLPModel; A = jac(nlp, x) gx = grad(nlp, x) y = lsmr(A', gx)[1] - W = Symmetric(hess(nlp, x, y = y), :L) - Z = nullspace(A) + W = Symmetric(hess(nlp, x, y), :L) + Z = nullspace(Matrix(A)) last_but_one_rejected = last_rejected last_rejected = true last_accepted_μ = μ From 5aad1cd8f87bf67a086382cdad302658dd54c790 Mon Sep 17 00:00:00 2001 From: rodrigosgr Date: Mon, 25 May 2020 18:14:51 -0300 Subject: [PATCH 2/3] second order correction --- src/SQP.jl | 70 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/src/SQP.jl b/src/SQP.jl index 20c5797..c1641cd 100644 --- a/src/SQP.jl +++ b/src/SQP.jl @@ -12,14 +12,14 @@ using JSOSolvers function sqp(nlp :: AbstractNLPModel; - atol :: Real = 1e-8, - rtol :: Real = 1e-8, + x :: AbstractVector = copy(nlp.meta.x0), + atol :: Real = sqrt(eps(eltype(x))), + rtol :: Real = sqrt(eps(eltype(x))), max_eval :: Int = -1, - cons_tol :: Real = 1e-8, - max_iter :: Int = 1000, + max_iter :: Int = 25, max_time :: Float64 = 30.0, relax_param :: Float64 = 0.6, - trust_reg :: Float64 = 3.0, + trust_reg :: Float64 = 1.0, μ0 :: Float64 = 1.0) @@ -35,11 +35,10 @@ function sqp(nlp :: AbstractNLPModel; error("This SQP implementation only works for equality constraints and unbounded variables") end - iter = 1 + iter = 0 start_time = time() n = nlp.meta.nvar m = nlp.meta.ncon - x = copy(nlp.meta.x0) y = copy(nlp.meta.y0) fx = obj(nlp, x) cx = cons(nlp, x) - nlp.meta.ucon @@ -59,8 +58,7 @@ function sqp(nlp :: AbstractNLPModel; exitflag = :unknow dual = A'*y - gx normdual = norm(dual) - tol = atol + rtol * normdual - success = normdual < tol && norm_cx < cons_tol + success = normdual < atol + rtol * normdual && norm_cx < atol + rtol * norm_cx if success exitflag = :first_order end @@ -80,11 +78,12 @@ function sqp(nlp :: AbstractNLPModel; @info log_row(Any[iter, Δt, normdual, norm_cx, tr.radius, ρ]) while !(success || tired) - v = lsmr(A, -cx, radius = relax_param * tr.radius)[1] + v = lsmr(A, -cx, radius = relax_param * tr.radius, atol = atol, rtol = rtol, itmax = max(2 * n, 50))[1] ZWZ = Z' * W * Z ZWv = Z' * (W*v + gx) - u = cg(ZWZ, -ZWv, radius = sqrt(tr.radius^2 - norm(v)^2))[1] - d = v + Z * u + u = cg(ZWZ, -ZWv, radius = sqrt(tr.radius^2 - norm(v)^2), atol = atol, rtol = 0.0, itmax = max(2 * n, 50))[1] + Zu = Z * u + d = v + Zu next_x = x + d next_f = obj(nlp, next_x) @@ -95,10 +94,10 @@ function sqp(nlp :: AbstractNLPModel; μ_bar = 0.1 + upred / vpred # auxiliary variable for μ update μ_plus = max(μ, μ_bar) # another auxiliary variable - if μ_plus > μ && μ_plus < 5*μ && μ > last_accepted_μ && norm_cx > 0.2*last_accepted_norm_c && (last_rejected || last_but_one_rejected) - μ_plus = min(5*μ, μ_plus + 25*(μ_plus - last_accepted_μ)) + if μ_plus > μ && μ_plus < 5 * μ && μ > last_accepted_μ && norm_cx > 0.2 * last_accepted_norm_c && (last_rejected || last_but_one_rejected) + μ_plus = min(5 * μ, μ_plus + 25 * (μ_plus - last_accepted_μ)) end - if μ_plus == μ && norm(v) < relax_param * tr.radius/10 && norm_cx < 1e4 * tol + if μ_plus == μ && norm(v) < relax_param * tr.radius/10 && norm_cx < 1e4 * atol μ_plus = max(μ0, μ_bar, norm(y)) end @@ -109,10 +108,14 @@ function sqp(nlp :: AbstractNLPModel; Δm = μ * vpred - upred ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, dot(d, gx) - μ_plus * norm_cx) - ρ = (ared + tol) / (pred + tol) + ρ = ared / pred set_property!(tr, :ratio, ρ) - if acceptable(tr) + norm_v = norm(v) + norm_Zu = norm(Zu) + + + if acceptable(tr) x = next_x fx = next_f cx = next_c @@ -123,9 +126,38 @@ function sqp(nlp :: AbstractNLPModel; W = Symmetric(hess(nlp, x, y), :L) Z = nullspace(Matrix(A)) last_but_one_rejected = last_rejected - last_rejected = true + last_rejected = false last_accepted_μ = μ last_accepted_norm_c = norm_cx + elseif norm_v < 0.8 * relax_param * tr.radius && norm_v < 0.1 * norm_Zu + aux_sist = cg(A*A', next_c)[1] + d -= A'*aux_sist + next_x = x + d + next_f = obj(nlp, next_x) + next_cx = cons(nlp, next_x) - nlp.meta.ucon + next_norm_c = norm(next_cx) + ϕx = fx + μ_plus * norm_cx + ϕn = next_f + μ_plus * next_norm_c + Δm = μ * vpred - upred + ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, dot(d, gx) - μ_plus * norm_cx) + ρ = ared / pred + set_property!(tr, :ratio, ρ) + x = next_x + fx = next_f + cx = next_c + norm_cx = next_norm_c + A = jac(nlp, x) + gx = grad(nlp, x) + y = lsmr(A', gx)[1] + W = Symmetric(hess(nlp, x, y), :L) + Z = nullspace(Matrix(A)) + last_but_one_rejected = last_rejected + last_rejected = false + last_accepted_μ = μ + last_accepted_norm_c = norm_cx + else + last_but_one_rejected = last_rejected + last_rejected = true end μ = μ_plus @@ -134,7 +166,7 @@ function sqp(nlp :: AbstractNLPModel; dual = A'*y - gx normdual = norm(dual) - success = normdual < tol && norm_cx < cons_tol + success = normdual < atol + rtol * normdual && norm_cx < atol + rtol * norm_cx if success exitflag = :first_order end From 2a6b667c9996993448ca24aaf60fc57a220a6ac3 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Thu, 9 Jul 2020 11:13:19 -0300 Subject: [PATCH 3/3] changes in mu, merit function, SOC for new test in CUTEst --- Project.toml | 3 + src/SQP.jl | 165 ++++++++++++++++++++++++--------------------------- 2 files changed, 82 insertions(+), 86 deletions(-) diff --git a/Project.toml b/Project.toml index 9911e17..522c322 100644 --- a/Project.toml +++ b/Project.toml @@ -9,6 +9,9 @@ Krylov = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" NLPModels = "a4795742-8479-5a88-8948-cc11e1c8c1a6" +NLPModelsIpopt = "f4238b75-b362-5c4c-b852-0801c9a21d71" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" SolverTools = "b5612192-2639-5dc1-abfe-fbedd65fab29" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/SQP.jl b/src/SQP.jl index c1641cd..0b2b61c 100644 --- a/src/SQP.jl +++ b/src/SQP.jl @@ -1,28 +1,24 @@ -module SQP - +module SQP export sqp - using LinearAlgebra using Krylov using NLPModels using SolverTools using JSOSolvers - function sqp(nlp :: AbstractNLPModel; x :: AbstractVector = copy(nlp.meta.x0), atol :: Real = sqrt(eps(eltype(x))), rtol :: Real = sqrt(eps(eltype(x))), max_eval :: Int = -1, - max_iter :: Int = 25, + max_iter :: Int = 1000, max_time :: Float64 = 30.0, relax_param :: Float64 = 0.6, trust_reg :: Float64 = 1.0, μ0 :: Float64 = 1.0) - if bound_constrained(nlp) return tron(nlp, x = copy(nlp.meta.x0), max_time = max_time, atol = atol, rtol = rtol, max_eval = max_eval) end @@ -39,21 +35,19 @@ function sqp(nlp :: AbstractNLPModel; start_time = time() n = nlp.meta.nvar m = nlp.meta.ncon - y = copy(nlp.meta.y0) fx = obj(nlp, x) cx = cons(nlp, x) - nlp.meta.ucon gx = grad(nlp, x) A = jac(nlp, x) + LSMR_dual = lsmr(A', gx) + y = LSMR_dual[1] + maior_y = norm(y, Inf) W = Symmetric(hess(nlp, x, y), :L) Z = nullspace(Matrix(A)) norm_cx = norm(cx) tr = TrustRegion(trust_reg) ρ = 0.0 μ = μ0 - last_accepted_μ = μ0 # for the first iteration - last_accepted_norm_c = norm_cx - last_rejected = false # the information from the last two steps is needed for the μ update - last_but_one_rejected = false exitflag = :unknow dual = A'*y - gx @@ -65,7 +59,7 @@ function sqp(nlp :: AbstractNLPModel; Δt = time() - start_time tired = Δt > max_time || iter > max_iter || neval_obj(nlp) > max_eval > 0 if tired - if Δt > max_time + if Δt > max_time exitflag = :max_time elseif iter > max_iter exitflag = :max_iter @@ -78,91 +72,93 @@ function sqp(nlp :: AbstractNLPModel; @info log_row(Any[iter, Δt, normdual, norm_cx, tr.radius, ρ]) while !(success || tired) - v = lsmr(A, -cx, radius = relax_param * tr.radius, atol = atol, rtol = rtol, itmax = max(2 * n, 50))[1] - ZWZ = Z' * W * Z + LSMR = lsmr(A, -cx, radius = relax_param * tr.radius, atol = atol, rtol = rtol, itmax = max(2 * n, 50)) + v = LSMR[1] + ZWZ = Z' * W * Z ZWv = Z' * (W*v + gx) - u = cg(ZWZ, -ZWv, radius = sqrt(tr.radius^2 - norm(v)^2), atol = atol, rtol = 0.0, itmax = max(2 * n, 50))[1] - Zu = Z * u + CG = cg(ZWZ, -ZWv, radius = sqrt(tr.radius^2 - norm(v)^2), atol = atol, rtol= 0.0, itmax = max(2 * n, 50)) + u = CG[1] + Zu = Z * u d = v + Zu + norm_v = norm(v) next_x = x + d next_f = obj(nlp, next_x) next_c = cons(nlp, next_x) - nlp.meta.ucon - next_norm_c = norm(next_c) + next_norm_c = norm(next_c, 1) vpred = norm_cx - norm(A*v + cx) - upred = 0.5 * (u'*ZWZ*u)[1] + dot(ZWv,u) - μ_bar = 0.1 + upred / vpred # auxiliary variable for μ update - - μ_plus = max(μ, μ_bar) # another auxiliary variable - if μ_plus > μ && μ_plus < 5 * μ && μ > last_accepted_μ && norm_cx > 0.2 * last_accepted_norm_c && (last_rejected || last_but_one_rejected) - μ_plus = min(5 * μ, μ_plus + 25 * (μ_plus - last_accepted_μ)) - end - if μ_plus == μ && norm(v) < relax_param * tr.radius/10 && norm_cx < 1e4 * atol - μ_plus = max(μ0, μ_bar, norm(y)) + D = dot(d, gx) + dWd = (d'*W*d)[1] + dpred = 0.5 * dWd + D + + μ_bar = maior_y + 0.1 + if(dWd >= 0) + if(μ > μ_bar) + μ_plus = μ + else + μ_plus = μ_bar + end + else + μ_plus = μ_bar - dWd / norm_cx end - #ϕ(x) = obj(nlp, x) + μ_plus * norm(cons(nlp, x)) - #nlp_aux = ADNLPModel(ϕ, x) - ϕx = fx + μ_plus * norm_cx - ϕn = next_f + μ_plus * next_norm_c - Δm = μ * vpred - upred + μ = max(μ_plus, dpred / (0.7 * vpred) + 0.1) + + ϕx = fx + μ * norm_cx + ϕn = next_f + μ * next_norm_c + Δm = μ * vpred - dpred + μ_norm_cx = μ * norm_cx - ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, dot(d, gx) - μ_plus * norm_cx) + ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, D - μ_norm_cx) ρ = ared / pred set_property!(tr, :ratio, ρ) - norm_v = norm(v) - norm_Zu = norm(Zu) - - - if acceptable(tr) - x = next_x - fx = next_f - cx = next_c - norm_cx = next_norm_c - A = jac(nlp, x) - gx = grad(nlp, x) - y = lsmr(A', gx)[1] - W = Symmetric(hess(nlp, x, y), :L) - Z = nullspace(Matrix(A)) - last_but_one_rejected = last_rejected - last_rejected = false - last_accepted_μ = μ - last_accepted_norm_c = norm_cx - elseif norm_v < 0.8 * relax_param * tr.radius && norm_v < 0.1 * norm_Zu - aux_sist = cg(A*A', next_c)[1] - d -= A'*aux_sist - next_x = x + d - next_f = obj(nlp, next_x) - next_cx = cons(nlp, next_x) - nlp.meta.ucon - next_norm_c = norm(next_cx) - ϕx = fx + μ_plus * norm_cx - ϕn = next_f + μ_plus * next_norm_c - Δm = μ * vpred - upred - ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, dot(d, gx) - μ_plus * norm_cx) - ρ = ared / pred - set_property!(tr, :ratio, ρ) - x = next_x - fx = next_f - cx = next_c - norm_cx = next_norm_c - A = jac(nlp, x) - gx = grad(nlp, x) - y = lsmr(A', gx)[1] - W = Symmetric(hess(nlp, x, y), :L) - Z = nullspace(Matrix(A)) - last_but_one_rejected = last_rejected - last_rejected = false - last_accepted_μ = μ - last_accepted_norm_c = norm_cx - else - last_but_one_rejected = last_rejected - last_rejected = true + normv = norm(v) + normu = norm(Zu) + + if acceptable(tr) + x = next_x + fx = next_f + cx = next_c + norm_cx = next_norm_c + A = jac(nlp, x) + gx = grad(nlp, x) + LSMR_dual = lsmr(A', gx) + y = LSMR_dual[1] + W = Symmetric(hess(nlp, x, y), :L) + Z = nullspace(Matrix(A)) + elseif (normv <= 0.1 * normu) && (normv <= 0.8 * relax_param * tr.radius) + LSMR_aux = lsmr(A, next_c, atol = atol, rtol = rtol) + w = LSMR_aux[1] + d_soc = d + w + next_x = x + d_soc + next_f = obj(nlp, next_x) + next_cx = cons(nlp, next_x) - nlp.meta.ucon + next_norm_c = norm(next_cx) + ϕx = fx + μ * norm_cx + ϕn = next_f + μ * next_norm_c + D = dot(d_soc, gx) + Δm = μ * (norm_cx - norm(A*d_soc + cx)) - 0.5 * (d_soc'*W*d_soc)[1] - D + + ared, pred = aredpred(nlp, ϕn, ϕx, Δm, next_x, d, D - μ_norm_cx) + ρ = ared / pred + set_property!(tr, :ratio, ρ) + + if acceptable(tr) + x = next_x + fx = next_f + cx = next_c + norm_cx = next_norm_c + A = jac(nlp, x) + gx = grad(nlp, x) + LSMR_dual = lsmr(A', gx) + y = LSMR_dual[1] + W = Symmetric(hess(nlp, x, y), :L) + Z = nullspace(Matrix(A)) + end end - - μ = μ_plus - - update!(tr, norm(d)) + + update!(tr, norm(d, 2)) dual = A'*y - gx normdual = norm(dual) @@ -184,14 +180,11 @@ function sqp(nlp :: AbstractNLPModel; end @info log_row(Any[iter, Δt, normdual, norm_cx, tr.radius, ρ]) - end cx = cx + nlp.meta.ucon return GenericExecutionStats(exitflag, nlp, solution = x, objective = fx, dual_feas = normdual, primal_feas = norm_cx, iter = iter, elapsed_time = Δt) - end - end # module