adaptive_iterator.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. * adaptive_iterator.cpp
  3. *
  4. * Copyright 2012-2013 Karsten Ahnert
  5. * Copyright 2012 Mario Mulansky
  6. *
  7. * Distributed under the Boost Software License, Version 1.0.
  8. * (See accompanying file LICENSE_1_0.txt or
  9. * copy at http://www.boost.org/LICENSE_1_0.txt)
  10. */
  11. #include <iostream>
  12. #include <iterator>
  13. #include <utility>
  14. #include <algorithm>
  15. #include <cassert>
  16. #include <boost/array.hpp>
  17. #include <boost/range/algorithm.hpp>
  18. #include <boost/range/adaptor/filtered.hpp>
  19. #include <boost/range/numeric.hpp>
  20. #include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
  21. #include <boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp>
  22. #include <boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp>
  23. #include <boost/numeric/odeint/stepper/generation.hpp>
  24. #include <boost/numeric/odeint/iterator/adaptive_iterator.hpp>
  25. #include <boost/numeric/odeint/iterator/adaptive_time_iterator.hpp>
  26. #define tab "\t"
  27. using namespace std;
  28. using namespace boost::numeric::odeint;
  29. const double sigma = 10.0;
  30. const double R = 28.0;
  31. const double b = 8.0 / 3.0;
  32. struct lorenz
  33. {
  34. template< class State , class Deriv >
  35. void operator()( const State &x , Deriv &dxdt , double t ) const
  36. {
  37. dxdt[0] = sigma * ( x[1] - x[0] );
  38. dxdt[1] = R * x[0] - x[1] - x[0] * x[2];
  39. dxdt[2] = -b * x[2] + x[0] * x[1];
  40. }
  41. };
  42. #include <typeinfo>
  43. int main( int argc , char **argv )
  44. {
  45. typedef boost::array< double , 3 > state_type;
  46. /*
  47. * Controlled steppers with time iterator
  48. */
  49. // std::for_each
  50. {
  51. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  52. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  53. std::for_each( make_adaptive_time_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  54. make_adaptive_time_iterator_end( stepper , lorenz() , x ) ,
  55. []( const std::pair< const state_type&, double > &x ) {
  56. std::cout << x.second << tab << x.first[0] << tab << x.first[1] << tab << x.first[2] << "\n"; } );
  57. }
  58. // std::copy_if
  59. {
  60. std::vector< pair< state_type , double > > res;
  61. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  62. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  63. std::copy_if( make_adaptive_time_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  64. make_adaptive_time_iterator_end( stepper , lorenz() , x ) ,
  65. std::back_inserter( res ) ,
  66. []( const pair< const state_type& , double > &x ) {
  67. return ( x.first[0] > 0.0 ) ? true : false; } );
  68. for( size_t i=0 ; i<res.size() ; ++i )
  69. cout << res[i].first[0] << tab << res[i].first[1] << tab << res[i].first[2] << "\n";
  70. }
  71. // std::accumulate
  72. {
  73. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  74. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  75. double res = std::accumulate( make_adaptive_time_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  76. make_adaptive_time_iterator_end( stepper , lorenz() , x ) ,
  77. 0.0 ,
  78. []( double sum , const pair< const state_type& , double > &x ) {
  79. return sum + x.first[0]; } );
  80. cout << res << endl;
  81. }
  82. // std::transform
  83. {
  84. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  85. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  86. vector< double > weights;
  87. std::transform( make_adaptive_time_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  88. make_adaptive_time_iterator_end( stepper , lorenz() , x ) ,
  89. back_inserter( weights ) ,
  90. []( const pair< const state_type& , double > &x ) {
  91. return sqrt( x.first[0] * x.first[0] + x.first[1] * x.first[1] + x.first[2] * x.first[2] ); } );
  92. for( size_t i=0 ; i<weights.size() ; ++i )
  93. cout << weights[i] << "\n";
  94. }
  95. /*
  96. * Boost.Range versions of controlled stepper with time iterator
  97. */
  98. // boost::range::for_each
  99. {
  100. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  101. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  102. boost::range::for_each( make_adaptive_time_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  103. []( const std::pair< const state_type& , double > &x ) {
  104. std::cout << x.second << tab << x.first[0] << tab << x.first[1] << tab << x.first[2] << "\n"; } );
  105. }
  106. // boost::range::copy with filtered adaptor (simulating std::copy_if)
  107. {
  108. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  109. std::vector< std::pair< state_type , double > > res;
  110. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  111. boost::range::copy( make_adaptive_time_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) |
  112. boost::adaptors::filtered( [] ( const pair< const state_type& , double > &x ) { return ( x.first[0] > 0.0 ); } ) ,
  113. std::back_inserter( res ) );
  114. for( size_t i=0 ; i<res.size() ; ++i )
  115. cout << res[i].first[0] << tab << res[i].first[1] << tab << res[i].first[2] << "\n";
  116. }
  117. // boost::range::accumulate
  118. {
  119. //[adaptive_time_iterator_accumulate_range
  120. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  121. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  122. double res = boost::accumulate( make_adaptive_time_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) , 0.0 ,
  123. []( double sum , const pair< const state_type& , double > &x ) {
  124. return sum + x.first[0]; } );
  125. cout << res << endl;
  126. //]
  127. }
  128. // boost::range::transform
  129. {
  130. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  131. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  132. vector< double > weights;
  133. boost::transform( make_adaptive_time_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) , back_inserter( weights ) ,
  134. []( const pair< const state_type& , double > &x ) {
  135. return sqrt( x.first[0] * x.first[0] + x.first[1] * x.first[1] + x.first[2] * x.first[2] ); } );
  136. for( size_t i=0 ; i<weights.size() ; ++i )
  137. cout << weights[i] << "\n";
  138. }
  139. // boost::range::find with time iterator
  140. {
  141. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  142. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  143. auto iter = boost::find_if( make_adaptive_time_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  144. []( const std::pair< const state_type & , double > &x ) {
  145. return ( x.first[0] < 0.0 ); } );
  146. cout << iter->second << "\t" << iter->first[0] << "\t" << iter->first[1] << "\t" << iter->first[2] << "\n";
  147. }
  148. // /*
  149. // * Boost.Range versions for dense output steppers
  150. // */
  151. // // boost::range::for_each
  152. // {
  153. // runge_kutta_dopri5< state_type > stepper;
  154. // state_type x = {{ 10.0 , 10.0 , 10.0 }};
  155. // boost::range::for_each( make_adaptive_range( make_dense_output( 1.0e-6 , 1.0e-6 , stepper ) , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  156. // []( const state_type &x ) {
  157. // std::cout << x[0] << tab << x[1] << tab << x[2] << "\n"; } );
  158. // }
  159. // // boost::range::for_each with time iterator
  160. // {
  161. // runge_kutta_dopri5< state_type > stepper;
  162. // state_type x = {{ 10.0 , 10.0 , 10.0 }};
  163. // boost::range::for_each( make_adaptive_time_range( make_dense_output( 1.0e-6 , 1.0e-6 , stepper ) , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  164. // []( const std::pair< state_type& , double > &x ) {
  165. // std::cout << x.second << tab << x.first[0] << tab << x.first[1] << tab << x.first[2] << "\n"; } );
  166. // }
  167. /*
  168. * Pure iterators for controlled stepper without time iterator
  169. */
  170. // std::for_each
  171. {
  172. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  173. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  174. std::for_each( make_adaptive_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  175. make_adaptive_iterator_end( stepper , lorenz() , x ) ,
  176. []( const state_type& x ) {
  177. std::cout << x[0] << tab << x[1] << tab << x[2] << "\n"; } );
  178. }
  179. // std::copy_if
  180. {
  181. std::vector< state_type > res;
  182. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  183. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  184. std::copy_if( make_adaptive_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  185. make_adaptive_iterator_end( stepper , lorenz() , x ) ,
  186. std::back_inserter( res ) ,
  187. []( const state_type& x ) {
  188. return ( x[0] > 0.0 ) ? true : false; } );
  189. for( size_t i=0 ; i<res.size() ; ++i )
  190. cout << res[i][0] << tab << res[i][1] << tab << res[i][2] << "\n";
  191. }
  192. // std::accumulate
  193. {
  194. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  195. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  196. double res = std::accumulate( make_adaptive_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  197. make_adaptive_iterator_end( stepper , lorenz() , x ) ,
  198. 0.0 ,
  199. []( double sum , const state_type& x ) {
  200. return sum + x[0]; } );
  201. cout << res << endl;
  202. }
  203. // std::transform
  204. {
  205. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  206. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  207. vector< double > weights;
  208. std::transform( make_adaptive_iterator_begin( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  209. make_adaptive_iterator_end( stepper , lorenz() , x ) ,
  210. back_inserter( weights ) ,
  211. []( const state_type& x ) {
  212. return sqrt( x[0] * x[0] + x[1] * x[1] + x[2] * x[2] ); } );
  213. for( size_t i=0 ; i<weights.size() ; ++i )
  214. cout << weights[i] << "\n";
  215. }
  216. /*
  217. * Boost.Range versions of controlled stepper WITHOUT time iterator
  218. */
  219. // boost::range::for_each
  220. {
  221. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  222. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  223. boost::range::for_each( make_adaptive_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  224. []( const state_type &x ) {
  225. std::cout << x[0] << tab << x[1] << tab << x[2] << "\n"; } );
  226. }
  227. // boost::range::copy with filtered adaptor (simulating std::copy_if)
  228. {
  229. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  230. std::vector< state_type > res;
  231. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  232. boost::range::copy( make_adaptive_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) |
  233. boost::adaptors::filtered( [] ( const state_type& x ) { return ( x[0] > 0.0 ); } ) ,
  234. std::back_inserter( res ) );
  235. for( size_t i=0 ; i<res.size() ; ++i )
  236. cout << res[i][0] << tab << res[i][1] << tab << res[i][2] << "\n";
  237. }
  238. // boost::range::accumulate
  239. {
  240. //[adaptive_iterator_accumulate_range
  241. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  242. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  243. double res = boost::accumulate( make_adaptive_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) , 0.0 ,
  244. []( double sum , const state_type& x ) {
  245. return sum + x[0]; } );
  246. cout << res << endl;
  247. //]
  248. }
  249. // boost::range::transform
  250. {
  251. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  252. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  253. vector< double > weights;
  254. boost::transform( make_adaptive_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) , back_inserter( weights ) ,
  255. []( const state_type& x ) {
  256. return sqrt( x[0] * x[0] + x[1] * x[1] + x[2] * x[2] ); } );
  257. for( size_t i=0 ; i<weights.size() ; ++i )
  258. cout << weights[i] << "\n";
  259. }
  260. // boost::range::find
  261. {
  262. auto stepper = make_controlled( 1.0e-6 , 1.0e-6 , runge_kutta_cash_karp54< state_type >() );
  263. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  264. auto iter = boost::find_if( make_adaptive_range( stepper , lorenz() , x , 0.0 , 1.0 , 0.01 ) ,
  265. []( const state_type &x ) {
  266. return ( x[0] < 0.0 ); } );
  267. cout << (*iter)[0] << "\t" << (*iter)[1] << "\t" << (*iter)[2] << "\n";
  268. }
  269. return 0;
  270. }