Documentation
API
Dist

# Dist

Distributions are the flagship data type in Squiggle. The distribution type is a generic data type that contains one of three different formats of distributions.

These subtypes are point set, sample set, and symbolic. The first two of these have a few custom functions that only work on them. You can read more about the differences between these formats here.

Several functions below only can work on particular distribution formats. For example, scoring and pointwise math requires the point set format. When this happens, the types are automatically converted to the correct format. These conversions are lossy.

Distributions are created as sample sets by default. To create a symbolic distribution, use `Sym.` namespace: `Sym.normal`, `Sym.beta` and so on.

## Distributions

These are functions for creating primitive distributions. Many of these could optionally take in distributions as inputs. In these cases, Monte Carlo Sampling will be used to generate the greater distribution. This can be used for simple hierarchical models.

See a longer tutorial on creating distributions here.

### make

Signatures
Dist.make(Dist) => Dist
Dist.make(Number) => SymbolicDist
Examples
`Dist.make(5)`
`Dist.make(normal({p5: 4, p95: 10}))`

### mixture

The `mixture` function takes a list of distributions and a list of weights, and returns a new distribution that is a mixture of the distributions in the list. The weights should be positive numbers that sum to 1. If no weights are provided, the function will assume that all distributions have equal weight.

Note: If you want to pass in over 5 distributions, you must use the list syntax.

Namespace optional
Signatures
Dist.mixture(List(Dist|Number), List(Number)?) => Dist
Dist.mixture(Dist|Number) => Dist
Dist.mixture(Dist|Number, Dist|Number, [Number, Number]?) => Dist
Dist.mixture(Dist|Number, Dist|Number, Dist|Number, [Number, Number, Number]?) => Dist
Dist.mixture(Dist|Number, Dist|Number, Dist|Number, Dist|Number, [Number, Number, Number, Number]?) => Dist
Dist.mixture(Dist|Number, Dist|Number, Dist|Number, Dist|Number, Dist|Number, [Number, Number, Number, Number, Number]?) => Dist
Examples
`mixture(1,normal(5,2))`
`mixture(normal(5,2), normal(10,2), normal(15,2), [0.3, 0.5, 0.2])`
`mixture([normal(5,2), normal(10,2), normal(15,2), normal(20,1)], [0.3, 0.5, 0.1, 0.1])`

### mx

Alias for mixture()

Namespace optional
Signatures
Dist.mx(List(Dist|Number), List(Number)?) => Dist
Dist.mx(Dist|Number) => Dist
Dist.mx(Dist|Number, Dist|Number, [Number, Number]?) => Dist
Dist.mx(Dist|Number, Dist|Number, Dist|Number, [Number, Number, Number]?) => Dist
Dist.mx(Dist|Number, Dist|Number, Dist|Number, Dist|Number, [Number, Number, Number, Number]?) => Dist
Dist.mx(Dist|Number, Dist|Number, Dist|Number, Dist|Number, Dist|Number, [Number, Number, Number, Number, Number]?) => Dist
Examples
`mx(1,normal(5,2))`

### normal

Namespace optional
Signatures
Dist.normal(Dist|Number, Dist|Number) => SampleSetDist
Dist.normal({p5: Number, p95: Number}) => SampleSetDist
Dist.normal({p10: Number, p90: Number}) => SampleSetDist
Dist.normal({p25: Number, p75: Number}) => SampleSetDist
Dist.normal({mean: Number, stdev: Number}) => SampleSetDist
Examples
`normal(5,1)`
`normal({p5: 4, p95: 10})`
`normal({p10: 4, p90: 10})`
`normal({p25: 4, p75: 10})`
`normal({mean: 5, stdev: 2})`

### lognormal

Namespace optional
Signatures
Dist.lognormal(Dist|Number, Dist|Number) => SampleSetDist
Dist.lognormal({p5: Number, p95: Number}) => SampleSetDist
Dist.lognormal({p10: Number, p90: Number}) => SampleSetDist
Dist.lognormal({p25: Number, p75: Number}) => SampleSetDist
Dist.lognormal({mean: Number, stdev: Number}) => SampleSetDist
Examples
`lognormal(0.5, 0.8)`
`lognormal({p5: 4, p95: 10})`
`lognormal({p10: 4, p90: 10})`
`lognormal({p25: 4, p75: 10})`
`lognormal({mean: 5, stdev: 2})`

### uniform

Namespace optional
Signatures
Dist.uniform(Dist|Number, Dist|Number) => SampleSetDist
Examples
`uniform(10, 12)`

### beta

Namespace optional
Signatures
Dist.beta(Dist|Number, Dist|Number) => SampleSetDist
Dist.beta({mean: Number, stdev: Number}) => SampleSetDist
Examples
`beta(20, 25)`
`beta({mean: 0.39, stdev: 0.1})`

### cauchy

Namespace optional
Signatures
Dist.cauchy(Dist|Number, Dist|Number) => SampleSetDist
Examples
`cauchy(5, 1)`

### gamma

Namespace optional
Signatures
Dist.gamma(Dist|Number, Dist|Number) => SampleSetDist
Examples
`gamma(5, 1)`

### logistic

Namespace optional
Signatures
Dist.logistic(Dist|Number, Dist|Number) => SampleSetDist
Examples
`logistic(5, 1)`

### to

The "to" function is a shorthand for lognormal({p5:min, p95:max}). It does not accept values of 0 or less, as those are not valid for lognormal distributions.

infix: to
Namespace optional
Signatures
Dist.to(Dist|Number, Dist|Number) => SampleSetDist
Examples
`5 to 10`
`to(5,10)`

### exponential

Namespace optional
Signatures
Dist.exponential(Dist|Number) => SampleSetDist
Examples
`exponential(2)`

### bernoulli

Namespace optional
Signatures
Dist.bernoulli(Dist|Number) => SampleSetDist
Examples
`bernoulli(0.5)`

### triangular

Namespace optional
Signatures
Dist.triangular(Number, Number, Number) => SampleSetDist
Examples
`triangular(3, 5, 10)`

## Basic Functions

### mean

Namespace optional
Signatures
Dist.mean(Dist) => Number

### median

Namespace optional
Signatures
Dist.median(Dist) => Number

### stdev

Namespace optional
Signatures
Dist.stdev(Dist) => Number

### variance

Namespace optional
Signatures
Dist.variance(Dist) => Number

### min

Namespace optional
Signatures
Dist.min(Dist) => Number

### max

Namespace optional
Signatures
Dist.max(Dist) => Number

### mode

Namespace optional
Signatures
Dist.mode(Dist) => Number

### sample

Namespace optional
Signatures
Dist.sample(Dist) => Number

### sampleN

Namespace optional
Signatures
Dist.sampleN(Dist, Number) => List(Number)

### exp

Namespace optional
Signatures
Dist.exp(Dist) => Dist

### cdf

Namespace optional
Signatures
Dist.cdf(Dist, Number) => Number

### pdf

Namespace optional
Signatures
Dist.pdf(Dist, Number) => Number

### inv

Namespace optional
Signatures
Dist.inv(Dist, Number) => Number

### quantile

Namespace optional
Signatures
Dist.quantile(Dist, Number) => Number

### truncate

Truncates both the left side and the right side of a distribution.

Sample set distributions are truncated by filtering samples, but point set distributions are truncated using direct geometric manipulation. Uniform distributions are truncated symbolically. Symbolic but non-uniform distributions get converted to Point Set distributions.

Namespace optional
Signatures
Dist.truncate(Dist, Number, Number) => Dist

### truncateLeft

Namespace optional
Signatures
Dist.truncateLeft(Dist, Number) => Dist

### truncateRight

Namespace optional
Signatures
Dist.truncateRight(Dist, Number) => Dist

## Algebra (Dist)

infix: +
Namespace optional
Signatures

### multiply

infix: *
Namespace optional
Signatures
Dist.multiply(Dist, Number) => Dist
Dist.multiply(Number, Dist) => Dist
Dist.multiply(Dist, Dist) => Dist

### subtract

infix: -
Namespace optional
Signatures
Dist.subtract(Dist, Number) => Dist
Dist.subtract(Number, Dist) => Dist
Dist.subtract(Dist, Dist) => Dist

### divide

infix: /
Namespace optional
Signatures
Dist.divide(Dist, Number) => Dist
Dist.divide(Number, Dist) => Dist
Dist.divide(Dist, Dist) => Dist

### pow

infix: ^
Namespace optional
Signatures
Dist.pow(Dist, Number) => Dist
Dist.pow(Number, Dist) => Dist
Dist.pow(Dist, Dist) => Dist

### log

Namespace optional
Signatures
Dist.log(Dist, Number) => Dist
Dist.log(Number, Dist) => Dist
Dist.log(Dist, Dist) => Dist

### log

Namespace optional
Signatures
Dist.log(Dist, Number) => Dist
Dist.log(Number, Dist) => Dist
Dist.log(Dist, Dist) => Dist

### log10

Namespace optional
Signatures
Dist.log10(Dist) => Dist

### unaryMinus

unary: -
Namespace optional
Signatures
Dist.unaryMinus(Dist) => Dist

## Algebra (List)

### sum

Namespace optional
Signatures
Dist.sum(List(Dist|Number)) => Dist

### product

Namespace optional
Signatures
Dist.product(List(Dist|Number)) => Dist

### cumsum

Namespace optional
Signatures
Dist.cumsum(List(Dist|Number)) => List(Dist)

### cumprod

Namespace optional
Signatures
Dist.cumprod(List(Dist|Number)) => List(Dist)

### diff

Namespace optional
Signatures
Dist.diff(List(Dist|Number)) => List(Dist)

## Pointwise Algebra

Pointwise arithmetic operations cover the standard arithmetic operations, but work in a different way than the regular operations. These operate on the y-values of the distributions instead of the x-values. A pointwise addition would add the y-values of two distributions.

The infixes `.+`,`.-`, `.*`, `./`, `.^` are supported for their respective operations. `Mixture` works using pointwise addition.

Pointwise operations work on Point Set distributions, so will convert other distributions to Point Set ones first. Pointwise arithmetic operations typically return unnormalized or completely invalid distributions. For example, the operation `normal(5,2) .- uniform(10,12)` results in a distribution-like object with negative probability mass.

Signatures

### dotMultiply

Signatures
Dist.dotMultiply(Dist, Number) => Dist
Dist.dotMultiply(Number, Dist) => Dist
Dist.dotMultiply(Dist, Dist) => Dist

### dotSubtract

Signatures
Dist.dotSubtract(Dist, Number) => Dist
Dist.dotSubtract(Number, Dist) => Dist
Dist.dotSubtract(Dist, Dist) => Dist

### dotDivide

Signatures
Dist.dotDivide(Dist, Number) => Dist
Dist.dotDivide(Number, Dist) => Dist
Dist.dotDivide(Dist, Dist) => Dist

### dotPow

Signatures
Dist.dotPow(Dist, Number) => Dist
Dist.dotPow(Number, Dist) => Dist
Dist.dotPow(Dist, Dist) => Dist

## Normalization

There are some situations where computation will return unnormalized distributions. This means that their cumulative sums are not equal to 1.0. Unnormalized distributions are not valid for many relevant functions; for example, klDivergence and scoring.

The only functions that do not return normalized distributions are the pointwise arithmetic operations and the scalewise arithmetic operations. If you use these functions, it is recommended that you consider normalizing the resulting distributions.

### normalize

Normalize a distribution. This means scaling it appropriately so that it's cumulative sum is equal to 1. This only impacts Point Set distributions, because those are the only ones that can be non-normlized.

Namespace optional
Signatures
Dist.normalize(Dist) => Dist

### isNormalized

Check if a distribution is normalized. This only impacts Point Set distributions, because those are the only ones that can be non-normlized. Most distributions are typically normalized, but there are some commands that could produce non-normalized distributions.

Namespace optional
Signatures
Dist.isNormalized(Dist) => Bool

### integralSum

Get the sum of the integral of a distribution. If the distribution is normalized, this will be 1.0. This is useful for understanding unnormalized distributions.

Namespace optional
Signatures
Dist.integralSum(Dist) => Number

## Utility

### sparkline

Produce a sparkline of length `n`. For example, `▁▁▁▁▁▂▄▆▇██▇▆▄▂▁▁▁▁▁`. These can be useful for testing or quick visualizations that can be copied and pasted into text.

Namespace optional
Signatures
Dist.sparkline(Dist, Number?) => String

## Scoring

### klDivergence

Kullback–Leibler divergence (opens in a new tab) between two distributions.

Note that this can be very brittle. If the second distribution has probability mass at areas where the first doesn't, then the result will be infinite. Due to numeric approximations, some probability mass in point set distributions is rounded to zero, leading to infinite results with klDivergence.

Signatures
Dist.klDivergence(Dist, Dist) => Number
Examples
`Dist.klDivergence(Sym.normal(5,2), Sym.normal(5,1.5))`

### logScore

A log loss score. Often that often acts as a scoring rule (opens in a new tab). Useful when evaluating the accuracy of a forecast.

Note that it is fairly slow.

Signatures
Dist.logScore({estimate: Dist, answer: Dist|Number, prior?: Dist}) => Number
Examples
`Dist.logScore({estimate: Sym.normal(5,2), answer: Sym.normal(5.2,1), prior: Sym.normal(5.5,3)})`
`Dist.logScore({estimate: Sym.normal(5,2), answer: Sym.normal(5.2,1)})`
`Dist.logScore({estimate: Sym.normal(5,2), answer: 4.5})`