00001 #ifndef INDII_ML_SDE_STOCHASTICADAPTIVEEULERMARUYAMA_HPP
00002 #define INDII_ML_SDE_STOCHASTICADAPTIVEEULERMARUYAMA_HPP
00003
00004 #include "StochasticDifferentialModel.hpp"
00005 #include "StochasticNumericalSolver.hpp"
00006
00007 namespace indii {
00008 namespace ml {
00009 namespace sde {
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 template <class DT = indii::ml::aux::matrix,
00034 class DDT = indii::ml::aux::zero_matrix>
00035 class StochasticAdaptiveEulerMaruyama :
00036 public indii::ml::sde::StochasticNumericalSolver {
00037 public:
00038
00039
00040
00041
00042
00043
00044
00045
00046 StochasticAdaptiveEulerMaruyama(StochasticDifferentialModel<DT,DDT>* model);
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 StochasticAdaptiveEulerMaruyama(StochasticDifferentialModel<DT,DDT>* model,
00057 const indii::ml::aux::vector& y0);
00058
00059
00060
00061
00062 virtual ~StochasticAdaptiveEulerMaruyama();
00063
00064 virtual double step(double upper);
00065
00066 virtual double stepBack(double lower);
00067
00068 virtual int calculateDerivativesForward(double t, const double y[],
00069 double dydt[]);
00070
00071 virtual int calculateDerivativesBackward(double t, const double y[],
00072 double dydt[]);
00073
00074 private:
00075
00076
00077
00078 StochasticDifferentialModel<DT,DDT>* model;
00079
00080
00081
00082
00083 indii::ml::aux::vector a1;
00084
00085
00086
00087
00088 indii::ml::aux::vector a_mid;
00089
00090
00091
00092
00093 DT B1;
00094
00095
00096
00097
00098 DT B_mid;
00099
00100 };
00101
00102 }
00103 }
00104 }
00105
00106 #include "boost/numeric/ublas/operation.hpp"
00107 #include "boost/numeric/ublas/operation_sparse.hpp"
00108
00109 template <class DT, class DDT>
00110 indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::StochasticAdaptiveEulerMaruyama(
00111 StochasticDifferentialModel<DT,DDT>* model) :
00112 StochasticNumericalSolver(model->getDimensions(),
00113 model->getNoiseDimensions()), model(model),
00114 a1(model->getDimensions()), a_mid(model->getDimensions()),
00115 B1(model->getDimensions(), model->getNoiseDimensions()),
00116 B_mid(model->getDimensions(), model->getNoiseDimensions()) {
00117 setStepType(gsl_odeiv_step_gear1);
00118 }
00119
00120 template <class DT, class DDT>
00121 indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::StochasticAdaptiveEulerMaruyama(
00122 StochasticDifferentialModel<DT,DDT>* model,
00123 const indii::ml::aux::vector& y0) : StochasticNumericalSolver(y0,
00124 model->getNoiseDimensions()), model(model),
00125 a1(model->getDimensions()), a_mid(model->getDimensions()),
00126 B1(model->getDimensions(), model->getNoiseDimensions()),
00127 B_mid(model->getDimensions(), model->getNoiseDimensions()) {
00128
00129
00130 assert (y0.size() == model->getDimensions());
00131
00132 setStepType(gsl_odeiv_step_gear1);
00133 }
00134
00135 template <class DT, class DDT>
00136 indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::~StochasticAdaptiveEulerMaruyama() {
00137
00138 }
00139
00140 template <class DT, class DDT>
00141 double indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::step(
00142 double upper) {
00143
00144 assert (upper > t);
00145
00146 const unsigned int N = model->getDimensions();
00147 const unsigned int V = model->getNoiseDimensions();
00148 double ts, ts_new, ts_mid, ts_prev = 0.0;
00149 double h, h_new, h_mid;
00150 double absErr, relErr;
00151 bool stepDecreased, numSound;
00152
00153
00154 double* state = (double*)gslControl->state;
00155 absErr = state[0];
00156 relErr = state[1];
00157
00158
00159 if (maxStepSize > 0.0 && stepSize > maxStepSize) {
00160 stepSize = maxStepSize;
00161 }
00162 ts = t + stepSize;
00163 if (ts > upper) {
00164 ts = upper;
00165 }
00166
00167
00168 aux::vector y(this->getState());
00169 aux::vector y1(N), y_mid(N), y2(N);
00170 aux::vector dW1(V), dW_mid(V);
00171 aux::vector epsilon(N), delta(N);
00172 unsigned int i;
00173
00174
00175 sampleNoise(&ts);
00176 h = ts - t;
00177
00178
00179 noalias(dW1) = dWf.top();
00180 model->calculateDrift(t, y, a1);
00181 model->calculateDiffusion(t, y, B1);
00182 noalias(y1) = y + h*a1;
00183 ublas::axpy_prod(B1, dW1, y1, false);
00184
00185 ts_mid = 0.5*(ts + t);
00186
00187 stepDecreased = true;
00188 numSound = sampleNoise(&ts_mid);
00189 while (stepDecreased && numSound) {
00190 h_mid = ts_mid - t;
00191
00192 noalias(dW_mid) = dWf.top();
00193 noalias(y_mid) = y + h_mid*a1;
00194 ublas::axpy_prod(B1, dW_mid, y_mid, false);
00195
00196 model->calculateDrift(t + h_mid, y_mid, a_mid);
00197 model->calculateDiffusion(t + h_mid, y_mid, B_mid);
00198 noalias(y2) = y_mid + h_mid*a_mid;
00199 ublas::axpy_prod(B_mid, dW1-dW_mid, y2, false);
00200
00201
00202
00203 for (i = 0; i < N; i++) {
00204 epsilon(i) = fabs(y1(i) - y2(i));
00205 delta(i) = absErr + relErr*fabs(y1(i));
00206 }
00207 stepDecreased = ublas::norm_inf(element_div(epsilon, delta)) > 1.0;
00208
00209 if (stepDecreased) {
00210 ts_prev = ts;
00211 ts = ts_mid;
00212 h = h_mid;
00213 noalias(dW1) = dW_mid;
00214 noalias(y1) = y_mid;
00215
00216 ts_mid = 0.5*(ts + t);
00217 numSound = sampleNoise(&ts_mid);
00218 }
00219 }
00220
00221
00222 if (ts_prev > 0.0) {
00223 stepSize = ts_prev - t;
00224 } else {
00225 stepSize = 2.0*(ts - t);
00226 }
00227
00228
00229 aux::vectorToArray(y1, this->y);
00230
00231
00232 t = ts;
00233
00234
00235 if (numSound) {
00236 tf.pop();
00237 dWf.pop();
00238 }
00239
00240 tf.pop();
00241 dWf.pop();
00242
00243
00244 assert (tf.empty() || t < tf.top());
00245 assert (t <= upper);
00246
00247 return t;
00248 }
00249
00250 template <class DT, class DDT>
00251 inline double indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::stepBack(
00252 double lower) {
00253 double t = NumericalSolver::stepBack(lower);
00254
00255 return t;
00256 }
00257
00258 template <class DT, class DDT>
00259 inline int indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::calculateDerivativesForward(
00260 double ts, const double y[], double dydt[]) {
00261
00262 assert (false);
00263
00264 return GSL_FAILURE;
00265 }
00266
00267 template <class DT, class DDT>
00268 inline int indii::ml::sde::StochasticAdaptiveEulerMaruyama<DT,DDT>::calculateDerivativesBackward(
00269 double t, const double y[], double dydt[]) {
00270
00271 assert (false);
00272
00273 return GSL_FAILURE;
00274 }
00275
00276 #endif
00277