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

Last change on this file since 3201 was 3195, checked in by cmv, 18 years ago

Impressionsi pb dans FunRan::FunRan(Histo) cmv 03/04/2007

File size: 8.8 KB
RevLine 
[2615]1#include "sopnamsp.h"
[244]2#include "machdefs.h"
3#include "pexceptions.h"
[220]4#include "perandom.h"
5#include "pemath.h"
[2322]6#include <iostream>
[220]7
[3075]8
[220]9////////////////////////////////////////////////////////////////////////////
[3075]10/*!
11 \class SOPHYA::FunRan
12 \ingroup NTools
13 Classe for generating random variables from 1D function
14*/
[220]15
[3075]16
17/********* Methode *********/
[3109]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
[3075]44*/
[3109]45FunRan::FunRan(FunRan::Func f, r_8 xMin, r_8 xMax, int_4 nBin, bool pdf)
46 : Histo(xMin,xMax,nBin)
[220]47{
[3109]48 if(nBin<=1)
[2840]49 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
[3109]50 for(int_4 i=0;i<nBin;i++) (*this)(i) = f(BinCenter(i));
51 create_DF(pdf);
52}
[2840]53
[3109]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);
[220]65}
66
[3075]67/********* Methode *********/
[3109]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).
[3075]71The return random values will be between 0 and nBin-1.
72See FunRan::FunRan(FunRan::Func...) for further comments.
73*/
[3109]74FunRan::FunRan(r_8 *tab, int_4 nBin, bool pdf)
[2840]75: Histo(-0.5,nBin-0.5,nBin)
[220]76{
[3109]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);
[220]81}
82
[3075]83/********* Methode *********/
[3109]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).
[3075]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*/
[3109]91FunRan::FunRan(r_8 *tab, int_4 nBin, r_8 xMin, r_8 xMax, bool pdf)
[2840]92: Histo(xMin,xMax,nBin)
[220]93{
[3109]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);
[220]98}
99
[3075]100/********* Methode *********/
[3109]101/*! Creator from an histogram
102If pdf=true, h is a probability density fonction (not necessary normalised).
[3075]103If pdf=false, h is a distribution function (not necessarly normalized to 1).
104See FunRan::FunRan(FunRan::Func...) for further comments.
105*/
[2840]106FunRan::FunRan(Histo &h, bool pdf)
[3109]107 : Histo(h)
[2838]108{
[3109]109 if(mBins<=1)
110 throw RangeCheckError("FunRan::FunRan less than 2 bins requested");
111 create_DF(pdf);
112}
[2840]113
[3109]114/********* Methode *********/
115void FunRan::create_DF(bool pdf)
116// Creation (si necessaire) et normalisation de la DF
117{
118 // On fabrique la FD si necessaire
119 if(pdf)
120 for(int_4 i=1;i<mBins;i++) (*this)(i) += (*this)(i-1);
[2840]121
[3109]122 // On normalise la FD
[3195]123 if((*this)(mBins-1)<=0.) {
124 cout<<"FunRan::FunRan(Histo) not a distribution function last bin is <=0"<<endl;
125 throw RangeCheckError("FunRan::FunRan(Histo) not a distribution function last bin is <=0");
126 }
[2840]127 for(int_4 i=0;i<mBins;i++) (*this)(i) /= (*this)(mBins-1);
[2838]128}
129
[3075]130/********* Methode *********/
131/*! Tirage avec retour du numero de bin entre 0 et mBins-1.
132It returns the first bin whose content is greater or equal
[3109]133to the random uniform number (in [0,1[)
[3075]134*/
[1092]135int_4 FunRan::BinRandom()
[220]136{
[2840]137 // recherche du premier bin plus grand ou egal a z
138 r_8 z=drand01();
139 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) return i;
140 return mBins-1;
[220]141}
142
[3075]143/********* Methode *********/
144/*! Tirage avec retour abscisse du bin non interpole. */
[1092]145r_8 FunRan::Random()
[220]146{
[2840]147 r_8 z=drand01();
148 int ibin = mBins-1;
[3109]149 for(int_4 i=0;i<mBins;i++) if(z<(*this)(i)) {ibin=i; break;}
[2840]150 return BinCenter(ibin);
[220]151}
152
[3109]153/********* Methode *********/
154/*! Tirage avec retour abscisse du bin interpole. */
155r_8 FunRan::RandomInterp(void)
156{
157 r_8 z=drand01();
158 int ibin = mBins-1;
159 r_8 z1=0., z2;
160 for(int_4 i=0;i<mBins;i++) {
161 z2 = (*this)(i);
162 if(z<z2) {ibin=i; break;}
163 z1 = z2;
164 }
[220]165
[3109]166 // l'algorithme garanti que "z2-z1 != 0" et "z1<z2"
167 return BinLowEdge(ibin) + (z-z1)/(z2-z1)*binWidth;
168
169}
170
[220]171////////////////////////////////////////////////////////////////////////////
[3075]172/*!
173 \class SOPHYA::FunRan2D
174 \ingroup NTools
175 Classe for generating random variables from 2D function
176*/
[220]177
[3075]178/********* Methode *********/
179/*! Creator for random from a table */
[1092]180FunRan2D::FunRan2D(r_8 *tab, int_4 nBinX, int_4 nBinY)
[220]181{
182 // Tirage en X, somme sur les Y.
[1092]183 r_8* tabX = new r_8[nBinX];
184 for (int_4 i=0; i<nBinX; i++) {
[220]185 tabX[i] = 0;
[1092]186 for (int_4 j=0; j<nBinY; j++) {
[220]187 tabX[i] += tab[i*nBinY +j];
188 }
189 }
190 ranX = new FunRan(tabX, nBinX);
191 delete[] tabX;
192
[2870]193 ranY = new FunRan* [nBinX];
[220]194
[1092]195 for (int_4 k=0; k<nBinX; k++)
[220]196 ranY[k] = new FunRan(tab + nBinY*k, nBinY);
197
198 nx = nBinX;
199}
200
[3075]201/********* Methode *********/
202/*! Creator for random from a table */
[1092]203FunRan2D::FunRan2D(r_8 **tab, int_4 nBinX, int_4 nBinY)
[220]204{
205 // Tirage en X, somme sur les Y.
[1092]206 r_8* tabX = new r_8[nBinX];
207 for (int_4 i=0; i<nBinX; i++) {
[220]208 tabX[i] = 0;
[1092]209 for (int_4 j=0; j<nBinY; j++) {
[220]210 tabX[i] += tab[i][j];
211 }
212 }
213 ranX = new FunRan(tabX, nBinX);
214
[2870]215 ranY = new FunRan* [nBinX];
[220]216
[1092]217 for (int_4 k=0; k<nBinX; k++)
[220]218 if (tabX[k] != 0)
219 ranY[k] = new FunRan(tab[k], nBinY);
220 else ranY[k] = NULL;
221
222 delete[] tabX;
223 nx = nBinX;
224}
225
[3075]226/********* Methode *********/
227/*! Destructor */
[220]228FunRan2D::~FunRan2D()
229{
[1092]230 for (int_4 i=nx-1; i>=0; i--)
[220]231 delete ranY[i];
232
233 delete[] ranY;
234
235 delete ranX;
236}
237
[3075]238/********* Methode *********/
239/*! Tirage avec retour du numeros de bin. */
[1092]240void FunRan2D::BinRandom(int_4& x, int_4& y)
[220]241{
242 x = ranX->BinRandom();
243 y = ranY[x]->BinRandom();
244}
245
[3075]246/********* Methode *********/
247/*! Tirage avec retour abscisse et ordonnee du bin interpole. */
[1092]248void FunRan2D::Random(r_8& x, r_8& y)
[220]249{
250 x = ranX->Random();
[1092]251 int_4 i = int_4(ceil(x));
[220]252 y = ranY[i]->Random();
253}
[3075]254
255
256
257/////////////////////////////////////////////////////////////////
258/*
[3109]259**** Remarques sur complex< r_8 > ComplexGaussRan(double sig) ****
260
261--- variables gaussiennes x,y independantes
262x gaussien: pdf f(x) = 1/(sqrt(2Pi) Sx) exp(-(x-Mx)^2/(2 Sx^2))
263y gaussien: pdf f(y) = 1/(sqrt(2Pi) Sy) exp(-(y-My)^2/(2 Sy^2))
[3075]264x,y independants --> pdf f(x,y) = f(x) f(y)
[3109]265On a:
266 <x> = Integrate[x*f(x)] = Mx
267 <x^2> = Integrate[x^2*f(x)] = Mx^2 + Sx^2
268
269--- On cherche la pdf g(r,t) du module et de la phase
270 x = r cos(t) , y = r sin(t)
271 r=sqrt(x^2+y^2 , t=atan2(y,x)
272 (r,t) --> (x,y): le Jacobien = r
273
[3075]274 g(r,t) = r f(x,y) = r f(x) f(y)
275 = r/(2Pi Sx Sy) exp(-(x-Mx)^2/(2 Sx^2)) exp(-(y-My)^2/(2 Sy^2))
[3109]276
[3075]277- Le cas general est complique
278 (cf D.Pelat cours DEA "bruits et signaux" section 4.5)
[3109]279
[3075]280- Cas ou "Mx = My = 0" et "Sx = Sy = S"
[3109]281 c'est la pdf du module et de la phase d'un nombre complexe
282 dont les parties reelles et imaginaires sont independantes
283 et sont distribuees selon des gaussiennes de variance S^2
[3075]284 g(r,t) = r/(2Pi S^2) exp(-r^2/(2 S^2))
285 La distribution de "r" est donc:
286 g(r) = Integrate[g(r,t),{t,0,2Pi}]
287 = r/S^2 exp(-r^2/(2 S^2))
288 La distribution de "t" est donc:
289 g(t) = Integrate[g(r,t),{r,0,Infinity}]
290 = 1 / 2Pi (distribution uniforme sur [0,2Pi[)
291 Les variables aleatoires r,t sont independantes:
[3109]292 g(r,t) = g(r) g(t)
293On a:
294 <r> = Integrate[r*g(r)] = sqrt(PI/2)*S
295 <r^2> = Integrate[r^2*g(r)] = 2*S^2
296 <r^3> = Integrate[r^3*g(r)] = 3*sqrt(PI/2)*S^3
297 <r^4> = Integrate[r^4*g(r)] = 8*S^4
298
[3097]299- Attention:
[3109]300La variable complexe "c = x+iy = r*exp(i*t)" ainsi definie verifie:
301 <|c|^2> = <c c*> = <x^2+y^2> = <r^2> = 2 S^2
[3097]302Si on veut generer une variable complexe gaussienne telle que
[3109]303 <c c*> = s^2 alors il faut prendre S = s/sqrt(2) comme argument
304
[3075]305*/
Note: See TracBrowser for help on using the repository browser.