indii/ml/sde/StochasticDifferentialModel.hpp

00001 #ifndef INDII_ML_ODE_STOCHASTICDIFFERENTIALMODEL_HPP
00002 #define INDII_ML_ODE_STOCHASTICDIFFERENTIALMODEL_HPP
00003 
00004 #include "../aux/vector.hpp"
00005 #include "../aux/matrix.hpp"
00006 
00007 #include "boost/serialization/serialization.hpp"
00008 
00009 #include <vector>
00010 
00011 namespace indii {
00012   namespace ml {
00013     namespace sde {
00014 /**
00015  * StochasticAdaptiveRungeKutta compatible model.
00016  *
00017  * @author Lawrence Murray <lawrence@indii.org>
00018  * @version $Rev: 565 $
00019  * @date $Date: 2008-09-13 22:25:02 +0100 (Sat, 13 Sep 2008) $
00020  *
00021  * @param DT Type of the diffusion matrix.
00022  * @param DDT Type of the diffusion partial derivative matrices.
00023  *
00024  * The model is of the form:
00025  *
00026  * \f[
00027  * d\mathbf{y} = \mathbf{a}(\mathbf{y},t)\,dt + B(\mathbf{y},t)\,d\mathbf{W},
00028  * \f]
00029  *
00030  * where \f$\mathbf{a}(\mathbf{y},t)\f$ is the drift term and
00031  * \f$B(\mathbf{y},t)\f$ the diffusion term. At any time \f$t\f$, the
00032  * time derivatives may be calculated as:
00033  *
00034  * \f[
00035  *   \frac{dy_k}{dt} = a_k(\mathbf{y},t) -
00036  *   \frac{1}{2}\sum_{ij}B_{ij}(\mathbf{y},t)\frac{\partial
00037  *   B_{kj}(\mathbf{y},t)}{\partial y_i} + \frac{1}{\Delta
00038  *   t}\sum_{i}B_{ki}(\mathbf{y},t)\Delta W_i,
00039  * \f]
00040  *
00041  * or in matrix form:
00042  *
00043  * \f[
00044  *   \frac{d\mathbf{y}}{dt} = \mathbf{a}(\mathbf{y},t) -
00045  *   \frac{1}{2}\sum_i \frac{\partial B(\mathbf{y},t)}{\partial
00046  *   y_i}B_{i,*}(\mathbf{y},t)^T + \frac{1}{\Delta t}
00047  *   B(\mathbf{y},t)\Delta \mathbf{W},
00048  * \f]
00049  *
00050  * where \f$\Delta t\f$ is the time step, \f$\Delta \mathbf{W}\f$ the
00051  * Wiener increment and \f$B_{i,*}(\mathbf{y},t)\f$ the \f$i\f$th row of
00052  * \f$B(\mathbf{y},t)\f$.
00053  *
00054  * This is all calculated by StochasticAdaptiveRungeKutta, although
00055  * the model must provide \f$\mathbf{a}(\mathbf{y},t)\f$,
00056  * \f$B(\mathbf{y},t)\f$ and optionally \f$\frac{\partial
00057  * B_{kj}(\mathbf{y},t)}{\partial y_i}\f$ through implementations of
00058  * the calculateDrift(), calculateDiffusion() and
00059  * calculateDiffusionDerivatives() functions, respectively.
00060  */
00061 template <class DT = indii::ml::aux::matrix,
00062     class DDT = indii::ml::aux::zero_matrix>
00063 class StochasticDifferentialModel {
00064 public:
00065   /**
00066    * Default constructor for restoring from serialization.
00067    */
00068   StochasticDifferentialModel();
00069 
00070   /**
00071    * Constructor.
00072    *
00073    * @param dimensions Number of state variables in the system.
00074    *
00075    * The Wiener process noise is assumed to have the same
00076    * dimensionality as the state.
00077    */
00078   StochasticDifferentialModel(const unsigned int dimensions);
00079 
00080   /**
00081    * Constructor.
00082    *
00083    * @param dimensions Number of state variables in the system.
00084    * @param noiseDimensions Number of noise variables in the system.
00085    */
00086   StochasticDifferentialModel(const unsigned int dimensions,
00087       const unsigned int noiseDimensions);
00088 
00089   /**
00090    * Destructor.
00091    */
00092   virtual ~StochasticDifferentialModel();
00093 
00094   /**
00095    * Number of state variables in the system.
00096    *
00097    * @return the number of state variables in the system.
00098    */
00099   unsigned int getDimensions();
00100 
00101   /**
00102    * Number of noise variables in the system.
00103    *
00104    * @return the number of noise variables in the system.
00105    */
00106   unsigned int getNoiseDimensions();
00107 
00108   /**
00109    * Calculate drift term of the system at a given time.
00110    *
00111    * @param ts \f$t_s\f$; the proposed new time.
00112    * @param y \f$\mathbf{y}(t)\f$; the values of all state variables
00113    * at time \f$t\f$.
00114    * @param a \f$\mathbf{a}(\mathbf{y}, t)\f$; vector into which to write
00115    * the drift term at time \f$t\f$. This is uninitialised.
00116    *
00117    * Default implementation calls the older, now deprecated method
00118    * calculateDrift(const double, const indii::ml::aux::vector&).
00119    */
00120   virtual void calculateDrift(const double ts,
00121       const indii::ml::aux::vector& y, indii::ml::aux::vector& a);
00122 
00123   /**
00124    * Calculate diffusion term of the system at a given time.
00125    *
00126    * @param ts \f$t_s\f$; the proposed new time.
00127    * @param y \f$\mathbf{y}(t)\f$; the values of all state variables
00128    * at time \f$t\f$.
00129    * @param B \f$B(\mathbf{y}, t)\f$; matrix into which to write the
00130    * diffusion term at time \f$t\f$. This is either cleared or contains
00131    * the last diffusion calculation when called.
00132    *
00133    * Default implementation calls the older, now deprecated method
00134    * calculateDiffusion(const double, const indii::ml::aux::vector&).
00135    */
00136   virtual void calculateDiffusion(const double ts,
00137       const indii::ml::aux::vector& y, DT& B);
00138 
00139   /**
00140    * Calculate the partial derivatives of the diffusion term with
00141    * respect to each state variable at a given time.
00142    *
00143    * @param ts \f$t_s\f$; the proposed new time.
00144    * @param y \f$\mathbf{y}(t)\f$; the values of all state variables
00145    * at time \f$t\f$.
00146    * @param dBdy A vector of \f$N\f$ matrices into which to write the
00147    * result, where matrix \f$i\f$ is
00148    * \f$\frac{\partial B(\mathbf{y},t)}{\partial y_i}\f$ at time
00149    * \f$t\f$. Each matrix is either cleared or contains the last
00150    * partial derivative calculation when called.
00151    */
00152   virtual void calculateDiffusionDerivatives(const double ts,
00153       const indii::ml::aux::vector& y, std::vector<DDT>& dBdy);
00154 
00155   /**
00156    * Calculate drift term of the system at a given time.
00157    *
00158    * @param ts \f$t_s\f$; the proposed new time.
00159    * @param y \f$\mathbf{y}(t)\f$; the values of all state variables
00160    * at time \f$t\f$.
00161    *
00162    * @return \f$\mathbf{a}(\mathbf{y}, t)\f$; the drift term at time
00163    * \f$t\f$.
00164    *
00165    * @deprecated Use calculateDrift(const double,
00166    * const indii::ml::aux::vector&, indii::ml::aux::vector&)
00167    */
00168   virtual indii::ml::aux::vector calculateDrift(const double ts,
00169       const indii::ml::aux::vector& y);
00170 
00171   /**
00172    * Calculate diffusion term of the system at a given time.
00173    *
00174    * @param ts \f$t_s\f$; the proposed new time.
00175    * @param y \f$\mathbf{y}(t)\f$; the values of all state variables
00176    * at time \f$t\f$.
00177    *
00178    * @return \f$B(\mathbf{y}, t)\f$; the diffusion term at time
00179    * \f$t\f$.
00180    *
00181    * @deprecated Use calculateDiffusion(const double,
00182    * const indii::ml::aux::vector&, DT&)
00183    */
00184   virtual DT calculateDiffusion(const double ts,
00185       const indii::ml::aux::vector& y);
00186 
00187   /**
00188    * Calculate the partial derivatives of the diffusion term with
00189    * respect to each state variable at a given time.
00190    *
00191    * @param ts \f$t_s\f$; the proposed new time.
00192    * @param y \f$\mathbf{y}(t)\f$; the values of all state variables
00193    * at time \f$t\f$.
00194    *
00195    * @return A vector of \f$N\f$ matrices, where matrix \f$i\f$ is
00196    * \f$\frac{\partial B(\mathbf{y},t)}{\partial y_i}\f$ at time
00197    * \f$t\f$. In the special case that \f$B(\mathbf{y}, t)\f$ is not
00198    * dependent on \f$\mathbf{y}\f$, may return an empty
00199    * std::vector<aux::matrix>. This is the behaviour of the default
00200    * implementation and has the same effect as returning a vector of
00201    * \f$N\f$ zero matrices.
00202    *
00203    * @deprecated Use calculateDiffusionDerivatives(const double,
00204    * const indii::ml::aux::vector&, std::vector<DDT>)
00205    */
00206   virtual std::vector<DDT> calculateDiffusionDerivatives(
00207       const double ts, const indii::ml::aux::vector& y);
00208 
00209 private:
00210   /**
00211    * Number of state variables in the system.
00212    */
00213   unsigned int dimensions;
00214 
00215   /**
00216    * Number of noise variables in the system.
00217    */
00218   unsigned int noiseDimensions;
00219 
00220   /**
00221    * Serialize, or restore from serialization.
00222    */
00223   template<class Archive>
00224   void serialize(Archive& ar, const unsigned int version);
00225 
00226   /*
00227    * Boost.Serialization requirements.
00228    */
00229   friend class boost::serialization::access;
00230   
00231 };
00232 
00233     }
00234   }
00235 }
00236 
00237 template <class DT, class DDT>
00238 indii::ml::sde::StochasticDifferentialModel<DT,DDT>::StochasticDifferentialModel() {
00239   this->dimensions = 0;
00240   this->noiseDimensions = 0;
00241 }
00242 
00243 template <class DT, class DDT>
00244 indii::ml::sde::StochasticDifferentialModel<DT,DDT>::StochasticDifferentialModel(
00245     const unsigned int dimensions) {
00246   this->dimensions = dimensions;
00247   this->noiseDimensions = dimensions;
00248 }
00249 
00250 template <class DT, class DDT>
00251 indii::ml::sde::StochasticDifferentialModel<DT,DDT>::StochasticDifferentialModel(
00252     const unsigned int dimensions, const unsigned int noiseDimensions) {
00253   this->dimensions = dimensions;
00254   this->noiseDimensions = noiseDimensions;
00255 }
00256 
00257 template <class DT, class DDT>
00258 indii::ml::sde::StochasticDifferentialModel<DT,DDT>::~StochasticDifferentialModel() {
00259   //
00260 }
00261 
00262 template <class DT, class DDT>
00263 inline unsigned int
00264     indii::ml::sde::StochasticDifferentialModel<DT,DDT>::getDimensions() {
00265   return dimensions;
00266 }
00267 
00268 template <class DT, class DDT>
00269 inline unsigned int indii::ml::sde::StochasticDifferentialModel<DT,DDT>::getNoiseDimensions() {
00270   return noiseDimensions;
00271 }
00272 
00273 template <class DT, class DDT>
00274 void indii::ml::sde::StochasticDifferentialModel<DT,DDT>::calculateDrift(
00275     const double ts, const indii::ml::aux::vector& y,
00276     indii::ml::aux::vector& a) {
00277   noalias(a) = calculateDrift(ts, y);
00278 }
00279 
00280 template <class DT, class DDT>
00281 void indii::ml::sde::StochasticDifferentialModel<DT,DDT>::calculateDiffusion(
00282     const double ts, const indii::ml::aux::vector& y, DT& B) {
00283   noalias(B) = calculateDiffusion(ts, y);
00284 }
00285 
00286 template <class DT, class DDT>
00287 void indii::ml::sde::StochasticDifferentialModel<DT,DDT>::calculateDiffusionDerivatives(
00288     const double ts, const indii::ml::aux::vector& y,
00289     std::vector<DDT>& dBdy) {
00290   dBdy = calculateDiffusionDerivatives(ts, y);
00291 }
00292 
00293 template <class DT, class DDT>
00294 indii::ml::aux::vector
00295     indii::ml::sde::StochasticDifferentialModel<DT,DDT>::calculateDrift(
00296     const double ts, const indii::ml::aux::vector& y) {
00297   indii::ml::aux::vector a(dimensions);
00298   a.clear();
00299   
00300   return a;
00301 }
00302 
00303 template <class DT, class DDT>
00304 DT indii::ml::sde::StochasticDifferentialModel<DT,DDT>::calculateDiffusion(
00305     const double ts, const indii::ml::aux::vector& y) {
00306   DT B(dimensions, noiseDimensions);
00307   B.clear();
00308   
00309   return B;
00310 }
00311 
00312 template <class DT, class DDT>
00313 std::vector<DDT> indii::ml::sde::StochasticDifferentialModel<DT,DDT>::calculateDiffusionDerivatives(
00314     const double ts, const indii::ml::aux::vector& y) {
00315   std::vector<DDT> nil;
00316 
00317   return nil;
00318 }
00319 
00320 template <class DT, class DDT>
00321 template<class Archive>
00322 void indii::ml::sde::StochasticDifferentialModel<DT,DDT>::serialize(Archive& ar,
00323     const unsigned int version) {
00324   ar & dimensions;
00325   ar & noiseDimensions;
00326 }
00327 
00328 #endif
00329 

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