Loading [MathJax]/jax/output/HTML-CSS/jax.js
  • Pre-requisites
  • Overview
  • 3x3 example
    • The General Approach
  • Session information

Last updated: 2017-01-02

Code version: 55e11cf8f7785ad926b716fb52e4e87b342f38e1

Pre-requisites

This document assumes basic familiarity with Markov chains and linear algebra.

Overview

In this note, we illustrate one way of analytically obtaining the stationary distribution for a finite discrete Markov chain.

3x3 example

Assume our probability transition matrix is: P=[0.70.20.10.40.60010]

Since every state is accessible from every other state, this Markov chain is irreducible. Every irreducible finite state space Markov chain has a unique stationary distribution. Recall that the stationary distribution π is the vector such that π=πP.

Therefore, we can find our stationary distribution by solving the following linear system: 0.7π1+0.4π2=π10.2π1+0.6π2+π3=π20.1π1=π3 subject to π1+π2+π3=1. Putting these four equations together and moving all of the variables to the left hand side, we get the following linear system: 0.3π1+0.4π2=00.2π1+0.4π2+π3=00.1π1π3=0π1+π2+π3=1

We will define the linear system in matrix notation: [0.30.400.20.410.101111]A[π1π2π3]=[0001]bAπ=b

Since this linear system has more equations than unknowns, it is an overdeterminted system. Recall from linear algebra that an overdetermined system is consistent (i.e. we can solve for π exactly) when b is in the column space of A. We can check this numerically by obtaining the rank of A, then obtaining the rank of an augmented matrix with b appended as a column of A. (Side note: it can be difficult to find the rank of an arbitrary matrix numerically, espeically for large matrices. But for our small example, we are safe.)

library(Matrix)
A        <- matrix(c(-0.3, 0.2, 0.1, 1, 0.4, -0.4, 0, 1, 0, 1, -1, 1 ), ncol=3,nrow=4)
b        <- c(0,0,0, 1)
rank.A   <- as.numeric(rankMatrix(A))
rank.Ab  <- as.numeric(rankMatrix(cbind(A,b)))
print(paste("The rank of A =", rank.A, "and the rank of the augmented matrix =", rank.Ab))
[1] "The rank of A = 3 and the rank of the augmented matrix = 3"

We see that A has full column rank, and that the rank is unchanged when we add b as a column. Therefore, b is in the column space of A, and this system is consistent. We can find π by solving the normal equations: ATAπ=ATb

We use the solve function in R to solve for the stationary distribution π:

pi        <- drop(solve(t(A) %*% A, t(A) %*% b))
names(pi) <- c('state.1', 'state.2', 'state.3')
pi 
   state.1    state.2    state.3 
0.54054054 0.40540541 0.05405405 

We find that: π10.54,π20.41,π30.05

Therefore, under proper conditions, we expect the Markov chain to spend more time in states 1 and 2 as the chain evolves.

The General Approach

Recall that we are attempting to find a solution to π=πP such that iπi=1. First we rearrange the expression above to get: ππP=0(IP)π=0

One challenge though is that we need the constrained solution which respects that π describes a probability distribution (i.e. πi=1). Luckily this is a linear constraint that is easily represented by adding another equation to the system. So as a small trick, we need to add a row of all 1’s to our (IP) (call this new matrix A) and a 1 to the last element of the zero vector on the right hand side (call this new vector b). Now we want to solve Aπ=b which is overdetermined, so we solve the normal equations ATAπ=ATb.

Session information

sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.5 LTS

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] knitr_1.14     MASS_7.3-45    expm_0.999-0   Matrix_1.2-7.1
[5] rmarkdown_1.1 

loaded via a namespace (and not attached):
 [1] Rcpp_0.12.7     lattice_0.20-34 gtools_3.5.0    digest_0.6.9   
 [5] assertthat_0.1  mime_0.4        R6_2.1.2        grid_3.3.2     
 [9] xtable_1.8-2    formatR_1.4     magrittr_1.5    evaluate_0.9   
[13] stringi_1.1.1   tools_3.3.2     stringr_1.0.0   shiny_0.13.2   
[17] httpuv_1.3.3    yaml_2.1.13     htmltools_0.3.5 tibble_1.2     

This site was created with R Markdown