34 using state_type = StateType;
35 using time_type =
typename StateType::value_type;
36 using value_type =
typename StateType::value_type;
39 using drift_function = std::function<void(time_type,
const state_type&, state_type&)>;
40 using diffusion_function = std::function<void(time_type,
const state_type&, state_type&)>;
41 using noise_function = std::function<void(time_type,
const state_type&, StateType&,
const StateType&)>;
43 SDEProblem(drift_function drift, diffusion_function diffusion,
44 NoiseType noise_type = NoiseType::DIAGONAL_NOISE)
45 : drift_(std::move(drift))
46 , diffusion_(std::move(diffusion))
47 , noise_type_(noise_type) {}
49 void drift(time_type t,
const state_type& x, state_type& fx)
const {
53 void diffusion(time_type t,
const state_type& x, state_type& gx)
const {
57 NoiseType get_noise_type()
const {
return noise_type_; }
59 void set_noise_function(noise_function noise) {
60 noise_ = std::move(noise);
63 bool has_custom_noise()
const {
return noise_ !=
nullptr; }
65 void apply_noise(time_type t,
const state_type& x, state_type& noise_term,
const state_type& dW)
const {
67 noise_(t, x, noise_term, dW);
70 apply_default_noise(noise_term, dW);
75 drift_function drift_;
76 diffusion_function diffusion_;
77 noise_function noise_;
78 NoiseType noise_type_;
80 void apply_default_noise(state_type& noise_term,
const state_type& dW)
const {
81 switch (noise_type_) {
82 case NoiseType::SCALAR_NOISE:
84 for (
size_t i = 0; i < noise_term.size(); ++i) {
85 noise_term[i] *= dW[0];
89 case NoiseType::DIAGONAL_NOISE:
91 for (
size_t i = 0; i < noise_term.size() && i < dW.size(); ++i) {
92 noise_term[i] *= dW[i];
96 case NoiseType::GENERAL_NOISE:
99 for (
size_t i = 0; i < noise_term.size() && i < dW.size(); ++i) {
100 noise_term[i] *= dW[i];
113 using state_type = StateType;
114 using time_type =
typename StateType::value_type;
115 using value_type =
typename StateType::value_type;
118 : dimension_(dimension)
119 , generator_(seed == 0 ? std::chrono::steady_clock::now().time_since_epoch().count() : seed)
120 , normal_dist_(0.0, 1.0) {}
122 void generate_increment(state_type& dW, time_type dt) {
123 value_type sqrt_dt = std::sqrt(
static_cast<value_type
>(dt));
125 for (
size_t i = 0; i < dimension_ && i < dW.size(); ++i) {
126 auto dW_it = dW.begin();
127 dW_it[i] =
static_cast<value_type
>(normal_dist_(generator_)) * sqrt_dt;
131 void set_seed(uint32_t seed) {
132 generator_.seed(seed);
135 size_t dimension()
const {
return dimension_; }
139 std::mt19937 generator_;
140 std::normal_distribution<double> normal_dist_;
149 using state_type = StateType;
150 using time_type =
typename StateType::value_type;
151 using value_type =
typename StateType::value_type;
156 std::shared_ptr<wiener_process_type> wiener =
nullptr)
158 , wiener_(wiener ? wiener : std::make_shared<wiener_process_type>(get_default_dimension(), 0))
159 , current_time_(0) {}
164 virtual void step(state_type& state, time_type dt) = 0;
165 virtual std::string name()
const = 0;
168 void integrate(state_type& state, time_type dt, time_type end_time) {
169 while (current_time_ < end_time) {
170 time_type step_size = std::min<time_type>(dt, end_time - current_time_);
171 step(state, step_size);
176 time_type current_time()
const {
return current_time_; }
177 void set_time(time_type t) { current_time_ = t; }
179 std::shared_ptr<sde_problem_type> get_problem()
const {
return problem_; }
180 std::shared_ptr<wiener_process_type> get_wiener_process()
const {
return wiener_; }
182 void set_wiener_process(std::shared_ptr<wiener_process_type> wiener) {
187 void advance_time(time_type dt) { current_time_ += dt; }
189 virtual size_t get_default_dimension() {
194 std::shared_ptr<sde_problem_type> problem_;
195 std::shared_ptr<wiener_process_type> wiener_;
196 time_type current_time_;
204template<system_state StateType>
205auto make_sde_problem(
206 typename SDEProblem<StateType>::drift_function drift,
207 typename SDEProblem<StateType>::diffusion_function diffusion,
208 NoiseType noise_type = NoiseType::DIAGONAL_NOISE) {
209 return std::make_shared<SDEProblem<StateType>>(std::move(drift), std::move(diffusion), noise_type);
212template<system_state StateType>
213auto make_wiener_process(
size_t dimension, uint32_t seed = 0) {
214 return std::make_shared<WienerProcess<StateType>>(dimension, seed);