A simple library for simulating Markov Chains. Initially used in Stochastic Processes course in NTUA.
This library is loosely based on the code developed by tetraktida. The original files can be found here.
#!/usr/bin/env python3
from simple_markov import MarkovChain
# initial facing of the coin
initial_probs = {
'Heads': 0.5,
'Tails': 0.5
}
# transition table for coin tosses
transition_table = {
'Heads': [('Heads', 0.5), ('Tails', 0.5)],
'Tails': [('Heads', 0.5), ('Tails', 0.5)]
}
chain = MarkovChain(initial_probs, transition_table)
# get the first 10 coin tosses:
for i, step in zip(chain, range(10)):
print('Step %d: %s' % (step + 1, i))
#!/usr/bin/env python3
from simple_markov import MarkovChain
# initial facing of the unfair coin
initial_probs = {
'Heads': 0.5,
'Tails': 0.5
}
# transition table for coin tosses
transition_table = {
'Heads': [('Heads', 1.0)],
'Tails': [('Heads', 0.2), ('Tails', 0.8)]
}
chain = MarkovChain(initial_probs, transition_table)
# get state probability after N = 3 steps
states_after = chain.state_probabilities(3)
print(states_after) # prints {'Heads': 0.744, 'Tails': 0.256}#!/usr/bin/env python3
from simple_markov import MarkovChain
# Create a markov chain with 4 states and 2 communication classes
initial_probs = {
'A': 0.25,
'B': 0.25,
'C': 0.25,
'D': 0.25
}
transition_table = {
'A': [('A', 0.5), ('B', 0.4), ('C', 0.1)],
'B': [('A', 1.0)],
'C': [('C', 0.2), ('D', 0.8)],
'D': [('C', 0.5), ('D', 0.5)]
}
chain = MarkovChain(initial_probs, transition_table)
# get the communication classes
comm_classes = chain.communication_classes()
print(comm_classes)In recent versions, you can use any kind of object as state label, as long as it is an ordered (required for fundamental operations, e.g. choosing next state) and hashable type. For example:
from simple_markov import MarkovChain
class P(object):
def __init__(self, val):
self.val = val
# other parameters here
def __hash__(self):
# make sure __hash__ is overloaded properly
# other overloads here (__gt__, __ge__, __lt__, __le__ ideally)
def __str__(self):
return 'P: %s' % str(self.val)
def __repr__(self):
return 'P: %s' % repr(self.val)
init_probs = {
P(1): 0.2,
P(2): 0.3,
P(4): 0.5
}
transition_table = {
P(1): [(P(4), 0.1), (P(2), 0.9)],
P(2): [(P(4), 1)],
P(4): [(P(1), 1)]
}
chain = MarkovChain(init_probs, transition_table)You can also read chains from .yaml or .json files, using the io subpackage.
In JSON, the structure of the file should be:
{
"Initial": {
"State 1": Probability 1,
"State 2": Probability 2,
...
"State N": Probability N
},
"Table": {
"State 1": {
"State 1": Transition Probability 1,
"State 2": Transition Probability 2,
...
"State K": Transition Probability K
},
...
"State N": {
...
}
}
}
An example JSON-formatted chain is given below:
$ cat chain.json
{
"Initial": {
"A": 0.25,
"B": 0.25,
"C": 0.5
},
"Table": {
"A": {
"A": 0.1,
"B": 0.5,
"C": 0.4
},
"B": {
"A": 0.5,
"C": 0.5
},
"C": {
"C": 0.9
"A": 0.1
}
}
}You can read this file into a markov chain using the JSON_Reader class.
from simple_markov import MarkovChain
from simple_markov.io import JSON_Reader
rdr = JSON_Reader('chain.json') # creates a JSON reader that loads the file
init_table, transition_table = rdr.parse_data() # parses the data
chain = MarkovChain(init_table, transition_table)or, more simply:
chain = MarkovChain(*JSON_Reader('chain.json').parse_data())The same can be done with a .yaml file. The format is similar to JSON:
Initial:
State 1: Probability 1
State 2: Probability 2
...
State N: Probability N
Table:
State 1:
State 1: Transition Probability 1
State 2: Transition Probability 2
...
State K: Transition Probability K
State 2:
...
...
State N:
...Let's try the file 'chain.yaml':
$ cat chain.yaml
Initial:
A: 0.5
B: 0.2
C: 0.3
Table:
A:
B: 0.2
C: 0.8
B:
A: 0.5
B: 0.5
C:
A: 0.9
C: 0.1You can parse the chain from this file using YAML_Reader. Similarly to
before:
from simple_markov import MarkovChain
from simple_markov.io import YAML_Reader
yaml_rdr = YAML_Reader('chain.yaml')
init_table, transition_table = yaml_rdr.parse_data()
chain = MarkovChain(init_table, transition_table)For now, simple-markov has not been added to the PyPI package index.
Therefore you will need to work locally.
First, clone the package branch of the repo:
git clone [email protected]:Mandragorian/simple-markov.gitThen, run pip install -r requirements.txt . to get all dependencies and then:
python setup.py installMake sure to use sudo if required, or use virtualenv to build a local
environment.