Distributions

Sigma relies on measure theory as a mathematical framework to describe probability and probabilistic inference. We've defined our probability measure $\mathbb{P}$ as a uniform measure. This does not preclude non-uniform distributions, simply because random variables can be non-linear functions.

Inverse Transform Sampling

Density functions are not the same as random variables. But often we want to construct a random variable that is distributed according to some density. There are many ways to do this, many of which are applicable only to a particular density function - for instance the box-muller transform for normal distributions. One general method is inverse transform sampling, which we can use when we have access to the inverse of the cumulative density function, known as the quantile function.

If we can generate random numbers uniformly between $0$ and $1$ we can generate samples from an arbitrary distribution by applying its quantile function to the uniformly distributed samples. We can demonstrate this using the Distributions package in Julia, which provides quantile functions for many common distributions such as the Normal:


In [1]:
using Distributions
using Gadfly

# Generate Samples form standard normal distribution
samples = rand(10000)
normal_quantile(x) = quantile(Normal(0,1),x)
normal_samples = map(normal_quantile, samples)
plot(x = normal_samples, Geom.density)


Out[1]:
x -20 -15 -10 -5 0 5 10 15 20 -15.0 -14.5 -14.0 -13.5 -13.0 -12.5 -12.0 -11.5 -11.0 -10.5 -10.0 -9.5 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 10.0 10.5 11.0 11.5 12.0 12.5 13.0 13.5 14.0 14.5 15.0 -20 -10 0 10 20 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 -0.50 -0.48 -0.46 -0.44 -0.42 -0.40 -0.38 -0.36 -0.34 -0.32 -0.30 -0.28 -0.26 -0.24 -0.22 -0.20 -0.18 -0.16 -0.14 -0.12 -0.10 -0.08 -0.06 -0.04 -0.02 0.00 0.02 0.04 0.06 0.08 0.10 0.12 0.14 0.16 0.18 0.20 0.22 0.24 0.26 0.28 0.30 0.32 0.34 0.36 0.38 0.40 0.42 0.44 0.46 0.48 0.50 0.52 0.54 0.56 0.58 0.60 0.62 0.64 0.66 0.68 0.70 0.72 0.74 0.76 0.78 0.80 0.82 0.84 0.86 0.88 0.90 0.92 0.94 0.96 0.98 1.00 -0.5 0.0 0.5 1.0 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00

This method to define non-uniform distributions invoked sampling, and hence randomness. We can more generally define a non-uniformly distributed random variable without involving any randomness at all. In Sigma, since $\Omega = [0,1]$ and $\mathbb{P}$ is a uniform measure, given a quantile function we define a random variable as:

$$X(\omega) = quantile(\omega)$$

Set operations with quantile functions

If you have read section (?) you will know that Sigma does inference by evaluating random variables with infinite sets, often represented as intervals. It should be possible to treat the quantile function as any other function and use abstract interpretation or SMT to evaluate the quantile with a set (e.g. interval) input. However, quantile functions can be extremely conplex and this approach would in many cases lead to a great deal of imprecision. Also, from a practical perspective, many quantile functions are written using a variety of imperative tricks and numerical hacks to improve performance or accuracy; reimplementing them as pure functions would be cumbersome. It would be preferable if we could treat the quantile functions as black-boxes.

Black-box functions are usually anathematic to Sigma, because given no additional information it is impossible to assert anything meaningful about the output of a function applied to an input set. Fortunately, in the case of quantile functions, we know that they are 1. monotonic 2. total. To evaapproximationluate a quantile function on an interval $A = [a,b]$ we simply evaluate it on lower and upper bounds to yield $B = [quantile(a),quantile(b)]$ as the result.

This is valid because monotonicity ensures that $B$ is a sound over approximation - there can exist no $x \in A$ where $x < b$ and $quantile(x) \ge quantile(b)$. Similarly there is no $x \in A$ where $x > a$ and $quantile(x) \le quantile(a)$. That the quantile is total ensures that the approximation is precise, i.e. there are no spurrious elements in the interval $B$ that do not belong to the true image of $A$ under the quantile function.

Random Parameters

In inference, especially when taking a fully Bayesian approach, the parameters to our random variables are not values but also themselves random variables. Often the inference task is inferring the posterior distribution of the parameter random variables after observing evidence on random variables "lower down".

Supporting parameters as random variables in Sigma poses some challenges which depend upon the actual distributions of interest. In general, when the random variable belongs to a certain family of distributions which are parameterised by a scaling (multiplicative) and shifting (additive) parameter, we can generate arbitrary distributions within the family by transforming a standard random variable. For example, in the uniform case this standard random variable is defined on the unit interval, in the normal case we have mean 0 and variance 1. We illustrate this by sampling from a normal distribution using inverse transform sampling and shifting and scaling:


In [4]:
# Generate samples from normal(5,3)
samples = rand(10000)
std_normal_quantile(x) = quantile(Normal(0,1),x)
std_normal_samples = map(normal_quantile, samples)
shifted_normal_samples = std_normal_samples * 3 + 5
plot(x = shifted_normal_samples, Geom.density)


Out[4]:
x -50 -40 -30 -20 -10 0 10 20 30 40 50 60 -40 -39 -38 -37 -36 -35 -34 -33 -32 -31 -30 -29 -28 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 -50 0 50 -40 -38 -36 -34 -32 -30 -28 -26 -24 -22 -20 -18 -16 -14 -12 -10 -8 -6 -4 -2 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 -0.155 -0.150 -0.145 -0.140 -0.135 -0.130 -0.125 -0.120 -0.115 -0.110 -0.105 -0.100 -0.095 -0.090 -0.085 -0.080 -0.075 -0.070 -0.065 -0.060 -0.055 -0.050 -0.045 -0.040 -0.035 -0.030 -0.025 -0.020 -0.015 -0.010 -0.005 0.000 0.005 0.010 0.015 0.020 0.025 0.030 0.035 0.040 0.045 0.050 0.055 0.060 0.065 0.070 0.075 0.080 0.085 0.090 0.095 0.100 0.105 0.110 0.115 0.120 0.125 0.130 0.135 0.140 0.145 0.150 0.155 0.160 0.165 0.170 0.175 0.180 0.185 0.190 0.195 0.200 0.205 0.210 0.215 0.220 0.225 0.230 0.235 0.240 0.245 0.250 0.255 0.260 0.265 0.270 0.275 0.280 0.285 0.290 0.295 0.300 0.305 -0.2 0.0 0.2 0.4 -0.16 -0.15 -0.14 -0.13 -0.12 -0.11 -0.10 -0.09 -0.08 -0.07 -0.06 -0.05 -0.04 -0.03 -0.02 -0.01 0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31

Because shifting and scaling are involes simply multiplication and addition, which are implementing in Sigma, we can implement this approach directly.


In [6]:
using Sigma
A = normal(5,2)
rand(A)


Out[6]:
4.415210771061971

Unfortunately there are many distributions which do not belong to this scale-shift family, but where we would still like to use random variables as their parameters. The gamma, beta, categorical, geometric, and poisson distributions are examples in this category; we would like to be able to write categorical(diriclet([0.2,0.5,0.3])) or geometric(beta(0.5,1.0)).

We shall call the parameter random variable (dirichlet and beta in the above examples) $\Phi$. For a random variable $X$ parametrised with $\Phi$, to evaluate $X(A)$ where $A \in \Sigma$. we first consider the quantile function as a function of both the parameters and $p$ - $quantile(\phi,p)$. Then $X(A) = [a,b]$, where

$$a = \min_{\phi \in \Phi^\rightarrow(A),p \in A} quantile(\phi,p)$$$$b = \max_{\phi \in \Phi^\rightarrow(A),p \in A} quantile(\phi,p)$$

For reasons which depend upon the continuity and totality arguments given above (TODO: Describe), it suffices to consider only the bounds of $p$. If $p=[i,j]$, we can find $B$ by instead finding

$$a = \min_{\phi \in \Phi^\rightarrow(A)} quantile(\phi,i)$$$$b = \max_{\phi \in \Phi^\rightarrow(A)} quantile(\phi,j)$$

Categorical Family

The categorical family takes a real valued weight vector $w$ as its parameter. It returns an integer-valued random variable which takes value $j$ with a probability $w_j$. In the Bayesian setting $w$ is replaced with multivariate random variable $\Phi$, a RandArray in Sigma. One common example is a Dirichlet random variable, e.g.:

X = categorical(dirichlet([1,2]))

Φ = dirichlet([1,2]) returns a RandArray in Sigma, if we apply it to an event $A$, i.e., $B_{\Phi} = \Phi(A)$, the result is a subset of $\mathbb{R}^2$:


In [6]:
A = [Interval(0,0.5),Interval(0.5,0.9)]
Φ = dirichlet(1,[1.,2.])
call(Φ, A)


Out[6]:
2-element Array{Any,1}:
 [0.0 0.4129939664938205]              
 [0.3662220312486563 2.317589981693128]

By virtue of the fact that it is represented by a pair of intervals, this subset is rectangular. In higher dimensions - when the parameter vector is longer - it will be a high dimensional rectangle.

It's important to remember that this subset is an over-approximation. For a categorical distribution each $w_j$ must each lie between 0 and 1, and $w$ must sum to 1. These constraints define a plane within the unit hypercube; only points on this plane are valid parameters. Rather than consider the entire plane, we will need to consider its intersection with the parameter over-approximation $B_{\phi}$:

$$B'_{\Phi} = \left\{w \in \Phi(A) : 0 \le w_i \le 1 , \sum_i w_i = 1 \right\}$$

Given a probability $p$, a categorical quantile function, determines

$$quantile(\phi,p) = \operatorname*{arg\,min}_j \sum_j \phi_j \ge p$$

Recalling that $A$ also induces an interval $p=[i,j]$, to find $X(A) = [a,b]$ we then must find

$$a = \min_{\phi \in B'_{\Phi}} quantile(\phi,i)$$$$b = \max_{\phi \in B'_{\Phi}} quantile(\phi,j)$$

To find $a$ my idea was basically enumeration. Enumerate $j$ from $1$ to $n$, each time using a linear solver to determine whether there exists a point in $B'_\phi$ such that the sum of its first $j$ components is greater than i. The enumeration implements the arg min, and the linear solver implments the minimisation over all of $B'_\phi$

To find $b$, we might think to ask a series of complementary questions in the same way - "For all the possible parameters in this set, do any have a quantile of n, of n-1", then stop at the first point the answer is "yes". This is valid, but this approach breaks down when we try to implement the method of finding the quantile function as before, that is if we say "For all the possible parameters in this set, do any have a sum of their first of n compnents being greater than p, of n-1".


In [64]:
r = 0.99
plot([p->cdf(Categorical([r,1-r]),p)],0,10)


Out[64]:
x -15 -10 -5 0 5 10 15 20 25 -10.0 -9.5 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 10.0 10.5 11.0 11.5 12.0 12.5 13.0 13.5 14.0 14.5 15.0 15.5 16.0 16.5 17.0 17.5 18.0 18.5 19.0 19.5 20.0 -10 0 10 20 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 f(x) -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 -1.00 -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 -1 0 1 2 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0

In [46]:
quantile_fs = ϕ->quantile(Geometric(ϕ),0.5)
plot([quantile_fs],0.2,.3)


Out[46]:
x 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.000 0.005 0.010 0.015 0.020 0.025 0.030 0.035 0.040 0.045 0.050 0.055 0.060 0.065 0.070 0.075 0.080 0.085 0.090 0.095 0.100 0.105 0.110 0.115 0.120 0.125 0.130 0.135 0.140 0.145 0.150 0.155 0.160 0.165 0.170 0.175 0.180 0.185 0.190 0.195 0.200 0.205 0.210 0.215 0.220 0.225 0.230 0.235 0.240 0.245 0.250 0.255 0.260 0.265 0.270 0.275 0.280 0.285 0.290 0.295 0.300 0.305 0.310 0.315 0.320 0.325 0.330 0.335 0.340 0.345 0.350 0.355 0.360 0.365 0.370 0.375 0.380 0.385 0.390 0.395 0.400 0.405 0.0 0.5 0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 f(x) -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 -2 0 2 4 6 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 3.2 3.4 3.6 3.8 4.0 4.2 4.4 4.6 4.8 5.0

In [30]:
quantile_fs = [x -> quantile(Normal(i,1),x) for i = 0.5:0.5:10.0]
plot(quantile_fs,0.0001,0.99999)


Out[30]:
x -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 -1.00 -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 -1 0 1 2 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 f11 f12 f13 f14 f15 f16 f17 f18 f19 f20 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 Color f(x) -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 -40 -20 0 20 40 -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35

In [32]:
quantiles = [x -> quantile(Normal(i,j),x) for i = 0.5:3:10.0, j = 0.5:3:10.0]
plot(quantiles[:],0.0001,0.99999)


Out[32]:
x -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 -1.00 -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 -1 0 1 2 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 f9 f10 f11 f12 f13 f14 f15 f16 f1 f2 f3 f4 f5 f6 f7 f8 Color f(x) -160 -140 -120 -100 -80 -60 -40 -20 0 20 40 60 80 100 120 140 160 180 -140 -135 -130 -125 -120 -115 -110 -105 -100 -95 -90 -85 -80 -75 -70 -65 -60 -55 -50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 150 155 160 -200 -100 0 100 200 -140 -130 -120 -110 -100 -90 -80 -70 -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160

In [36]:
quantiles = [x -> quantile(Beta(0.5,i),x) for i = 0.5:0.5:10.0]
plot(quantiles[:],0.0001,0.99999)


Out[36]:
x -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 -1.00 -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 -1 0 1 2 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 f11 f12 f13 f14 f15 f16 f17 f18 f19 f20 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 Color f(x) -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 -1.00 -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 -1 0 1 2 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0

In [45]:
quantiles = [x -> quantile(Geometric(i),x) for i = 0.5:0.1:0.9999]
plot(quantiles[:],0.0001,0.99999)


Out[45]:
x -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 -1.00 -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75 0.80 0.85 0.90 0.95 1.00 1.05 1.10 1.15 1.20 1.25 1.30 1.35 1.40 1.45 1.50 1.55 1.60 1.65 1.70 1.75 1.80 1.85 1.90 1.95 2.00 -1 0 1 2 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 f1 f2 f3 f4 f5 Color f(x) -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 45 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 -20 0 20 40 -20 -18 -16 -14 -12 -10 -8 -6 -4 -2 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40