diff --git a/src/settings.jl b/src/settings.jl index 615bbf60..c0dc1f59 100644 --- a/src/settings.jl +++ b/src/settings.jl @@ -102,7 +102,7 @@ Base.@kwdef mutable struct Settings{T <: AbstractFloat} #cones and line search parameters linesearch_backtrack_step::T = 0.8 - min_switch_step_length::T = 1e-1 + min_switch_step_length::T = 1e-2 min_terminate_step_length::T = 1e-4 #maximum solver threads for multithreaded KKT solvers diff --git a/src/solver.jl b/src/solver.jl index d1bbee73..202d62d1 100644 --- a/src/solver.jl +++ b/src/solver.jl @@ -337,7 +337,7 @@ function solve!( α = solver_get_step_length(s,:combined,scaling) # check for undersized step and update strategy - (action,scaling) = _strategy_checkpoint_small_step(s, α, scaling) + (action,scaling) = _strategy_checkpoint_small_step(s, α, μ, scaling) if action === NoUpdate; (); #just keep going elseif action === Update; α = zero(T); continue; elseif action === Fail; α = zero(T); break; @@ -445,7 +445,7 @@ end # Mehrotra heuristic function _calc_centering_parameter(α::T) where{T} - return σ = (1-α)^3 + return σ = (1-α)*min((1-α)^2, 0.25) end @@ -489,7 +489,45 @@ function _strategy_checkpoint_numerical_error(s::Solver{T}, is_kkt_solve_success end -function _strategy_checkpoint_small_step(s::Solver{T}, α::T, scaling::ScalingStrategy) where {T} +function _strategy_checkpoint_small_step(s::Solver{T}, α::T, μ::T, scaling::ScalingStrategy) where {T} + + # Pure centering step if the step size is too small + if (α < s.settings.min_switch_step_length) + σ = _calc_centering_parameter(α) + + variables_affine_step_rhs!( + s.step_rhs, s.residuals, + s.variables, s.cones + ) + + #calculate the combined step and length + #-------------- + variables_pure_corrector_step_rhs!( + s.step_rhs, s.residuals, + s.variables, s.cones, + s.step_lhs, σ, μ + ) + + @timeit s.timers "kkt solve" begin + is_kkt_solve_success = + kkt_solve!( + s.kktsystem, s.step_lhs, s.step_rhs, + s.data, s.variables, s.cones, :combined + ) + end + + # check for numerical failure + if !is_kkt_solve_success + #out of tricks. Bail out with an error + s.info.status = NUMERICAL_ERROR + return (Fail::StrategyCheckpoint,scaling) + end + + #compute final step length and update the current iterate + #-------------- + α = solver_get_step_length(s,:combined,scaling) + + end if !is_symmetric(s.cones) && scaling == PrimalDual::ScalingStrategy && α < s.settings.min_switch_step_length diff --git a/src/variables.jl b/src/variables.jl index c6b78990..1bf92605 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -161,6 +161,40 @@ function variables_combined_step_rhs!( return nothing end +# Pure corrector used only when the step size is too small +function variables_pure_corrector_step_rhs!( + d::DefaultVariables{T}, + r::DefaultResiduals{T}, + variables::DefaultVariables{T}, + cones::CompositeCone{T}, + step::DefaultVariables{T}, + σ::T, + μ::T +) where {T} + + dotσμ = σ*μ + + @. d.x = -σ*r.rx + d.τ = -σ*r.rτ + d.κ = - dotσμ + + # ds is different for symmetric and asymmetric cones: + # Symmetric cones: d.s = − σμe + # Asymmetric cones: d.s = σμ*g(z) + + # YC: No higher_correction by setting Δz to 0 + # it is less efficient but ok since the correction rarely happens + step.z .= zero(T) + combined_ds_shift!(cones,d.z,step.z,step.s,dotσμ) + + @. d.s = d.z + + # now we copy the scaled res for rz and d.z is no longer work + @. d.z = -σ*r.rz + + return nothing +end + # Calls shift_to_cone on all conic variables and does not # touch the primal variables. Used for symmetric problems.