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
71 , value_type obj_increase_threshold
72 , value_type max_pos_penalty_increase
73 , value_type pos_to_neg_penalty_increase
74 , value_type incr_mult_factor )
75 : merit_func_(merit_func), eta_(eta), after_k_iter_(after_k_iter)
76 , obj_increase_threshold_(obj_increase_threshold)
77 , max_pos_penalty_increase_(max_pos_penalty_increase)
78 , pos_to_neg_penalty_increase_(pos_to_neg_penalty_increase)
79 , incr_mult_factor_(incr_mult_factor)
84 , poss_type assoc_step_poss)
90 NLPAlgoState &s = algo.rsqp_state();
93 std::ostream&
out = algo.track().journal_out();
101 MeritFuncPenaltyParams
102 *params =
dynamic_cast<MeritFuncPenaltyParams*
>(&merit_func());
104 std::ostringstream omsg;
106 <<
"MeritFunc_ModifiedL1LargerSteps_AddedStep::do_step(...), Error "
107 <<
"The class " <<
typeName(&merit_func()) <<
" does not support the "
108 <<
"MeritFuncPenaltyParams iterface\n";
110 throw std::logic_error( omsg.str() );
113 bool consider_modifications = s.k() >= after_k_iter();
115 if( !consider_modifications )
119 out <<
"\nk = " << s.k() <<
" >= " <<
" after_k_iter = " << after_k_iter()
120 <<
"\nConsidering increasing the penalty parameters ...\n";
127 &f_k = s.f().get_k(0),
128 &f_kp1 = s.f().get_k(+1);
131 &c_k = s.c().get_k(0).cv(),
132 &c_kp1 = s.c().get_k(+1).cv();
135 &Gf_k = s.Gf().get_k(0).cv(),
136 &d_k = s.d().get_k(0).cv();
142 obj_increase = ( f_kp1 - f_k ) / ::fabs( f_kp1 + f_k + very_small );
143 bool attempt_modifications = obj_increase >= obj_increase_threshold();
145 if( (
int)olevel >= (
int)PRINT_ALGORITHM_STEPS ) {
146 out <<
"\n(f_kp1-f_k)/|f_kp1+f_k+very_small| = " << obj_increase
147 << ( attempt_modifications ?
" >= " :
" < " )
148 <<
"obj_increase_threshold = " << obj_increase_threshold() << std::endl;
151 if( obj_increase < obj_increase_threshold() ) {
152 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
153 out <<
"\nLeave the penalty parameters as they are.\n";
158 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
159 out <<
"\nTry to increase the penalty parameters to allow a larger SQP step... .\n";
234 mu_max =
norm_inf( mu ) * (1.0 + incr_mult_factor());
238 pos_denom_term = 0.0,
239 neg_denom_term = 0.0;
241 typedef std::vector<bool> del_pos_t;
243 del_pos( mu.size() );
246 DVectorSlice::const_iterator
248 DVector::const_iterator
249 c_k_itr = c_k.begin(),
250 c_kp1_itr = c_kp1.begin();
253 del_pos_itr = del_pos.begin();
255 for( ; c_k_itr != c_k.end(); ++mu_itr, ++c_k_itr, ++c_kp1_itr, ++del_pos_itr ) {
261 del_j = ( 1 - eta() ) * ::fabs( *c_k_itr ) - ::fabs( *c_kp1_itr );
263 num_term += (*mu_itr) * del_j;
267 pos_denom_term += ( mu_max - (*mu_itr) ) * del_j;
270 *del_pos_itr =
false;
271 neg_denom_term += ( mu_max - (*mu_itr) ) * del_j;
274 neg_denom_term /= pos_to_neg_penalty_increase();
279 a = ( f_kp1 - f_k - eta() *
dot(Gf_k,d_k) - num_term)
280 / ( pos_denom_term + neg_denom_term );
282 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
283 out <<
"\nnum_term = " << num_term
284 <<
"\npos_denom_term = " << pos_denom_term
285 <<
"\nneg_denom_term = " << neg_denom_term
286 <<
"\n\na = " << a << std::endl;
290 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
291 out <<
"\na < 0 : Leave the penalty parameters alone\n";
295 else if( a > max_pos_penalty_increase() ) {
296 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
297 out <<
"\na > max_pos_penalty_increase = " << max_pos_penalty_increase()
298 <<
"\nSet a = max_pos_penalty_increase ...\n";
300 a = max_pos_penalty_increase();
303 if( (
int)olevel >= (
int)PRINT_ALGORITHM_STEPS ) {
304 out <<
"\n0 <= a <= max_pos_penalty_increase = " << max_pos_penalty_increase()
305 <<
"\nWe should be able to take a full SQP step ...\n";
313 neg_step = pos_step / pos_to_neg_penalty_increase();
314 del_pos_t::const_iterator
315 del_pos_itr =
const_cast<const del_pos_t&
>(del_pos).begin();
316 DVectorSlice::iterator
318 for( ; mu_itr != mu.end(); ++del_pos_itr, ++mu_itr ) {
321 + (*del_pos_itr ?pos_step :neg_step) * (mu_max - (*mu_itr));
325 if( (
int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
327 <<
"\nmin(|mu(j)|) = " << (*std::min_element( mu.begin(), mu.end() ))
332 out <<
"\nmu = \n" << mu;
341 , std::ostream& out,
const std::string& L )
const
344 << L <<
"*** Increase the penalty parameters for the modified L1 merit function\n"
345 << L <<
"*** so as to allow for a larger SQP step.\n"
346 << L <<
"default: eta = " << eta() << std::endl
347 << L <<
" after_k_iter = " << after_k_iter() << std::endl
348 << L <<
" obj_increase_threshold = " << obj_increase_threshold() << std::endl
349 << L <<
" max_pos_penalty_increase = " << max_pos_penalty_increase() << std::endl
350 << L <<
" pos_to_neg_penalty_increase = " << pos_to_neg_penalty_increase() << std::endl
351 << L <<
" incr_mult_factor = " << incr_mult_factor() << std::endl
352 << L <<
"if k < after_k_iter then\n"
353 << L <<
" goto next step\n"
355 << L <<
"if (f_kp1-f_k)/abs(f_kp1+f_k+very_small) >= obj_increase_threshold then\n"
356 << L <<
" mu = phi.mu()\n"
357 << L <<
" *** Try to increase to penalty parameters mu(j) to allow for a full step.\n"
358 << L <<
" mu_max = norm(mu,inf) * (1.0+incr_mult_factor)\n"
359 << L <<
" num_term = 0\n"
360 << L <<
" pos_denom_term = 0\n"
361 << L <<
" neg_denom_term = 0\n"
362 << L <<
" for j = 1 ... m\n"
363 << L <<
" del(j) = (1-eta)*abs(c_k(j)) - abs(c_kp1(k))\n"
364 << L <<
" num_term = num_term + mu(j) * del(j)\n"
365 << L <<
" if del(j) > 0 then\n"
366 << L <<
" del_pos(j) = true\n"
367 << L <<
" pos_denom_term = pos_denom_term + (mu_max - mu(j)) * del(j)\n"
369 << L <<
" del_pos(j) = false\n"
370 << L <<
" neg_denom_term = neg_denom_term + (mu_max - mu(j)) * del(j)\n"
373 << L <<
" neg_denom_term = (1/pos_to_neg_penalty_increase) * neg_denom_term\n"
374 << L <<
" a = ( f_kp1 - f_k - eta * dot(Gf_k,d_k) - num_term)\n"
375 << L <<
" / ( pos_denom_term + neg_denom_term )\n"
376 << L <<
" if a < 0 then\n"
377 << L <<
" *** We can't take a larger SQP step by increasing mu(j)\n"
378 << L <<
" goto next step\n"
379 << L <<
" else if a > max_pos_penalty_increase then\n"
380 << L <<
" *** We are not allowed to increase mu(j) enough to allow a\n"
381 << L <<
" *** full SQP step but we will still increase mu(j) to take\n"
382 << L <<
" *** a hopefully larger step\n"
383 << L <<
" a = max_pos_penalty_increase\n"
385 << L <<
" *** We can increase mu(j) and take a full SQP step\n"
387 << L <<
" *** Increase the multipliers\n"
388 << L <<
" for j = 1...m\n"
389 << L <<
" if del_pos(j) == true then\n"
390 << L <<
" mu(j) = mu(j) + a*(mu_max - mu(j))\n"
392 << L <<
" mu(j) = mu(j) + (a/pos_to_neg_penalty_increase)*(mu_max - mu(j))\n"
MeritFunc_ModifiedL1LargerSteps_AddedStep()
std::string typeName(const T &t)
bool do_step(Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss)
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 max_element(const Vector &v)
Compute the maximum element in a vector.
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)
const f_int f_dbl_prec a[]
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
result = v_rhs1' * v_rhs2
DenseLinAlgPack::VectorSliceTmpl< value_type > DVectorSlice
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.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
value_type dot(const DVectorSlice &vs_rhs1, const DVectorSlice &vs_rhs2)
result = vs_rhs1' * vs_rhs2 (BLAS xDOT)