#include "IpCGPenaltyLSAcceptor.hpp"
#include "IpCGPenaltyData.hpp"
#include "IpCGPenaltyCq.hpp"
#include "IpJournalist.hpp"
#include "IpRestoPhase.hpp"
#include "IpAlgTypes.hpp"
#include "IpIpoptAlg.hpp"
#include <cmath>
#include <limits>
namespace Ipopt
{
#if IPOPT_VERBOSITY > 0
static const Index dbg_verbosity = 0;
#endif
CGPenaltyLSAcceptor::CGPenaltyLSAcceptor(
const SmartPtr<PDSystemSolver>& pd_solver
)
: PiecewisePenalty_(1),
pd_solver_(pd_solver)
{
DBG_START_FUN("CGPenaltyLSAcceptor::CGPenaltyLSAcceptor",
dbg_verbosity);
}
CGPenaltyLSAcceptor::~CGPenaltyLSAcceptor()
{
DBG_START_FUN("CGPenaltyLSAcceptor::~CGPenaltyLSAcceptor()",
dbg_verbosity);
}
void CGPenaltyLSAcceptor::RegisterOptions(
SmartPtr<RegisteredOptions> roptions
)
{
roptions->AddBoolOption(
"never_use_piecewise_penalty_ls",
"Toggle to switch off the piecewise penalty method",
false);
roptions->AddBoundedNumberOption(
"eta_penalty",
"Relaxation factor in the Armijo condition for the penalty function.",
0., true,
0.5, true,
1e-8);
roptions->AddLowerBoundedNumberOption(
"penalty_update_infeasibility_tol",
"Threshold for infeasibility in penalty parameter update test.",
0., true,
1e-9,
"If the new constraint violation is smaller than this tolerance, the penalty parameter is not increased.");
roptions->AddLowerBoundedNumberOption(
"eta_min",
"", 0., true,
1e1,
"",
true);
roptions->AddLowerBoundedNumberOption(
"pen_theta_max_fact",
"Determines upper bound for constraint violation in the filter.",
0., true,
1e4,
"The algorithmic parameter theta_max is determined as theta_max_fact times the maximum of 1 and "
"the constraint violation at initial point. "
"Any point with a constraint violation larger than theta_max is unacceptable to the filter "
"(see Eqn. (21) in implementation paper).");
roptions->AddLowerBoundedNumberOption(
"penalty_update_compl_tol",
"", 0., true,
1e1,
"",
true);
roptions->AddLowerBoundedNumberOption(
"chi_hat",
"", 0., true,
2.,
"",
true);
roptions->AddLowerBoundedNumberOption(
"chi_tilde",
"", 0., true,
5.,
"",
true);
roptions->AddLowerBoundedNumberOption(
"chi_cup",
"", 0., true,
1.5,
"",
true);
roptions->AddLowerBoundedNumberOption(
"gamma_hat",
"", 0., true,
0.04,
"",
true);
roptions->AddLowerBoundedNumberOption(
"gamma_tilde",
"", 0., true,
4.,
"",
true);
roptions->AddLowerBoundedNumberOption(
"epsilon_c",
"", 0., true,
1e-2,
"",
true);
roptions->AddLowerBoundedNumberOption(
"piecewisepenalty_gamma_obj",
"", 0., true,
1e-13,
"",
true);
roptions->AddLowerBoundedNumberOption(
"piecewisepenalty_gamma_infeasi",
"", 0., true,
1e-13,
"",
true);
roptions->AddLowerBoundedNumberOption(
"min_alpha_primal",
"", 0., true,
1e-13,
"",
true);
roptions->AddLowerBoundedNumberOption(
"theta_min",
"", 0., true,
1e-6,
"",
true);
roptions->AddLowerBoundedNumberOption(
"mult_diverg_feasibility_tol",
"tolerance for deciding if the multipliers are diverging",
0., true,
1e-7,
"",
true);
roptions->AddLowerBoundedNumberOption(
"mult_diverg_y_tol",
"tolerance for deciding if the multipliers are diverging",
0., true,
1e8,
"",
true);
}
bool CGPenaltyLSAcceptor::InitializeImpl(
const OptionsList& options,
const std::string& prefix
)
{
options.GetBoolValue("never_use_piecewise_penalty_ls", never_use_piecewise_penalty_ls_, prefix);
options.GetNumericValue("eta_penalty", eta_penalty_, prefix);
options.GetNumericValue("penalty_update_infeasibility_tol", penalty_update_infeasibility_tol_, prefix);
options.GetNumericValue("eta_min", eta_min_, prefix);
options.GetNumericValue("penalty_update_compl_tol", penalty_update_compl_tol_, prefix);
options.GetNumericValue("chi_hat", chi_hat_, prefix);
options.GetNumericValue("chi_tilde", chi_tilde_, prefix);
options.GetNumericValue("chi_cup", chi_cup_, prefix);
options.GetNumericValue("gamma_hat", gamma_hat_, prefix);
options.GetNumericValue("gamma_tilde", gamma_tilde_, prefix);
options.GetNumericValue("epsilon_c", epsilon_c_, prefix);
options.GetNumericValue("piecewisepenalty_gamma_obj", piecewisepenalty_gamma_obj_, prefix);
options.GetNumericValue("piecewisepenalty_gamma_infeasi", piecewisepenalty_gamma_infeasi_, prefix);
options.GetNumericValue("pen_theta_max_fact", pen_theta_max_fact_, prefix);
options.GetNumericValue("min_alpha_primal", min_alpha_primal_, prefix);
options.GetNumericValue("theta_min", theta_min_, prefix);
options.GetNumericValue("mult_diverg_feasibility_tol", mult_diverg_feasibility_tol_, prefix);
options.GetNumericValue("mult_diverg_y_tol", mult_diverg_y_tol_, prefix);
options.GetIntegerValue("max_soc", max_soc_, prefix);
options.GetNumericValue("penalty_max", penalty_max_, prefix);
if( max_soc_ > 0 )
{
ASSERT_EXCEPTION(IsValid(pd_solver_), OPTION_INVALID,
"Option \"max_soc\": This option is non-negative, but no linear solver for computing the SOC given to FilterLSAcceptor object.");
}
options.GetNumericValue("kappa_soc", kappa_soc_, prefix);
pen_theta_max_ = -1.;
pen_curr_mu_ = IpData().curr_mu();
counter_first_type_penalty_updates_ = 0;
counter_second_type_penalty_updates_ = 0;
curr_eta_ = -1.;
CGPenData().SetPenaltyUninitialized();
ls_counter_ = 0;
best_KKT_error_ = -1.;
accepted_by_Armijo_ = true;
jump_for_tiny_step_ = 0;
return true;
}
void CGPenaltyLSAcceptor::InitThisLineSearch(
bool in_watchdog
)
{
DBG_START_METH("CGPenaltyLSAcceptor::InitThisLineSearch",
dbg_verbosity);
accepted_by_Armijo_ = true;
ls_counter_ = 0;
if( CGPenData().restor_iter() == IpData().iter_count() )
{
Reset();
}
if( pen_curr_mu_ > IpData().curr_mu() )
{
Reset();
}
if( reset_piecewise_penalty_ )
{
Number curr_barr = IpCq().curr_barrier_obj();
Number curr_infeasi = IpCq().curr_constraint_violation();
PiecewisePenalty_.InitPiecewisePenaltyList(0., curr_barr, curr_infeasi);
reset_piecewise_penalty_ = false;
}
if( !in_watchdog )
{
reference_penalty_function_ = CGPenCq().curr_penalty_function();
reference_theta_ = IpCq().curr_constraint_violation();
if( CGPenData().HaveCgFastDeltas() )
{
reference_direct_deriv_penalty_function_ = CGPenCq().curr_fast_direct_deriv_penalty_function();
}
else
{
reference_direct_deriv_penalty_function_ = CGPenCq().curr_direct_deriv_penalty_function();
}
}
else
{
reference_penalty_function_ = watchdog_penalty_function_;
reference_direct_deriv_penalty_function_ = watchdog_direct_deriv_penalty_function_;
}
}
bool CGPenaltyLSAcceptor::CheckAcceptabilityOfTrialPoint(
Number alpha_primal_test
)
{
DBG_START_METH("CGPenaltyLSAcceptor::CheckAcceptabilityOfTrialPoint",
dbg_verbosity);
Number curr_barr = IpCq().curr_barrier_obj();
Number curr_infeasi = IpCq().curr_constraint_violation();
Number trial_infeasi = IpCq().trial_constraint_violation();
ls_counter_++;
if( ls_counter_ == 1 )
{
CGPenData().SetPrimalStepSize(alpha_primal_test);
}
if( jump_for_tiny_step_ == 1 )
{
jump_for_tiny_step_ = 0;
Reset();
IpData().Append_info_string("jump");
return true;
}
if( PiecewisePenalty_.IsPiecewisePenaltyListEmpty() )
{
PiecewisePenalty_.InitPiecewisePenaltyList(0., curr_barr, curr_infeasi);
}
if( pen_theta_max_ < 0. )
{
pen_theta_max_ = pen_theta_max_fact_ * Max(Number(1.0), reference_theta_);
}
if( pen_theta_max_ > 0 && trial_infeasi > pen_theta_max_ )
{
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
"trial_infeasi = %e is larger than theta_max = %e\n", trial_infeasi, pen_theta_max_);
return false;
}
bool accept = ArmijoHolds(alpha_primal_test);
if( !accept && !never_use_piecewise_penalty_ls_ )
{
accept = IsAcceptableToPiecewisePenalty(alpha_primal_test);
if( accept )
{
accepted_by_Armijo_ = false;
}
}
if( alpha_primal_test < min_alpha_primal_ && !accept )
{
accept = true;
}
if( accept )
{
if( ls_counter_ > 15 && alpha_primal_test < 1e-5 && jump_for_tiny_step_ == 0 )
{
jump_for_tiny_step_ = 1;
}
ls_counter_ = 0;
}
return accept;
}
Number CGPenaltyLSAcceptor::CalculateAlphaMin()
{
Number min_step_size = 0.;
return min_step_size;
}
bool CGPenaltyLSAcceptor::IsAcceptableToPiecewisePenalty(
Number alpha_primal_test
)
{
DBG_START_METH("CGPenaltyLSAcceptor::IsAcceptableToPiecewisePenalty",
dbg_verbosity);
bool accept = false;
Number infeasibility = IpCq().curr_primal_infeasibility(NORM_MAX);
SmartPtr<const Vector> dx = IpData().delta()->x();
SmartPtr<const Vector> ds = IpData().delta()->s();
Number curr_barr = IpCq().curr_barrier_obj();
Number trial_barr = IpCq().trial_barrier_obj();
Number nrm_dx_ds = std::pow(dx->Nrm2(), 2.) + std::pow(ds->Nrm2(), 2.);
if( infeasibility < theta_min_ )
{
Number biggest_barr = PiecewisePenalty_.BiggestBarr();
accept = Compare_le(trial_barr - biggest_barr, -alpha_primal_test * piecewisepenalty_gamma_obj_ * nrm_dx_ds,
curr_barr);
if( !accept )
{
return false;
}
}
Number Fzconst, Fzlin;
Fzconst = IpCq().trial_barrier_obj() + alpha_primal_test * piecewisepenalty_gamma_obj_ * nrm_dx_ds;
Fzlin = IpCq().trial_constraint_violation()
+ alpha_primal_test * piecewisepenalty_gamma_infeasi_ * IpCq().curr_constraint_violation();
accept = PiecewisePenalty_.Acceptable(Fzconst, Fzlin);
return accept;
}
bool CGPenaltyLSAcceptor::ArmijoHolds(
Number alpha_primal_test
)
{
DBG_START_METH("CGPenaltyLSAcceptor::ArmijoHolds",
dbg_verbosity);
bool accept = false;
Number trial_penalty_function = CGPenCq().trial_penalty_function();
DBG_ASSERT(IsFiniteNumber(trial_penalty_function));
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
"Checking acceptability for trial step size alpha_primal_test=%13.6e:\n", alpha_primal_test);
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
" New values of penalty function = %23.16e (reference %23.16e):\n", trial_penalty_function, reference_penalty_function_);
if( Jnlst().ProduceOutput(J_DETAILED, J_LINE_SEARCH) )
{
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
"curr_barr = %23.16e curr_inf = %23.16e\n", IpCq().curr_barrier_obj(), IpCq().curr_constraint_violation());
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
"trial_barr = %23.16e trial_inf = %23.16e\n", IpCq().trial_barrier_obj(), IpCq().trial_constraint_violation());
}
accept = Compare_le(trial_penalty_function - reference_penalty_function_,
eta_penalty_ * alpha_primal_test * reference_direct_deriv_penalty_function_, reference_penalty_function_);
return accept;
}
bool CGPenaltyLSAcceptor::Compare_le(
Number lhs,
Number rhs,
Number BasVal
)
{
DBG_START_FUN("CGPenaltyLSAcceptor::Compare_le",
dbg_verbosity);
DBG_PRINT((1, "lhs = %27.16e rhs = %27.16e BasVal = %27.16e\n", lhs, rhs, BasVal));
Number mach_eps = std::numeric_limits<Number>::epsilon();
return (lhs - rhs <= 10. * mach_eps * std::abs(BasVal));
}
void CGPenaltyLSAcceptor::StartWatchDog()
{
DBG_START_FUN("CGPenaltyLSAcceptor::StartWatchDog", dbg_verbosity);
watchdog_penalty_function_ = CGPenCq().curr_penalty_function();
watchdog_direct_deriv_penalty_function_ = CGPenCq().curr_direct_deriv_penalty_function();
watchdog_delta_cgpen_ = CGPenData().delta_cgpen();
}
void CGPenaltyLSAcceptor::StopWatchDog()
{
DBG_START_FUN("CGPenaltyLSAcceptor::StopWatchDog", dbg_verbosity);
reference_penalty_function_ = watchdog_penalty_function_;
reference_direct_deriv_penalty_function_ = watchdog_direct_deriv_penalty_function_;
CGPenData().set_delta_cgpen(watchdog_delta_cgpen_);
watchdog_delta_cgpen_ = NULL;
}
void CGPenaltyLSAcceptor::Reset()
{
DBG_START_FUN("CGPenaltyLSAcceptor::Reset", dbg_verbosity);
reset_piecewise_penalty_ = true;
pen_theta_max_ = -1.;
curr_eta_ = -1.;
pen_curr_mu_ = IpData().curr_mu();
}
bool CGPenaltyLSAcceptor::TrySecondOrderCorrection(
Number alpha_primal_test,
Number& alpha_primal,
SmartPtr<IteratesVector>& actual_delta
)
{
DBG_START_METH("CGPenaltyLSAcceptor::TrySecondOrderCorrection",
dbg_verbosity);
if( max_soc_ == 0 )
{
return false;
}
bool accept = false;
Index count_soc = 0;
Number theta_soc_old = 0.;
Number theta_soc_old2 = 0.;
Number theta_trial = IpCq().trial_constraint_violation();
Number theta_trial2 = IpCq().curr_primal_infeasibility(NORM_2);
Number alpha_primal_soc = alpha_primal;
SmartPtr<const Vector> delta_y_c = IpData().delta()->y_c();
SmartPtr<const Vector> delta_y_d = IpData().delta()->y_d();
SmartPtr<Vector> c_soc = IpCq().curr_c()->MakeNewCopy();
SmartPtr<Vector> dms_soc = IpCq().curr_d_minus_s()->MakeNewCopy();
while( count_soc < max_soc_ && !accept
&& (count_soc == 0 || (theta_trial <= kappa_soc_ * theta_soc_old || theta_trial2 <= kappa_soc_ * theta_soc_old2)) )
{
theta_soc_old = theta_trial;
theta_soc_old2 = theta_trial2;
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
"Trying second order correction number %" IPOPT_INDEX_FORMAT "\n", count_soc + 1);
c_soc->AddTwoVectors(1.0, *IpCq().trial_c(), -CGPenData().CurrPenaltyPert(), *delta_y_c, alpha_primal_soc);
dms_soc->AddTwoVectors(1.0, *IpCq().trial_d_minus_s(), -CGPenData().CurrPenaltyPert(), *delta_y_d,
alpha_primal_soc);
SmartPtr<IteratesVector> delta_soc = actual_delta->MakeNewIteratesVector(true);
SmartPtr<IteratesVector> rhs = actual_delta->MakeNewContainer();
rhs->Set_x(*IpCq().curr_grad_lag_with_damping_x());
rhs->Set_s(*IpCq().curr_grad_lag_with_damping_s());
rhs->Set_y_c(*c_soc);
rhs->Set_y_d(*dms_soc);
rhs->Set_z_L(*IpCq().curr_relaxed_compl_x_L());
rhs->Set_z_U(*IpCq().curr_relaxed_compl_x_U());
rhs->Set_v_L(*IpCq().curr_relaxed_compl_s_L());
rhs->Set_v_U(*IpCq().curr_relaxed_compl_s_U());
pd_solver_->Solve(-1.0, 0.0, *rhs, *delta_soc, true);
delta_y_c = ConstPtr(delta_soc->y_c());
delta_y_d = ConstPtr(delta_soc->y_d());
alpha_primal_soc = IpCq().primal_frac_to_the_bound(IpData().curr_tau(), *delta_soc->x(), *delta_soc->s());
try
{
IpData().SetTrialPrimalVariablesFromStep(alpha_primal_soc, *delta_soc->x(), *delta_soc->s());
accept = CheckAcceptabilityOfTrialPoint(alpha_primal_test);
}
catch( IpoptNLP::Eval_Error& e )
{
e.ReportException(Jnlst(), J_DETAILED);
Jnlst().Printf(J_WARNING, J_MAIN,
"Warning: SOC step rejected due to evaluation error\n");
IpData().Append_info_string("e");
accept = false;
break;
}
if( accept )
{
Jnlst().Printf(J_DETAILED, J_LINE_SEARCH,
"Second order correction step accepted with %" IPOPT_INDEX_FORMAT " corrections.\n", count_soc + 1);
alpha_primal = alpha_primal_soc;
actual_delta = delta_soc;
}
else
{
count_soc++;
theta_trial = IpCq().trial_constraint_violation();
theta_trial2 = IpCq().trial_primal_infeasibility(NORM_2);
}
}
if( accept )
{
ls_counter_ = 0;
}
return accept;
}
bool CGPenaltyLSAcceptor::TryCorrector(
Number ,
Number& ,
SmartPtr<IteratesVector>&
)
{
DBG_START_METH("CGPenaltyLSAcceptor::TryCorrector",
dbg_verbosity);
return false;
}
char CGPenaltyLSAcceptor::UpdateForNextIteration(
Number
)
{
char info_alpha_primal_char = 'n';
if( pen_curr_mu_ > IpData().curr_mu() )
{
pen_curr_mu_ = IpData().curr_mu();
best_KKT_error_ = -1.;
}
if( CurrentIsBest() )
{
StoreBestPoint();
}
PiecewisePenalty_.Print(Jnlst());
if( !accepted_by_Armijo_ )
{
PiecewisePenalty_.UpdateEntry(IpCq().trial_barrier_obj(), IpCq().trial_constraint_violation());
}
PiecewisePenalty_.Print(Jnlst());
if( CGPenData().CurrPenaltyPert() != 0 )
{
info_alpha_primal_char = UpdatePenaltyParameter();
}
return info_alpha_primal_char;
}
bool CGPenaltyLSAcceptor::RestoredIterate()
{
bool restored_iterate = false;
if( CGPenData().restor_counter() < 3. )
{
if( MultipliersDiverged() )
{
if( RestoreBestPoint() )
{
Index restor_iter = IpData().iter_count() + 1;
Number restor_counter = CGPenData().restor_counter();
CGPenData().SetRestorCounter(restor_counter + 1);
CGPenData().SetNeverTryPureNewton(true);
CGPenData().SetRestorIter(restor_iter);
restored_iterate = true;
}
}
}
return restored_iterate;
}
bool CGPenaltyLSAcceptor::NeverRestorationPhase()
{
return true;
}
bool CGPenaltyLSAcceptor::CurrentIsBest()
{
DBG_START_METH("CGPenaltyLSAcceptor::CurrentIsBest",
dbg_verbosity);
Number dual_inf = IpCq().unscaled_curr_dual_infeasibility(NORM_MAX);
Number constr_viol = IpCq().unscaled_curr_nlp_constraint_violation(NORM_MAX);
Number compl_inf = IpCq().unscaled_curr_complementarity(0., NORM_MAX);
Number KKT_error = Max(dual_inf, Max(constr_viol, compl_inf));
DBG_PRINT((1, "dual_inf = %e\n", dual_inf));
DBG_PRINT((1, "constr_viol = %e\n", constr_viol));
DBG_PRINT((1, "compl_inf = %e\n", compl_inf));
DBG_PRINT((1, "best_KKT_error_= %e\n", best_KKT_error_));
bool best = false;
if( KKT_error < best_KKT_error_ || best_KKT_error_ < 0. )
{
best_KKT_error_ = KKT_error;
best = true;
}
return best;
}
void CGPenaltyLSAcceptor::StoreBestPoint()
{
DBG_START_METH("CGPenaltyLSAcceptor::StoreBestPoint",
dbg_verbosity);
best_iterate_ = IpData().curr();
}
bool CGPenaltyLSAcceptor::RestoreBestPoint()
{
DBG_START_METH("CGPenaltyLSAcceptor::RestoreBestPoint",
dbg_verbosity);
if( !IsValid(best_iterate_) )
{
return false;
}
SmartPtr<IteratesVector> prev_iterate = best_iterate_->MakeNewContainer();
IpData().set_trial(prev_iterate);
return true;
}
bool CGPenaltyLSAcceptor::MultipliersDiverged()
{
DBG_START_METH("CGPenaltyLSAcceptor::MultipliersDiverged",
dbg_verbosity);
bool diverged = false;
Number curr_inf = IpCq().curr_primal_infeasibility(NORM_2);
Number trial_inf = IpCq().trial_primal_infeasibility(NORM_2);
if( curr_inf > mult_diverg_feasibility_tol_ && trial_inf > mult_diverg_feasibility_tol_
&& IpCq().curr_dual_infeasibility(NORM_MAX) > 1e4 )
{
Number y_ref_big_step = mult_diverg_y_tol_;
Number y_ref_tiny_step = 1e4;
Number alpha_ref = 1e-4;
Number y_Amax = CGPenCq().curr_scaled_y_Amax();
if( (y_Amax > y_ref_big_step
&& (IpData().curr()->z_L()->Dim() + IpData().curr()->z_U()->Dim() + IpData().curr()->v_L()->Dim()
+ IpData().curr()->v_U()->Dim() + IpData().curr()->y_d()->Dim() == 0 || CGPenData().PrimalStepSize() < 1e-2))
|| (CGPenData().PrimalStepSize() < alpha_ref && y_Amax > y_ref_tiny_step) )
{
diverged = true;
}
}
return diverged;
}
char CGPenaltyLSAcceptor::UpdatePenaltyParameter()
{
DBG_START_METH("CGPenaltyLSAcceptor::UpdatePenaltyParameter",
dbg_verbosity);
char info_alpha_primal_char = 'n';
Number trial_inf = IpCq().trial_primal_infeasibility(NORM_2);
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"trial infeasibility = %8.2g\n", trial_inf);
if( curr_eta_ < 0. )
{
curr_eta_ = Max(eta_min_, Min(gamma_tilde_, gamma_hat_ * IpCq().curr_nlp_error()));
}
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"Starting tests for penalty parameter update:\n");
bool increase = (trial_inf >= penalty_update_infeasibility_tol_);
if( !increase )
{
info_alpha_primal_char = 'i';
}
if( increase )
{
Number max_step = Max(CGPenData().delta_cgpen()->x()->Amax(), CGPenData().delta_cgpen()->s()->Amax());
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"Max norm of step = %8.2g\n", max_step);
increase = (max_step <= curr_eta_);
if( !increase )
{
info_alpha_primal_char = 'd';
}
}
Number mu = IpData().curr_mu();
if( increase )
{
Number min_compl = mu;
Number max_compl = mu;
if( IpNLP().x_L()->Dim() > 0 )
{
SmartPtr<const Vector> compl_x_L = IpCq().curr_compl_x_L();
min_compl = Min(min_compl, compl_x_L->Min());
max_compl = Max(max_compl, compl_x_L->Max());
}
if( IpNLP().x_U()->Dim() > 0 )
{
SmartPtr<const Vector> compl_x_U = IpCq().curr_compl_x_U();
min_compl = Min(min_compl, compl_x_U->Min());
max_compl = Max(max_compl, compl_x_U->Max());
}
if( IpNLP().d_L()->Dim() > 0 )
{
SmartPtr<const Vector> compl_s_L = IpCq().curr_compl_s_L();
min_compl = Min(min_compl, compl_s_L->Min());
max_compl = Max(max_compl, compl_s_L->Max());
}
if( IpNLP().d_U()->Dim() > 0 )
{
SmartPtr<const Vector> compl_s_U = IpCq().curr_compl_s_U();
min_compl = Min(min_compl, compl_s_U->Min());
max_compl = Max(max_compl, compl_s_U->Max());
}
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"Minimal compl = %8.2g\n", min_compl);
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"Maximal compl = %8.2g\n", max_compl);
increase = (min_compl >= mu * penalty_update_compl_tol_ && max_compl <= mu / penalty_update_compl_tol_);
if( !increase )
{
info_alpha_primal_char = 'c';
}
}
if( increase )
{
SmartPtr<Vector> vec = IpData().curr()->y_c()->MakeNewCopy();
vec->AddTwoVectors(1., *CGPenData().delta_cgpen()->y_c(), -1. / CGPenCq().curr_cg_pert_fact(), *IpCq().curr_c(), 1.);
Number omega_test = vec->Amax();
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"omega_test for c = %8.2g\n", omega_test);
increase = (omega_test < curr_eta_);
if( increase )
{
vec = IpData().curr()->y_d()->MakeNewCopy();
vec->AddTwoVectors(1., *IpData().delta()->y_d(), -1. / CGPenCq().curr_cg_pert_fact(), *IpCq().curr_d_minus_s(), 1.);
omega_test = vec->Amax();
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"omega_test for d = %8.2g\n", omega_test);
increase = (omega_test < curr_eta_);
}
if( !increase )
{
info_alpha_primal_char = 'm';
}
}
if( increase )
{
counter_first_type_penalty_updates_++;
curr_eta_ = Max(eta_min_, curr_eta_ / Number(2.));
Jnlst().Printf(J_MOREDETAILED, J_LINE_SEARCH,
"Updating eta to = %8.2g\n", curr_eta_);
Number penalty = CGPenData().curr_kkt_penalty();
Number y_full_step_max;
SmartPtr<Vector> vec = IpData().curr()->y_c()->MakeNew();
vec->AddTwoVectors(1., *IpData().curr()->y_c(), 1., *CGPenData().delta_cgpen()->y_c(), 0.);
y_full_step_max = vec->Amax();
vec = IpData().curr()->y_d()->MakeNew();
vec->AddTwoVectors(1., *IpData().curr()->y_d(), 1., *CGPenData().delta_cgpen()->y_d(), 0.);
y_full_step_max = Max(y_full_step_max, vec->Amax());
if( IpCq().curr_primal_infeasibility(NORM_2) >= epsilon_c_ )
{
penalty = Max(chi_hat_ * penalty, y_full_step_max + Number(1.));
info_alpha_primal_char = 'l';
}
else
{
penalty = Max(chi_tilde_ * penalty, chi_cup_ * y_full_step_max);
info_alpha_primal_char = 's';
}
if( penalty > penalty_max_ )
{
THROW_EXCEPTION(IpoptException, "Penalty parameter becomes too large.");
}
CGPenData().Set_kkt_penalty(penalty);
if( CGPenData().NeverTryPureNewton() )
{
CGPenData().Set_penalty(penalty);
}
}
if( IpData().curr()->y_c()->Dim() + IpData().curr()->y_d()->Dim() > 0 && !never_use_piecewise_penalty_ls_ )
{
Number scaled_y_Amax = CGPenCq().curr_scaled_y_Amax();
if( scaled_y_Amax <= 1e4 || counter_second_type_penalty_updates_ < 5 )
{
Number result;
SmartPtr<const Vector> ty_c = IpData().curr()->y_c();
SmartPtr<const Vector> ty_d = IpData().curr()->y_d();
SmartPtr<const Vector> dy_c = IpData().delta()->y_c();
SmartPtr<const Vector> dy_d = IpData().delta()->y_d();
Number curr_inf = IpCq().curr_primal_infeasibility(NORM_2);
result = dy_c->Dot(*IpCq().curr_c()) + dy_d->Dot(*IpCq().curr_d_minus_s());
if( !CGPenData().HaveCgFastDeltas() )
{
result += ty_c->Dot(*IpCq().curr_c()) + ty_d->Dot(*IpCq().curr_d_minus_s());
}
Number k_pen = CGPenData().curr_kkt_penalty();
if( result > 0.5 * k_pen * curr_inf || result < -0.5 * k_pen * curr_inf )
{
Number nrm2_y = CGPenCq().curr_added_y_nrm2();
result = 5. * nrm2_y;
CGPenData().Set_kkt_penalty(result);
if( CGPenData().NeverTryPureNewton() )
{
CGPenData().Set_penalty(result);
}
if( scaled_y_Amax > 1e4 )
{
counter_second_type_penalty_updates_++;
}
}
}
}
return info_alpha_primal_char;
}
bool CGPenaltyLSAcceptor::DoFallback()
{
if( RestoreBestPoint() )
{
Index restor_iter = IpData().iter_count() + 1;
CGPenData().SetRestorIter(restor_iter);
CGPenData().SetNeverTryPureNewton(true);
IpData().Append_info_string("help");
return true;
}
else
{
return false;
}
}
void CGPenaltyLSAcceptor::PrepareRestoPhaseStart()
{
DBG_ASSERT(false && "PrepareRestoPhaseStart not yet implemented");
}
}