DOpE
reduced_snopt_algorithm.h
Go to the documentation of this file.
1 
24 #ifndef _REDUCED_SNOPT__ALGORITHM_H_
25 #define _REDUCED_SNOPT__ALGORITHM_H_
26 
27 #include "reducedalgorithm.h"
28 #include "parameterreader.h"
29 
30 #include "snopt_wrapper.h"
31 
32 #include <iostream>
33 #include <assert.h>
34 #include <iomanip>
35 
36 namespace DOpE
37 {
52  template<typename PROBLEM, typename VECTOR>
53  class Reduced_SnoptAlgorithm : public ReducedAlgorithm<PROBLEM, VECTOR>
54  {
55  public:
56  Reduced_SnoptAlgorithm(PROBLEM* OP,
58  std::string vector_behavior, ParameterReader &param_reader,
59  DOpEExceptionHandler<VECTOR>* Except = NULL,
60  DOpEOutputHandler<VECTOR>* Output = NULL, int base_priority = 0);
62 
68  static void
69  declare_params(ParameterReader &param_reader);
70 
83  virtual int
84  Solve(ControlVector<VECTOR>& q, double global_tol = -1.);
85 
86  protected:
87 
88  private:
89 #ifdef WITH_SNOPT
90  int rsa_func_(DOpEWrapper::SNOPT_FUNC_DATA& data);
91 #endif
92  std::string _postindex;
93  std::string _vector_behavior;
94 
95  double _func_prec, _feas_tol, _opt_tol;
96  int _max_inner_iter, _max_outer_iter;
97  bool _capture_out;
98  };
99 
100  /***************************************************************************************/
101  /****************************************IMPLEMENTATION*********************************/
102  /***************************************************************************************/
103  using namespace dealii;
104 
105  /******************************************************/
106 
107  template<typename PROBLEM, typename VECTOR>
108  void
110  ParameterReader &param_reader)
111  {
112  param_reader.SetSubsection("reduced_snoptalgorithm parameters");
113  param_reader.declare_entry("function precision", "1.e-6",
114  Patterns::Double(0, 1),
115  "Declares how many digits we assume to have computed correctly, this should correspond to the tolerance used for the PDE solve");
116  param_reader.declare_entry("feasibility tol", "1.e-5",
117  Patterns::Double(0, 1),
118  "Tolerance with respect to the feasibility of the constraints.");
119  param_reader.declare_entry("optimality tol", "1.e-5",
120  Patterns::Double(0, 1),
121  "Tolerance with respect to the optimality condition.");
122  param_reader.declare_entry("max inner iterations", "500",
123  Patterns::Integer(0),
124  "Maximal allowed number of inner iterations over all outer iterations");
125  param_reader.declare_entry("max iterations", "1000", Patterns::Integer(0),
126  "Maximal allowed number of outer iterations over all outer iterations");
127  param_reader.declare_entry("capture snopt output", "true",
128  Patterns::Bool(),
129  "Select if the snopt output should be stored in log file");
131  }
132 
133  /******************************************************/
134 
135  template<typename PROBLEM, typename VECTOR>
138  std::string vector_behavior, ParameterReader &param_reader,
140  int base_priority) :
141  ReducedAlgorithm<PROBLEM, VECTOR>(OP, S, param_reader, Except, Output,
142  base_priority)
143  {
144 
145  param_reader.SetSubsection("reduced_snoptalgorithm parameters");
146 
147  _func_prec = param_reader.get_double("function precision");
148  _feas_tol = param_reader.get_double("feasibility tol");
149  _opt_tol = param_reader.get_double("optimality tol");
150  _max_inner_iter = param_reader.get_integer("max inner iterations");
151  _max_outer_iter = param_reader.get_integer("max iterations");
152  _capture_out = param_reader.get_bool("capture snopt output");
153 
154  _vector_behavior = vector_behavior;
155  _postindex = "_" + this->GetProblem()->GetName();
156 
157  }
158 
159  /******************************************************/
160 
161  template<typename PROBLEM, typename VECTOR>
163  {
164 
165  }
166 
167  /******************************************************/
168 
169  template<typename PROBLEM, typename VECTOR>
170  int
172  double global_tol)
173  {
174 #ifndef WITH_SNOPT
175  throw DOpEException("To use this algorithm you need to have SNOPT installed! To use this set the WITH_SNOPT CompilerFlag.","Reduced_SnoptAlgorithm::Solve");
176 #else
177  q.ReInit();
178 
179  ControlVector<VECTOR> dq(q);
180  ControlVector<VECTOR> q_min(q), q_max(q);
181  this->GetReducedProblem()->GetControlBoxConstraints(q_min,q_max);
182 
183  ConstraintVector<VECTOR> constraints(this->GetReducedProblem()->GetProblem()->GetSpaceTimeHandler(),_vector_behavior);
184 
185  unsigned int iter=0;
186  double cost=0.;
187  double cost_start=0.;
188  std::stringstream out;
189  this->GetOutputHandler()->InitNewtonOut(out);
190  global_tol = std::max(_opt_tol,global_tol);
191 
192  out << "**************************************************\n";
193  out << "* Starting Solution using SNOPT *\n";
194  out << "* Solving : "<<this->GetProblem()->GetName()<<"\t*\n";
195  out << "* CDoFs : ";
196  q.PrintInfos(out);
197  out << "* SDoFs : ";
198  this->GetReducedProblem()->StateSizeInfo(out);
199  out << "* Constraints : ";
200  constraints.PrintInfos(out);
201  out << "**************************************************";
202  this->GetOutputHandler()->Write(out,1+this->GetBasePriority(),1,1);
203 
204  this->GetOutputHandler()->SetIterationNumber(iter,"Opt_Snopt"+_postindex);
205 
206  this->GetOutputHandler()->Write(q,"Control"+_postindex,"control");
207 
208  try
209  {
210  cost_start = cost = this->GetReducedProblem()->ComputeReducedCostFunctional(q);
211  }
212  catch(DOpEException& e)
213  {
214  this->GetExceptionHandler()->HandleCriticalException(e,"Reduced_SnoptAlgorithm::Solve");
215  }
216 
217  this->GetOutputHandler()->InitOut(out);
218  out<< "CostFunctional: " << cost;
219  this->GetOutputHandler()->Write(out,2+this->GetBasePriority());
220  this->GetOutputHandler()->InitNewtonOut(out);
221 
223  out<<"************************************************\n";
224  out<<"* Calling SNOPT *\n";
225  if(_capture_out)
226  out<<"* output will be written to logfile only! *\n";
227  else
228  out<<"* output will not be written to logfile! *\n";
229  out<<"************************************************\n\n";
230  this->GetOutputHandler()->Write(out,1+this->GetBasePriority());
231 
232  this->GetOutputHandler()->DisallowAllOutput();
233  if(_capture_out)
234  this->GetOutputHandler()->StartSaveCTypeOutputToLog();
235 
236  int ret_val;
237  {
238  DOpEWrapper::SNOPT_Problem RSAProb;
239 
240  integer n=q.GetSpacialVector().size();
241  integer neF =1+constraints.GetGlobalConstraints().size();
242  integer lenA=0;
243  integer neA=0;
244  integer *iAfun = NULL;
245  integer *jAvar = NULL;
246  doublereal *A = NULL;
247 
248  integer lenG = n*(neF); //We have that the derivative of J and the global constraints
249  //are nonzero w.r.t. all components.
250  integer neG = lenG; //Predefine the number of valid entries in iGfun and jGvar will be lenG.
251  integer *iGfun = new integer[lenG];
252  integer *jGvar = new integer[lenG];
253 
254  doublereal *x = new doublereal[n];
255  doublereal *xlow = new doublereal[n];
256  doublereal *xupp = new doublereal[n];
257  doublereal *xmul = new doublereal[n];
258  integer *xstate = new integer[n];
259 
260  doublereal *F = new doublereal[neF];
261  doublereal *Flow = new doublereal[neF];
262  doublereal *Fupp = new doublereal[neF];
263  doublereal *Fmul = new doublereal[neF];
264  integer *Fstate = new integer[neF];
265 
266  integer nxnames = 1;
267  integer nFnames = 1;
268  char *xnames = new char[nxnames*8];
269  char *Fnames = new char[nFnames*8];
270 
271  integer ObjRow = 0;
272  doublereal ObjAdd = 0;
273 
274  {
275  const VECTOR& gv_q = q.GetSpacialVector();
276  const VECTOR& gv_qmin = q_min.GetSpacialVector();
277  const VECTOR& gv_qmax = q_max.GetSpacialVector();
278 
279  for(unsigned int i=0; i < n; i++)
280  {
281  x[i] = gv_q(i);
282  xlow[i] = gv_qmin(i);
283  xupp[i] = gv_qmax(i);
284  xstate[i] = 0;
285  iGfun[i] = 0;
286  jGvar[i] = i;
287  }
288  Flow[0] = -1.e+20;
289  Fupp[0] = 1.e+20;
290  Fstate[0] = 0;
291  for(unsigned int j = 1; j<neF; j++)
292  { //Global constraints are to be given by the user such that
293  //The feasible region is given by <= 0
294  //TODO this should be defineable by the user...
295  Flow[j] = -1.e+20;
296  Fupp[j] = 0.;
297  Fstate[j] = 0;
298  for(unsigned int i=0; i < n; i++)
299  {
300  iGfun[n*j+i] = j;
301  jGvar[n*j+i] = i;
302  }
303  }
304  }
305 
306  //RSAProb.setPrintFile ( "RSA.out" );
307  RSAProb.setProblemSize( n, neF );
308  RSAProb.setObjective ( ObjRow, ObjAdd );
309  RSAProb.setA ( lenA, iAfun, jAvar, A );
310  RSAProb.setG ( lenG, iGfun, jGvar );
311  RSAProb.setX ( x, xlow, xupp, xmul, xstate );
312  RSAProb.setF ( F, Flow, Fupp, Fmul, Fstate );
313  RSAProb.setXNames ( xnames, nxnames );
314  RSAProb.setFNames ( Fnames, nFnames );
315  RSAProb.setProbName ( "RSA" );
316  RSAProb.setNeA ( neA );
317  RSAProb.setNeG ( neG );
318 
319  DOpEWrapper::SNOPT_A_userfunc_interface = boost::bind<int>(boost::mem_fn(&Reduced_SnoptAlgorithm<PROBLEM, VECTOR>::rsa_func_),boost::ref(*this),_1);
320  RSAProb.setUserFun ( DOpEWrapper::SNOPT_A_userfunc_ );
321 
322  RSAProb.setIntParameter( "Derivative option", 1 );
323  RSAProb.setRealParameter( "Function precison", _func_prec);
324  RSAProb.setRealParameter( "Major optimality tolerance", global_tol);
325  RSAProb.setRealParameter( "Major feasibility tolerance", _feas_tol);
326  RSAProb.setRealParameter( "Minor feasibility tolerance", _feas_tol);
327  RSAProb.setIntParameter( "Minor iterations limit", _max_inner_iter);
328  RSAProb.setIntParameter( "Major iterations limit", _max_outer_iter);
329  RSAProb.solve(2);
330  ret_val = RSAProb.GetReturnStatus();
331  {
332  VECTOR& gv_q = q.GetSpacialVector();
333  for(unsigned int i=0; i < gv_q.size(); i++)
334  gv_q(i) = x[i];
335  }
336  if(iAfun != NULL)
337  delete []iAfun;
338  if(jAvar != NULL)
339  delete []jAvar;
340  if(A != NULL)
341  delete []A;
342  delete []iGfun; delete []jGvar;
343 
344  delete []x; delete []xlow; delete []xupp;
345  delete []xmul; delete []xstate;
346 
347  delete []F; delete []Flow; delete []Fupp;
348  delete []Fmul; delete []Fstate;
349 
350  delete []xnames; delete []Fnames;
351 
352  }
353 
354  if(_capture_out)
355  this->GetOutputHandler()->StopSaveCTypeOutputToLog();
356  this->GetOutputHandler()->ResumeOutput();
357  out<<"\n************************************************\n";
358  out<<"* SNOPT Finished *\n";
359  out<<"* with Exit Code: "<<std::setw(3)<<ret_val;
360  if(ret_val == 1)
361  out<<" (success) *\n";
362  else
363  out<<" (unknown error) *\n";
364  out<<"************************************************\n";
365  //FIXME What is the result...
366  this->GetOutputHandler()->Write(out,1+this->GetBasePriority());
367 
368  iter++;
369  this->GetOutputHandler()->SetIterationNumber(iter,"Opt_Snopt"+_postindex);
370 
371  this->GetOutputHandler()->Write(q,"Control"+_postindex,"control");
372  try
373  {
374  cost = this->GetReducedProblem()->ComputeReducedCostFunctional(q);
375  }
376  catch(DOpEException& e)
377  {
378  this->GetExceptionHandler()->HandleCriticalException(e,"Reduced_SnoptAlgorithm::Solve");
379  }
380  //We are done write total evaluation
381  this->GetOutputHandler()->InitOut(out);
382  out<< "CostFunctional: " << cost;
383  this->GetOutputHandler()->Write(out,2+this->GetBasePriority());
384  this->GetOutputHandler()->InitNewtonOut(out);
385  try
386  {
387  this->GetReducedProblem()->ComputeReducedFunctionals(q);
388  }
389  catch(DOpEException& e)
390  {
391  this->GetExceptionHandler()->HandleCriticalException(e,"Reduced_SnoptAlgorithm::Solve");
392  }
393 
394  out << "**************************************************\n";
395  out << "* Stopping Solution Using SNOPT *\n";
396  out << "* Relative reduction in cost functional:"<<std::scientific << std::setw(11) << this->GetOutputHandler()->ZeroTolerance((cost-cost_start)/fabs(0.5*(cost_start+cost)),1.0) <<" *\n";
397  out.precision(7);
398  out << "* Final value: "<<cost<<" *\n";
399  out << "**************************************************";
400  this->GetOutputHandler()->Write(out,1+this->GetBasePriority(),1,1);
401  return iter;
402 #endif //Endof ifdef WITHSNOPT
403  }
404 
405 /******************************************************/
406 
407 #ifdef WITH_SNOPT
408 template <typename PROBLEM, typename VECTOR>
410 ::rsa_func_(DOpEWrapper::SNOPT_FUNC_DATA& data )
411 {
412  //Needs to implement the evaluation of j and its derivative using the
413  //Interface required by SNOPT
414  ConstraintVector<VECTOR>* constraints = NULL;
415  ControlVector<VECTOR> tmp(this->GetReducedProblem()->GetProblem()->GetSpaceTimeHandler(),_vector_behavior);
416  VECTOR& ref_x = tmp.GetSpacialVector();
417  assert(ref_x.size() == *(data.n));
418  for(unsigned int i=0; i < ref_x.size(); i++)
419  ref_x(i) = (data.x)[i];
420 
421  assert(*(data.needF) > 0);
422  try
423  {
424  (data.F)[0] = this->GetReducedProblem()->ComputeReducedCostFunctional(tmp);
425  }
426  catch(DOpEException& e)
427  {
428  *(data.Status) = -1;
429  this->GetExceptionHandler()->HandleException(e,"Reduced_SnoptAlgorithm::rsa_func_");
430  return -1;
431  }
432 
433  if(*(data.neF) > 1)
434  {
435  constraints = new ConstraintVector<VECTOR>(this->GetReducedProblem()->GetProblem()->GetSpaceTimeHandler(),_vector_behavior);
436  try
437  {
438  this->GetReducedProblem()->ComputeReducedConstraints(tmp,*constraints);
439  }
440  catch(DOpEException& e)
441  {
442  *(data.Status) = -1;
443  this->GetExceptionHandler()->HandleException(e,"Reduced_SnoptAlgorithm::rsa_func_");
444 
445  if(constraints != NULL)
446  delete constraints;
447  return -1;
448  }
449  const dealii::Vector<double>& gc = constraints->GetGlobalConstraints();
450  assert(*(data.neF) == gc.size()+1);
451  for(unsigned int i=0; i < gc.size(); i++)
452  {
453  (data.F)[i+1] = gc(i);
454  }
455  }
456 
457  if(*(data.needG) > 0)
458  {
459  ControlVector<VECTOR> gradient(tmp);
460  ControlVector<VECTOR> gradient_transposed(tmp);
461 
462  try
463  {
464  this->GetReducedProblem()->ComputeReducedGradient(tmp,gradient,gradient_transposed);
465  }
466  catch(DOpEException& e)
467  {
468  *(data.Status) = -2;
469  this->GetExceptionHandler()->HandleException(e,"Reduced_SnoptAlgorithm::rsa_func_");
470 
471  if(constraints != NULL)
472  delete constraints;
473  return -1;
474  }
475  assert(*(data.neG) == *(data.n)**(data.neF));
476  const VECTOR& ref_g = gradient_transposed.GetSpacialVector();
477  for(unsigned int i=0; i < *(data.n); i++)
478  {
479  (data.G)[i] = ref_g(i);
480  }
481  if(constraints != NULL)
482  {
483  //Evaluate global constraint gradients
484  const dealii::Vector<double>& gc = constraints->GetGlobalConstraints();
485  for(unsigned int j=0; j < gc.size(); j++)
486  {
487  try
488  {
489  this->GetReducedProblem()->ComputeReducedGradientOfGlobalConstraints(j,tmp,*constraints,gradient,gradient_transposed);
490  }
491  catch(DOpEException& e)
492  {
493  *(data.Status) = -2;
494  this->GetExceptionHandler()->HandleException(e,"Reduced_SnoptAlgorithm::rsa_func_");
495 
496  if(constraints != NULL)
497  delete constraints;
498  return -1;
499  }
500  const VECTOR& ref_g = gradient_transposed.GetSpacialVector();
501  for(unsigned int i=0; i < *(data.n); i++)
502  {
503  (data.G)[*(data.n)*(j+1)+i] = ref_g(i);
504  }
505  }
506  }
507  }
508 
509  if(constraints != NULL)
510  delete constraints;
511  *(data.Status) = 0;
512  return 0;
513 }
514 #endif //Endof ifdef WITHSNOPT
515 /*****************************END_OF_NAMESPACE_DOpE*********************************/
516 }
517 #endif
void PrintInfos(std::stringstream &out)
Definition: controlvector.cc:542
Definition: constraintvector.h:47
Reduced_SnoptAlgorithm(PROBLEM *OP, ReducedProblemInterface< PROBLEM, VECTOR > *S, std::string vector_behavior, ParameterReader &param_reader, DOpEExceptionHandler< VECTOR > *Except=NULL, DOpEOutputHandler< VECTOR > *Output=NULL, int base_priority=0)
Definition: reduced_snopt_algorithm.h:136
double get_double(const std::string &entry_name)
Definition: parameterreader.h:115
bool get_bool(const std::string &entry_name)
Definition: parameterreader.h:148
Definition: parameterreader.h:36
Definition: optproblemcontainer.h:70
~Reduced_SnoptAlgorithm()
Definition: reduced_snopt_algorithm.h:162
const dealii::Vector< double > & GetGlobalConstraints() const
Definition: constraintvector.cc:174
void PrintInfos(std::stringstream &out)
Definition: constraintvector.cc:450
static void declare_params(ParameterReader &param_reader)
Definition: reduced_snopt_algorithm.h:109
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
Definition: parameterreader.h:98
Definition: controlvector.h:48
PROBLEM * GetProblem()
Definition: reducedalgorithm.h:187
Definition: reducedalgorithm.h:54
void ReInit()
Definition: controlvector.cc:60
virtual int Solve(ControlVector< VECTOR > &q, double global_tol=-1.)
Definition: reduced_snopt_algorithm.h:171
VECTOR & GetSpacialVector()
Definition: controlvector.cc:118
Definition: reduced_snopt_algorithm.h:53
static void declare_params(ParameterReader &param_reader)
Definition: reducedalgorithm.h:241
int get_integer(const std::string &entry_name)
Definition: parameterreader.h:126
void SetSubsection(const std::string subsection)
Definition: parameterreader.h:93
Definition: reducedprobleminterface.h:338
VECTOR & GetSpacialVector(std::string name)
Definition: constraintvector.cc:130
Definition: dopeexception.h:35
Definition: optproblemcontainer.h:72