# basic libraries import
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

%matplotlib notebook

sns.set_context("paper")

"""
Explanation: <h1>Table of Contents<span class="tocSkip"></span></h1>
<div class="toc" style="margin-top: 1em;"><ul class="toc-item"><li><span><a href="#Intro" data-toc-modified-id="Intro-1"><span class="toc-item-num">1&nbsp;&nbsp;</span>Intro</a></span></li><li><span><a href="#Markov-Models" data-toc-modified-id="Markov-Models-2"><span class="toc-item-num">2&nbsp;&nbsp;</span>Markov Models</a></span><ul class="toc-item"><li><span><a href="#Transition-Matrix" data-toc-modified-id="Transition-Matrix-2.1"><span class="toc-item-num">2.1&nbsp;&nbsp;</span>Transition Matrix</a></span></li><li><span><a href="#Latent-Variable-and-State-Space" data-toc-modified-id="Latent-Variable-and-State-Space-2.2"><span class="toc-item-num">2.2&nbsp;&nbsp;</span>Latent Variable and State Space</a></span></li><li><span><a href="#Hidden-Markov-Model-(HMM)" data-toc-modified-id="Hidden-Markov-Model-(HMM)-2.3"><span class="toc-item-num">2.3&nbsp;&nbsp;</span>Hidden Markov Model (HMM)</a></span></li></ul></li></ul></div>

Intro
Exploratory notebook related to introductory concepts and theory behind Markov Models. Includes toy examples implementation and relative visualization.
End of explanation
"""


# possible states of our system
states = ['sun', 'rain', 'cloud']

# transition matrix
data = [
    [0.5, 0.1, 0.4],
    [0.2, 0.4, 0.4],
    [0.4, 0.3, 0.3]
]
transition_matrix = pd.DataFrame(data, index=states, columns=states)

transition_matrix

# each row must sum up to 1
for state in states:
    assert transition_matrix.loc[state].sum() == 1.0

"""
Explanation: Markov Models
Also called Markov Chains, Markov Models are a common approach to treat sequential data. Sequential data can be seen as a set of dependent data points for which we consequently lose the independent and identically distributed (i.i.d.) assumption.
We still assume stationarity and limited horizon, meaning that future predictions depend only on a fixed amount of most recent observations. 
For example if we assume that a data point depends only on the previous most recent observation, we are dealing with first-order Markov chain.
Transition Matrix
A model can be represented via a transition matrix. Each entry represents the probability to move from current state (row value) to next state (column value). Each row must sum up to 1.
End of explanation
"""


observations = np.array(["sun", "sun", "cloud", "cloud", "rain", "cloud", "sun", "sun", "rain", "cloud", "cloud", "sun"])

# count how many time each transition (from_state -> to_state) occured in the past
transition_matrix = pd.DataFrame(np.zeros((len(states), len(states))), index=states, columns=states)
for (from_state, to_state) in list(zip(observations, np.roll(observations, -1)))[:-1]: 
    transition_matrix.set_value(from_state, to_state, transition_matrix.loc[from_state, to_state]+1)

transition_matrix

# normalize to obtain transition probabilities
transition_matrix = transition_matrix.div(transition_matrix.sum(axis=1), axis=0)

transition_matrix

"""
Explanation: One can derive a transition matrix from historical data
End of explanation
"""


