MOOCHO (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MoochoPack_MeritFunc_PenaltyParamUpdateGuts_AddedStep.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
5 // Copyright (2003) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #include <ostream>
43 #include <typeinfo>
44 
53 
54 namespace {
55 template< class T >
56 inline
57 T my_max( const T& v1, const T& v2 ) { return v1 > v2 ? v1 : v2; }
58 } // end namespace
59 
60 namespace MoochoPack {
61 
63  value_type small_mu
64  ,value_type mult_factor
65  ,value_type kkt_near_sol
66  )
67  :near_solution_(false)
68  ,small_mu_(small_mu)
69  ,mult_factor_(mult_factor)
70  ,kkt_near_sol_(kkt_near_sol)
71 {}
72 
74  Algorithm& _algo, poss_type step_poss, IterationPack::EDoStepType type
75  ,poss_type assoc_step_poss
76  )
77 {
78  NLPAlgo &algo = rsqp_algo(_algo);
79  NLPAlgoState &s = algo.rsqp_state();
80  NLP &nlp = algo.nlp();
81 
82  EJournalOutputLevel olevel = algo.algo_cntr().journal_output_level();
83  std::ostream& out = algo.track().journal_out();
84 
85  // print step header.
86  if( static_cast<int>(olevel) >= static_cast<int>(PRINT_ALGORITHM_STEPS) ) {
88  print_algorithm_step( algo, step_poss, type, assoc_step_poss, out );
89  }
90 
91  const size_type
92  //n = nlp.n(),
93  m = nlp.m();
94  IterQuantityAccess<MeritFuncNLP>
95  &merit_func_nlp_iq = s.merit_func_nlp();
96 
97  if( !merit_func_nlp_iq.updated_k(0) ) {
98  const int merit_func_k_last_updated = merit_func_nlp_iq.last_updated();
99  if( merit_func_k_last_updated != IterQuantity::NONE_UPDATED ) {
100  MeritFuncNLP
101  &merit_func_nlp_k_last = merit_func_nlp_iq.get_k(merit_func_k_last_updated);
102  merit_func_nlp_iq.set_k(0) = merit_func_nlp_k_last;
103  }
104  else {
105  merit_func_nlp_iq.set_k(0); // Just use default constructor
106  }
107  MeritFuncNLP
108  &merit_func_nlp_k = merit_func_nlp_iq.get_k(0);
109  MeritFuncPenaltyParam
110  *param = dynamic_cast<MeritFuncPenaltyParam*>(&merit_func_nlp_k);
112  !param, std::logic_error
113  ,"MeritFunc_PenaltyParamUpdateGuts_AddedStep::do_step(...), Error "
114  << "The class " << typeName(merit_func_nlp_k) << " does not support the "
115  << "MeritFuncPenaltyParam iterface" );
116  MeritFuncNLPDirecDeriv
117  *direc_deriv = dynamic_cast<MeritFuncNLPDirecDeriv*>(&merit_func_nlp_k);
119  !direc_deriv, std::logic_error
120  ,"MeritFunc_PenaltyParamUpdateGuts_AddedStep::do_step(...), Error "
121  << "The class " << typeName(merit_func_nlp_k) << " does not support the "
122  << "MeritFuncNLPDirecDeriv iterface" );
123  value_type new_mu = 0.0;
124  value_type min_mu = 0.0;
125  if ( this->min_mu(s,&min_mu) ) {
126  // Update the penalty parameter as defined in the fortran rSQP code (EXACT2())
127  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
128  out << "\nUpdate the penalty parameter...\n";
129  }
130  value_type
131  mu_km1 = param->mu(),
132  mult_fact = (1.0 + mult_factor_);
133  if(near_solution_) {
134  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
135  out << "\nNear solution, forcing mu_k >= mu_km1...\n";
136  }
137  new_mu = my_max( my_max( mu_km1, mult_fact * min_mu ), small_mu_ );
138  }
139  else {
140  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
141  out << "\nNot near solution, allowing reduction in mu ...\n";
142  }
143  new_mu = my_max(
144  (3.0 * mu_km1 + min_mu) / 4.0
145  , my_max( mult_fact * min_mu, small_mu_ )
146  );
147  value_type
148  kkt_error = s.opt_kkt_err().get_k(0) + s.feas_kkt_err().get_k(0);
149  if(kkt_error <= kkt_near_sol_) {
150  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
151  out << "\nkkt_error = " << kkt_error << " <= kkt_near_sol = "
152  << kkt_near_sol_ << std::endl
153  << "Switching to forcing mu_k >= mu_km1 in the future\n";
154  }
155  near_solution_ = true;
156  }
157  }
158  }
159  else {
160  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
161  out << "\nDon't have the info to update penalty parameter so just use the last updated...\n";
162  }
163  new_mu = param->mu();
164  }
165  // Set the penalty parameter
166  param->mu( new_mu );
167  // In addition also compute the directional derivative
168  direc_deriv->calc_deriv(
169  s.Gf().get_k(0)
170  ,m ? &s.c().get_k(0) : NULL
171  ,NULL // h
172  ,NULL // hl
173  ,NULL // hu
174  ,s.d().get_k(0)
175  );
176 
177  if( (int)olevel >= (int)PRINT_ALGORITHM_STEPS ) {
178  out << "\nmu = " << new_mu << "\n";
179  }
180  }
181  return true;
182 }
183 
185  , poss_type step_poss, IterationPack::EDoStepType type, poss_type assoc_step_poss
186  , std::ostream& out, const std::string& L ) const
187 {
188  out
189  << L << "*** Update the penalty parameter for the merit function to ensure\n"
190  << L << "*** a descent direction a directional derivatieve.\n"
191  << L << "*** phi is a merit function object that uses the penalty parameter mu.\n"
192  << L << "default: near_solution = false\n"
193  << L << " small_mu = " << small_mu_ << std::endl
194  << L << " mult_factor = " << mult_factor_ << std::endl
195  << L << " kkt_near_sol = " << kkt_near_sol_ << std::endl
196  << L << "if merit_func_nlp_k is not already updated then\n"
197  << L << " if some merit_func_nlp_k(?) has been udpated then\n"
198  << L << " merit_func_nlp_k = merit_func_nlp_k(last_udpated)\n"
199  << L << " else\n"
200  << L << " merit_func_nlp_k = default construction\n"
201  << L << " end\n"
202  << L << " if merit_func_nlp_k does not support MeritFuncPenaltyParam throw excpetion\n"
203  << L << " if merit_func_nlp_k does not support MeritFuncNLPDirecDeriv throw excpetion\n"
204  ;
205  print_min_mu_step( out, L + " " );
206  out
207  << L << " mu_new = merit_func_nlp_k.mu()\n"
208  << L << " if update_mu == true then\n"
209  << L << " mu_last = merit_func_nlp_k.mu()\n"
210  << L << " mult_fact = 1.0 + mult_factor\n"
211  << L << " if near_solution == true\n"
212  << L << " mu_new = max( max( mu_last, mult_fact*min_mu ), small_mu )\n"
213  << L << " else\n"
214  << L << " mu_new = max( ( 3.0 * mu_last + min_mu ) / 4.0\n"
215  << L << " , max( mult_fact * min_mu , small_mu ) )\n"
216  << L << " kkt_error = opt_kkt_err_k + feas_kkt_err_k\n"
217  << L << " if kkt_error <= kkt_near_sol then\n"
218  << L << " near_solution = true\n"
219  << L << " end\n"
220  << L << " end\n"
221  << L << " else\n"
222  << L << " mu_new = merit_func_nlp_k.mu()\n"
223  << L << " end\n"
224  << L << " merit_func_nlp_k..mu(mu_new)\n"
225  << L << " merit_func_nlp_k.calc_deriv(Gf_k,c_k,h_k,hl,hu,d_k)\n"
226  << L << "end\n"
227  ;
228 }
229 
230 // Overridden from MeritFunc_PenaltyParamUpdate_AddedStep
231 
233 {
235 }
236 
238 {
239  return small_mu_;
240 }
241 
243 {
245 }
246 
248 {
249  return mult_factor_;
250 }
251 
253 {
255 }
256 
258 {
259  return kkt_near_sol_;
260 }
261 
262 } // end namespace MoochoPack
AbstractLinAlgPack::size_type size_type
std::string typeName(const T &t)
MeritFunc_PenaltyParamUpdateGuts_AddedStep(value_type small_mu, value_type mult_factor, value_type kkt_near_sol)
virtual void print_min_mu_step(std::ostream &out, const std::string &leading_str) const =0
Override to print how min_mu calculated.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual bool min_mu(NLPAlgoState &s, value_type *min_mu) const =0
Override to determine the mininum value of mu the penalty parameter can take on.
rSQP Algorithm control class.
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
virtual std::ostream & journal_out() const
Return a reference to a std::ostream to be used to output debug information and the like...
EJournalOutputLevel
enum for journal output.
Reduced space SQP state encapsulation interface.
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.
AlgorithmTracker & track()
AbstractLinAlgPack::value_type value_type
Acts as the central hub for an iterative algorithm.
NLPAlgoState & rsqp_state()
<<std aggr>="">> members for algo_cntr
NLPAlgo & rsqp_algo(Algorithm &algo)
Convert from a Algorithm to a NLPAlgo.