1 // Copyright (C) 2004, 2006 International Business Machines and others. 2 // All Rights Reserved. 3 // This code is published under the Common Public License. 4 // 5 // $Id: IpOptErrorConvCheck.cpp 759 2006-07-07 03:07:08Z andreasw $ 6 // 7 // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13 8 9 #include "IpOptErrorConvCheck.hpp" 10 11 namespace SimTKIpopt 12 { 13 #ifdef IP_DEBUG 14 static const Index dbg_verbosity = 0; 15 #endif 16 OptimalityErrorConvergenceCheck()17 OptimalityErrorConvergenceCheck::OptimalityErrorConvergenceCheck() 18 {} 19 ~OptimalityErrorConvergenceCheck()20 OptimalityErrorConvergenceCheck::~OptimalityErrorConvergenceCheck() 21 {} 22 RegisterOptions(SmartPtr<RegisteredOptions> roptions)23 void OptimalityErrorConvergenceCheck::RegisterOptions(SmartPtr<RegisteredOptions> roptions) 24 { 25 roptions->AddLowerBoundedIntegerOption( 26 "max_iter", 27 "Maximum number of iterations.", 28 0, 3000, 29 "The algorithm terminates with an error message if the number of " 30 "iterations exceeded this number."); 31 roptions->AddLowerBoundedNumberOption( 32 "dual_inf_tol", 33 "Desired threshold for the dual infeasibility.", 34 0.0, true, 1e-4, 35 "Absolute tolerance on the dual infeasibility. Successful termination " 36 "requires that the max-norm of the (unscaled) dual infeasibility is less than this " 37 "threshold."); 38 roptions->AddLowerBoundedNumberOption( 39 "constr_viol_tol", 40 "Desired threshold for the constraint violation.", 41 0.0, true, 1e-4, 42 "Absolute tolerance on the constraint violation. Successful termination " 43 "requires that the max-norm of the (unscaled) constraint violation is less than this " 44 "threshold."); 45 roptions->AddLowerBoundedNumberOption( 46 "compl_inf_tol", 47 "Desired threshold for the complementarity conditions.", 48 0.0, true, 1e-4, 49 "Absolute tolerance on the complementarity. Successful termination " 50 "requires that the max-norm of the (unscaled) complementarity is less than this " 51 "threshold."); 52 roptions->AddLowerBoundedNumberOption( 53 "acceptable_tol", 54 "\"Acceptable\" convergence tolerance (relative).", 55 0.0, true, 1e-6, 56 "Determines which (scaled) overall optimality error is considered to be" 57 " \"acceptable.\" There are two levels of termination criteria. If the " 58 "usual \"desired\" tolerances (see tol, dual_inf_tol etc) are satisfied " 59 "at an iteration, the algorithm immediately terminates with a success " 60 "message. On the other hand, if the algorithm encounters " 61 "\"acceptable_iter\" many iterations in a row that are considered " 62 "\"acceptable\", it will terminate before the desired convergence " 63 "tolerance is met. This is useful in cases where the algorithm might " 64 "not be able to achieve the \"desired\" level of accuracy."); 65 roptions->AddLowerBoundedIntegerOption( 66 "acceptable_iter", 67 "Number of \"acceptable\" iterates before triggering termination.", 68 0, 15, 69 "If the algorithm encounters this many successive \"acceptable\" iterates " 70 "(see \"acceptable_tol\"), it terminates, assuming that the problem " 71 "has been solved to best possible accuracy given round-off. If it is " 72 "set to zero, this heuristic is disabled."); 73 roptions->AddLowerBoundedNumberOption( 74 "acceptable_dual_inf_tol", 75 "\"Acceptance\" threshold for the dual infeasibility.", 76 0.0, true, 1e-2, 77 "Absolute tolerance on the dual infeasibility. \"Acceptable\" termination " 78 "requires that the (max-norm of the unscaled) dual infeasibility is less than this " 79 "threshold; see also acceptable_tol."); 80 roptions->AddLowerBoundedNumberOption( 81 "acceptable_constr_viol_tol", 82 "\"Acceptance\" threshold for the constraint violation.", 83 0.0, true, 1e-2, 84 "Absolute tolerance on the constraint violation. \"Acceptable\" termination " 85 "requires that the max-norm of the (unscaled) constraint violation is less than this " 86 "threshold; see also acceptable_tol."); 87 roptions->AddLowerBoundedNumberOption( 88 "acceptable_compl_inf_tol", 89 "\"Acceptance\" threshold for the complementarity conditions.", 90 0.0, true, 1e-2, 91 "Absolute tolerance on the complementarity. \"Acceptable\" termination " 92 "requires that the max-norm of the (unscaled) complementarity is less than this " 93 "threshold; see also acceptable_tol."); 94 roptions->AddLowerBoundedNumberOption( 95 "diverging_iterates_tol", 96 "Threshold for maximal value of primal iterates.", 97 0.0, true, 1e20, 98 "If any component of the primal iterates exceeded this value (in " 99 "absolute terms), the optimization is aborted with the exit message " 100 "that the iterates seem to be diverging."); 101 } 102 103 bool InitializeImpl(const OptionsList & options,const std::string & prefix)104 OptimalityErrorConvergenceCheck::InitializeImpl(const OptionsList& options, 105 const std::string& prefix) 106 { 107 options.GetIntegerValue("max_iter", max_iterations_, prefix); 108 options.GetNumericValue("dual_inf_tol", dual_inf_tol_, prefix); 109 options.GetNumericValue("constr_viol_tol", constr_viol_tol_, prefix); 110 options.GetNumericValue("compl_inf_tol", compl_inf_tol_, prefix); 111 options.GetIntegerValue("acceptable_iter", acceptable_iter_, prefix); 112 options.GetNumericValue("acceptable_tol", acceptable_tol_, prefix); 113 options.GetNumericValue("acceptable_dual_inf_tol", acceptable_dual_inf_tol_, prefix); 114 options.GetNumericValue("acceptable_constr_viol_tol", acceptable_constr_viol_tol_, prefix); 115 options.GetNumericValue("acceptable_compl_inf_tol", acceptable_compl_inf_tol_, prefix); 116 options.GetNumericValue("diverging_iterates_tol", diverging_iterates_tol_, prefix); 117 acceptable_counter_ = 0; 118 119 return true; 120 } 121 122 ConvergenceCheck::ConvergenceStatus CheckConvergence(bool call_intermediate_callback)123 OptimalityErrorConvergenceCheck::CheckConvergence(bool call_intermediate_callback /*= true*/) 124 { 125 DBG_START_METH("OptimalityErrorConvergenceCheck::CheckConvergence", dbg_verbosity); 126 127 if (call_intermediate_callback) { 128 // Check if user requested termination by calling the intermediate 129 // user callback function 130 AlgorithmMode mode = RegularMode; 131 // Gather the information also used in the iteration output 132 Index iter = IpData().iter_count(); 133 Number inf_pr = IpCq().curr_primal_infeasibility(NORM_MAX); 134 Number inf_du = IpCq().curr_dual_infeasibility(NORM_MAX); 135 Number mu = IpData().curr_mu(); 136 Number dnrm; 137 if (IsValid(IpData().delta()) && IsValid(IpData().delta()->x()) && IsValid(IpData().delta()->s())) { 138 dnrm = Max(IpData().delta()->x()->Amax(), IpData().delta()->s()->Amax()); 139 } 140 else { 141 // This is the first iteration - no search direction has been 142 // computed yet. 143 dnrm = 0.; 144 } 145 Number alpha_primal = IpData().info_alpha_primal(); 146 Number alpha_dual = IpData().info_alpha_dual(); 147 Number regu_x = IpData().info_regu_x(); 148 Number unscaled_f = IpCq().unscaled_curr_f(); 149 Index ls_count = IpData().info_ls_count(); 150 bool request_stop = 151 !IpNLP().IntermediateCallBack(mode, iter, unscaled_f, inf_pr, inf_du, 152 mu, dnrm, regu_x, alpha_dual, 153 alpha_primal, ls_count, 154 &IpData(), &IpCq()); 155 156 if (request_stop) { 157 return ConvergenceCheck::USER_STOP; 158 } 159 } 160 161 if (IpData().iter_count() >= max_iterations_) { 162 return ConvergenceCheck::MAXITER_EXCEEDED; 163 } 164 165 Number overall_error = IpCq().curr_nlp_error(); 166 Number dual_inf = IpCq().unscaled_curr_dual_infeasibility(NORM_MAX); 167 Number constr_viol = IpCq().unscaled_curr_nlp_constraint_violation(NORM_MAX); 168 Number compl_inf = IpCq().unscaled_curr_complementarity(0., NORM_MAX); 169 170 if (IpData().curr()->x()->Dim()==IpData().curr()->y_c()->Dim()) { 171 // the problem is square, there is no point in looking at dual 172 // infeasibility and complementarity as termination criterion 173 dual_inf_tol_ = 1e300; 174 compl_inf_tol_ = 1e300; 175 } 176 177 if (overall_error <= IpData().tol() && 178 dual_inf <= dual_inf_tol_ && 179 constr_viol <= constr_viol_tol_ && 180 compl_inf <= compl_inf_tol_) { 181 return ConvergenceCheck::CONVERGED; 182 } 183 184 if (acceptable_iter_>0 && CurrentIsAcceptable()) { 185 IpData().Append_info_string("A"); 186 acceptable_counter_++; 187 if (acceptable_counter_ >= acceptable_iter_) { 188 return ConvergenceCheck::CONVERGED_TO_ACCEPTABLE_POINT; 189 } 190 } 191 else { 192 acceptable_counter_ = 0; 193 } 194 195 if (IpData().curr()->x()->Amax() > diverging_iterates_tol_) { 196 return ConvergenceCheck::DIVERGING; 197 } 198 199 return ConvergenceCheck::CONTINUE; 200 } 201 CurrentIsAcceptable()202 bool OptimalityErrorConvergenceCheck::CurrentIsAcceptable() 203 { 204 DBG_START_METH("OptimalityErrorConvergenceCheck::CurrentIsAcceptable", 205 dbg_verbosity); 206 207 Number overall_error = IpCq().curr_nlp_error(); 208 Number dual_inf = IpCq().unscaled_curr_dual_infeasibility(NORM_MAX); 209 Number constr_viol = IpCq().unscaled_curr_nlp_constraint_violation(NORM_MAX); 210 Number compl_inf = IpCq().unscaled_curr_complementarity(0., NORM_MAX); 211 212 DBG_PRINT((1, "overall_error = %e\n", overall_error)); 213 DBG_PRINT((1, "dual_inf = %e\n", dual_inf)); 214 DBG_PRINT((1, "constr_viol = %e\n", constr_viol)); 215 DBG_PRINT((1, "compl_inf = %e\n", compl_inf)); 216 217 DBG_PRINT((1, "acceptable_tol_ = %e\n", acceptable_tol_)); 218 DBG_PRINT((1, "acceptable_dual_inf_tol_ = %e\n", acceptable_dual_inf_tol_)); 219 DBG_PRINT((1, "acceptable_constr_viol_tol_ = %e\n", acceptable_constr_viol_tol_)); 220 DBG_PRINT((1, "acceptable_compl_inf_tol_ = %e\n", acceptable_compl_inf_tol_)); 221 222 if (IpData().curr()->x()->Dim()==IpData().curr()->y_c()->Dim()) { 223 // the problem is square, there is no point in looking at dual 224 // infeasibility and complementarity as termination criterion 225 acceptable_dual_inf_tol_ = 1e300; 226 acceptable_compl_inf_tol_ = 1e300; 227 } 228 229 return (overall_error <= acceptable_tol_ && 230 dual_inf <= acceptable_dual_inf_tol_ && 231 constr_viol <= acceptable_constr_viol_tol_ && 232 compl_inf <= acceptable_compl_inf_tol_); 233 } 234 235 236 } // namespace Ipopt 237