1 // Copyright (C) 2005, 2006 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // $Id$
6 //
7 // Authors:  Andreas Waechter           IBM    2005-10-18
8 
9 #ifndef __MITTELMANNPARACNTRL_HPP__
10 #define __MITTELMANNPARACNTRL_HPP__
11 
12 #include "RegisteredTNLP.hpp"
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #else
17 #include "configall_system.h"
18 #endif
19 
20 #ifdef HAVE_CMATH
21 # include <cmath>
22 #else
23 # ifdef HAVE_MATH_H
24 #  include <math.h>
25 # else
26 #  error "don't have header file for math"
27 # endif
28 #endif
29 
30 using namespace Ipopt;
31 
32 /** Base class for parabolic and elliptic control problems, as
33  *  formulated by Hans Mittelmann as problem (P) in "Sufficient
34  *  Optimality for Discretized Parabolic and Elliptic Control
35  *  Problems"
36  */
37 template<class T>
38 class MittelmannParaCntrlBase : public RegisteredTNLP
39 {
40 public:
41   /** Constructor. */
42   MittelmannParaCntrlBase();
43 
44   /** Default destructor */
45   virtual ~MittelmannParaCntrlBase();
46 
47   /**@name Overloaded from TNLP */
48   //@{
49   /** Method to return some info about the nlp */
50   virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
51                             Index& nnz_h_lag, IndexStyleEnum& index_style);
52 
53   /** Method to return the bounds for my problem */
54   virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
55                                Index m, Number* g_l, Number* g_u);
56 
57   /** Method to return the starting point for the algorithm */
58   virtual bool get_starting_point(Index n, bool init_x, Number* x,
59                                   bool init_z, Number* z_L, Number* z_U,
60                                   Index m, bool init_lambda,
61                                   Number* lambda);
62 
63   /** Method to return the objective value */
64   virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value);
65 
66   /** Method to return the gradient of the objective */
67   virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f);
68 
69   /** Method to return the constraint residuals */
70   virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g);
71 
72   /** Method to return:
73    *   1) The structure of the jacobian (if "values" is NULL)
74    *   2) The values of the jacobian (if "values" is not NULL)
75    */
76   virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
77                           Index m, Index nele_jac, Index* iRow, Index *jCol,
78                           Number* values);
79 
80   /** Method to return:
81    *   1) The structure of the hessian of the lagrangian (if "values" is NULL)
82    *   2) The values of the hessian of the lagrangian (if "values" is not NULL)
83    */
84   virtual bool eval_h(Index n, const Number* x, bool new_x,
85                       Number obj_factor, Index m, const Number* lambda,
86                       bool new_lambda, Index nele_hess, Index* iRow,
87                       Index* jCol, Number* values);
88 
89   //@}
90 
91   /** Method for returning scaling parameters */
92   virtual bool get_scaling_parameters(Number& obj_scaling,
93                                       bool& use_x_scaling, Index n,
94                                       Number* x_scaling,
95                                       bool& use_g_scaling, Index m,
96                                       Number* g_scaling);
97 
98   /** @name Solution Methods */
99   //@{
100   /** This method is called after the optimization, and could write an
101    *  output file with the optimal profiles */
102   virtual void finalize_solution(SolverReturn status,
103                                  Index n, const Number* x, const Number* z_L, const Number* z_U,
104                                  Index m, const Number* g, const Number* lambda,
105                                  Number obj_value,
106 				 const IpoptData* ip_data,
107 				 IpoptCalculatedQuantities* ip_cq);
108   //@}
109 
110   virtual bool InitializeProblem(Index N);
111 
112 private:
113   /**@name Methods to block default compiler methods.
114    * The compiler automatically generates the following three methods.
115    *  Since the default compiler implementation is generally not what
116    *  you want (for all but the most simple classes), we usually
117    *  put the declarations of these methods in the private section
118    *  and never implement them. This prevents the compiler from
119    *  implementing an incorrect "default" behavior without us
120    *  knowing. (See Scott Meyers book, "Effective C++")
121    *
122    */
123   //@{
124   MittelmannParaCntrlBase(const MittelmannParaCntrlBase<T>&);
125   MittelmannParaCntrlBase& operator=(const MittelmannParaCntrlBase<T>&);
126   //@}
127 
128   /**@name Problem specification */
129   //@{
130   /** Upper bound on t */
131   Number T_;
132   /** Upper bound on x */
133   Number l_;
134   /** Number of mesh points in t direction */
135   Index Nt_;
136   /** Number of mesh points in x direction */
137   Index Nx_;
138   /** Step size in t direction*/
139   Number dt_;
140   /** Step size in x direction*/
141   Number dx_;
142   /** overall lower bound on y */
143   Number lb_y_;
144   /** overall upper bound on y */
145   Number ub_y_;
146   /** overall lower bound on u */
147   Number lb_u_;
148   /** overall upper bound on u */
149   Number ub_u_;
150   /** Weighting parameter for the control target deviation functional
151    *  in the objective */
152   Number alpha_;
153   /** Weighting parameter in PDE */
154   Number beta_;
155   /** Array for the target profile for y in objective */
156   Number* y_T_;
157   /** Array for weighting function a_y in objective */
158   Number* a_y_;
159   /** Array for weighting function a_u in objective */
160   Number* a_u_;
161   //@}
162 
163   /**@name Auxilliary methods */
164   //@{
165   /** Translation of mesh point indices to NLP variable indices for
166    *  y(x_ij) */
y_index(Index jx,Index it) const167   inline Index y_index(Index jx, Index it) const
168   {
169     return jx + (Nx_+1)*it;
170   }
u_index(Index it) const171   inline Index u_index(Index it) const
172   {
173     return (Nt_+1)*(Nx_+1) + it - 1;
174   }
175   /** Compute the grid coordinate for given index in t direction */
t_grid(Index i) const176   inline Number t_grid(Index i) const
177   {
178     return dt_*(Number)i;
179   }
180   /** Compute the grid coordinate for given index in x direction */
x_grid(Index j) const181   inline Number x_grid(Index j) const
182   {
183     return dx_*(Number)j;
184   }
185   //@}
186 };
187 
188 template <class T>
MittelmannParaCntrlBase()189 MittelmannParaCntrlBase<T>::MittelmannParaCntrlBase()
190     :
191     y_T_(NULL),
192     a_y_(NULL),
193     a_u_(NULL)
194 {}
195 
196 template <class T>
~MittelmannParaCntrlBase()197 MittelmannParaCntrlBase<T>::~MittelmannParaCntrlBase()
198 {
199   delete [] y_T_;
200   delete [] a_y_;
201   delete [] a_u_;
202 }
203 
204 template <class T>
205 bool MittelmannParaCntrlBase<T>::
InitializeProblem(Index N)206 InitializeProblem(Index N)
207 {
208   typename T::ProblemSpecs p;
209 
210   if (N<1) {
211     printf("N has to be at least 1.");
212     return false;
213   }
214 
215   T_ = p.T();
216   l_ = p.l();
217   Nt_ = N;
218   Nx_ = N;
219   dt_ = T_/Nt_;
220   dx_ = l_/Nx_;
221   lb_y_ = p.lb_y();
222   ub_y_ = p.ub_y();
223   lb_u_ = p.lb_u();
224   ub_u_ = p.ub_u();
225   alpha_ = p.alpha();
226   beta_ = p.beta();
227 
228   y_T_ = new Number[Nx_+1];
229   for (Index j=0; j<=Nx_; j++) {
230     y_T_[j] = p.y_T(x_grid(j));
231   }
232   a_y_ = new Number[Nt_];
233   for (Index i=1; i<=Nt_; i++) {
234     a_y_[i-1] = p.a_y(t_grid(i));
235   }
236   a_u_ = new Number[Nt_];
237   for (Index i=1; i<=Nt_; i++) {
238     a_u_[i-1] = p.a_u(t_grid(i));
239   }
240 
241   return true;
242 }
243 
244 template <class T>
245 bool MittelmannParaCntrlBase<T>::
get_nlp_info(Index & n,Index & m,Index & nnz_jac_g,Index & nnz_h_lag,IndexStyleEnum & index_style)246 get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
247              Index& nnz_h_lag, IndexStyleEnum& index_style)
248 {
249   typename T::ProblemSpecs p;
250 
251   n = (Nt_+1)*(Nx_+1) + Nt_;
252 
253   m = Nt_*(Nx_-1) + Nt_ + Nt_;
254 
255   nnz_jac_g = 6*Nt_*(Nx_-1) + 3*Nt_ + 4*Nt_;
256 
257   nnz_h_lag = Nx_+1 + Nt_;
258   if (!p.phi_dydy_always_zero()) {
259     nnz_h_lag += Nt_;
260   }
261 
262   index_style = C_STYLE;
263 
264   return true;
265 }
266 
267 template <class T>
268 bool MittelmannParaCntrlBase<T>::
get_bounds_info(Index n,Number * x_l,Number * x_u,Index m,Number * g_l,Number * g_u)269 get_bounds_info(Index n, Number* x_l, Number* x_u,
270                 Index m, Number* g_l, Number* g_u)
271 {
272   typename T::ProblemSpecs p;
273 
274   // Set overall bounds on the variables
275   for (Index jx=0; jx<=Nx_; jx++) {
276     for (Index it=1; it<=Nt_; it++) {
277       Index iy = y_index(jx,it);
278       x_l[iy] = lb_y_;
279       x_u[iy] = ub_y_;
280     }
281   }
282   for (Index i=1; i<=Nt_; i++) {
283     Index iu = u_index(i);
284     x_l[iu] = lb_u_;
285     x_u[iu] = ub_u_;
286   }
287 
288   /*
289   // Boundary condition for t=0
290   for (Index it=0; it<=Nt_; it++) {
291     Index iy = y_index(0,it);
292     x_u[iy] = x_l[iy] = p.a(t_grid(it));
293   }
294   */
295   // Boundary condition for t=0
296   for (Index jx=0; jx<=Nx_; jx++) {
297     Index iy = y_index(jx,0);
298     x_u[iy] = x_l[iy] = p.a(x_grid(jx));
299   }
300 
301   // all discretized PDE constraints have right hand side zero
302   for (Index i=0; i<Nt_*(Nx_-1) + Nt_; i++) {
303     g_l[i] = 0.;
304     g_u[i] = 0.;
305   }
306 
307   // but we put b on the right hand side for the x=L boundary condition
308   for (Index i=0; i<Nt_; i++) {
309     g_l[Nt_*(Nx_-1) + Nt_ + i]
310     = g_u[Nt_*(Nx_-1) + Nt_ + i]
311       = p.b(t_grid(i+1));
312   }
313 
314   return true;
315 }
316 
317 template <class T>
318 bool MittelmannParaCntrlBase<T>::
get_starting_point(Index n,bool init_x,Number * x,bool init_z,Number * z_L,Number * z_U,Index m,bool init_lambda,Number * lambda)319 get_starting_point(Index n, bool init_x, Number* x,
320                    bool init_z, Number* z_L, Number* z_U,
321                    Index m, bool init_lambda,
322                    Number* lambda)
323 {
324   DBG_ASSERT(init_x==true && init_z==false && init_lambda==false);
325 
326   // Set starting point for y
327   for (Index jx=0; jx<=Nx_; jx++) {
328     for (Index it=0; it<=Nt_; it++) {
329       x[y_index(jx,it)] = 0.;
330     }
331   }
332   // for u
333   for (Index i=1; i<=Nt_; i++) {
334     x[u_index(i)] = (ub_u_+lb_u_)/2.;
335   }
336 
337   /*
338   // DELETEME
339   for (Index i=0; i<n; i++) {
340     x[i] += 0.01*i;
341   }
342   */
343 
344   return true;
345 }
346 
347 template <class T>
348 bool MittelmannParaCntrlBase<T>::
get_scaling_parameters(Number & obj_scaling,bool & use_x_scaling,Index n,Number * x_scaling,bool & use_g_scaling,Index m,Number * g_scaling)349 get_scaling_parameters(Number& obj_scaling,
350                        bool& use_x_scaling,
351                        Index n, Number* x_scaling,
352                        bool& use_g_scaling,
353                        Index m, Number* g_scaling)
354 {
355   obj_scaling = 1./Min(dx_,dt_);
356   use_x_scaling = false;
357   use_g_scaling = false;
358   return true;
359 }
360 
361 template <class T>
362 bool MittelmannParaCntrlBase<T>::
eval_f(Index n,const Number * x,bool new_x,Number & obj_value)363 eval_f(Index n, const Number* x,
364        bool new_x, Number& obj_value)
365 {
366   // Deviation of y from target
367   Number a = x[y_index(0,Nt_)] - y_T_[0];
368   Number sum = 0.5*a*a;
369   for (Index jx=1; jx<Nx_; jx++) {
370     a = x[y_index(jx,Nt_)] - y_T_[jx];
371     sum += a*a;
372   }
373   a = x[y_index(Nx_,Nt_)] - y_T_[Nx_];
374   sum += 0.5*a*a;
375   obj_value = 0.5*dx_*sum;
376 
377   // smoothing for control
378   if (alpha_!=.0) {
379     sum = 0.5*x[u_index(Nt_)]*x[u_index(Nt_)];
380     for (Index it=1; it < Nt_; it++) {
381       sum += x[u_index(it)]*x[u_index(it)];
382     }
383     obj_value += 0.5*alpha_*dt_*sum;
384   }
385 
386   // third term
387   sum = 0.;
388   for (Index it=1; it<Nt_; it++) {
389     sum += a_y_[it-1]*x[y_index(Nx_,it)] + a_u_[it-1]*x[u_index(it)];
390   }
391   sum += 0.5*(a_y_[Nt_-1]*x[y_index(Nx_,Nt_)] + a_u_[Nt_-1]*x[u_index(Nt_)]);
392   obj_value += dt_*sum;
393 
394   return true;
395 }
396 
397 template <class T>
398 bool MittelmannParaCntrlBase<T>::
eval_grad_f(Index n,const Number * x,bool new_x,Number * grad_f)399 eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
400 {
401   // First set all y entries to zero
402   for (Index jx=0; jx<=Nx_; jx++) {
403     for (Index it=0; it<=Nt_; it++) {
404       grad_f[y_index(jx,it)] = 0.;
405     }
406   }
407 
408   // y entries from y target
409   grad_f[y_index(0,Nt_)] = 0.5*dx_*(x[y_index(0,Nt_)] - y_T_[0]);
410   for (Index jx=1; jx<Nx_; jx++) {
411     grad_f[y_index(jx,Nt_)] = dx_*(x[y_index(jx,Nt_)] - y_T_[jx]);
412   }
413   grad_f[y_index(Nx_,Nt_)] = 0.5*dx_*(x[y_index(Nx_,Nt_)] - y_T_[Nx_]);
414 
415   // y entries from thrid term
416   for (Index it=1; it<Nt_; it++) {
417     grad_f[y_index(Nx_,it)] = dt_*a_y_[it-1];
418   }
419   grad_f[y_index(Nx_,Nt_)] += 0.5*dt_*a_y_[Nt_-1];
420 
421   // u entries from smoothing and third term
422   for (Index it=1; it<Nt_; it++) {
423     grad_f[u_index(it)] = alpha_*dt_*x[u_index(it)] + dt_*a_u_[it-1];
424   }
425   grad_f[u_index(Nt_)] = 0.5*dt_*(alpha_*x[u_index(Nt_)] + a_u_[Nt_-1]);
426 
427   return true;
428 }
429 
430 template <class T>
431 bool MittelmannParaCntrlBase<T>::
eval_g(Index n,const Number * x,bool new_x,Index m,Number * g)432 eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
433 {
434   typename T::ProblemSpecs p;
435 
436   Index ig=0;
437 
438   Number f = 1./(2.*dx_*dx_);
439   for (Index jx=1; jx<Nx_; jx++) {
440     for (Index it=0; it<Nt_; it++) {
441       g[ig] = (x[y_index(jx,it)]-x[y_index(jx,it+1)])/dt_
442               + f*(x[y_index(jx-1,it)] - 2.*x[y_index(jx,it)]
443                    + x[y_index(jx+1,it)] + x[y_index(jx-1,it+1)]
444                    - 2.*x[y_index(jx,it+1)] + x[y_index(jx+1,it+1)]);
445       ig++;
446     }
447   }
448 
449   for (Index it=1; it<=Nt_; it++) {
450     g[ig] = (x[y_index(2,it)] - 4.*x[y_index(1,it)] + 3.*x[y_index(0,it)]);
451     ig++;
452   }
453 
454   f = 1./(2.*dx_);
455   for (Index it=1; it<=Nt_; it++) {
456     g[ig] =
457       f*(x[y_index(Nx_-2,it)] - 4.*x[y_index(Nx_-1,it)]
458          + 3.*x[y_index(Nx_,it)]) + beta_*x[y_index(Nx_,it)]
459       - x[u_index(it)] + p.phi(x[y_index(Nx_,it)]);
460     ig++;
461   }
462 
463   DBG_ASSERT(ig == m);
464 
465   return true;
466 }
467 
468 template <class T>
469 bool MittelmannParaCntrlBase<T>::
eval_jac_g(Index n,const Number * x,bool new_x,Index m,Index nele_jac,Index * iRow,Index * jCol,Number * values)470 eval_jac_g(Index n, const Number* x, bool new_x,
471            Index m, Index nele_jac, Index* iRow, Index *jCol,
472            Number* values)
473 {
474   typename T::ProblemSpecs p;
475 
476   Index ijac = 0;
477 
478   if (values == NULL) {
479     Index ig = 0;
480     for (Index jx=1; jx<Nx_; jx++) {
481       for (Index it=0; it<Nt_; it++) {
482         iRow[ijac] = ig;
483         jCol[ijac] = y_index(jx-1,it);
484         ijac++;
485         iRow[ijac] = ig;
486         jCol[ijac] = y_index(jx,it);
487         ijac++;
488         iRow[ijac] = ig;
489         jCol[ijac] = y_index(jx+1,it);
490         ijac++;
491         iRow[ijac] = ig;
492         jCol[ijac] = y_index(jx-1,it+1);
493         ijac++;
494         iRow[ijac] = ig;
495         jCol[ijac] = y_index(jx,it+1);
496         ijac++;
497         iRow[ijac] = ig;
498         jCol[ijac] = y_index(jx+1,it+1);
499         ijac++;
500 
501         ig++;
502       }
503     }
504 
505     for (Index it=1; it<=Nt_; it++) {
506       iRow[ijac] = ig;
507       jCol[ijac] = y_index(0,it);
508       ijac++;
509       iRow[ijac] = ig;
510       jCol[ijac] = y_index(1,it);
511       ijac++;
512       iRow[ijac] = ig;
513       jCol[ijac] = y_index(2,it);
514       ijac++;
515 
516       ig++;
517     }
518 
519     for (Index it=1; it<=Nt_; it++) {
520       iRow[ijac] = ig;
521       jCol[ijac] = y_index(Nx_-2,it);
522       ijac++;
523       iRow[ijac] = ig;
524       jCol[ijac] = y_index(Nx_-1,it);
525       ijac++;
526       iRow[ijac] = ig;
527       jCol[ijac] = y_index(Nx_,it);
528       ijac++;
529       iRow[ijac] = ig;
530       jCol[ijac] = u_index(it);
531       ijac++;
532 
533       ig++;
534     }
535     DBG_ASSERT(ig == m);
536   }
537   else {
538     Number f = 1./(2.*dx_*dx_);
539     Number f2 = 1./dt_;
540     for (Index jx=1; jx<Nx_; jx++) {
541       for (Index it=0; it<Nt_; it++) {
542         values[ijac++] = f;
543         values[ijac++] = f2 - 2.*f;
544         values[ijac++] = f;
545         values[ijac++] = f;
546         values[ijac++] = -f2 - 2.*f;
547         values[ijac++] = f;
548       }
549     }
550 
551     for (Index it=1; it<=Nt_; it++) {
552       values[ijac++] = 3.;
553       values[ijac++] = -4.;
554       values[ijac++] = 1.;
555     }
556 
557     f = 1./(2.*dx_);
558     for (Index it=1; it<=Nt_; it++) {
559       values[ijac++] = f;
560       values[ijac++] = -4.*f;
561       values[ijac++] = 3.*f + beta_ + p.phi_dy(x[y_index(Nx_,it)]);
562       values[ijac++] = -1.;
563     }
564 
565   }
566 
567   return true;
568 }
569 
570 template <class T>
571 bool MittelmannParaCntrlBase<T>::
eval_h(Index n,const Number * x,bool new_x,Number obj_factor,Index m,const Number * lambda,bool new_lambda,Index nele_hess,Index * iRow,Index * jCol,Number * values)572 eval_h(Index n, const Number* x, bool new_x,
573        Number obj_factor, Index m, const Number* lambda,
574        bool new_lambda, Index nele_hess, Index* iRow,
575        Index* jCol, Number* values)
576 {
577   typename T::ProblemSpecs p;
578 
579   Index ihes = 0;
580 
581   if (values == NULL) {
582     // y values from objective
583     for (Index jx=0; jx<= Nx_; jx++) {
584       iRow[ihes] = y_index(jx,Nt_);
585       jCol[ihes] = y_index(jx,Nt_);
586       ihes++;
587     }
588     // u from objective
589     for (Index it=1; it<=Nt_; it++) {
590       iRow[ihes] = u_index(it);
591       jCol[ihes] = u_index(it);
592       ihes++;
593     }
594 
595     // constraint
596     if (!p.phi_dydy_always_zero()) {
597       for (Index it=1; it<=Nt_; it++) {
598         iRow[ihes] = y_index(Nx_,it);
599         jCol[ihes] = y_index(Nx_,it);
600         ihes++;
601       }
602     }
603   }
604   else {
605     // y values from objective
606     values[ihes++] = obj_factor*0.5*dx_;
607     for (Index jx=1; jx<Nx_; jx++) {
608       values[ihes++] = obj_factor*dx_;
609     }
610     values[ihes++] = obj_factor*0.5*dx_;
611     // u from objective
612     for (Index it=1; it<Nt_; it++) {
613       values[ihes++] = obj_factor*alpha_*dt_;
614     }
615     values[ihes++] = obj_factor*0.5*alpha_*dt_;
616 
617     // constrainT
618     if (!p.phi_dydy_always_zero()) {
619       Index ig = (Nx_-1)*Nt_ + Nt_;
620       for (Index it=1; it<=Nt_; it++) {
621         values[ihes++] = lambda[ig++]*p.phi_dydy(x[y_index(Nx_,it)]);
622       }
623     }
624   }
625 
626   DBG_ASSERT(ihes==nele_hess);
627 
628   return true;
629 }
630 
631 template <class T>
632 void MittelmannParaCntrlBase<T>::
finalize_solution(SolverReturn status,Index n,const Number * x,const Number * z_L,const Number * z_U,Index m,const Number * g,const Number * lambda,Number obj_value,const IpoptData * ip_data,IpoptCalculatedQuantities * ip_cq)633 finalize_solution(SolverReturn status,
634                   Index n, const Number* x, const Number* z_L,
635                   const Number* z_U,
636                   Index m, const Number* g, const Number* lambda,
637                   Number obj_value,
638 		  const IpoptData* ip_data,
639 		  IpoptCalculatedQuantities* ip_cq)
640 {}
641 
642 class MittelmannParaCntrl5_1
643 {
644 public:
645   class ProblemSpecs
646   {
647   public:
ProblemSpecs()648     ProblemSpecs ()
649         :
650         pi_(4.*atan(1.)),
651         exp13_(exp(1./3.)),
652         exp23_(exp(2./3.)),
653         exp1_(exp(1.)),
654         expm1_(exp(-1.)),
655         sqrt2_(sqrt(2.))
656     {}
T()657     Number T()
658     {
659       return 1.;
660     }
l()661     Number l()
662     {
663       return pi_/4.;
664     }
lb_y()665     Number lb_y()
666     {
667       return -1e20;
668     }
ub_y()669     Number ub_y()
670     {
671       return 1e20;
672     }
lb_u()673     Number lb_u()
674     {
675       return 0.;
676     }
ub_u()677     Number ub_u()
678     {
679       return 1.;
680     }
alpha()681     Number alpha()
682     {
683       return sqrt2_/2.*(exp23_-exp13_);
684     }
beta()685     Number beta()
686     {
687       return 1.;
688     }
y_T(Number x)689     inline Number y_T(Number x)
690     {
691       return (exp1_ + expm1_)*cos(x);
692     }
a(Number x)693     inline Number a(Number x)
694     {
695       return cos(x);
696     }
a_y(Number t)697     inline Number a_y(Number t)
698     {
699       return -exp(-2.*t);
700     }
a_u(Number t)701     inline Number a_u(Number t)
702     {
703       return sqrt2_/2.*exp13_;
704     }
b(Number t)705     inline Number b(Number t)
706     {
707       return exp(-4.*t)/4.
708              - Min(1.,Max(0.,(exp(t)-exp13_)/(exp23_-exp13_)));
709     }
phi(Number y)710     inline Number phi(Number y)
711     {
712       return y*pow(fabs(y),3);
713     }
phi_dy(Number y)714     inline Number phi_dy(Number y)
715     {
716       return 4.*pow(fabs(y),3);
717     }
phi_dydy(Number y)718     inline Number phi_dydy(Number y)
719     {
720       return 12.*y*y;
721     }
phi_dydy_always_zero()722     inline bool phi_dydy_always_zero()
723     {
724       return false;
725     }
726   private:
727     const Number pi_;
728     const Number exp13_;
729     const Number exp23_;
730     const Number exp1_;
731     const Number expm1_;
732     const Number sqrt2_;
733   };
734 };
735 
736 class MittelmannParaCntrl5_2_1
737 {
738 public:
739   class ProblemSpecs
740   {
741   public:
ProblemSpecs()742     ProblemSpecs ()
743     {}
T()744     Number T()
745     {
746       return 1.58;
747     }
l()748     Number l()
749     {
750       return 1.;
751     }
lb_y()752     Number lb_y()
753     {
754       return -1e20;
755     }
ub_y()756     Number ub_y()
757     {
758       return 1e20;
759     }
lb_u()760     Number lb_u()
761     {
762       return -1.;
763     }
ub_u()764     Number ub_u()
765     {
766       return 1.;
767     }
alpha()768     Number alpha()
769     {
770       return 0.001;
771     }
beta()772     Number beta()
773     {
774       return 1.;
775     }
y_T(Number x)776     inline Number y_T(Number x)
777     {
778       return .5*(1.-x*x);
779     }
a(Number x)780     inline Number a(Number x)
781     {
782       return 0.;
783     }
a_y(Number t)784     inline Number a_y(Number t)
785     {
786       return 0.;
787     }
a_u(Number t)788     inline Number a_u(Number t)
789     {
790       return 0.;
791     }
b(Number t)792     inline Number b(Number t)
793     {
794       return 0.;
795     }
phi(Number y)796     inline Number phi(Number y)
797     {
798       return 0.;
799     }
phi_dy(Number y)800     inline Number phi_dy(Number y)
801     {
802       return 0.;
803     }
phi_dydy(Number y)804     inline Number phi_dydy(Number y)
805     {
806       DBG_ASSERT(false);
807       return 0.;
808     }
phi_dydy_always_zero()809     inline bool phi_dydy_always_zero()
810     {
811       return true;
812     }
813   };
814 };
815 
816 class MittelmannParaCntrl5_2_2
817 {
818 public:
819   class ProblemSpecs
820   {
821   public:
ProblemSpecs()822     ProblemSpecs ()
823     {}
T()824     Number T()
825     {
826       return 1.58;
827     }
l()828     Number l()
829     {
830       return 1.;
831     }
lb_y()832     Number lb_y()
833     {
834       return -1e20;
835     }
ub_y()836     Number ub_y()
837     {
838       return 1e20;
839     }
lb_u()840     Number lb_u()
841     {
842       return -1.;
843     }
ub_u()844     Number ub_u()
845     {
846       return 1.;
847     }
alpha()848     Number alpha()
849     {
850       return 0.001;
851     }
beta()852     Number beta()
853     {
854       return 0.;
855     }
y_T(Number x)856     inline Number y_T(Number x)
857     {
858       return .5*(1.-x*x);
859     }
a(Number x)860     inline Number a(Number x)
861     {
862       return 0.;
863     }
a_y(Number t)864     inline Number a_y(Number t)
865     {
866       return 0.;
867     }
a_u(Number t)868     inline Number a_u(Number t)
869     {
870       return 0.;
871     }
b(Number t)872     inline Number b(Number t)
873     {
874       return 0.;
875     }
phi(Number y)876     inline Number phi(Number y)
877     {
878       return y*y;
879     }
phi_dy(Number y)880     inline Number phi_dy(Number y)
881     {
882       return 2.*y;
883     }
phi_dydy(Number y)884     inline Number phi_dydy(Number y)
885     {
886       return 2.;
887     }
phi_dydy_always_zero()888     inline bool phi_dydy_always_zero()
889     {
890       return false;
891     }
892   };
893 };
894 
895 class MittelmannParaCntrl5_2_3
896 {
897 public:
898   class ProblemSpecs
899   {
900   public:
ProblemSpecs()901     ProblemSpecs ()
902     {}
T()903     Number T()
904     {
905       return 1.58;
906     }
l()907     Number l()
908     {
909       return 1.;
910     }
lb_y()911     Number lb_y()
912     {
913       return 0.;
914     }
ub_y()915     Number ub_y()
916     {
917       return 0.675;
918     }
lb_u()919     Number lb_u()
920     {
921       return -1.;
922     }
ub_u()923     Number ub_u()
924     {
925       return 1.;
926     }
alpha()927     Number alpha()
928     {
929       return 0.001;
930     }
beta()931     Number beta()
932     {
933       return 0.;
934     }
y_T(Number x)935     inline Number y_T(Number x)
936     {
937       return .5*(1.-x*x);
938     }
a(Number x)939     inline Number a(Number x)
940     {
941       return 0.;
942     }
a_y(Number t)943     inline Number a_y(Number t)
944     {
945       return 0.;
946     }
a_u(Number t)947     inline Number a_u(Number t)
948     {
949       return 0.;
950     }
b(Number t)951     inline Number b(Number t)
952     {
953       return 0.;
954     }
phi(Number y)955     inline Number phi(Number y)
956     {
957       return y*y;
958     }
phi_dy(Number y)959     inline Number phi_dy(Number y)
960     {
961       return 2.*y;
962     }
phi_dydy(Number y)963     inline Number phi_dydy(Number y)
964     {
965       return 2.;
966     }
phi_dydy_always_zero()967     inline bool phi_dydy_always_zero()
968     {
969       return false;
970     }
971   };
972 };
973 
974 class MittelmannParaCntrl5_try
975 {
976 public:
977   class ProblemSpecs
978   {
979   public:
ProblemSpecs()980     ProblemSpecs ()
981         :
982         pi_(4.*atan(1.)),
983         exp13_(exp(1./3.)),
984         exp23_(exp(2./3.)),
985         exp1_(exp(1.)),
986         expm1_(exp(-1.)),
987         sqrt2_(sqrt(2.))
988     {}
T()989     Number T()
990     {
991       return 1.;
992     }
l()993     Number l()
994     {
995       return pi_/4.;
996     }
lb_y()997     Number lb_y()
998     {
999       return -1e20;
1000     }
ub_y()1001     Number ub_y()
1002     {
1003       return 1e20;
1004     }
lb_u()1005     Number lb_u()
1006     {
1007       return 0.;
1008     }
ub_u()1009     Number ub_u()
1010     {
1011       return 1.;
1012     }
alpha()1013     Number alpha()
1014     {
1015       return sqrt2_/2.*(exp23_-exp13_);
1016     }
beta()1017     Number beta()
1018     {
1019       return 1.;
1020     }
y_T(Number x)1021     inline Number y_T(Number x)
1022     {
1023       return (exp1_ + expm1_)*cos(x);
1024     }
a(Number x)1025     inline Number a(Number x)
1026     {
1027       return cos(x);
1028     }
a_y(Number t)1029     inline Number a_y(Number t)
1030     {
1031       return -exp(-2.*t);
1032     }
a_u(Number t)1033     inline Number a_u(Number t)
1034     {
1035       return sqrt2_/2.*exp13_;
1036     }
b(Number t)1037     inline Number b(Number t)
1038     {
1039       return exp(-4.*t)/4.
1040              - Min(1.,Max(0.,(exp(t)-exp13_)/(exp23_-exp13_)));
1041     }
phi(Number y)1042     inline Number phi(Number y)
1043     {
1044       return -y*sin(y/10.);
1045     }
phi_dy(Number y)1046     inline Number phi_dy(Number y)
1047     {
1048       return -y*cos(y/10.)/10. - sin(y/10.);
1049     }
phi_dydy(Number y)1050     inline Number phi_dydy(Number y)
1051     {
1052       return y*sin(y/10.)/100.;
1053     }
phi_dydy_always_zero()1054     inline bool phi_dydy_always_zero()
1055     {
1056       return false;
1057     }
1058   private:
1059     const Number pi_;
1060     const Number exp13_;
1061     const Number exp23_;
1062     const Number exp1_;
1063     const Number expm1_;
1064     const Number sqrt2_;
1065   };
1066 };
1067 
1068 #endif
1069