| Prev | Next |  |  |  |  |  | ipopt_nlp_ode_fast.hpp | Headings

ODE Fitting Using Fast Representation
`

    # include "ode_problem.hpp"

    namespace {
         using namespace cppad_ipopt;

         class FG_fast : public cppad_ipopt_fg_info
         {
         private:
              bool       retape_;
              SizeVector N_;
              SizeVector S_;
         public:
              // derived class part of constructor
              FG_fast(bool retape_in, const SizeVector& N)
              : retape_ (retape_in), N_(N)
              {     assert( N_[0] == 0 );
                   S_.resize( N_.size() );
                   S_[0] = 0;
                   for(size_t i = 1; i < N_.size(); i++)
                        S_[i] = S_[i-1] + N_[i];
              }
              // r^k for k = 0, 1, ..., Nz-1 used for measurements
              // r^k for k = Nz              use for initial condition
              // r^k for k = Nz+1, ..., 2*Nz used for trapezoidal approx
              size_t number_functions(void)
              {     return Nz + 1 + Nz; }
              ADVector eval_r(size_t k, const ADVector &u)
              {     count_eval_r();

                   size_t j;
                   ADVector y(Ny), a(Na);
                   // objective function --------------------------------
                   if( k < Nz )
                   {     // used for measurement with index k+1
                        ADVector r(1); // return value is a scalar
                        // u is [y( s[k+1] ) , a]
                        for(j = 0; j < Ny; j++)
                             y[j] = u[j];
                        for(j = 0; j < Na; j++)
                             a[j] = u[Ny + j];
                        r[0] = eval_H<ADNumber>(k+1, y, a);
                        return r;
                   }
                   // initial condition ---------------------------------
                   if( k == Nz )
                   {     ADVector r(Ny), F(Ny);
                        // u is [y(t), a] at t = 0
                        for(j = 0; j < Ny; j++)
                             y[j] = u[j];
                        for(j = 0; j < Na; j++)
                             a[j] = u[Ny + j];
                        F    = eval_F(a);
                        for(j = 0; j < Ny; j++)
                             r[j]   = y[j] - F[j];
                        return  r;
                   }
                   // trapezoidal approximation -------------------------
                   ADVector ym(Ny), G(Ny), Gm(Ny), r(Ny);
                   // r^k for k = Nz+1, ... , 2*Nz
                   // interval between data samples
                   Number T = s[k-Nz] - s[k-Nz-1];
                   // integration step size
                   Number dt = T / Number( N_[k-Nz] );
                   // u = [ y(t[i-1], a) , y(t[i], a), a )
                   for(j = 0; j < Ny; j++)
                   {     ym[j] = u[j];
                        y[j]  = u[Ny + j];
                   }
                   for(j = 0; j < Na; j++)
                        a[j] = u[2 * Ny + j];
                   Gm  = eval_G(ym, a);
                   G   = eval_G(y,  a);
                   for(j = 0; j < Ny; j++)
                        r[j] = y[j] - ym[j] - (G[j] + Gm[j]) * dt / 2.;
                   return r;
              }
              // The operations sequence for r_eval does not depend on u,
              // hence retape = false should work and be faster.
              bool retape(size_t k)
              {     return retape_; }
              // size of the vector u in eval_r
              size_t domain_size(size_t k)
              {     if( k < Nz )
                        return Ny + Na;   // objective function
                   if( k == Nz )
                        return Ny + Na;  // initial value constraint
                   return 2 * Ny + Na;      // trapezodial constraints
              }
              // size of the return value from eval_r
              size_t range_size(size_t k)
              {     if( k < Nz )
                        return 1;
                   return Ny;
              }
              // number of terms that use this value of k
              size_t number_terms(size_t k)
              {     if( k <= Nz )
                        return 1;  // r^k used once for k <= Nz
                   // r^k used N_[k-Nz] times for k > Nz
                   return N_[k-Nz];
              }
              void index(size_t k, size_t ell, SizeVector& I, SizeVector& J)
              {     size_t i, j;
                   // # of components of x corresponding to values for y
                   size_t ny_inx = (S_[Nz] + 1) * Ny;
                   // objective function -------------------------------
                   if( k < Nz )
                   {     // index in fg corresponding to objective
                        I[0] = 0;
                        // u = [ y(t, a) , a ]
                        // The first Ny components of u is y(t) at
                        //     t = s[k+1] = t[S_[k+1]]
                        // x indices corresponding to this value of y
                        for(j = 0; j < Ny; j++)
                             J[j] = S_[k + 1] * Ny + j;
                        // components of x correspondig to a
                        for(j = 0; j < Na; j++)
                             J[Ny + j] = ny_inx + j;
                        return;
                   }
                   // initial conditions --------------------------------
                   if( k == Nz )
                   {     // index in fg for inidial condition constraint
                        for(j = 0; j < Ny; j++)
                             I[j] = 1 + j;
                        // u = [ y(t, a) , a ] where t = 0
                        // x indices corresponding to this value of y
                        for(j = 0; j < Ny; j++)
                             J[j] = j;
                        // following that, u contains the vector a
                        for(j = 0; j < Na; j++)
                             J[Ny + j] = ny_inx + j;
                        return;
                   }
                   // trapoziodal approximation -------------------------
                   // index of first grid point in this approximation
                   i = S_[k - Nz - 1]  + ell;
                   // There are Ny difference equations for each time
                   // point.  Add one for the objective function, and Ny
                   // for the initial value constraints.
                   for(j = 0; j < Ny; j++)
                        I[j] = 1 + Ny + i * Ny + j;
                   // u = [ y(t, a) , y(t+dt, a) , a ] at t = t[i]
                   for(j = 0; j < Ny; j++)
                   {     J[j]      = i * Ny  + j; // y^i indices
                        J[Ny + j] = J[j] + Ny;   // y^{i+1} indices
                   }
                   for(j = 0; j < Na; j++)
                        J[2 * Ny + j] = ny_inx + j; // a indices
              }
         };

    }

`

Input File: cppad_ipopt/example/ode_fast.hpp