Skip to content
Matthew Robinson edited this page Mar 29, 2016 · 2 revisions

Markov Chains

The Markov Chain class in the stochastic processes module supports the analysis of discrete time markov chains. All of the Markov Chain procedures work with both rational and floating point numbers. Some procedures required the user to explicity specify that rational output is required. Matrix operations on rational numbers may be slower, and are more memory intensive. However, no accuracy is lost due to machine precision. The default output for Markov Chain procedures is a numpy array. The vector_display and matrix_display functions allow for the output to be displayed with the names of the states in the state space.

Creating a Markov Chain

Markov Chains are implemented as a class object. A transition probability matrix is required to initiate the Markov Chain. Optionally, an initial state for the Markov Chain can be specified and the states in the state space can be name. Procedures that deal with conditional probability usually require the initial conditions for the Markov Chain. Others do not. If no names are chosen for the states in the state space, they are name 0,1,...,n-1 by default.

Syntax

MarkovChain(P,[init],[states])

Examples:

In [3]: Y = MarkovChain(P=[[.97,.03],[.04,.96]],
                        init=[.7,.3],
                        states=['red','blue'])

In [4]: Y.display()
The transition probability matrix:
       red  blue
red   0.97  0.03
blue  0.04  0.96
----------------------------------------
The initial system state:
      Prob
red    0.7
blue   0.3

Absorption Probability

The absorption probability procedure computes the probability of absorption into the specified state, given any other starting state for the Markov Chain. The output is a vector where v[i] is the probability of absorption, given that i is the starting state. The state specified for this procedure must be an absorbing state.

Syntax

X.absorbing(state)

Examples:

In [8]: P = np.array([
   ...:         [1,0,0,0],
   ...:         [Rational(3,10),Rational(4,10),Rational(1,10),Rational(2,10)],
   ...:         [0,0,1,0],
   ...:         [Rational(2,10),Rational(3,10),Rational(4,10),Rational(1,10)]
   ...:     ])

In [9]: X = MarkovChain(P, states = ['red','blue','black','green'])

In [10]: abs_red = X.absorption_prob('red')

In [11]: vector_display(abs_red,X.state_space)
Out[11]: 
        Prob
red        1
blue   31/48
black      0
green   7/16

Steps to Absorption

This procedure computes the expected number of steps to absorption for the Markov Chain, given any starting point for the Markov Chain. This procedure requires the Markov Chain the have at least one absorbing state. The output is a vector where v[i] is the expected number of steps to absorption, given that i is the starting state

Syntax

X.absorption_steps()

Examples:

In [12]: abs_steps = X.absorption_steps()

In [13]: vector_display(abs_steps, X.state_space)
Out[13]: 
        Prob
red        0
blue   55/24
black      0
green   15/8

Classifying States

This procedures identifies equivalence classes in the Markov Chain and labels them as transient or recurrent. The method for classifying states is described in Weiss, B. 'A non-recursive algorithm for classifying the states of a finite Markov chain'. 1987. European Journal of Operations Research. The output is a dictionary of of labeled equivalence classes.

Syntax

X.classify_states()

Examples:

In [14]: X = MarkovChain(P =[
   ....:     [0, 0.1, 0.5, 0, 0.2, 0.2, 0, 0],
   ....:     [0.1, 0.2, 0, 0, 0.6, 0, 0, 0.1],
   ....:     [0, 0, 1, 0, 0, 0, 0, 0],
   ....:     [0, 0, 0, 0, 1, 0, 0, 0],
   ....:     [0, 0, 0, 1, 0, 0, 0, 0],
   ....:     [0, 0, 0, 0, 0, 0.2, 0, 0.8],
   ....:     [0, 0.3, 0, 0, 0, 0.4, 0.1, 0.2],
   ....:     [0, 0, 0, 0, 0, 0.6, 0, 0.4]
   ....:     ], 
   ....:     states = ['blue','green','purple','red',
   ....:         'yellow', 'black', 'orange', 'white'])

In [15]: X.classify_states()
Out[15]: 
{'Recurrent 1': ['red', 'yellow'],
 'Recurrent 2': ['black', 'white'],
 'Recurrent 3': ['purple'],
 'Transient': ['blue', 'green', 'orange']}

Long Run Probabilities

This procedure computes the long run fraction of time spent in each state, given that the Markov Chain starts at any other state. These probabilities can be computed for both reducible and irreducible Markov Chains. The user must specify the method as rational if rational output is desired. The floating point method is less computationally expensive and uses less memory.

Syntax

X.long_run_probs()

Examples:

In [16]: P = np.array([
   ....:         [Rational(2,10),0,0,Rational(8,10)],
   ....:         [0,1,0,0],
   ....:         [Rational(1,10),Rational(4,10),Rational(2,10),Rational(3,10)],
   ....:         [Rational(7,10),0,0,Rational(3,10)]         
   ....:     ])

In [17]: X = MarkovChain(P, states = ['red','blue','black','green'])

In [18]: Pi = X.long_run_probs(method = 'rational')

In [19]: matrix_display(Pi,X.state_space)
Out[19]: 
        red blue black green
red    7/15    0     0  8/15
blue      0    1     0     0
black  7/30  1/2     0  4/15
green  7/15    0     0  8/15

Probabilities

This computes the probability of reaching a sequence of states, given the specified conditions. The desired states are entered as a list of tuples, consisting of two elements. The first element is the time period in which the state is realized, and the second element is the name of the state. A second list of sequences can be entered to compute a conditional probability. If the probability is not conditional, the initial conditions must be specified for the Markov Chain.

Syntax

X.probability(states,[given])

Examples:

In [23]: Y = MarkovChain(P=
   ....: [[Rational(97,100), Rational(3,100)],
   ....: [Rational(4,100), Rational(96,100)]],
   ....: init = [Rational(7,10), Rational(3,10)],
   ....: states = ['red','blue'])

In [24]: Y.probability([(2,'blue'),(1,'red'),(0,'red')])
Out[24]: 
 2037 
──────
100000

In [25]: Y.probability([(2,'blue')],given=[(1,'blue')])
Out[25]: 
24
──
25

Reachability Matrix

This procedure computes a matrix B, where B[i,j] = True if state j is reachable from state i, and is false otherwise. The method for computing this matrix is described in Weiss, B. 'A non-recursive algorithm for classifying the states of a finite Markov chain'. 1987. European Journal of Operations Research. The output is a dictionary of of labeled equivalence classes.

Syntax

X.reachability()

Examples:

In [26]: X = MarkovChain(P =[
   ....:     [0, 0.1, 0.5, 0, 0.2, 0.2, 0, 0],
   ....:     [0.1, 0.2, 0, 0, 0.6, 0, 0, 0.1],
   ....:     [0, 0, 1, 0, 0, 0, 0, 0],
   ....:     [0, 0, 0, 0, 1, 0, 0, 0],
   ....:     [0, 0, 0, 1, 0, 0, 0, 0],
   ....:     [0, 0, 0, 0, 0, 0.2, 0, 0.8],
   ....:     [0, 0.3, 0, 0, 0, 0.4, 0.1, 0.2],
   ....:     [0, 0, 0, 0, 0, 0.6, 0, 0.4]
   ....:     ])

In [27]: B = X.reachability()

In [28]: matrix_display(B,X.state_space)
Out[28]: 
       0      1      2      3      4      5      6      7
0   True   True   True   True   True   True  False   True
1   True   True   True   True   True   True  False   True
2  False  False   True  False  False  False  False  False
3  False  False  False   True   True  False  False  False
4  False  False  False   True   True  False  False  False
5  False  False  False  False  False   True  False   True
6   True   True   True   True   True   True   True   True
7  False  False  False  False  False   True  False   True

Steady State Probability

The steady state procedure computes the long run probability that the Markov Chain is in each state. This procedure only works for irreducible Markov Chains. For reducible Markov Chains, use the long run probability procedure. The user must specify the method as rational if rational output is desired. The floating point method is less computationally expensive and uses less memory.

Syntax

X.steady_state([method])

Examples:

In [29]: X = MarkovChain([[Rational(3,10),Rational(3,10),Rational(4,10),0,0],
   ....:                  [0,Rational(3,10),Rational(3,10),Rational(4,10),0],
   ....:                  [0,0,Rational(3,10),Rational(3,10),Rational(4,10)],
   ....:                  [Rational(3,10),Rational(3,10),Rational(4,10),0,0],
   ....:                  [Rational(3,10),Rational(3,10),Rational(4,10),0,0]],
   ....:                states = ['blue','green','black', 'yellow','orange'])

In [30]: steady = X.steady_state(method='rational')

In [31]: vector_display(steady,X.state_space)
Out[31]: 
            Prob
blue    147/1070
green     21/107
black     37/107
yellow    39/214
orange    74/535

Transition Matrix

This procedure computes the transition probability matrix for n steps of the Markov Chain. The user must specify the method as rational if rational output is desired. The floating point method is less computationally expensive and uses less memory.

Syntax

X.trans_mat(n,[method])

Examples:

In [34]: X = MarkovChain([[.3,.3,.4,0,0],
                 [0,.3,.3,.4,0],
                 [0,0,.3,.3,.4],
                 [.3,.3,.4,0,0],
                 [.3,.3,.4,0,0]])

In [35]: X3 = X.trans_mat(n=3)

In [36]: matrix_display(X3,X.state_space)
Out[36]: 
       0      1      2      3      4
0  0.147  0.201  0.349  0.171  0.132
1  0.135  0.198  0.345  0.186  0.136
2  0.126  0.189  0.342  0.195  0.148
3  0.147  0.201  0.349  0.171  0.132
4  0.147  0.201  0.349  0.171  0.132