Stochastic Methods#
We found that the hard sphere gas is ergodic: Due to the chaotic nature of the system, after a long enough time the dynamical variables are essentially random. Moreover, we claimed that they are sampled uniformly from all allowed states.
This leads to a different way of modelling the system. Instead of integrating the equations of motion, we can instead sample from the allowed states, and deduce equilibrium properties from those samples. To sensibly talk about these things we first need to think about sampling.
Sampling#
What does in mean to sample from a distribution?
It is useful to consider two separate cases: a discrete distribution and a continuous one. Lets start with the discrete distribution.
Discrete Distributions#
We usually describe a distribution by the “probability” of the outcomes. For example we might say
Here is a practical demonstration
mysample()=if rand()<0.5 ; -1; else ;1; end
mysample (generic function with 1 method)
using Plots
mysamples=[mysample() for j in 1:100]
histogram(mysamples)
The fact that the samples are independent means that the value of one sample does not depend on any of the other values. This means we can figure out the probability of any given set of outcomes by counting.
For example, suppose I draw 10 realizations, and want to know the probability of getting 4 ones and 6 minus ones.
There are
Warning: This all seems simple, but these discrete probabilities are somewhat counter-intuitive. Suppose you are playing the lottery, and you need to choose 6 numbers between 1 and 49. Which pattern is more likely?
As you can imagine, Julia has a function for sampling from a discrete distribution
using StatsBase
sample([1,-1],Weights([0.5,0.5]))
-1
Weights([0.5,0.5])
2-element Weights{Float64, Float64, Vector{Float64}}:
0.5
0.5
Continuous distributions#
For a continuous distribution, we specify the probability density. Lets think about 1D, in which case we might write that the probability of finding a particle between points
The total probability must be 1, so
A simple example is a uniform distribution:
In Julia we can sample from a uniform distribution with rand
rand()
0.04766349983427909
we can also ask for a list or array of random numbers
rand(5)
5-element Vector{Float64}:
0.22263402030579593
0.830845210182813
0.061544518835685236
0.6115764528499936
0.5453439465782544
rand(2,3)
2×3 Matrix{Float64}:
0.107404 0.429609 0.996006
0.25372 0.181249 0.207257
If we want a uniformly distributed number over a different range, we can just scale the output:
2*rand()-1 # gives random number from -1 to 1
-0.6613577730458822
What if we want to sample a non-uniform distribution? For example
A typical trick is to try to find a function
Let
Lets make
or more compactly
In the present case
We can solve this for
ylist=rand(1000)
xlist=sqrt.(ylist)
histogram(xlist)
One obvious confusion here is that we want to use
## In Class Activity
What distribution would you get if you uniformly sample a random variable between
Sampling in higher dimensions#
Suppose we want to uniformly sample all points inside the unit disk. You might naively think you could just sample the radii and the angle.
rads=rand(1000)
angles=2*pi*rand(1000)
pnts=[(r*cos(ϕ),r*sin(ϕ)) for (r,ϕ) in zip(rads,angles)]
scatter(pnts,aspect_ratio=:equal)
Clearly that is wrong – as we ended up with more particles in the center. The correct sampling is to note that the probability distribution for the radial coordinate is
Thus by our 1D result, we actually want to uniformly sample r^2
sqrads=rand(1000)
angles=2*pi*rand(1000)
rads=sqrt.(sqrads)
pnts=[(r*cos(ϕ),r*sin(ϕ)) for (r,ϕ) in zip(rads,angles)]
scatter(pnts,aspect_ratio=:equal)
More generally, if I have a change of variables
## In Class Activity
How would you uniformly sample from the surface of a sphere in 3 dimensions? That is, you want to produce
Sampling from a Gaussian#
A particularly useful distribution to sample is the Gaussian
Lets use the technique we have learned to try to sample this. We are going to transform to a
If
which is an error function, and has no simple way to evaluate.
There is a trick, known as the Box-Muller algorithm, where one gets around this problem by working in 2 dimensions. Lets try to sample from the 2-dimensional Gaussian
We can do this by uniformly sampling the angle
But we can sample this, since
We compare this with
and conclude that we need to uniformly sample
function boxmuller(n)
halfn=Int64(ceil(n/2))
svals=rand(halfn)
phivals=2*pi*rand(halfn)
scaledsvals= @. sqrt(-log(svals))
vcat(scaledsvals.*cos.(phivals),scaledsvals.*cos.(phivals))[1:n]
end
boxmuller (generic function with 1 method)
histogram(boxmuller(50000),normed=true,label="")
plot!(x->exp(-x^2)/sqrt(pi),-2,2,label="",xlabel="x",ylabel="p")
One caution is that this Gaussian has a standard deviation of
We do not need to write our own Box-Muller algorithm, as Julia already has it implemented:
using Distributions
d=Normal()
Normal{Float64}(μ=0.0, σ=1.0)
histogram(rand(d,50000),label="",normed=true)
plot!(x->exp(-x^2/2)/sqrt(2*pi),-2,2,label="",xlabel="x",ylabel="p")
Rejection sampling#
Another way to sample from a non-uniform distribution is to use rejection sampling. Lets return to our example of
What we will do is uniformly sample
function rsample()
x=0.
while true
x=rand()
y=rand()
if y<x
break
end
end
return x
end
rsample(n)=[rsample() for j in 1:n]
rsample (generic function with 2 methods)
histogram(rsample(10000),normed=true)
The reason this works is we can write
The probability of selecting
Markov Chains#
So far all of our sampling methods have given us independent samples. There are also approaches to finding series of samples, where the individual realizations are correlated, but after a large number of steps you have an unbiased sample.
A great example is shuffling cards. Every time you do a riffle shuffle, you somewhat mix up the cards, but they are not fully randomized. However, if you do many riffles, you end up with a truly random set of cards.
A classic example for thinking about this is the Ehrenfest urn model, also known as the dog and flea model. Suppose you have two dogs, which have in total
Suppose there are
We say that in each step the probability of going from state
function simulate_urn(initialj,N,numsteps)
j=initialj
path=[j]
for i in 1:numsteps
gammaplus=(N-j)/N
if rand()<gammaplus
j+=1
else
j-=1
end
push!(path,j)
end
path
end
simulate_urn (generic function with 1 method)
Lets now simulate this for 100 steps, repeating the process 1000 times.
plt=plot(xlabel="t",ylabel="j")
for j in 1:50
plot!(simulate_urn(50,100,1000),label="")
end
display(plt)
As you can see, things settle into some sort of steady state. Here is the distribution at the final time
data=hcat([simulate_urn(50,100,1000) for j in 1:2000]...)
histogram(data[end,:],bins=-0.5:1:101.5,normed=true)
We can get better statistics if we bin all of the times:
histogram(vcat(data[100:end,:]...),bins=-0.5:1:100.5,normed=true)
How can we understand this distribution?
Let
It is useful to write this in terms of the change in probability:
The terms in square brackets have a physical meaning: They are the probability fluxes. They are the net flow of probability between two sites.
After long time we reach a steady state, and these fluxes should vanish:
In our particular case
One can show that the solution to this recurrance relationship is the binomial distribution
which we encountered earlier with our coin flip example. Thus we can use this stochastic sequence to sample from the binomial distribution.
histogram(vcat(data[100:end,:]...),bins=-0.5:1:100.5,normed=true)
jlist=0:100
plist=[binomial(big(100),big(j))/(2.)^100 for j in jlist]
plot!(jlist,plist,label="")
Here I used big
to convert integers into BigInt
objects – which are a form of integer which can be arbitrarily large
factorial(big(100))
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
factorial(100)
OverflowError: 100 is too large to look up in the table; consider using `factorial(big(100))` instead
Stacktrace:
[1] factorial_lookup
@ ./combinatorics.jl:19 [inlined]
[2] factorial(n::Int64)
@ Base ./combinatorics.jl:27
[3] top-level scope
@ In[26]:1
The Ehrenfest model is an example of a Markov chain. A Markov chain is the simplest form of stochastic process. It consists of a set of states
though I should note that you are generically allowed to stay put:
Typically a Markov chain will reach a steady-state distribution. By definition, the steady state distribution obeys a ballance condition
The net flux in to a state is equal to the net flux out. In most cases that steady state distribution satisfies a stronger condition – detailed balance – meaning that the net flux between any two state vanishes:
Using Markov chains to sample arbitrary distributions#
An important application of Markov chains is we can use them to sample arbitrary distributions. For example, suppose we want to sample
One algorithm for coming up with the transition rates is the Metropolis algorithm. It explicitly constructs
We break
In this case, lets keep the proposal simple. We will only propose moves which change
Next, we choose
In our case
Lets code that up, passing the (non-normalized) distribution to the function
function markov_walk(initialj,distribution,numsteps)
j=initialj
path=[j]
for i in 1:numsteps
# randomly propose left or right
if rand()<1/2 # propose left
if j==1 || rand()>min(1,distribution[j-1]/distribution[j])
push!(path,j)
continue # go to next step of i loop
end
j-=1
push!(path,j)
continue
end
# We have chosen right
if j==length(distribution) ||
rand()>min(1,distribution[j+1]/distribution[j])
push!(path,j)
continue
end
j+=1
push!(path,j)
end
path
end
markov_walk (generic function with 1 method)
w=markov_walk(1,collect(1:100),1000000)
plot(w[1:1000])
plot(w[1:100:end])
histogram(w[1000:100:end],bins=-0.5:1:100.5)
What is particularly useful about this approach is that one only needs to know the probability distribution up to a multiplicative factor. It turns out that in statistical mechanics we will often know the ratios of probabilities, but not the absolute scale (state A is twice as likely as state B).