DensityGrid#
- class lintsampler.DensityGrid(edges, pdf, vectorizedpdf=False, pdf_args=(), pdf_kwargs={})#
Grid-like object over which density function is evaluated.
DensityGriduses the parameteredgesto construct a rectilinear grid.edgesshould contain one or k sequences of numbers representing the edges of a one- or k-dimensional grid. The given edges need not be evenly spaced, but should be monotonically increasing. After the grid is constructed, the given PDF function is evaluated on the vertices of the grid.See the examples below for the various usage patterns.
- Parameters:
- edges1D iterable or tuple of 1D iterables
If a single 1D iterable (i.e., array, tuple, list of numbers), then this represents the cell edges of a 1D grid. So a 1D grid with N cells should have
edgesparameter as a 1D array with N+1 elements. If a tuple of 1D iterables, then this represents the edge values for a k-dimensional grid with dimensionality equal to the length of the tuple. So, a kD grid with (N1 x N2 x … x Nk) cells should take a length-k tuple, with arrays length N1+1, N2+1 etc.- pdffunction
Probability density function to evaluate on grid. Function should take coordinate vector (or batch of vectors if vectorized; see vectorizedpdf parameter) and return (unnormalised) density (or batch of densities). Additional arguments can be passed to the function via pdf_args and pdf_kwargs parameters.
- vectorizedpdfbool, optional
if True, assumes that the pdf function is vectorized, i.e., it accepts (…, k)-shaped batches of coordinate vectors and returns (…)-shaped batches of densities. If False, assumes that the pdf function simply accepts (k,)-shaped coordinate vectors and returns single densities. Default is False.
- pdf_argstuple, optional
Additional positional arguments to pass to pdf function; function call is pdf(position, *pdf_args, **pdf_kwargs). Default is empty tuple (no additional positional arguments).
- pdf_kwargsdict, optional
Additional keyword arguments to pass to pdf function; function call is pdf(position, *pdf_args, **pdf_kwargs). Default is empty dict (no additional keyword arguments).
Examples
These examples demonstrate the various ways to set up and use an instance of
DensityGrid.A one-dimensional grid, spanning x=0 to x=10 with 32 cells (so 33 edges). As an example PDF we can take an unnormalised Gaussian:
>>> pdf = lambda x: np.exp(-x**2) >>> g = DensityGrid(np.linspace(0, 30, 33), pdf)
At this point, the object
ghas various attributes set up describing the grid and its geometry. We’ll save a demonstration of these for the next example, where they will be more interesting.A two-dimensional grid, with 32 x 64 cells (so 33 gridlines along one axis and 65 along the other). For the PDF function, rather than writing our own we’ll use the bivariate standard normal PDF from
scipy.stats.multivariate_normal:>>> pdf = multivariate_normal(mean=np.zeros(2), cov=np.eye(2)).pdf >>> x = np.linspace(-2, 2, 33) >>> y = np.linspace(-4, 4, 65) >>> g = DensityGrid((x, y), pdf)
Let’s explore some of the attributes of
g. First, some basic descriptors of the grid geometry:>>> g.dim 2 >>> g.shape (32, 64) >>> g.ncells 2048
There are also array attributes called
minsandmaxswhich give the coordinates of the ‘first’ and ‘last’ corners of the grid. In 2D, these are the bottom-left and top-right:>>> g.mins array([ 0., 100.]) >>> g.maxs array([ 10., 200.])
Meanwhile,
edgearraysgives a list of the input edge arrays:>>> len(g.edgearrays) 2 >>> all(g.edgearrays[0] == x) True >>> all(g.edgearrays[1] == y) True
There are also various attributes which relate to the evaluated probability densities and masses:
>>> g.vertex_densities array([[7.22562324e-06, 1.18203307e-05, 1.90369817e-05, ..., 1.90369817e-05, 1.18203307e-05, 7.22562324e-06], [9.20568282e-06, 1.50594920e-05, 2.42537439e-05, ..., 2.42537439e-05, 1.50594920e-05, 9.20568282e-06], [1.15465131e-05, 1.88888347e-05, 3.04210101e-05, ..., 3.04210101e-05, 1.88888347e-05, 1.15465131e-05], ..., [1.15465131e-05, 1.88888347e-05, 3.04210101e-05, ..., 3.04210101e-05, 1.88888347e-05, 1.15465131e-05], [9.20568282e-06, 1.50594920e-05, 2.42537439e-05, ..., 2.42537439e-05, 1.50594920e-05, 9.20568282e-06], [7.22562324e-06, 1.18203307e-05, 1.90369817e-05, ..., 1.90369817e-05, 1.18203307e-05, 7.22562324e-06]]) >>> g.masses array([[1.69184097e-07, 2.74103704e-07, 4.37229522e-07, ..., 4.37229522e-07, 2.74103704e-07, 1.69184097e-07], [2.13673916e-07, 3.46183909e-07, 5.52206419e-07, ..., 5.52206419e-07, 3.46183909e-07, 2.13673916e-07], [2.65695257e-07, 4.30466311e-07, 6.86647340e-07, ..., 6.86647340e-07, 4.30466311e-07, 2.65695257e-07], ..., [2.65695257e-07, 4.30466311e-07, 6.86647340e-07, ..., 6.86647340e-07, 4.30466311e-07, 2.65695257e-07], [2.13673916e-07, 3.46183909e-07, 5.52206419e-07, ..., 5.52206419e-07, 3.46183909e-07, 2.13673916e-07], [1.69184097e-07, 2.74103704e-07, 4.37229522e-07, ..., 4.37229522e-07, 2.74103704e-07, 1.69184097e-07]]) >>> g.total_mass 0.9541568382986452
vertex_densitiesis a 2D (33 x 65) array containing the densities on all of the grid vertices, whilemassesis a 2D (32 x 64) array giving the probability masses of grid cells, andtotal_massgives the total probability mass across the grid.Things are slightly more efficient when the PDF function is vectorized, i.e., the PDF function takes a batch of input positions and returns a corresponding batch of densities. As it happens, the PDF function we used above is already nicely vectorized, so we can let DensityGrid know about this with a simple Boolean flag:
>>> pdf = multivariate_normal(mean=np.zeros(2), cov=np.eye(2)).pdf >>> x = np.linspace(0, 10, 33) >>> y = np.linspace(100, 200, 65) >>> g = DensityGrid((x, y), pdf, vectorizedpdf=True)
It is also possible to construct a grid with just a single cell.
In one dimension:
>>> pdf = lambda x: np.exp(-x**2) >>> g = DensityGrid([-5, 5], pdf) >>> g.ncells 1
In multiple dimensions:
>>> pdf = multivariate_normal(mean=np.zeros(2), cov=np.eye(2)).pdf >>> g = DensityGrid(([0, 10], [100, 200]), pdf) >>> g.ncells 1
Example usage of
choose_cellsmethodThe
choose_cellsmethod can be used to randomly select grid cells (weighted by their masses), given a 1D array of uniform samples.>>> pdf = multivariate_normal(mean=np.zeros(2), cov=np.eye(2)).pdf >>> x = y = np.linspace(-3, 3, 129) >>> g = DensityGrid((x, y), pdf, vectorizedpdf=True) >>> u = np.random.default_rng().uniform(size=10) >>> mins, maxs, corners = g.choose_cells(u)
Let’s inspect the returned arrays:
>>> mins array([[ 1.546875, 0.703125], [-0.234375, -0.234375], [ 0. , 0.84375 ], [ 1.03125 , 1.359375], [-0.9375 , 0. ], [ 0.09375 , -0.9375 ], [-1.453125, -0.046875], [-0.890625, -0.84375 ], [-1.265625, -0.515625], [-1.3125 , -0.84375 ]]) >>> maxs array([[ 1.59375 , 0.75 ], [-0.1875 , -0.1875 ], [ 0.046875, 0.890625], [ 1.078125, 1.40625 ], [-0.890625, 0.046875], [ 0.140625, -0.890625], [-1.40625 , 0. ], [-0.84375 , -0.796875], [-1.21875 , -0.46875 ], [-1.265625, -0.796875]]) >>> corners (array([0.03757259, 0.15064809, 0.11148847, 0.03712126, 0.10255765, 0.10210795, 0.0553122 , 0.074987 , 0.06255463, 0.04711508]), array([0.0363145 , 0.15214504, 0.1070474 , 0.03479141, 0.10244504, 0.10657801, 0.055373 , 0.07792656, 0.06401463, 0.04896204]), array([0.03490626, 0.15214504, 0.11136605, 0.03533066, 0.1070474 , 0.10154859, 0.05914606, 0.07809798, 0.06630517, 0.05004977]), array([0.03373746, 0.15365686, 0.10692986, 0.0331132 , 0.10692986, 0.10599417, 0.05921108, 0.0811595 , 0.0678527 , 0.05201177]))
minsandmaxsare both arrays shaped (10, 2), 10 because we fed in 10 uniform samples and 2 because we have a 2D grid (and bivariate PDF).cornersis a length-4 tuple of length-10 arrays. 4 because each of the 10 cells has 4 corners. So, the first array contains the densities at the 00-corner of each cell, the second array contains the 01-densities, the third array gives the 10-densities, and the fourth array gives the 11-densities.
- Attributes:
minsnumpyarrayMinimum boundary values (i.e., first corner) of the structure.
maxsnumpyarrayMaximum boundary values (i.e., last corner) of the structure.
dimintDimension of the density structure.
total_massfloatTotal probability mass of the structure.
- shapetuple
dim-length tuple giving grid shape. For example, ifedgearrayshave lengths N1+1, N2+1, … Nk+1, thenshapeis (N1, N2, …, Nk).- ncellsint
Total number of cells in grid, i.e., the product over the shape tuple.
- edgearrayslist
Length
dimlist of arrays of grid edges along each dimension.- vertex_densities
numpyarray k-dimensional array giving densities at vertices of grid. Shape is (N1+1, N2+1, …) if grid has (N1, N2, …) cells along each dimension.
- masses
numpyarray k-dimensional array of probability masses of grid cells. Shape is equal to grid shape (
shapeattribute). Masses are calculated according to trapezoid rule, i.e., cell volumes multiplied by average vertex densities.
Methods
choose_cells(u)Choose cells given 1D array of uniform samples.
- choose_cells(u)#
Choose cells given 1D array of uniform samples.
Method enforced by base class
DensityStructure.- Parameters:
- u1D array of floats, shape (N,)
Array of uniform samples ~ U(0, 1).
- Returns:
- mins2D array of floats, shape (N, k)
Coordinate vector of first corner of each cell.
- maxs2D array of floats, shape (N, k)
Coordinate vector of last corner of each cell.
- corners2^k-tuple of 1D arrays, each length N
Densities at corners of given cells. Conventional ordering applies, e.g., in 3D: (f000, f001, f010, f011, f100, f101, f110, f111)
- property dim#
Dimension of the density structure.
- Returns:
- int
The dimension of the structure.
- property maxs#
Maximum boundary values (i.e., last corner) of the structure.
- Returns:
- array_like
1D array, length-k, giving the coordinates of the last corner of the k-dimensional structure.
- property mins#
Minimum boundary values (i.e., first corner) of the structure.
- Returns:
- array_like
1D array, length-k, giving the coordinates of the first corner of the k-dimensional structure.
- property total_mass#
Total probability mass of the structure.
- Returns:
- float
The total probability mass, summed over all the cells of the structure.