2017-04-17 8 views
1

Cela a déjà été adressé (Using boost's skewed_normal_distribution) mais j'ai rencontré des difficultés et le thread précédent n'incluait aucun code de solution.Utilisation de Boost skew_normal_distribution

Je voudrais échantillon d'une distribution asymétrique normale en utilisant les fonctions intégrées dans la bibliothèque Boost

J'adaptais code que je sais fonctionne très bien avec le normal_distribution <> classe mais quand je lance le code que je continue à recevoir l'erreur montrée ci-dessous. Si quelqu'un pouvait m'aider avec ça, je serais très reconnaissant.

#include <boost/random.hpp> 
#include <boost/random/normal_distribution.hpp> 
#include <boost/math/distributions/skew_normal.hpp> 

int main() { 

boost::mt19937 rng2; 

boost::math::skew_normal_distribution<> snd(0.0, 1.0, 1.0); 

boost::variate_generator<boost::mt19937&, 
     boost::math::skew_normal_distribution<> > var_snd(rng2, snd); 

int i = 0; for (; i < 10; ++i) 
{ 
    double d = var_snd(); 
    std::cout << d << std::endl; 
} 


    return 0; 
} 

Erreur:

[ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.o 
In file included from /usr/include/boost/random.hpp:55:0, 
       from /home/jack/CLionProjects/untitled/main.cpp:1: 
/usr/include/boost/random/variate_generator.hpp: In instantiation of ‘class boost::random::variate_generator<boost::random::mersenne_twister_engine<unsigned int, 32ul, 624ul, 397ul, 31ul, 2567483615u, 11ul, 4294967295u, 7ul, 2636928640u, 15ul, 4022730752u, 18ul, 1812433253u>&, boost::math::skew_normal_distribution<double> >’: 
/home/jack/CLionProjects/untitled/main.cpp:13:63: required from here 
/usr/include/boost/random/variate_generator.hpp:59:48: error: no type named ‘result_type’ in ‘class boost::math::skew_normal_distribution<double>’ 
    typedef typename Distribution::result_type result_type; 

Jack

Répondre

0

Il y a deux espaces de noms différents dans Boost qui contiennent toutes les deux classes de distribution: boost :: aléatoires et boost :: mathématiques. Malheureusement, ces deux espaces de noms différents sont écrits avec des objectifs différents et par conséquent, les distributions sous-jacentes ne peuvent pas être immédiatement échangées comme vous essayez de le faire ici.

Vous remarquerez que la classe de distribution normale avec laquelle vous avez démarré à l'origine appartient à l'espace de nommage boost :: random. Alors que la classe skew_normal appartient à l'espace de nommage boost :: math; d'où l'incompatibilité.

Si vous souhaitez simplement générer des échantillons d'un coup de pouce :: mathématiques :: la distribution skew_normal cependant, vous êtes en mesure de le faire en utilisant la méthode suivante (en supposant que vous utilisez C++ 11):

#include <boost/math/distributions/skew_normal.hpp> 

// Setup generators 
std::random_device rd; 
std::default_random_engine noise_generator; 

// Sample from a uniform distribution i.e. [0,1) 
std::uniform_real_distribution<double> uniform_dist(0,1.0); 

// Take a different value every time to generate probabilities from 0 to 1 
noise_generator.seed(rd()); 
auto probability = uniform_dist(noise_generator); 

auto skew_norm_dist = boost::math::skew_normal_distribution<double>(
    0, 1., 10.); 

// Use the probability from the uniform distribution with the percent point 
// function of the skew_normal 
double skew_normal_sample_point = boost::math::quantile(skew_norm_dist, probability); 
std::cout << "Sample point: " << skew_normal_sample_point << std::endl; 

Ici, vous générez essentiellement une valeur de probabilité à partir d'une distribution uniforme, puis vous l'utilisez pour rechercher une valeur à partir de la fonction de pourcentage de skew_normal_distribution.

Si vous mettez ces quatre dernières lignes dans une boucle et produisez un grand nombre de points, par ex.

for(unsigned int i = 0; i < 10000; ++i) 
{ 
    noise_generator.seed(rd()); 
    auto probability = uniform_dist(noise_generator); 
    double skew_normal_sample_point = boost::math::quantile(skew_norm_dist, probability); 
    std::cout << skew_normal_sample_point << std::endl; 
} 

puis tracer les résultats dans un histogramme, vous verrez qu'ils sont conformes à la distribution asymétrique normale que vous avez créé.