52 #include "ConstrainedOptPack/src/VectorWithNorms.h"
60 inline value_type
max(value_type v1, value_type v2)
61 {
return (v1 > v2) ? v1 : v2; }
65 namespace MoochoPack {
68 const merit_func_ptr_t& merit_func, value_type small_mu, value_type min_mu_ratio
69 , value_type mult_factor, value_type kkt_near_sol )
70 : merit_func_(merit_func), near_solution_(false)
71 , small_mu_(small_mu), min_mu_ratio_(min_mu_ratio), mult_factor_(mult_factor)
72 , kkt_near_sol_(kkt_near_sol), norm_inf_mu_last_(0.0)
77 , poss_type assoc_step_poss)
82 NLPAlgoState &s = algo.rsqp_state();
85 std::ostream&
out = algo.track().journal_out();
93 MeritFuncPenaltyParams
94 *params =
dynamic_cast<MeritFuncPenaltyParams*
>(&merit_func());
96 std::ostringstream omsg;
98 <<
"MeritFunc_PenaltyParamsUpdateWithMult_AddedStep::do_step(...), Error "
99 <<
"The class " <<
typeName(&merit_func()) <<
" does not support the "
100 <<
"MeritFuncPenaltyParams iterface\n";
102 throw std::logic_error( omsg.str() );
105 MeritFuncNLPDirecDeriv
106 *direc_deriv =
dynamic_cast<MeritFuncNLPDirecDeriv*
>(&merit_func());
108 std::ostringstream omsg;
110 <<
"MeritFunc_PenaltyParamsUpdateWithMult_AddedStep::do_step(...), Error "
111 <<
"The class " <<
typeName(&merit_func()) <<
" does not support the "
112 <<
"MeritFuncNLPDirecDeriv iterface\n";
114 throw std::logic_error( omsg.str() );
117 bool perform_update =
true;
119 if( s.mu().updated_k(0) ) {
121 out <<
"\nmu_k is already updated by someone else?\n";
123 const value_type mu_k = s.mu().get_k(0);
127 <<
"\nso we will take this as a signal to skip the update.\n";
129 perform_update =
false;
134 <<
"\nso we will ignore this and perform the update anyway.\n";
140 if ( s.lambda().updated_k(0) ) {
143 out <<
"\nUpdate the penalty parameter...\n";
147 &lambda_k = s.lambda().get_k(0).cv();
149 if( params->mu().size() != lambda_k.
size() )
155 max_lambda =
norm_inf( lambda_k() ),
160 out <<
"\nNear solution, forcing mu(j) >= mu_old(j)...\n";
162 DVector::const_iterator lb_itr = lambda_k.begin();
163 DVectorSlice::iterator mu_itr = mu.begin();
164 for( ; lb_itr != lambda_k.end(); ++mu_itr, ++ lb_itr )
165 *mu_itr =
max(
max( *mu_itr, mult_fact * ::fabs(*lb_itr) ),
small_mu_ );
169 out <<
"\nNot near solution, allowing reduction in mu(j) ...\n";
171 DVector::const_iterator lb_itr = lambda_k.begin();
172 DVectorSlice::iterator mu_itr = mu.begin();
173 for( ; lb_itr != lambda_k.end(); ++mu_itr, ++ lb_itr ) {
174 const value_type lb_j = ::fabs(*lb_itr);
176 (3.0 * (*mu_itr) + lb_j) / 4.0
180 value_type kkt_error = s.opt_kkt_err().get_k(0) + s.feas_kkt_err().get_k(0);
183 out <<
"\nkkt_error = " << kkt_error <<
" <= kkt_near_sol = "
185 <<
"Switching to forcing mu_k >= mu_km1 in the future\n";
195 for(DVectorSlice::iterator mu_itr = mu.begin(); mu_itr != mu.end(); ++mu_itr)
196 *mu_itr =
max( (*mu_itr), min_mu );
202 <<
"\nmin(|mu(j)|) = " << (*std::min_element( mu.begin(), mu.end() ))
207 out <<
"\nmu = \n" << mu;
211 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
212 out <<
"\nDon't have the info to update penalty parameter so just use the last updated...\n";
218 direc_deriv->calc_deriv( s.Gf().get_k(0)(), s.c().get_k(0)(), s.d().get_k(0)() );
220 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
221 out <<
"\nmu_k = " << s.mu().get_k(0) <<
"\n";
229 , std::ostream& out,
const std::string& L )
const
232 << L <<
"*** Update the penalty parameter for the merit function to ensure\n"
233 << L <<
"*** a descent direction a directional derivatieve.\n"
234 << L <<
"*** phi is a merit function object that uses the penalty parameter mu.\n"
235 << L <<
"default: near_solution = false\n"
236 << L <<
" small_mu = " <<
small_mu_ << std::endl
240 << L <<
"perform_update = true\n"
241 << L <<
"if mu_k is already updated then\n"
242 << L <<
" if mu_k == norm_inf_mu_last then\n"
243 << L <<
" *** We will use this as a signal to skip the update\n"
244 << L <<
" perform_update = false\n"
246 << L <<
" *** We will perform the update anyway\n"
248 << L <<
"if perform_update == true then\n"
249 << L <<
" if lambda_k is updated then\n"
250 << L <<
" max_lambda = norm(lambda_k,inf)\n"
251 << L <<
" mult_fact = (1+mult_factor)\n"
252 << L <<
" mu = phi.mu()\n"
253 << L <<
" if near_solution == true\n"
254 << L <<
" for j = 1...m\n"
255 << L <<
" mu(j) = max(max(mu(j),mult_fact*abs(lambda_k(j))),small_mu)\n"
258 << L <<
" for j = 1...m\n"
259 << L <<
" mu(j) = max( ( 3.0 * mu(j) + abs(lambda_k(j)) ) / 4.0\n"
260 << L <<
" , max( 1.001 * abs(lambda_k(j)) , small_mu ) )\n"
262 << L <<
" kkt_error = opt_kkt_err_k + feas_kkt_err_k\n"
263 << L <<
" if kkt_error <= kkt_near_sol then\n"
264 << L <<
" near_solution = true\n"
267 << L <<
" min_mu = min_mu_ratio * norm(mu,inf)\n"
268 << L <<
" for j = 1...m\n"
269 << L <<
" mu(j) = max( mu(j), min_mu )\n"
272 << L <<
" *** Don't have the information to perform the update.\n"
275 << L <<
"phi.calc_deriv(Gf_k,c_k,d_k)\n";
MeritFunc_PenaltyParamsUpdateWithMult_AddedStep(const merit_func_ptr_t &merit_func, value_type small_mu=1e-6, value_type min_mu_ratio=1e-8, value_type mult_factor=1e-4, value_type kkt_near_sol=1e-1)
std::string typeName(const T &t)
value_type norm_inf_mu_last_
value_type max_element(const Vector &v)
Compute the maximum element in a vector.
int resize(OrdinalType length_in)
value_type mult_factor() const
bool do_step(Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss)
EJournalOutputLevel
enum for journal output.
void print_algorithm_step(const Algorithm &algo, Algorithm::poss_type step_poss, EDoStepType type, Algorithm::poss_type assoc_step_poss, std::ostream &out)
Prints to 'out' the algorithm step.
value_type norm_inf(const SparseVectorSlice< T_Ele > &sv_rhs)
result = ||sv_rhs||inf (BLAS IxAMAX)
void print_step(const Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss, std::ostream &out, const std::string &leading_str) const
value_type kkt_near_sol() const
int size(OrdinalType length_in)
value_type min_mu_ratio() const
DenseLinAlgPack::VectorSliceTmpl< value_type > DVectorSlice
value_type small_mu() const
AbstractLinAlgPack::value_type value_type
value_type norm_inf(const DVectorSlice &vs_rhs)
result = ||vs_rhs||infinity (BLAS IxAMAX)
NLPAlgo & rsqp_algo(Algorithm &algo)
Convert from a Algorithm to a NLPAlgo.