vSMC
vSMC: Scalable Monte Carlo
stable_distribution.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/stable_distribution.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013,2014, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_RNG_STABLE_DISTRIBUTION_HPP
33 #define VSMC_RNG_STABLE_DISTRIBUTION_HPP
34 
36 
37 #define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_STABILITY(a) \
38  VSMC_RUNTIME_ASSERT((a > 0 && a <= 2), \
39  ("**StableDistribution** CONSTRUCTED WITH INVALID " \
40  "STABILITY PARAMETER VALUE"))
41 
42 #define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SKEWNESS(a) \
43  VSMC_RUNTIME_ASSERT((a >= -1 && a <= 1), \
44  ("**StableDistribution** CONSTRUCTED WITH INVALID " \
45  "SKEWNESS PARAMETER VALUE"))
46 
47 #define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SCALE(a) \
48  VSMC_RUNTIME_ASSERT((a > 0), \
49  ("**StableDistribution** CONSTRUCTED WITH INVALID " \
50  "SCALE PARAMETER VALUE"))
51 
52 namespace vsmc {
53 
56 template <typename FPType>
58 {
59  private :
60 
61  public :
62 
63  typedef FPType result_type;
64 
65  struct param_type
66  {
67  typedef FPType result_type;
68 
70 
71  explicit param_type (
72  result_type stability = 1, result_type skewness = 0,
73  result_type location = 0, result_type scale = 1) :
74  stability_(stability), skewness_(skewness),
75  location_(location), scale_(scale) {}
76 
77  result_type stability () const {return stability_;}
78  result_type skewness () const {return skewness_;}
79  result_type location () const {return location_;}
80  result_type scale () const {return scale_;}
81 
82  friend inline bool operator== (
83  const param_type &param1, const param_type &param2)
84  {
85  if (param1.stability_ < param2.stability_ ||
86  param1.stability_ > param2.stability_)
87  return false;
88  if (param1.skewness_ < param2.skewness_ ||
89  param1.skewness_ > param2.skewness_)
90  return false;
91  if (param1.location_ < param2.location_ ||
92  param1.location_ > param2.location_)
93  return false;
94  if (param1.scale_ < param2.scale_ ||
95  param1.scale_ > param2.scale_)
96  return false;
97  return true;
98  }
99 
100  friend inline bool operator!= (
101  const param_type param1, const param_type param2)
102  {return !(param1 == param2);}
103 
104  template <typename CharT, typename Traits>
105  friend inline std::basic_ostream<CharT, Traits> &operator<< (
106  std::basic_ostream<CharT, Traits> &os, const param_type &param)
107  {
108  if (!os.good())
109  return os;
110 
111  os << param.stability_ << ' ' << param.skewness_ << ' ';
112  os << param.location_ << ' ' << param.scale_ << ' ';
113 
114  return os;
115  }
116 
117  template <typename CharT, typename Traits>
118  friend inline std::basic_istream<CharT, Traits> &operator>> (
119  std::basic_istream<CharT, Traits> &is, param_type &param)
120  {
121  if (!is.good())
122  return is;
123 
124  result_type stability = 0;
125  result_type skewness = 0;
126  result_type location = 0;
127  result_type scale = 0;
128  is >> std::ws >> stability;
129  is >> std::ws >> skewness;
130  is >> std::ws >> location;
131  is >> std::ws >> scale;
132 
133  if (is.good()) {
134  if (stability > 0 && stability <= 2 &&
135  skewness >= -1 && skewness <= 1 && scale > 0) {
136  param.stability_ = stability;
137  param.skewness_ = skewness;
138  param.location_ = location;
139  param.scale_ = scale;
140  } else {
141  is.setstate(std::ios_base::failbit);
142  }
143  }
144 
145  return is;
146  }
147 
148  private :
149 
150  result_type stability_;
151  result_type skewness_;
152  result_type location_;
153  result_type scale_;
154  }; // class param_type
155 
157  result_type stability = 1, result_type skewness = 0,
158  result_type location = 0, result_type scale = 1) :
159  stability_(stability), skewness_(skewness),
160  location_(location), scale_(scale),
161  zeta_(0), xi_(0), stability_1_(false)
162  {
164  stability_);
166  skewness_);
168  scale_);
169  invariant();
170  }
171 
172  explicit StableDistribution (const param_type &param) :
173  stability_(param.stability()), skewness_(param.skewness()),
174  location_(param.location()), scale_(param.scale()),
175  zeta_(0), xi_(0), stability_1_(false)
176  {
178  stability_);
180  skewness_);
182  scale_);
183  invariant();
184  }
185 
186  param_type param () const
187  {return param_type(stability_, skewness_, location_, scale_);}
188 
189  void param (const param_type &param)
190  {
191  stability_ = param.stability();
192  skewness_ = param.skewness();
193  location_ = param.location();
194  scale_ = param.scale();
195  invariant();
196  }
197 
198  void reset () const {}
199 
200  result_type stability () const {return stability_;}
201  result_type skewness () const {return skewness_;}
202  result_type location () const {return location_;}
203  result_type scale () const {return scale_;}
204  result_type min VSMC_MNE () const
205  {return -std::numeric_limits<result_type>::infinity();}
206  result_type max VSMC_MNE () const
207  {return std::numeric_limits<result_type>::infinity();}
208 
209  template <typename Eng>
210  result_type operator() (Eng &eng) const
211  {
212  if (stability_1_)
213  return trans_1(standard_1(eng));
214  else
215  return trans_a(standard_a(eng));
216  }
217 
218  friend inline bool operator== (
219  const StableDistribution<FPType> &rstable1,
220  const StableDistribution<FPType> &rstable2)
221  {
222  if (rstable1.stability_ < rstable2.stability_ ||
223  rstable1.stability_ > rstable2.stability_)
224  return false;
225  if (rstable1.skewness_ < rstable2.skewness_ ||
226  rstable1.skewness_ > rstable2.skewness_)
227  return false;
228  if (rstable1.location_ < rstable2.location_ ||
229  rstable1.location_ > rstable2.location_)
230  return false;
231  if (rstable1.scale_ < rstable2.scale_ ||
232  rstable1.scale_ > rstable2.scale_)
233  return false;
234  return true;
235  }
236 
237  friend inline bool operator!= (
238  const StableDistribution<FPType> &rstable1,
239  const StableDistribution<FPType> &rstable2)
240  {return !(rstable1 == rstable2);}
241 
242  template <typename CharT, typename Traits>
243  friend inline std::basic_ostream<CharT, Traits> &operator<< (
244  std::basic_ostream<CharT, Traits> &os,
245  const StableDistribution<FPType> &rstable)
246  {
247  if (!os.good())
248  return os;
249 
250  os << rstable.stability_ << ' ' << rstable.skewness_ << ' ';
251  os << rstable.location_ << ' ' << rstable.scale_ << ' ';
252 
253  return os;
254  }
255 
256  template <typename CharT, typename Traits>
257  friend inline std::basic_istream<CharT, Traits> &operator>> (
258  std::basic_istream<CharT, Traits> &is,
260  {
261  if (!is.good())
262  return is;
263 
264  result_type stability = 0;
265  result_type skewness = 0;
266  result_type location = 0;
267  result_type scale = 0;
268  is >> std::ws >> stability;
269  is >> std::ws >> skewness;
270  is >> std::ws >> location;
271  is >> std::ws >> scale;
272 
273  if (is.good()) {
274  if (stability > 0 && stability <= 2 &&
275  skewness >= -1 && skewness <= 1 && scale > 0) {
276  rstable.stability_ = stability;
277  rstable.skewness_ = skewness;
278  rstable.location_ = location;
279  rstable.scale_ = scale;
280  } else {
281  is.setstate(std::ios_base::failbit);
282  }
283  }
284 
285  return is;
286  }
287 
288  private :
289 
290  result_type stability_;
291  result_type skewness_;
292  result_type location_;
293  result_type scale_;
294  result_type zeta_;
295  result_type xi_;
296  bool stability_1_;
297 
298  template <typename Eng>
299  result_type standard_1 (Eng &eng) const
300  {
301  using std::cos;
302  using std::log;
303  using std::tan;
304 
305  cxx11::uniform_real_distribution<result_type> runif(0, 1);
306  result_type w = -log(runif(eng));
307  result_type u = (runif(eng) - 0.5) * math::pi<result_type>();
308  result_type a = (math::pi_by2<result_type>() + skewness_ * u) * tan(u);
309  result_type b = log(math::pi_by2<result_type>() * w * cos(u));
310  result_type c = log(math::pi_by2<result_type>() + skewness_ * u);
311  result_type x = (a - skewness_ * (b - c)) / xi_;
312 
313  return x;
314  }
315 
316  template <typename Eng>
317  result_type standard_a (Eng &eng) const
318  {
319  using std::cos;
320  using std::exp;
321  using std::log;
322  using std::sin;
323 
324  cxx11::uniform_real_distribution<result_type> runif(0, 1);
325  result_type w = -log(runif(eng));
326  result_type u = (runif(eng) - 0.5) * math::pi<result_type>();
327  result_type a = 0.5 * log(1 + zeta_ * zeta_) / stability_;
328  result_type b = sin(stability_ * (u + xi_));
329  result_type c = log(cos(u)) / stability_;
330  result_type d = (1 - stability_) / stability_ * log(
331  cos(u - stability_ * (u + xi_)) / w);
332  result_type x = b * std::exp(a - c + d);
333 
334  return x;
335  }
336 
337  result_type trans_1 (result_type x) const
338  {
339  using std::log;
340 
341  return scale_ * x + location_ +
342  2 * math::pi_inv<result_type>() * skewness_ * scale_ * log(scale_);
343  }
344 
345  result_type trans_a (result_type x) const
346  {return scale_ * x + location_;}
347 
348  void invariant ()
349  {
350  using std::atan;
351  using std::tan;
352 
353  if (stability_ < 1 || stability_ > 1) {
354  stability_1_ = false;
355  zeta_ = -skewness_ * tan(math::pi_by2<result_type>() * stability_);
356  xi_ = 1 / stability_ * atan(-zeta_);
357  } else {
358  stability_1_ = true;
359  zeta_ = -std::numeric_limits<result_type>::infinity();
360  xi_ = math::pi_by2<result_type>();
361  }
362  }
363 }; // class StableDistributionBase
364 
365 } // namespace vsmc
366 
367 #endif // VSMC_RNG_STABLE_DISTRIBUTION_HPP
Definition: adapter.hpp:37
param_type(result_type stability=1, result_type skewness=0, result_type location=0, result_type scale=1)
StableDistribution< FPType > distribution_type
result_type skewness() const
StableDistribution(const param_type &param)
#define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SKEWNESS(a)
friend bool operator!=(const StableDistribution< FPType > &rstable1, const StableDistribution< FPType > &rstable2)
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, StableDistribution< FPType > &rstable)
#define VSMC_MNE
Avoid MSVC stupid behavior: MNE = Macro No Expansion.
Definition: defines.hpp:38
friend bool operator==(const param_type &param1, const param_type &param2)
friend bool operator==(const StableDistribution< FPType > &rstable1, const StableDistribution< FPType > &rstable2)
void param(const param_type &param)
StableDistribution(result_type stability=1, result_type skewness=0, result_type location=0, result_type scale=1)
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const param_type &param)
#define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_SCALE(a)
friend bool operator!=(const param_type param1, const param_type param2)
result_type operator()(Eng &eng) const
result_type stability() const
result_type location() const
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const StableDistribution< FPType > &rstable)
#define VSMC_RUNTIME_ASSERT_RNG_STABLE_DISTRIBUTION_PARAM_CHECK_STABILITY(a)
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, param_type &param)