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