MOOCHO (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MoochoPack_MeritFunc_PenaltyParamsUpdateWithMult_AddedStep.cpp
Go to the documentation of this file.
1 #if 0
2 
3 // @HEADER
4 // ***********************************************************************
5 //
6 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
7 // Copyright (2003) Sandia Corporation
8 //
9 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
10 // license for use of this work by or on behalf of the U.S. Government.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
40 //
41 // ***********************************************************************
42 // @HEADER
43 
44 #include <ostream>
45 #include <typeinfo>
46 
52 #include "ConstrainedOptPack/src/VectorWithNorms.h"
56 
57 namespace {
58 
60 inline value_type max(value_type v1, value_type v2)
61 { return (v1 > v2) ? v1 : v2; }
62 
63 }
64 
65 namespace MoochoPack {
66 
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)
73 {}
74 
76  , poss_type step_poss, IterationPack::EDoStepType type
77  , poss_type assoc_step_poss)
78 {
80 
81  NLPAlgo &algo = rsqp_algo(_algo);
82  NLPAlgoState &s = algo.rsqp_state();
83 
84  EJournalOutputLevel olevel = algo.algo_cntr().journal_output_level();
85  std::ostream& out = algo.track().journal_out();
86 
87  // print step header.
88  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
90  print_algorithm_step( algo, step_poss, type, assoc_step_poss, out );
91  }
92 
93  MeritFuncPenaltyParams
94  *params = dynamic_cast<MeritFuncPenaltyParams*>(&merit_func());
95  if( !params ) {
96  std::ostringstream omsg;
97  omsg
98  << "MeritFunc_PenaltyParamsUpdateWithMult_AddedStep::do_step(...), Error "
99  << "The class " << typeName(&merit_func()) << " does not support the "
100  << "MeritFuncPenaltyParams iterface\n";
101  out << omsg.str();
102  throw std::logic_error( omsg.str() );
103  }
104 
105  MeritFuncNLPDirecDeriv
106  *direc_deriv = dynamic_cast<MeritFuncNLPDirecDeriv*>(&merit_func());
107  if( !direc_deriv ) {
108  std::ostringstream omsg;
109  omsg
110  << "MeritFunc_PenaltyParamsUpdateWithMult_AddedStep::do_step(...), Error "
111  << "The class " << typeName(&merit_func()) << " does not support the "
112  << "MeritFuncNLPDirecDeriv iterface\n";
113  out << omsg.str();
114  throw std::logic_error( omsg.str() );
115  }
116 
117  bool perform_update = true;
118 
119  if( s.mu().updated_k(0) ) {
120  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
121  out << "\nmu_k is already updated by someone else?\n";
122  }
123  const value_type mu_k = s.mu().get_k(0);
124  if( mu_k == norm_inf_mu_last_ ) {
125  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
126  out << "\nmu_k " << mu_k << " == norm_inf_mu_last = " << norm_inf_mu_last_
127  << "\nso we will take this as a signal to skip the update.\n";
128  }
129  perform_update = false;
130  }
131  else {
132  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
133  out << "\nmu_k " << mu_k << " != norm_inf_mu_last = " << norm_inf_mu_last_
134  << "\nso we will ignore this and perform the update anyway.\n";
135  }
136  }
137  }
138  if(perform_update) {
139 
140  if ( s.lambda().updated_k(0) ) {
141 
142  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
143  out << "\nUpdate the penalty parameter...\n";
144  }
145 
146  const DVector
147  &lambda_k = s.lambda().get_k(0).cv();
148 
149  if( params->mu().size() != lambda_k.size() )
150  params->resize( lambda_k.size() );
152  mu = params->mu();
153 
154  const value_type
155  max_lambda = norm_inf( lambda_k() ),
156  mult_fact = (1.0 + mult_factor_);
157 
158  if(near_solution_) {
159  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
160  out << "\nNear solution, forcing mu(j) >= mu_old(j)...\n";
161  }
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_ );
166  }
167  else {
168  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
169  out << "\nNot near solution, allowing reduction in mu(j) ...\n";
170  }
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);
175  *mu_itr = max(
176  (3.0 * (*mu_itr) + lb_j) / 4.0
177  , max( mult_fact * lb_j, small_mu_ )
178  );
179  }
180  value_type kkt_error = s.opt_kkt_err().get_k(0) + s.feas_kkt_err().get_k(0);
181  if(kkt_error <= kkt_near_sol_) {
182  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
183  out << "\nkkt_error = " << kkt_error << " <= kkt_near_sol = "
184  << kkt_near_sol_ << std::endl
185  << "Switching to forcing mu_k >= mu_km1 in the future\n";
186  }
187  near_solution_ = true;
188  }
189  }
190 
191  // Force the ratio
192  const value_type
193  max_mu = norm_inf( mu() ),
194  min_mu = min_mu_ratio_ * max_mu;
195  for(DVectorSlice::iterator mu_itr = mu.begin(); mu_itr != mu.end(); ++mu_itr)
196  *mu_itr = max( (*mu_itr), min_mu );
197 
198  s.mu().set_k(0) = norm_inf_mu_last_ = max_mu;
199 
200  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
201  out << "\nmax(|mu(j)|) = " << (*std::max_element( mu.begin(), mu.end() ))
202  << "\nmin(|mu(j)|) = " << (*std::min_element( mu.begin(), mu.end() ))
203  << std::endl;
204  }
205 
206  if( (int)olevel >= (int)PRINT_VECTORS ) {
207  out << "\nmu = \n" << mu;
208  }
209  }
210  else {
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";
213  }
214  }
215  }
216 
217  // In addition also compute the directional derivative
218  direc_deriv->calc_deriv( s.Gf().get_k(0)(), s.c().get_k(0)(), s.d().get_k(0)() );
219 
220  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
221  out << "\nmu_k = " << s.mu().get_k(0) << "\n";
222  }
223 
224  return true;
225 }
226 
228  , poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss
229  , std::ostream& out, const std::string& L ) const
230 {
231  out
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
237  << L << " min_mu_ratio = " << min_mu_ratio_ << std::endl
238  << L << " mult_factor = " << mult_factor_ << std::endl
239  << L << " kkt_near_sol = " << kkt_near_sol_ << 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"
245  << L << " else\n"
246  << L << " *** We will perform the update anyway\n"
247  << L << " end\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"
256  << L << " end\n"
257  << L << " else\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"
261  << L << " end\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"
265  << L << " end\n"
266  << L << " end\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"
270  << L << " end\n"
271  << L << " else\n"
272  << L << " *** Don't have the information to perform the update.\n"
273  << L << " end\n"
274  << L << "end\n"
275  << L << "phi.calc_deriv(Gf_k,c_k,d_k)\n";
276 }
277 
278 // Overridden from MeritFunc_PenaltyParamUpdate_AddedStep
279 
281 {
283 }
284 
286 {
287  return small_mu_;
288 }
289 
291 {
293 }
294 
296 {
297  return min_mu_ratio_;
298 }
299 
301 {
303 }
304 
306 {
307  return mult_factor_;
308 }
309 
311 {
313 }
314 
316 {
317  return kkt_near_sol_;
318 }
319 
320 
321 } // end namespace MoochoPack
322 
323 #endif // 0
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 max_element(const Vector &v)
Compute the maximum element in a vector.
int resize(OrdinalType length_in)
bool do_step(Algorithm &algo, poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss)
EJournalOutputLevel
enum for journal output.
std::ostream * out
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
int size(OrdinalType length_in)
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.