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