/[PAMELA software]/PamUnfold/src/RanGen.cpp
ViewVC logotype

Annotation of /PamUnfold/src/RanGen.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Thu Aug 30 16:51:05 2018 UTC (6 years, 3 months ago) by mayorov
Branch: MAIN
CVS Tags: PU1r1, HEAD
PamUnfold was upload to CVS

1 mayorov 1.1 #include <RanGen.h>
2    
3     using namespace std;
4    
5     ClassImp(RanGen);
6    
7     RanGen::RanGen(Int_t seed) : TRandom3(seed){
8     }
9    
10     RanGen::~RanGen(){};
11    
12     Double_t RanGen::Gamma(Int_t n, Double_t theta){
13    
14     Double_t value = 0;
15    
16     for(Int_t i=0; i<n; i++) value -= TMath::Log( this->Uniform() );
17    
18     return value;
19    
20     }
21    
22    
23     vector<Double_t> RanGen::Dirichlet(Int_t n, vector<Int_t> x){
24    
25     Double_t sum = 0;
26     vector<Double_t> gammas(n);
27     vector<Double_t> value(n);
28    
29     for(Int_t i=0; i<n; i++){
30     gammas[i] = Gamma(x[i], 1);
31     sum += gammas[i];
32     }
33    
34     for(Int_t i=0; i<n; i++){
35     if(sum)
36     value[i] = gammas[i]/sum;
37     else
38     value[i] = 0;
39     }
40    
41     return value;
42    
43     }
44    
45    
46     Int_t RanGen::Binomial(Int_t n, Double_t p){
47     unsigned int i, a, b, k = 0;
48     while (n > 10) /* This parameter is tunable */
49     {
50     double X;
51     a = 1 + (n / 2);
52     b = 1 + n - a;
53    
54     X = this->Beta((Int_t) a, (Int_t) b);
55    
56     if (X >= p)
57     {
58     n = a - 1;
59     p /= X;
60     }
61     else
62     {
63     k += a;
64     n = b - 1;
65     p = (p - X) / (1 - X);
66     }
67     }
68    
69     for (i = 0; i < n; i++)
70     {
71     double u = this->Uniform();
72     if (u < p)
73     k++;
74     }
75    
76     return k;
77    
78     }
79    
80     Double_t RanGen::Beta(const Int_t a, const Int_t b){
81     double x1 = this->Gamma(a, 1.0);
82     double x2 = this->Gamma(b, 1.0);
83    
84     return x1 / (x1 + x2);
85     }
86    
87     vector<Int_t> RanGen::Multinomial(Int_t N, vector<Double_t> p){
88    
89     /* From the GSL Library:
90     The multinomial distribution has the form
91    
92     N! n_1 n_2 n_K
93     prob(n_1, n_2, ... n_K) = -------------------- p_1 p_2 ... p_K
94     (n_1! n_2! ... n_K!)
95    
96     where n_1, n_2, ... n_K are nonnegative integers, sum_{k=1,K} n_k = N,
97     and p = (p_1, p_2, ..., p_K) is a probability distribution.
98    
99     Random variates are generated using the conditional binomial method.
100     This scales well with N and does not require a setup step.
101    
102     Ref:
103     C.S. David, The computer generation of multinomial random variates,
104     Comp. Stat. Data Anal. 16 (1993) 205-217
105     */
106    
107     size_t K = p.size();
108     vector<Int_t> n(K);
109    
110     size_t k;
111     double norm = 0.0;
112     double sum_p = 0.0;
113    
114     unsigned int sum_n = 0;
115    
116     /* p[k] may contain non-negative weights that do not sum to 1.0.
117     * Even a probability distribution will not exactly sum to 1.0
118     * due to rounding errors.
119     */
120    
121     for (k = 0; k < K; k++)
122     {
123     norm += p[k];
124     }
125    
126     for (k = 0; k < K; k++)
127     {
128     if (p[k] > 0.0)
129     {
130     n[k] = this->Binomial(N - sum_n, p[k] / (norm - sum_p));
131     }
132     else
133     {
134     n[k] = 0;
135     }
136    
137     sum_p += p[k];
138     sum_n += n[k];
139     }
140     return n;
141    
142     }

  ViewVC Help
Powered by ViewVC 1.1.23