source: Sophya/trunk/SophyaLib/NTools/perandom.cc@ 3503

Last change on this file since 3503 was 3321, checked in by cmv, 18 years ago

createur par copie/default pour FunRan cmv 05/09/2007

File size: 9.0 KB
Line 
1#include "sopnamsp.h"
2#include "machdefs.h"
3#include "pexceptions.h"
4#include "perandom.h"
5#include "pemath.h"
6#include <iostream>
7
8
9////////////////////////////////////////////////////////////////////////////
10/*!
11 \class SOPHYA::FunRan
12 \ingroup NTools
13 Classe for generating random variables from 1D function
14*/
15
16
17/********* Methode *********/
18/*! Creator from a function.
19\verbatim
20 - if pdf==true: f est une densite de probabilite (PDF)
21 non necessairement normalisee
22 if pdf==false: f est une fonction de distribution (DF).
23 non necessairement normalisee
24 - Le tirage aleatoire est fait sur un histogramme
25 Histo(xMin,xMax,nBin) (voir convention dans Histo).
26 - Chaque bin de l'histogramme contient la valeur de la PDF
27 (ou de la DF) au centre du bin: h(i)=f(BinCenter(i))
28 - Les valeurs retournees sont les valeurs du centre des bins
29 pour le tirage non interpole et toutes les valeurs
30 entre [xmin,xmax] pour le tirage interpole
31 - La pdf doit etre interpretee comme etant nulle
32 pour des x<=xmin et x>=xmax
33 - Dans le bin "i" entre [x1,x2[ et de centre x0, h(i)=pdf(x0).
34 Pour le tirage interpole, la DF est approximee par un segment
35 et pdf(x0) est l'exces de proba entre x1 et x2:
36 bin 0 entre [xmin,BinHighEdge(0)[ :
37 la pdf va de 0 a pdf(BinCenter(0))
38 bin 1 entre [BinLowEdge(1),BinHighEdge(1)[:
39 la pdf va de pdf(BinCenter(0)) a pdf(BinCenter(1))
40 ...
41 bin n-1 entre [BinLowEdge(n-1),xmax[:
42 la pdf va de pdf(BinCenter(n-2)) a pdf(BinCenter(n-1))
43\endverbatim
44*/
45FunRan::FunRan(FunRan::Func f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
46 : Histo(xMin,xMax,nBin)
47{
48 if(nBin<=1)
49 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
50 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
51 create_DF(pdf);
52}
53
54/********* Methode *********/
55/*! Creator from a ClassFunc
56See FunRan::FunRan(FunRan::Func...) for further comments.
57*/
58FunRan::FunRan(ClassFunc& f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
59 : Histo(xMin,xMax,nBin)
60{
61 if(nBin<=1)
62 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
63 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
64 create_DF(pdf);
65}
66
67/********* Methode *********/
68/*! Creator from an table.
69If pdf=true, tab is a probability density fonction (not necessary normalised).
70If pdf=false, tab is a distribution function (not necessarly normalized to 1).
71The return random values will be between 0 and nBin-1.
72See FunRan::FunRan(FunRan::Func...) for further comments.
73*/
74FunRan::FunRan(r_8 *tab, int_4 nBin, bool pdf)
75: Histo(-0.5,nBin-0.5,nBin)
76{
77 if(nBin<=1)
78 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
79 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab[i];
80 create_DF(pdf);
81}
82
83/********* Methode *********/
84/*! Creator from an table.
85If pdf=true, tab is a probability density fonction (not necessary normalised).
86If pdf=false, tab is a distribution function (not necessarly normalized to 1).
87The content of tab is identified has the content of
88an Histogram define by Histo(xMin,xMax,nBin).
89See FunRan::FunRan(FunRan::Func...) for further comments.
90*/
91FunRan::FunRan(r_8 *tab, int_4 nBin, r_8 xMin, r_8 xMax, bool pdf)
92: Histo(xMin,xMax,nBin)
93{
94 if(nBin<=1)
95 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
96 for(int_4 i=0;i<nBin;i++) (*this)(i) = tab[i];
97 create_DF(pdf);
98}
99
100/********* Methode *********/
101/*! Creator from an histogram
102If pdf=true, h is a probability density fonction (not necessary normalised).
103If pdf=false, h is a distribution function (not necessarly normalized to 1).
104See FunRan::FunRan(FunRan::Func...) for further comments.
105*/
106FunRan::FunRan(Histo &h, bool pdf)
107 : Histo(h)
108{
109 if(mBins<=1)
110 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
111 create_DF(pdf);
112}
113
114/********* Methode *********/
115/*! Creator by copy */
116FunRan::FunRan(const FunRan& fh)
117 : Histo(fh)
118{
119}
120
121/********* Methode *********/
122/*! Creator by default */
123FunRan::FunRan(void)
124{
125}
126
127/********* Methode *********/
128void FunRan::create_DF(bool pdf)
129// Creation (si necessaire) et normalisation de la DF
130{
131 // On fabrique la FD si necessaire
132 if(pdf)
133 for(int_4 i=1;i<mBins;i++) (*this)(i) += (*this)(i-1);
134
135 // On normalise la FD
136 if((*this)(mBins-1)<=0.) {
137 cout<<"FunRan::FunRan(Histo) not a distribution function last bin is <=0"<<endl;
138 throw RangeCheckError("FunRan::FunRan(Histo) not a distribution function last bin is <=0");
139 }
140 for(int_4 i=0;i<mBins;i++) (*this)(i) /= (*this)(mBins-1);
141}
142
143/********* Methode *********/
144/*! Tirage avec retour du numero de bin entre 0 et mBins-1.
145It returns the first bin whose content is greater or equal
146to the random uniform number (in [0,1[)
147*/
148int_4 FunRan::BinRandom()
149{
150 // recherche du premier bin plus grand ou egal a z
151 r_8 z=drand01();
152 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) return i;
153 return mBins-1;
154}
155
156/********* Methode *********/
157/*! Tirage avec retour abscisse du bin non interpole. */
158r_8 FunRan::Random()
159{
160 r_8 z=drand01();
161 int ibin = mBins-1;
162 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) {ibin=i; break;}
163 return BinCenter(ibin);
164}
165
166/********* Methode *********/
167/*! Tirage avec retour abscisse du bin interpole. */
168r_8 FunRan::RandomInterp(void)
169{
170 r_8 z=drand01();
171 int ibin = mBins-1;
172 r_8 z1=0., z2;
173 for(int_4 i=0;i<mBins;i++) {
174 z2 = (*this)(i);
175 if(z<z2) {ibin=i; break;}
176 z1 = z2;
177 }
178
179 // l'algorithme garanti que "z2-z1 != 0" et "z1<z2"
180 return BinLowEdge(ibin) + (z-z1)/(z2-z1)*binWidth;
181
182}
183
184////////////////////////////////////////////////////////////////////////////
185/*!
186 \class SOPHYA::FunRan2D
187 \ingroup NTools
188 Classe for generating random variables from 2D function
189*/
190
191/********* Methode *********/
192/*! Creator for random from a table */
193FunRan2D::FunRan2D(r_8 *tab, int_4 nBinX, int_4 nBinY)
194{
195 // Tirage en X, somme sur les Y.
196 r_8* tabX = new r_8[nBinX];
197 for (int_4 i=0; i<nBinX; i++) {
198 tabX[i] = 0;
199 for (int_4 j=0; j<nBinY; j++) {
200 tabX[i] += tab[i*nBinY +j];
201 }
202 }
203 ranX = new FunRan(tabX, nBinX);
204 delete[] tabX;
205
206 ranY = new FunRan* [nBinX];
207
208 for (int_4 k=0; k<nBinX; k++)
209 ranY[k] = new FunRan(tab + nBinY*k, nBinY);
210
211 nx = nBinX;
212}
213
214/********* Methode *********/
215/*! Creator for random from a table */
216FunRan2D::FunRan2D(r_8 **tab, int_4 nBinX, int_4 nBinY)
217{
218 // Tirage en X, somme sur les Y.
219 r_8* tabX = new r_8[nBinX];
220 for (int_4 i=0; i<nBinX; i++) {
221 tabX[i] = 0;
222 for (int_4 j=0; j<nBinY; j++) {
223 tabX[i] += tab[i][j];
224 }
225 }
226 ranX = new FunRan(tabX, nBinX);
227
228 ranY = new FunRan* [nBinX];
229
230 for (int_4 k=0; k<nBinX; k++)
231 if (tabX[k] != 0)
232 ranY[k] = new FunRan(tab[k], nBinY);
233 else ranY[k] = NULL;
234
235 delete[] tabX;
236 nx = nBinX;
237}
238
239/********* Methode *********/
240/*! Destructor */
241FunRan2D::~FunRan2D()
242{
243 for (int_4 i=nx-1; i>=0; i--)
244 delete ranY[i];
245
246 delete[] ranY;
247
248 delete ranX;
249}
250
251/********* Methode *********/
252/*! Tirage avec retour du numeros de bin. */
253void FunRan2D::BinRandom(int_4& x, int_4& y)
254{
255 x = ranX->BinRandom();
256 y = ranY[x]->BinRandom();
257}
258
259/********* Methode *********/
260/*! Tirage avec retour abscisse et ordonnee du bin interpole. */
261void FunRan2D::Random(r_8& x, r_8& y)
262{
263 x = ranX->Random();
264 int_4 i = int_4(ceil(x));
265 y = ranY[i]->Random();
266}
267
268
269
270/////////////////////////////////////////////////////////////////
271/*
272**** Remarques sur complex< r_8 > ComplexGaussRan(double sig) ****
273
274--- variables gaussiennes x,y independantes
275x gaussien: pdf f(x) = 1/(sqrt(2Pi) Sx) exp(-(x-Mx)^2/(2 Sx^2))
276y gaussien: pdf f(y) = 1/(sqrt(2Pi) Sy) exp(-(y-My)^2/(2 Sy^2))
277x,y independants --> pdf f(x,y) = f(x) f(y)
278On a:
279 <x> = Integrate[x*f(x)] = Mx
280 <x^2> = Integrate[x^2*f(x)] = Mx^2 + Sx^2
281
282--- On cherche la pdf g(r,t) du module et de la phase
283 x = r cos(t) , y = r sin(t)
284 r=sqrt(x^2+y^2 , t=atan2(y,x)
285 (r,t) --> (x,y): le Jacobien = r
286
287 g(r,t) = r f(x,y) = r f(x) f(y)
288 = r/(2Pi Sx Sy) exp(-(x-Mx)^2/(2 Sx^2)) exp(-(y-My)^2/(2 Sy^2))
289
290- Le cas general est complique
291 (cf D.Pelat cours DEA "bruits et signaux" section 4.5)
292
293- Cas ou "Mx = My = 0" et "Sx = Sy = S"
294 c'est la pdf du module et de la phase d'un nombre complexe
295 dont les parties reelles et imaginaires sont independantes
296 et sont distribuees selon des gaussiennes de variance S^2
297 g(r,t) = r/(2Pi S^2) exp(-r^2/(2 S^2))
298 La distribution de "r" est donc:
299 g(r) = Integrate[g(r,t),{t,0,2Pi}]
300 = r/S^2 exp(-r^2/(2 S^2))
301 La distribution de "t" est donc:
302 g(t) = Integrate[g(r,t),{r,0,Infinity}]
303 = 1 / 2Pi (distribution uniforme sur [0,2Pi[)
304 Les variables aleatoires r,t sont independantes:
305 g(r,t) = g(r) g(t)
306On a:
307 <r> = Integrate[r*g(r)] = sqrt(PI/2)*S
308 <r^2> = Integrate[r^2*g(r)] = 2*S^2
309 <r^3> = Integrate[r^3*g(r)] = 3*sqrt(PI/2)*S^3
310 <r^4> = Integrate[r^4*g(r)] = 8*S^4
311
312- Attention:
313La variable complexe "c = x+iy = r*exp(i*t)" ainsi definie verifie:
314 <|c|^2> = <c c*> = <x^2+y^2> = <r^2> = 2 S^2
315Si on veut generer une variable complexe gaussienne telle que
316 <c c*> = s^2 alors il faut prendre S = s/sqrt(2) comme argument
317
318*/
Note: See TracBrowser for help on using the repository browser.