Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
coupled_ode_system.hpp
Go to the documentation of this file.
1 #ifndef STAN__AGRAD__REV__ODE__COUPLED_ODE_SYSTEM_HPP
2 #define STAN__AGRAD__REV__ODE__COUPLED_ODE_SYSTEM_HPP
3 
4 #include <ostream>
5 #include <vector>
12 #include <stan/meta/traits.hpp>
13 
14 namespace stan {
15 
16  namespace math {
17 
18  // This code is in this directory because it includes agrad::var
19  // It is in namespace stan::math so that the partial template
20  // specializations are treated as such.
21 
22 
34  void add_initial_values(const std::vector<stan::agrad::var>& y0,
35  std::vector<std::vector<stan::agrad::var> >& y) {
36  for (size_t n = 0; n < y.size(); n++)
37  for (size_t m = 0; m < y0.size(); m++)
38  y[n][m] += y0[m];
39  }
40 
62  template <typename F>
63  struct coupled_ode_system <F, double, stan::agrad::var> {
64 
65  const F& f_;
66  const std::vector<double>& y0_dbl_;
67  const std::vector<stan::agrad::var>& theta_;
68  std::vector<double> theta_dbl_;
69  const std::vector<double>& x_;
70  const std::vector<int>& x_int_;
71  const int N_;
72  const int M_;
73  const int size_;
74  std::ostream* msgs_;
75 
88  coupled_ode_system(const F& f,
89  const std::vector<double>& y0,
90  const std::vector<stan::agrad::var>& theta,
91  const std::vector<double>& x,
92  const std::vector<int>& x_int,
93  std::ostream* msgs)
94  : f_(f),
95  y0_dbl_(y0),
96  theta_(theta),
97  theta_dbl_(theta.size(), 0.0),
98  x_(x),
99  x_int_(x_int),
100  N_(y0.size()),
101  M_(theta.size()),
102  size_(N_ + N_ * M_),
103  msgs_(msgs) {
104 
105  for (int m = 0; m < M_; m++)
106  theta_dbl_[m] = stan::agrad::value_of(theta[m]);
107  }
108 
123  void operator()(const std::vector<double>& y,
124  std::vector<double>& dy_dt,
125  double t) {
126  using std::vector;
127  using stan::agrad::var;
128 
129  vector<double> y_base(y.begin(), y.begin()+N_);
130  dy_dt = f_(t,y_base,theta_dbl_,x_,x_int_,msgs_);
131  stan::math::check_equal("coupled_ode_system(%1%)",
132  dy_dt.size(),N_,"dy_dt",
133  static_cast<double*>(0));
134 
135  vector<double> coupled_sys(N_ * M_);
136  vector<var> theta_temp;
137  vector<var> y_temp;
138  vector<var> dy_dt_temp;
139  vector<double> grad;
140  vector<var> vars;
141 
142  for (int i = 0; i < N_; i++) {
143  theta_temp.clear();
144  y_temp.clear();
145  dy_dt_temp.clear();
146  grad.clear();
147  vars.clear();
148  try {
150  for (int j = 0; j < N_; j++) {
151  y_temp.push_back(y[j]);
152  vars.push_back(y_temp[j]);
153  }
154 
155  for (int j = 0; j < M_; j++) {
156  theta_temp.push_back(theta_dbl_[j]);
157  vars.push_back(theta_temp[j]);
158  }
159  dy_dt_temp = f_(t,y_temp,theta_temp,x_,x_int_,msgs_);
160  dy_dt_temp[i].grad(vars, grad);
161 
162  for (int j = 0; j < M_; j++) {
163  // orders derivatives by equation (i.e. if there are 2 eqns
164  // (y1, y2) and 2 parameters (a, b), dy_dt will be ordered as:
165  // dy1_dt, dy2_dt, dy1_da, dy2_da, dy1_db, dy2_db
166  double temp_deriv = grad[y_temp.size() + j];
167  for (int k = 0; k < N_; k++)
168  temp_deriv += y[N_ + N_ * j + k] * grad[k];
169 
170  coupled_sys[i + j * N_] = temp_deriv;
171  }
172  } catch (const std::exception& e) {
174  throw;
175  }
177  }
178 
179  dy_dt.insert(dy_dt.end(), coupled_sys.begin(), coupled_sys.end());
180  }
181 
187  int size() const {
188  return size_;
189  }
190 
204  std::vector<double> initial_state() {
205  std::vector<double> state(size_, 0.0);
206  for (int n = 0; n < N_; n++)
207  state[n] = y0_dbl_[n];
208  return state;
209  }
210 
211 
218  std::vector<std::vector<stan::agrad::var> >
219  decouple_states(const std::vector<std::vector<double> >& y) {
221  std::vector<stan::agrad::var> temp_vars;
222  std::vector<double> temp_gradients;
223  std::vector<std::vector<stan::agrad::var> > y_return(y.size());
224 
225  for (size_t i = 0; i < y.size(); i++) {
226  temp_vars.clear();
227 
228  //iterate over number of equations
229  for (size_t j = 0; j < N_; j++) {
230  temp_gradients.clear();
231 
232  //iterate over parameters for each equation
233  for (size_t k = 0; k < M_; k++)
234  temp_gradients.push_back(y[i][y0_dbl_.size()
235  + y0_dbl_.size() * k + j]);
236 
237  temp_vars.push_back(precomputed_gradients(y[i][j],
238  theta_,
239  temp_gradients));
240  }
241  y_return[i] = temp_vars;
242  }
243 
244  return y_return;
245  }
246 
247  };
248 
249 
250 
251 
252 
253 
280  template <typename F>
281  struct coupled_ode_system <F, stan::agrad::var, double> {
282 
283  const F& f_;
284  const std::vector<stan::agrad::var>& y0_;
285  std::vector<double> y0_dbl_;
286  const std::vector<double>& theta_dbl_;
287  const std::vector<double>& x_;
288  const std::vector<int>& x_int_;
289  std::ostream* msgs_;
290  const int N_;
291  const int M_;
292  const int size_;
293 
307  coupled_ode_system(const F& f,
308  const std::vector<stan::agrad::var>& y0,
309  const std::vector<double>& theta,
310  const std::vector<double>& x,
311  const std::vector<int>& x_int,
312  std::ostream* msgs)
313  : f_(f),
314  y0_(y0),
315  y0_dbl_(y0.size(), 0.0),
316  theta_dbl_(theta),
317  x_(x),
318  x_int_(x_int),
319  msgs_(msgs),
320  N_(y0.size()),
321  M_(theta.size()),
322  size_(N_ + N_ * N_) {
323 
324  for (int n = 0; n < N_; n++)
325  y0_dbl_[n] = stan::agrad::value_of(y0_[n]);
326  }
327 
341  void operator()(const std::vector<double>& y,
342  std::vector<double>& dy_dt,
343  double t) {
344  std::vector<double> y_base(y.begin(), y.begin() + N_);
345  for (int n = 0; n < N_; n++)
346  y_base[n] += y0_dbl_[n];
347 
348  dy_dt = f_(t,y_base,theta_dbl_,x_,x_int_,msgs_);
349  stan::math::check_equal("coupled_ode_system(%1%)",
350  dy_dt.size(),N_,"dy_dt",
351  static_cast<double*>(0));
352 
353  std::vector<double> coupled_sys(N_ * N_);
354 
355  std::vector<stan::agrad::var> y_temp;
356  std::vector<stan::agrad::var> dy_dt_temp;
357  std::vector<double> grad;
358  std::vector<stan::agrad::var> vars;
359 
360  for (int i = 0; i < N_; i++) {
361  y_temp.clear();
362  dy_dt_temp.clear();
363  grad.clear();
364  vars.clear();
365  try {
367  for (int j = 0; j < N_; j++) {
368  y_temp.push_back(y[j] + y0_dbl_[j]);
369  vars.push_back(y_temp[j]);
370  }
371 
372  dy_dt_temp = f_(t,y_temp,theta_dbl_,x_,x_int_,msgs_);
373  dy_dt_temp[i].grad(vars, grad);
374 
375  for (int j = 0; j < N_; j++) {
376  // orders derivatives by equation (i.e. if there are 2 eqns
377  // (y1, y2) and 2 parameters (a, b), dy_dt will be ordered as:
378  // dy1_dt, dy2_dt, dy1_da, dy2_da, dy1_db, dy2_db
379  double temp_deriv = grad[j];
380  for (int k = 0; k < N_; k++)
381  temp_deriv += y[N_ + N_ * j + k] * grad[k];
382 
383  coupled_sys[i+j*N_] = temp_deriv;
384  }
385  } catch (const std::exception& e) {
387  throw;
388  }
390  }
391 
392  dy_dt.insert(dy_dt.end(), coupled_sys.begin(), coupled_sys.end());
393  }
394 
400  int size() const {
401  return size_;
402  }
403 
418  std::vector<double> initial_state() {
419  return std::vector<double>(size_, 0.0);
420  }
421 
429  std::vector<std::vector<stan::agrad::var> >
430  decouple_states(const std::vector<std::vector<double> >& y) {
432  using stan::agrad::var;
433  using std::vector;
434 
435  vector<var> temp_vars;
436  vector<double> temp_gradients;
437  vector<vector<var> > y_return(y.size());
438 
439  for (size_t i = 0; i < y.size(); i++) {
440  temp_vars.clear();
441 
442  // iterate over number of equations
443  for (size_t j = 0; j < N_; j++) {
444  temp_gradients.clear();
445 
446  // iterate over parameters for each equation
447  for (size_t k = 0; k < N_; k++)
448  temp_gradients.push_back(y[i][y0_.size() + y0_.size() * k + j]);
449 
450  temp_vars.push_back(precomputed_gradients(y[i][j],
451  y0_, temp_gradients));
452  }
453 
454  y_return[i] = temp_vars;
455  }
456 
457  add_initial_values(y0_, y_return);
458 
459  return y_return;
460  }
461 
462  };
463 
464 
465 
466 
467 
468 
469 
505  template <typename F>
507  const F& f_;
508  const std::vector<stan::agrad::var>& y0_;
509  std::vector<double> y0_dbl_;
510  const std::vector<stan::agrad::var>& theta_;
511  std::vector<double> theta_dbl_;
512  const std::vector<double>& x_;
513  const std::vector<int>& x_int_;
514  const int N_;
515  const int M_;
516  const int size_;
517  std::ostream* msgs_;
518 
532  coupled_ode_system(const F& f,
533  const std::vector<stan::agrad::var>& y0,
534  const std::vector<stan::agrad::var>& theta,
535  const std::vector<double>& x,
536  const std::vector<int>& x_int,
537  std::ostream* msgs)
538  : f_(f),
539  y0_(y0),
540  y0_dbl_(y0.size(), 0.0),
541  theta_(theta),
542  theta_dbl_(theta.size(), 0.0),
543  x_(x),
544  x_int_(x_int),
545  N_(y0.size()),
546  M_(theta.size()),
547  size_(N_ + N_ * (N_ + M_)),
548  msgs_(msgs) {
549 
550  for (int n = 0; n < N_; n++)
551  y0_dbl_[n] = stan::agrad::value_of(y0[n]);
552 
553  for (int m = 0; m < M_; m++)
554  theta_dbl_[m] = stan::agrad::value_of(theta[m]);
555  }
556 
570  void operator()(const std::vector<double>& y,
571  std::vector<double>& dy_dt,
572  double t) {
573  using std::vector;
574  using stan::agrad::var;
575 
576  vector<double> y_base(y.begin(), y.begin()+N_);
577  for (int n = 0; n < N_; n++)
578  y_base[n] += y0_dbl_[n];
579 
580  dy_dt = f_(t,y_base,theta_dbl_,x_,x_int_,msgs_);
581  stan::math::check_equal("coupled_ode_system(%1%)",
582  dy_dt.size(),N_,"dy_dt",
583  static_cast<double*>(0));
584 
585  vector<double> coupled_sys(N_ * (N_ + M_));
586  vector<var> theta_temp;
587  vector<var> y_temp;
588  vector<var> dy_dt_temp;
589  vector<double> grad;
590  vector<var> vars;
591 
592  for (int i = 0; i < N_; i++) {
593  theta_temp.clear();
594  y_temp.clear();
595  dy_dt_temp.clear();
596  grad.clear();
597  vars.clear();
598  try {
600 
601  for (int j = 0; j < N_; j++) {
602  y_temp.push_back(y[j] + y0_dbl_[j]);
603  vars.push_back(y_temp[j]);
604  }
605 
606  for (int j = 0; j < M_; j++) {
607  theta_temp.push_back(theta_dbl_[j]);
608  vars.push_back(theta_temp[j]);
609  }
610 
611  dy_dt_temp = f_(t,y_temp,theta_temp,x_,x_int_,msgs_);
612  dy_dt_temp[i].grad(vars, grad);
613 
614  for (int j = 0; j < N_+M_; j++) {
615  // orders derivatives by equation (i.e. if there are 2 eqns
616  // (y1, y2) and 2 parameters (a, b), dy_dt will be ordered as:
617  // dy1_dt, dy2_dt, dy1_da, dy2_da, dy1_db, dy2_db
618  double temp_deriv = grad[j];
619  for (int k = 0; k < N_; k++)
620  temp_deriv += y[N_ + N_ * j + k] * grad[k];
621 
622  coupled_sys[i + j * N_] = temp_deriv;
623  }
624  } catch (const std::exception& e) {
626  throw;
627  }
629  }
630  dy_dt.insert(dy_dt.end(), coupled_sys.begin(), coupled_sys.end());
631  }
632 
638  int size() const {
639  return size_;
640  }
641 
653  std::vector<double> initial_state() {
654  return std::vector<double>(size_, 0.0);
655  }
656 
664  std::vector<std::vector<stan::agrad::var> >
665  decouple_states(const std::vector<std::vector<double> >& y) {
666  using std::vector;
667  using stan::agrad::var;
669 
670  vector<var> vars = y0_;
671  vars.insert(vars.end(), theta_.begin(), theta_.end());
672 
673  vector<var> temp_vars;
674  vector<double> temp_gradients;
675  vector<vector<var> > y_return(y.size());
676 
677  for (size_t i = 0; i < y.size(); i++) {
678  temp_vars.clear();
679 
680  //iterate over number of equations
681  for (size_t j = 0; j < N_; j++) {
682  temp_gradients.clear();
683 
684  //iterate over parameters for each equation
685  for (size_t k = 0; k < N_ + M_; k++)
686  temp_gradients.push_back(y[i][N_ + N_ * k + j]);
687 
688  temp_vars.push_back(precomputed_gradients(y[i][j],
689  vars, temp_gradients));
690  }
691  y_return[i] = temp_vars;
692  }
693  add_initial_values(y0_, y_return);
694  return y_return;
695  }
696 
697  };
698 
699 
700  }
701 
702 }
703 
704 #endif
bool check_equal(const char *function, const T_y &y, const T_eq &eq, const char *name, T_result *result)
Definition: check_equal.hpp:57
int N_
int size() const
Returns the size of the coupled system.
static void start_nested()
Record the current position so that recover_memory_nested() can find it.
Definition: var_stack.hpp:96
var precomputed_gradients(const double value, const std::vector< var > &vars, const std::vector< double > &gradients)
This function is provided for Stan users that want to compute gradients without using Stan's auto-dif...
int size() const
Returns the size of the coupled system.
static void grad(chainable *vi)
Compute the gradient for all variables starting from the specified root variable implementation.
Definition: chainable.hpp:110
std::vector< std::vector< stan::agrad::var > > decouple_states(const std::vector< std::vector< double > > &y)
Return the basic ODE solutions given the specified coupled system solutions, including the partials v...
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition: value_of.hpp:16
int size() const
Returns the size of the coupled system.
coupled_ode_system(const F &f, const std::vector< double > &y0, const std::vector< stan::agrad::var > &theta, const std::vector< double > &x, const std::vector< int > &x_int, std::ostream *msgs)
Construct a coupled ODE system with the specified base ODE system, base initial state, parameters, data, and a message stream.
coupled_ode_system(const F &f, const std::vector< stan::agrad::var > &y0, const std::vector< double > &theta, const std::vector< double > &x, const std::vector< int > &x_int, std::ostream *msgs)
Construct a coupled ODE system for an unknown initial state and known parameters givne the specified ...
void operator()(const std::vector< double > &y, std::vector< double > &dy_dt, double t)
Assign the derivative vector with the system derivatives at the specified state and time...
std::vector< double > initial_state()
Returns the initial state of the coupled system.
void operator()(const std::vector< double > &y, std::vector< double > &dy_dt, double t)
Populates the derivative vector with derivatives of the coupled ODE system state with respect to time...
std::vector< std::vector< stan::agrad::var > > decouple_states(const std::vector< std::vector< double > > &y)
Returns the base ODE system state corresponding to the specified coupled system state.
void add_initial_values(const std::vector< stan::agrad::var > &y0, std::vector< std::vector< stan::agrad::var > > &y)
Increment the state derived from the coupled system in the with the original initial state...
std::vector< std::vector< stan::agrad::var > > decouple_states(const std::vector< std::vector< double > > &y)
Return the solutions to the basic ODE system, including appropriate autodiff partial derivatives...
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:27
double e()
Return the base of the natural logarithm.
Definition: constants.hpp:86
int size(const std::vector< T > &x)
Definition: size.hpp:11
size_t size_
Definition: dot_self.hpp:18
Base template class for a coupled ordinary differential equation system, which adds sensitivities to ...
static void recover_memory_nested()
Recover only the memory used for the top nested call.
Definition: var_stack.hpp:72
std::vector< double > initial_state()
Returns the initial state of the coupled system.
std::vector< double > initial_state()
Returns the initial state of the coupled system.
coupled_ode_system(const F &f, const std::vector< stan::agrad::var > &y0, const std::vector< stan::agrad::var > &theta, const std::vector< double > &x, const std::vector< int > &x_int, std::ostream *msgs)
Construct a coupled ODE system with unknown initial value and known parameters, given the base ODE sy...
void operator()(const std::vector< double > &y, std::vector< double > &dy_dt, double t)
Calculates the derivative of the coupled ode system with respect to the state y at time t...
int M_

     [ Stan Home Page ] © 2011–2014, Stan Development Team.