indii/ml/sde/StochasticEulerMaruyama.hpp

00001 #ifndef INDII_ML_SDE_STOCHASTICEULERMARUYAMA_HPP
00002 #define INDII_ML_SDE_STOCHASTICEULERMARUYAMA_HPP
00003 
00004 #include "StochasticDifferentialModel.hpp"
00005 #include "StochasticNumericalSolver.hpp"
00006 
00007 namespace indii {
00008   namespace ml {
00009     namespace sde {    
00010 /**
00011  * Stochastic Euler-Maruyama method with fixed time step for solving a
00012  * system of stochastic differential equations.
00013  *
00014  * @author Lawrence Murray <lawrence@indii.org>
00015  * @version $Rev: 582 $
00016  * @date $Date: 2008-12-15 17:03:50 +0000 (Mon, 15 Dec 2008) $
00017  *
00018  * @param DT Type of the diffusion matrix.
00019  * @param DDT Type of the diffusion partial derivative matrices.
00020  *
00021  * This class numerically solves StochasticDifferentialModel models
00022  * defining a system of stochastic differential equations using an
00023  * Euler-Maruyama scheme. The time step is fixed and no error control
00024  * used.
00025  *
00026  * The general usage idiom is as for indii::ml::ode::AdaptiveRungeKutta.
00027  *
00028  * @todo This class is tightly coupled with the GSL and would benefit from
00029  * greater independence.
00030  */
00031 template <class DT = indii::ml::aux::matrix,
00032     class DDT = indii::ml::aux::zero_matrix>
00033 class StochasticEulerMaruyama :
00034     public indii::ml::sde::StochasticNumericalSolver {
00035 public:
00036   /**
00037    * Constructor.
00038    *
00039    * @param model Model to estimate.
00040    *
00041    * The time is initialised to zero, but the state is uninitialised
00042    * and should be set with setVariable() or setState().
00043    */
00044   StochasticEulerMaruyama(StochasticDifferentialModel<DT,DDT>* model);
00045 
00046   /**
00047    * Constructor.
00048    *
00049    * @param model Model to estimate.
00050    * @param y0 Initial state.
00051    *
00052    * The time is initialised to zero and the state to that given.
00053    */
00054   StochasticEulerMaruyama(StochasticDifferentialModel<DT,DDT>* model,
00055       const indii::ml::aux::vector& y0);
00056 
00057   /**
00058    * Destructor.
00059    */
00060   virtual ~StochasticEulerMaruyama();
00061 
00062   virtual double step(double upper);
00063 
00064   virtual double stepBack(double lower);
00065 
00066   virtual int calculateDerivativesForward(double t, const double y[],
00067       double dydt[]);
00068 
00069   virtual int calculateDerivativesBackward(double t, const double y[],
00070       double dydt[]);
00071 
00072 private:
00073   /**
00074    * Model.
00075    */
00076   StochasticDifferentialModel<DT,DDT>* model;
00077 
00078   /**
00079    * Drift.
00080    */
00081   indii::ml::aux::vector a;
00082   
00083   /**
00084    * Diffusion.
00085    */
00086   DT B;
00087 
00088 };
00089 
00090     }
00091   }
00092 }
00093 
00094 #include "boost/numeric/ublas/operation.hpp"
00095 #include "boost/numeric/ublas/operation_sparse.hpp"
00096 
00097 template <class DT, class DDT>
00098 indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::StochasticEulerMaruyama(
00099     StochasticDifferentialModel<DT,DDT>* model) :
00100     StochasticNumericalSolver(model->getDimensions(),
00101     model->getNoiseDimensions()), model(model), a(model->getDimensions()),
00102     B(model->getDimensions(), model->getNoiseDimensions()) {
00103   a.clear();
00104   B.clear();
00105   setStepType(gsl_odeiv_step_gear1);
00106 }
00107 
00108 template <class DT, class DDT>
00109 indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::StochasticEulerMaruyama(
00110     StochasticDifferentialModel<DT,DDT>* model,
00111     const indii::ml::aux::vector& y0) : StochasticNumericalSolver(y0,
00112     model->getNoiseDimensions()), model(model), a(model->getDimensions()),
00113     B(model->getDimensions(), model->getNoiseDimensions()) {
00114   /* pre-condition */
00115   assert (y0.size() == model->getDimensions());
00116 
00117   a.clear();
00118   B.clear();
00119   setStepType(gsl_odeiv_step_gear1);
00120 }
00121 
00122 template <class DT, class DDT>
00123 indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::~StochasticEulerMaruyama() {
00124   //
00125 }
00126 
00127 template <class DT, class DDT>
00128 double indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::step(
00129     double upper) {
00130   /* pre-condition */
00131   assert (upper > t);
00132 
00133   const unsigned int N = model->getDimensions();
00134   const unsigned int V = model->getNoiseDimensions();
00135   double ts, h;
00136 
00137   /* make sure step size won't exceed upper bound */
00138   if (maxStepSize > 0.0 && stepSize > maxStepSize) {
00139     stepSize = maxStepSize;
00140   }
00141   ts = t + stepSize;
00142   if (ts > upper) {
00143     ts = upper;
00144   }
00145 
00146   /* stepping variables */
00147   aux::vector y(this->getState());
00148 
00149   /* step */
00150   sampleNoise(&ts);
00151   h = ts - t;
00152 
00153   model->calculateDrift(t, y, a);
00154   model->calculateDiffusion(t, y, B);
00155   noalias(y) = y + h*a;
00156   ublas::axpy_prod(B, dWf.top(), y, false);
00157 
00158   /* update state */
00159   aux::vectorToArray(y, this->y); // don't use setState(), clears tf and dWf
00160 
00161   /* update time */
00162   t = ts;
00163 
00164   /* clean up future path */
00165   tf.pop(); // full step sample
00166   dWf.pop();
00167 
00168   /* post-condition */
00169   assert (tf.empty() || t < tf.top());
00170   assert (t <= upper);
00171 
00172   return t;
00173 }
00174 
00175 template <class DT, class DDT>
00176 inline double indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::stepBack(
00177     double lower) {
00178   double t = NumericalSolver::stepBack(lower);
00179 
00180   return t;
00181 }
00182 
00183 template <class DT, class DDT>
00184 inline int indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::calculateDerivativesForward(
00185     double ts, const double y[], double dydt[]) {
00186   /* not required by this implementation */
00187   assert (false);
00188   
00189   return GSL_FAILURE;
00190 }
00191 
00192 template <class DT, class DDT>
00193 inline int indii::ml::sde::StochasticEulerMaruyama<DT,DDT>::calculateDerivativesBackward(
00194     double t, const double y[], double dydt[]) {
00195   /* not required by this implementation */
00196   assert (false);
00197   
00198   return GSL_FAILURE;
00199 }
00200 
00201 #endif
00202 

Generated on Wed Dec 17 15:11:57 2008 for dysii Dynamical Systems Library by  doxygen 1.5.3