1@chapsummary 2@code{vpdl} is a library of probability distributions. 3 4This library contains data structures to represent univariate and 5multivariate probability distributions and provides algorithms to operate on them. 6This includes estimating a distribution from data points and 7sampling from a distribution. 8@code{vpdl} is built on top of @code{vnl} and @code{vnl_algo}. 9@endchapsummary 10 11@code{vpdl} is comprised of two programming paradigms: 12generic programming and polymorphic inheritance. 13The generic programming part is in its own sub-library called @code{vpdt}. 14@code{vpdt} is a template library (like STL). 15There is no compiled library for @code{vpdt}, 16only a collection of header files in subdirectory @code{vpdl/vpdt}. 17@code{vpdt} works with @code{vnl} types, 18but in many cases can generalize to other types. 19The goal of @code{vpdt} is to provide generic implementations that are both time and 20memory efficient when types are known at compile time. 21 22The rest of @code{vpdl} uses a polymorphic design and provides greater run time 23flexibility and easy of use. It is limited to distributions over scalar, 24@code{vnl_vector}, and @code{vnl_vector_fixed} types. 25 26 27@section History 28 29@code{vpdl} is the combination of two different design patterns 30for probability distributions. 31It was formed from the merger of three contrib libraries: 32@code{mul/vpdfl}, @code{mul/pdf1d}, and @code{brl/bbas/bsta}. 33 34Created by Manchester, @code{vpdfl} provided a polymorphic hierarchy 35(using virtual functions) for multivariate distributions based on 36@code{vnl_vector} and @code{vnl_matrix types}. 37For univariate distributions, @code{pdf1d} mirrored the design of @code{vpdfl}, 38but used scalar types (i.e. @code{double}). 39These libraries were very flexible at run time. 40Both distribution type and, in the case of @code{vpdfl}, 41dimension could be selected at run time. 42 43Created by Brown, @code{bsta} provided a generic programming hierarchy 44(using templates) for both univariate and multivariate distributions. 45Template parameters specified scalar type (@code{float} or @code{double}) 46and dimension. 47Templates allowed the same code base to use scalars in the univariate case and 48@code{vnl_vector_fixed} and @code{vnl_matrix_fixed} in the multivariate case. 49The goal of @code{bsta} was to be very efficient. 50Many optimizations are possible by assuming types and 51dimension are known at compile time. 52 53@code{vpdl} was designed as a core library 54to meet the needs of both original designs. 55The main library generalizes Manchester's polymorphic design with 56a templated distribution library. 57This creates polymorphic inheritance hierarchy 58for each choice to template parameters. 59The templates allow hierarchies based on scalar, 60@code{vnl_vector}, and @code{vnl_vector_fixed} types. 61When possible, the implementations of @code{vpdl} distributions are wrappers 62around corresponding @code{vpdt} distributions. 63The @code{vpdt} distributions provide even more generalized implementations but 64without virtual functions or inheritance. 65 66@section Polymorphic Distributions 67 68Each polymorphic distribution is derived (directly or indirectly) from 69a common templated base class called @code{vpdl_distribution<T,n>}. 70Template parameter @code{T} specifies the scalar numeric type 71(@code{float} or @code{double}) and @code{n} specifies the dimension. 72In particular: 73@itemize @bullet 74@item @code{n==0} uses @code{vnl_vector<T>} and @code{vnl_matrix<T>} 75 (dimension specified at run time) 76@item @code{n==1} uses @code{T} (scalar computations) 77@item @code{n>1} uses @code{vnl_vector_fixed<T,n>} and 78 @code{vnl_matrix_fixed<T,n,n>} (fixed dimension of @code{n}) 79@end itemize 80 81The distribution class is an abstract base class. 82The most important functions it defines are: 83@table @code 84@item virtual T density (const vector &pt) const=0; 85Evaluate the unnormalized density at a point. 86 87@item virtual T norm_const () const=0; 88The normalization constant for the density. 89 90@item virtual T prob_density (const vector &pt) const; 91Evaluate the probability density at a point. 92Defaults to @code{density(pt) * norm_const()}. 93@end table 94 95These functions allow the density of the distribution to be evaluated 96independently from the normalization constant. 97This is important because the normalization constant is sometimes 98expensive to compute and not required for some calculations. 99Furthermore, the normalization constant is independent of the evaluation point 100so it can be computed once in advance and reused. 101Alternatively, the function @code{prob_density} returns the normalized density directly. 102 103The type @code{vector} is a typedef defined in the class that selects the 104appropriate vector class depending on @code{T} and @code{n}. 105Similarly, the type @code{matrix} is defined to the appropriate matrix type. 106 107Several other functions are defined on the distribution base class including: 108@code{gradient_density}, @code{cumulative_prob}, @code{compute_mean}, 109and @code{compute_covar}. 110All of these functions provide a polymorphic interface to probability distributions. 111However, in most cases, the @code{vpdl} classes are simply light wrappers around 112generic @code{vpdt} implementations that do the real work. 113 114One additional component of the polymorphic wrappers is a class hierarchy. 115In @code{vpdt}, the distribution classes need not have any inheritance relations, 116but in @code{vpdl} the currently implemented distributions are arranged into 117the following class hierarchy. Each top level class below is derived directly 118from @code{vpdl_distribution} (template arguments are omitted). 119 120@itemize @bullet 121@item @code{vpdl_gaussian_base} - a base class for all Gaussian varieties. 122@itemize @bullet 123@item @code{vpdl_gaussian} - a general Gaussian with full covariance. 124@item @code{vpdl_gaussian_indep} - a Gaussian with independent (i.e. diagonal) covariance. 125@item @code{vpdl_gaussian_sphere} - a Gaussian with spherical (i.e. scaled identity) covariance. 126@end itemize 127@item @code{vpdl_muli_cmp_dist} - a base class for all multi-component distributions 128@itemize @bullet 129@item @code{vpdl_kernel_base} - a base class for kernel density distributions. 130@itemize @bullet 131@item @code{vpdl_kernel_fbw_base} - a base class for fixed bandwidth kernel densities 132@itemize @bullet 133@item @code{vpdl_kernel_gaussian_sfbw} - a fixed bandwidth spherical Gaussian kernel distribution 134@end itemize 135@item @code{vpdl_kernel_vbw_base} - a base class for variable bandwidth kernel densities 136@end itemize 137@item @code{vpdl_mixture} - a mixture distribution (linear combination of arbitrary distributions). 138@item @code{vpdl_mixture_of} - a mixture distribution where each component has the same type 139(but may have different parameters). 140@end itemize 141@end itemize 142 143@section Generic Probability (@code{vpdt}) 144 145The subdirectory @code{vpdl/vpdt} contains the 146generic programming components of this library. 147@code{vpdt} is a self-sufficient template library 148that does not depended on the rest of @code{vpdl}. 149However, there is nothing to stop @code{vpdl} distribution classes from being 150used as @code{vpdt} distribution types as long as they meet the requirements. 151Whenever possible, @code{vpdl} distributions should be wrappers around 152a generic @code{vpdt} implementation. 153This strategy allows the code to be used both in generic and polymorphic designs. 154 155Generic programming uses @emph{concepts} 156to implement compile time type polymorphism rather than inheritance 157to implement run time object-oriented polymorphism. 158Concepts are sets of requirements that a data type must meet. 159To satisfy a concept a class must define the required typedefs, 160static constants, member functions, or related global functions. 161Classes that satisfy a concept need not be related by inheritance. 162The Standard Template Library (STL) is built upon the definition of concepts. 163In STL, some concepts (like Iterators) are general enough 164to include built-in types (like pointers). 165In @code{vpdt}, there are also some basic concepts 166which can be satisfied by built-in types. 167However, the most useful concepts (like Distributions) 168are a bit more specific and require a class implementation. 169 170@subsection Basic Concepts 171 172A collection of more basic concepts will form the building blocks of the probability distribution concept. The relevant concepts are: 173@itemize @bullet 174@item Scalar 175@item Field 176@item Vector 177@item Matrix 178@end itemize 179 180@code{vnl} data structures satisfiy these concepts and are used in practice. 181However, other representations could be used 182if the appropriate functions are provided. 183These concepts are all interrelated by various function requirements. 184The type that meets the Field concept is considered the primary type. 185For each Field type there should be a unique associated 186Scalar, Vector, and Matrix type 187The @code{vpdt_field_traits<F>} struct defines these types for each @code{F}. 188@code{vpdt_field_traits<F>} needs to be specialized for each Field type. 189This traits struct defines the following typedefs: 190@table @code 191@item vpdt_field_traits<F>::dimension 192This is actually a @code{static const unsigned int} and indicates the 193fixed dimension of the Field type 194 195@item vpdt_field_traits<F>::scalar_type 196The Scalar type associated with the Field type 197 198@item vpdt_field_traits<F>::field_type 199The Field type itself (@code{F==field_type}). 200Redundant, but provided for consistency. 201 202@item vpdt_field_traits<F>::vector_type 203The Vector type associated with the Field type 204 205@item vpdt_field_traits<F>::matrix_type 206The Matrix type associated with the Field type 207@end table 208 209In the special case of univariate distributions, 210all four of these types become equal, and @code{dimension==1}. 211There is also a special typedef @code{vpdt_field_traits<F>::type_is_scalar} 212defined to @code{void} that only exists if @code{F} is scalar. 213Similarly, @code{vpdt_field_traits<F>::type_is_vector} is defined to 214@code{void} only if @code{F} is non-scalar. 215The existence of these special types is used to disambiguate some 216template specializations, and to provide faster implementations 217for the scalar case. 218 219@subheading Scalar 220 221A probability distribution is defined over some scalar field. 222The Scalar concept represents this value at each point in space. 223It is satisfied by floating point types. 224For now this is likely to be limited to @code{double} or @code{float}. 225Scalars must support all built in arithmetic operators (+, -, *, /, etc.) 226as well as all standard cmath functions like 227@code{sqrt}, @code{exp}, and @code{log}. 228If the type does not support these functions directly, 229it must be able to implicitly cast itself to and from a type that does. 230 231@subheading Field 232 233Each point in a probability space is represented by the Field concept. 234When used in @code{vpdl} distributions the Field is satisfied by either 235a scalar, a @code{vnl_vector}, or a @code{vnl_vector_fixed}. 236The Field has an associated Scalar and dimension. 237For dimension @code{n}, a Field contains @code{n} values of its Scalar type. 238A Field actually has two measure of dimension: 239a fixed (compile time) dimension and a variable (run time) dimension. 240These dimensions may or may not be equal. 241Field types with data allocated on the stack 242will have size specified at compile time. 243The fixed dimension and variable dimension will both equal this fixed size. 244Field types with data allocated on the heap 245will have a fixed dimension of zero and a variable dimension equal to 246the number of currently allocated Scalar objects. 247 248A Field type will be equal to its Scalar type 249in the case of univariate distributions. 250Since Scalar types are usually built-in C++ types, 251they can not be required to implement any member functions. 252Instead, they are required to implement a set of overloaded global functions 253to perform the required set of actions. 254For the standard types used in @code{vpdl}, 255these functions are implemented in @code{vpdl/vpdt/vpdt_access.h}. 256For some types that satisfy the concept these functions are trivial or even empty. 257In the table below the Field type is denoted @code{field} and 258its corresponding Scalar type is @code{scalar}. 259 260@table @code 261@item unsigned int vpdt_size(const field&) 262Access the run time size (i.e. dimension) 263 264@item void vpdt_set_size(field&, unsigned int) 265Change the run time size for heap-based structures, otherwise do nothing. 266 267@item void vpdt_fill(field&, const scalar&) 268Fill all dimensions of the field with the scalar value 269 270@item const scalar& vpdt_index(const field&, unsigned int) 271Access a scalar element reference (const) by index 272 273@item scalar& vpdt_index(field&, unsigned int) 274Access a scalar element reference (non-const) by index 275@end table 276 277The Field type should also support the subtraction operator on two Field types. 278The return type for the difference of two Field types is a Vector type. 279 280@subheading Vector 281 282The Vector concept represents the difference between two Field values. 283In the case of the default @code{vnl} types, 284the Field and Vector types are the same. 285The requirements for the Vector are a superset of 286the requirements for a Field. 287A Vector should support all the operation of Field 288plus several other arithmetic operations: 289@itemize @bullet 290@item @code{vector = vector + vector} @ @ @ (and equivalent for @code{-}) 291@item @code{vector += vector} @ @ @ (and equivalent for @code{-=}) 292@item @code{field = field + vector} @ @ @ (and equivalent for @code{-}) 293@item @code{field += vector} @ @ @ (and equivalent for @code{-=}) 294@item @code{vector = scalar + vector} @ @ @ (and equivalent for @code{-}) 295@item @code{vector += scalar} @ @ @ (and equivalent for @code{-=}) 296@item @code{vector = scalar * vector} 297@item @code{vector *= scalar} 298@end itemize 299 300Vectors should also define these global functions 301@itemize @bullet 302@item @code{scalar dot_product(const vector&, const vector&)} 303@item @code{vector element_product(const vector&, const vector&)} 304@item @code{matrix outer_product(const vector&, const vector&)} 305@end itemize 306 307@subheading Matrix 308 309The Matrix concept actually refers to a square matrix. 310It is used for second order statistics (like covariance). 311Since it is square, the matrix also has a single (fixed or variable) dimension 312like the Field and Vector. 313It requires all the same @code{vpdt_access.h} functions except 314the signature of the @code{vpdt_index} function now has two indices 315@itemize @bullet 316@item @code{const scalar& vpdt_index(const matrix&, unsigned int, unsigned int)} 317@item @code{scalar& vpdt_index(matrix&, unsigned int, unsigned int)} 318@end itemize 319A few arithmetic operations are also needed: 320@itemize @bullet 321@item @code{matrix = matrix + matrix} @ @ @ (and equivalent for @code{-}) 322@item @code{matrix += matrix} @ @ @ (and equivalent for @code{-=}) 323@item @code{matrix = scalar + matrix} @ @ @ (and equivalent for @code{-}) 324@item @code{matrix += scalar} @ @ @ (and equivalent for @code{-=}) 325@item @code{matrix = scalar * matrix} 326@item @code{matrix *= scalar} 327@end itemize 328 329 330@subsection Distribution Concept 331 332The Distribution concept is the central concept in @code{vpdt}. 333The Distribution is a probability distribution class that is analogous 334to @code{vpdl_distribution<T,n>}. 335In fact, @code{vpdl_distribution<T,n>} and all its subclasses satisfy 336the Distribution concept. 337The Distribution requires a subset of the functions that are 338declared virtual on @code{vpdl_distribution<T,n>}. 339The following example lays out the required API that 340a Distribution is required to have. 341In this example, it is assumed that a consistent set of basic types 342have been defined such that @code{T} satisfies Scalar, 343@code{F} satisfies Field, @code{V} satisfies Vector, 344and @code{M} satisfies Matrix. 345 346@example 347class vpdt_distribution 348@{ 349 public: 350 //: The field type 351 typedef F field_type; 352 353 354 //: Return the variable (run time) dimension 355 unsigned int dimension() const; 356 357 //: Evaluate the unnormalized density at a point 358 // This must be multiplied by norm_const() to integrate to 1 359 T density(const F& pt) const; 360 361 //: Compute the gradient of the density function, returned in \a g 362 // The return value of the function is the density itself 363 T gradient_density(const F& pt, V& g) const; 364 365 //: Compute the normalization constant (independent of sample point). 366 T norm_const() const; 367 368 //: Evaluate the cumulative distribution function at a point 369 // This is the integral of the density function from negative infinity 370 // (in all dimensions) to the point in question 371 T cumulative_prob(const F& pt) const; 372 373 //: Compute the mean of the distribution. 374 void compute_mean(F& m) const; 375 376 //: Compute the covariance matrix of the distribution. 377 void compute_covar(M& c) const; 378@}; 379@end example 380 381The other member functions that are defined in @code{vpdl_distribution<T,n>} 382are not needed for a @code{vpdt} Distribution because they can be 383implemented in terms of the required functions. 384These extra functions are provided as global functions instead. 385For example, @code{T vpdt_prob_density(const dist& d, const F& pt)} is a function 386that returns @code{d.density(pt) * d.norm_const()}. 387These functions can be overloaded when a more efficient implementation 388exists for a particular distribution class. 389For example, the default @code{vpdt_log_density} function applied to a 390Gaussian distribution would compute the log of an exponential. 391An overload of @code{vpdt_log_density} for Gaussians can eliminate this 392extra unnecessary step. 393