diff --git a/src/Optimization/hiopAlgFilterIPM.cpp b/src/Optimization/hiopAlgFilterIPM.cpp index d3bbee0a..2357ef76 100644 --- a/src/Optimization/hiopAlgFilterIPM.cpp +++ b/src/Optimization/hiopAlgFilterIPM.cpp @@ -1192,7 +1192,12 @@ hiopSolveStatus hiopAlgFilterIPMQuasiNewton::run() nlp->runStats.tmSolverInternal.start(); //maximum step - bret = it_curr->fractionToTheBdry(*dir, _tau, _alpha_primal, _alpha_dual); assert(bret); + bret = it_curr->fractionToTheBdry(*dir, _tau, _alpha_primal, _alpha_dual); + assert(bret); + //Step `_alpha_primal` may be reduced when option 'moving_lim_abs' or 'moving_lim_rel' is active. + //Return bool indicates if reduction was done. + bret = ensure_moving_lims(*it_curr, *dir, _alpha_primal); + double theta = onenorm_pr_curr_ = resid->get_theta(); //at it_curr double theta_trial; nlp->runStats.tmSolverInternal.stop(); @@ -2496,6 +2501,42 @@ void hiopAlgFilterIPMNewton::outputIteration(int lsStatus, int lsNum, int use_so } } +bool hiopAlgFilterIPMBase::ensure_moving_lims(const hiopIterate& it, const hiopIterate& dir, double& alpha_pr) +{ + auto moving_lim_rel = nlp->options->GetNumeric("moving_lim_rel"); + if(moving_lim_rel>0) { + const auto alpha_pr_in = alpha_pr; + alpha_pr = moving_lim_rel * alpha_pr; + nlp->log->printf(hovLinesearch, + "Moving lim (relative, [%7.3e]): step reduced: %7.3e -> %7.3e.\n", + moving_lim_rel, + alpha_pr_in, + alpha_pr); + return true; + } + + auto moving_lim_abs = nlp->options->GetNumeric("moving_lim_abs"); + if(moving_lim_abs>0) { + const auto alpha_pr_in = alpha_pr; + auto x_nrm = dir.get_x()->infnorm(); + auto step_nrm = alpha_pr*x_nrm; + if(step_nrm>moving_lim_abs) { + alpha_pr = moving_lim_abs / step_nrm; + nlp->log->printf(hovLinesearch, + "Moving lim (absolute, [%7.3e]): step reduced: %7.3e -> %7.3e.\n", + moving_lim_abs, + alpha_pr_in, + alpha_pr); + } else { + nlp->log->printf(hovLinesearch, + "Moving lim (absolute, [%7.3e]) satisfied, step (norm %7.3e) not reduced.\n", + moving_lim_abs, + step_nrm); + } + } // end of moving lim abs + return false; +} + int hiopAlgFilterIPMBase::accept_line_search_conditions(const double theta_curr, const double theta_trial, diff --git a/src/Optimization/hiopAlgFilterIPM.hpp b/src/Optimization/hiopAlgFilterIPM.hpp index 2558056f..11902144 100644 --- a/src/Optimization/hiopAlgFilterIPM.hpp +++ b/src/Optimization/hiopAlgFilterIPM.hpp @@ -183,7 +183,7 @@ class hiopAlgFilterIPMBase { const bool& elastic_mode_on, double& mu_new, double& tau_new); - +protected: // second order correction virtual int apply_second_order_correction(hiopKKTLinSys* kkt, const double theta_curr, @@ -198,7 +198,9 @@ class hiopAlgFilterIPMBase { const double alpha_primal, bool &grad_phi_dx_computed, double &grad_phi_dx); - + /// @brief Step-length `alpha_pr` may be reduced when option 'moving_lim_abs' or 'moving_lim_rel' is active. + bool ensure_moving_lims(const hiopIterate& it, const hiopIterate& dir, double& alpha_pr); +public: /// @brief do feasibility restoration virtual bool apply_feasibility_restoration(hiopKKTLinSys* kkt); virtual bool solve_soft_feasibility_restoration(hiopKKTLinSys* kkt); diff --git a/src/Utils/hiopLogger.cpp b/src/Utils/hiopLogger.cpp index 5a82fc70..29d3452a 100644 --- a/src/Utils/hiopLogger.cpp +++ b/src/Utils/hiopLogger.cpp @@ -155,8 +155,14 @@ void hiopLogger::printf_error(hiopOutVerbosity v, const char* format, ...) char buff[4096]; va_list args; va_start (args, format); - vsnprintf(buff,4096,format, args); - fprintf(stderr,"%s",buff); + vsnprintf(buff, 4096, format, args); + if(v<=hovError) { + fprintf(stderr, "ERROR: %s", buff); + } else if(v<=hovWarning) { + fprintf(stderr, "WARNING: %s", buff); + } else { + fprintf(stderr, "%s", buff); + } va_end (args); }; diff --git a/src/Utils/hiopOptions.cpp b/src/Utils/hiopOptions.cpp index 7ba0d096..154bd60d 100644 --- a/src/Utils/hiopOptions.cpp +++ b/src/Utils/hiopOptions.cpp @@ -677,6 +677,7 @@ void hiopOptionsNLP::register_options() 0., 1e+7, "Initial value of the initial multiplier of the identity in the secant approximation (default 1.0)"); + //step length controls { vector range(2); range[0] = "no"; range[1] = "yes"; register_str_option("accept_every_trial_step", "no", range, "Disable line-search and take close-to-boundary step"); @@ -688,18 +689,26 @@ void hiopOptionsNLP::register_options() "Minimum step size allowed in line-search (default 1e-16). If step size is less than this number, " "feasibility restoration problem is activated."); + auto d_abs = "Max allowed update of the 'x' primal variables after the line-search. Primal step-length may be reduced " + "so that the inf norm of the 'x' update is less or equal with the option's value. Default value: 0 (disabled)."; + register_num_option("moving_lim_abs", 0, 0.0, 1e+8, d_abs); + + auto d_rel = "Max allowed update of the primal variables relative to fraction-to-boundary (FTB) step. Line-search " + "will be started using the FTB step scaled by the option's value. Default value: 0 (disabled)."; + register_num_option("moving_lim_rel", 0, 0.0, 1., d_rel); + register_num_option("theta_max_fact", 1e+4, 0.0, 1e+7, - "Maximum constraint violation (theta_max) is scaled by this fact before using in the fileter line-search " + "Maximum constraint violation (theta_max) is scaled by this factor before using in the filter line-search " "algorithm (default 1e+4). (eqn (21) in Filt-IPM paper)"); register_num_option("theta_min_fact", 1e-4, 0.0, 1e+7, - "Minimum constraint violation (theta_min) is scaled by this fact before using in the fileter line-search " + "Minimum constraint violation (theta_min) is scaled by this factor before using in the filter line-search " "algorithm (default 1e-4). (eqn (21) in Filt-IPM paper)"); } { @@ -1532,6 +1541,15 @@ void hiopOptionsNLP::ensure_consistence() set_val("fact_acceptor", "inertia_free"); } } + + if(0 != GetNumeric("moving_lim_rel") * GetNumeric("moving_lim_abs")) { + if(is_user_defined("moving_lim_rel") || is_user_defined("moving_lim_abs")) { + log_printf(hovWarning, + "Options 'moving_lim_rel' and 'moving_lim_rel' are both active, which is not supported. " + "Option 'moving_lim_rel' will be disabled.\n"); + } + set_val("moving_lim_rel", 0.); + } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////