Conventions
- the examples below assume one specifies
the directive:
otherwise the namespace Pdf should be specified
where appropriate.
Probability distribution
functions (PDF)
- Probability distribution functions
are functions (or functors; see here) returning a value
representing a probability density (or probability) corresponding to
the double (or int) value that is passed as argument. More than one variable
can be passed as argument in the case of multi-dimensional distributions.
- Examples
are:
struct Gaussian { Gaussian( double m, double s ) : mean( m ), sigma( s ) { } double operator()( double x ) const { static const double norm( 1 / sqrt( 2 * M_PI ) ); double arg = ( x - mean ) / sigma; return exp( -0.5 * arg * arg ) * norm / sigma; } private: double mean, sigma; }; struct Poissonian { Poissonian( double m ) : mean( m ) { } double operator()( unsigned int n ) const { return ( exp( - mean ) * pow( mean, n ) / Funct::factorial( n ) ); } private: double mean; };
|
- Some of the most commonly used PDFs are provided.
More in details
PDF type |
arguments
|
parameter names
|
header file
|
Flat
|
double
|
min,
max
|
Pdf/Flat.h
|
Constant<T>
|
any (default:
double)
|
value
|
Pdf/Constant.h
|
Exponential
|
double
|
tau
|
Pdf/Exponential.h
|
Gaussian
|
double
|
mean,
sigma
|
Pdf/Gaussian.h
|
Poissonian
|
unsigned
int
|
mean
|
Pdf/Poissonian.h
|
Tag<n>
|
int
|
prob[0],
... prob[n]
|
Pdf/Tag.h
|
Triangular
|
double
|
-
|
Pdf/Triangular.h
|
- Generating
PDFs from expressions (header Pdf/Pdf.h)
- PDFs can be generated from expressions using the
Pdf template, passing the expression
type as template argument. Given that the expression is not in general normalized,
three types of PDF are provided in order to provide the appropriate normalization:
- PdfNoNormalization: assumes
that the expression is already normalized, and performs no normalization
- PdfNonParametric: computes the
normalization only once at the contruction time. This may be an optimized
choice if the normalization factor does not depend on expression parameters.
The integration is performed analytically by default. The user can always
specify to compute the integration numerically.
- PdfParametric: the normalization
is recomputed every time the operator "()" is called. This may be required
for instance when the normalization depends on a PDF parameter that is
fitted, and changes from call to call.
- Example:
X x;
// perform no normalization.
// for the following case it is not appropriate...
PdfNoNormalization< X > f1( sqr(sin(x) + cos(x))
);
// compute the integration only once
PdfNonParametric< X > f2( sqr(sin(x) + cos(x)), 0, 4*M_PI );
// recompute the normalization every time, since
// the parameter tau may change from call to call
Parameter tau( 0.123 );
PdfParametric< X > f3( x * exp( - tau * x ), 0, 10 );
|
Random number generators
- Random number generators generate random variables
according to a given PDF. The PDF type has to be specified as template
parameter. For each of the provided PDF type T a corresponding random generator
is provided as RandomGenerator< T >. Usually random
generators for a type XXX are defined in the header file
Pdf/RandomGeneratorXXX.h.
- Before using random generators, it is necessary
to specify which engine implementation should be used. This toolkit is not
intended to re-implement random number generators that are already nicely
implemented in other packages. Currently, CLHEP and ROOT implementations are
supported. The external packages are encapsulated internally, and a default
must be choosen by the user. This is specified in the header file Pdf/Ext/Defaults.h,
which is set to ROOT including Pdf/Exp/Root/RootRandom.h and
defining DefaultRandomGenerator as RootRandom
As alternative, the user may include the header Pdf/Ext/Clhep/ClhepRandom.h,
and define DefaultRandomGenerator as ClhepRandom.
It is also possible to mix generators using different engines passing the
generator as second template argument of RandomGenerator.
See the examples for more use cases.
- Example:
#include "Pdf/RandomGeneratorGaussian.h" Gaussian g( 0, 1 ); // a gaussian with mean 0 and r.m.s. 1 RandomGenerator< Gaussiam > r( g ); double x; r.generate( x ); // x is set to a random value according to g
|
- User can specify Random number generators for
custom PDFs by partial specialization of the RandomGenerator template.
As alternative, two random generator engines are provided using a sampling
algorithm, or a "hit-or-miss" algorithm.
- Examples of how to specify custom random generators
follow:
struct MyPdf { double operator()( double x ) { // . . . implementation of custom PDF } }; #include "Pdf/RandomGenerator.h" template< > struct RamdomGenerator< MyPdf > { void generate( double& x ) { x = myRandom(); } }; #include "Pdf/RandomGeneratorSample.h" // specify a sampling for MyPdf of 1024 point from -1 to 1 RANDOM_GENERATOR_SAMPLE( MyPdf, 1024, -1, 1 ) #include "Pdf/RandomGeneratorHitOrMiss.h" // specify a "hit-or-miss" algorithm from -1 to 1, // assuming a maximum of MyPdf of 100 RANDOM_GENERATOR_HITORMISS( MyPdf, -1, 1, 100 )
|
- Notice that random number generators for custom
PDFs are the for all the PDFs of the same type. In case of more custom PDFs from expressions,
it may be necessary to have different generators for different PDFs. This
is easily solved providing subclasses of the templated PDFs. Instead of
explicitly subclassing a PDF, it is possible to use the predefined preprocessor
macros DEFINE_PDFNONORMALIZATION, DEFINE_PDFNONPARAMETRIC
and DEFINE_PDFPARAMETRIC.
- Example:
template<
typename X >
struct MyPdf1 : public Pdf::PdfNoNormalization< X > {
template< typename F > MyPdf1
( const F& f ) :
Pdf::PdfNoNormalization<X>(
f ) { }
};
// equivalent to the above definition
DEFINE_PDFNONORMALIZATION( MyPdf2 )
RANDOM_GENERATOR_SAMPLE( MyPdf1<X>, 1024, 0, 10 )
RANDOM_GENERATOR_HITORMISS( MyPdf2<X>,
0, 5, ::exp(-1) )
X x;
MyPdf1 f1( exp( -x ) );
MyPdf2 f2( x * exp( -x ) );
RandomGenerator< MyPdf1 > r1;
RandomGenerator< MyPdf2 > r2;
|
Combining and manipulating PDFs
- PDFs cam be combined in order to obtain a richer
variety of Probability functions. Two basic mechanisms are provided: composition
of independent PDFs to obtain a multi-dimensional pdf, and mixure of PDFs.
Also, trasformation of variable is supported.
- Composition
of independent PDFs (defined in Pdf/Independent.h)
- Two PDFs in n and m variables
can be composed to obtain a n+m variable PDF which is the product
of the two original PDFs. Up to 10 PDFs can be combined in a single one.
The list of PDF types to be combined can be passed as template parameters.
The variable types of the combined function are the one of the original
PDF, in the specified order.
- Example:
#include "Pdf/Independent.h"
Gaussian g( 1, 2 );
Flat u( -1, 1 );
Independent< Gaussian, Flat > i( g, u );
|
- In order to be handled by the Independent
template, a PDF class has to specify the number
and types of its aguments. In order to do this automatically, it may be
convenient to inherit from the class Argument.
See the header file of the provided PDFs for more detail.
- A random generator for the combined PDF is provided.
It will generate random variables independently for the combined PDFs.
#include "RandomGeneratorIndependent.h"
typedef Independent< Gaussian, Gaussian, Flat > CombPdf;
RandomGenerator< CombPdf > CombRand;
CombRand r( i );
double x, y, z;
r.generate( x, y, z );
|
- Mixture of PDFs
(defined in Pdf/Mixture.h)
- Two PDFs having the same variables can be mixed
with relative fractions specified by the user. A specific random generator
is provided for mixture PDF type.
- Example:
#include "Pdf/Mixture.h"
Gaussian g( 0, 1 );
Flat u( -5, 5 );
// define a mixture, with gaussian fraction of 10%
Mixture< Gaussian, Flat > m( g, u, 0.1 );
|
- Transformation
of variables (defined in Pdf/Trandformed.h)
- A transformation of variable is a C++ class
(or struct) that implements direct and inverse transformation. As example,
the two-dimensional rotation (defined in Pdf/Rotation.h)
is shown:
struct Rotation2D {
Rotation2D( double phi ):
_cos( cos( phi ) ), _sin( sin( phi ) ) {}
void operator()( double & x0, double& x1 )
const {
double X = x0 * _cos - x1 * _sin;
double Y = x0 * _sin + x1 * _cos;
x0 = X; x1 = Y;
}
void inverse( double & x0, double & x1 ) const {
double X = x0 * _cos + x1 * _sin;
double Y = - x0 * _sin + x1 * _cos;
x0 = X; x1 = Y;
}
private:
double _cos, _sin;
};
|
- A PDF can be redefined in a new set of variables
traosformed from the original set according to a specified transformation.
The assumption that is made is that the Jacobian of the transformation
is 1 (i.e.: that the transformation preserves the probability). Handling
transformations with a non-trivial Jacobian is not implemented in the current
version.
- Example:
typedef Independent<Gaussian, Gaussian> BasicPdf;
typedef Transformed<Basic, Rotation2D> TransfPdf;
Gaussian g1( 0, 0.1 ), g2( 0, 1 );
TransfPdf pdf( BasicPdf( g1, g2 ), Rotation2D( M_PI / 4 ) );
// generate correlated gaussian variables
RandomGenerator< TransfPdf > rnd( pdf );
double x, y;
rnd.generate( x, y );
|
Examples
|