Repository: pgmpy/pgmpy
Pull request #797 (2016-12-23 11:21:35)

Added model.predict_probability
Added a new method that gives probabilities of missing variables given a predict data #794 

            B_0         B_1
        80  0.439178    0.560822
        81  0.581970    0.418030
        82  0.488275    0.511725
        83  0.581970    0.418030
        84  0.510794    0.489206
        85  0.439178    0.560822
        86  0.439178    0.560822
        87  0.417124    0.582876
        88  0.407978    0.592022
        89  0.429905    0.570095
        90  0.581970    0.418030
        91  0.407978    0.592022
        92  0.429905    0.570095
        93  0.429905    0.570095
        94  0.439178    0.560822
        95  0.407978    0.592022
        96  0.559904    0.440096
        97  0.417124    0.582876
        98  0.488275    0.511725
        99  0.407978    0.592022`

Also a new error test for predict that increases the coverage. 


Patch:
diff --git a/.travis.yml b/.travis.yml
index f1972807..3dae1288 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,8 +2,8 @@ language: python
 virtualenv:
     system_site_packages: false
 env:
-    - DISTRIB="conda" PYTHON_VERSION="3.5" COVERAGE="true"
     - DISTRIB="conda" PYTHON_VERSION="3.4" COVERAGE="true"
+    - DISTRIB="conda" PYTHON_VERSION="3.3" COVERAGE="true"
     - DISTRIB="conda" PYTHON_VERSION="2.7" COVERAGE="true"
 
 before_install:
diff --git a/appveyor.yml b/appveyor.yml
index afe897ba..3e08acec 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -21,7 +21,7 @@ build_script:
   - SET PATH=C:\Py;C:\Py\Scripts;C:\Py\Library\bin;%PATH%
   - conda config --set always_yes yes
   - conda update conda --quiet
-  - conda install numpy scipy pandas pip nose mock wrapt --quiet
+  - conda install numpy scipy pandas pip nose mock --quiet
   - pip install pyparsing
   - python setup.py develop
   - set "GIT_DIR=%cd%"
diff --git a/pgmpy/estimators/HillClimbSearch.py b/pgmpy/estimators/HillClimbSearch.py
index 09e57d1c..fe47c310 100644
--- a/pgmpy/estimators/HillClimbSearch.py
+++ b/pgmpy/estimators/HillClimbSearch.py
@@ -136,7 +136,7 @@ class HillClimbSearch(StructureEstimator):
         >>> est.estimate(max_indegree=1).edges()
         [('J', 'A'), ('B', 'J')]
         """
-        epsilon = 1e-8
+
         nodes = self.state_names.keys()
         if start is None:
             start = BayesianModel()
@@ -156,7 +156,7 @@ class HillClimbSearch(StructureEstimator):
                     best_operation = operation
                     best_score_delta = score_delta
 
-            if best_operation is None or best_score_delta < epsilon:
+            if best_operation is None:
                 break
             elif best_operation[0] == '+':
                 current_model.add_edge(*best_operation[1])
diff --git a/pgmpy/models/BayesianModel.py b/pgmpy/models/BayesianModel.py
index aa0f6501..d1426a1e 100644
--- a/pgmpy/models/BayesianModel.py
+++ b/pgmpy/models/BayesianModel.py
@@ -456,7 +456,7 @@ class BayesianModel(DirectedGraph):
 
     def local_independencies(self, variables):
         """
-        Returns an instance of Independencies containing the local independencies
+        Returns a independencies object containing the local independencies
         of each of the variables.
 
         Parameters
@@ -471,8 +471,12 @@ class BayesianModel(DirectedGraph):
         >>> student.add_edges_from([('diff', 'grade'), ('intel', 'grade'),
         >>>                         ('grade', 'letter'), ('intel', 'SAT')])
         >>> ind = student.local_independencies('grade')
-        >>> ind
-        (grade _|_ SAT | diff, intel)
+        >>> ind.event1
+        {'grade'}
+        >>> ind.event2
+        {'SAT'}
+        >>> ind.event3
+        {'diff', 'intel'}
         """
         def dfs(node):
             """
@@ -710,11 +714,20 @@ class BayesianModel(DirectedGraph):
         >>> predict_data.drop('E', axis=1, inplace=True)
         >>> y_pred = model.predict(predict_data)
         >>> y_pred
-        array([0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1,
-               1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1,
-               1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
-               1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1,
-               1, 1, 1, 0, 0, 0, 1, 0])
+            E
+        800 0
+        801 1
+        802 1
+        803 1
+        804 0
+        ... ...
+        993 0
+        994 0
+        995 1
+        996 1
+        997 0
+        998 0
+        999 0
         """
         from pgmpy.inference import VariableElimination
 
@@ -722,7 +735,7 @@ class BayesianModel(DirectedGraph):
             raise ValueError("No variable missing in data. Nothing to predict")
 
         elif set(data.columns) - set(self.nodes()):
-            raise ValueError("data has variables which are not in the model")
+            raise ValueError("Data has variables which are not in the model")
 
         missing_variables = set(self.nodes()) - set(data.columns)
         pred_values = defaultdict(list)
@@ -734,6 +747,72 @@ class BayesianModel(DirectedGraph):
                 pred_values[k].append(v)
         return pd.DataFrame(pred_values, index=data.index)
 
+    def predict_probability(self, data):
+        """
+        Predicts probabilities of all states of the missing variables.
+
+        Parameters
+        ----------
+        data : pandas DataFrame object
+            A DataFrame object with column names same as the variables in the model.
+
+        Examples
+        --------
+        >>> import numpy as np
+        >>> import pandas as pd
+        >>> from pgmpy.models import BayesianModel
+        >>> values = pd.DataFrame(np.random.randint(low=0, high=2, size=(100, 5)),
+        ...                       columns=['A', 'B', 'C', 'D', 'E'])
+        >>> train_data = values[:80]
+        >>> predict_data = values[80:]
+        >>> model = BayesianModel([('A', 'B'), ('C', 'B'), ('C', 'D'), ('B', 'E')])
+        >>> model.fit(values)
+        >>> predict_data = predict_data.copy()
+        >>> predict_data.drop('B', axis=1, inplace=True)
+        >>> y_prob = model.predict_probability(predict_data)
+        >>> y_prob 
+            B_0         B_1
+        80  0.439178    0.560822
+        81  0.581970    0.418030
+        82  0.488275    0.511725
+        83  0.581970    0.418030
+        84  0.510794    0.489206
+        85  0.439178    0.560822
+        86  0.439178    0.560822
+        87  0.417124    0.582876
+        88  0.407978    0.592022
+        89  0.429905    0.570095
+        90  0.581970    0.418030
+        91  0.407978    0.592022
+        92  0.429905    0.570095
+        93  0.429905    0.570095
+        94  0.439178    0.560822
+        95  0.407978    0.592022
+        96  0.559904    0.440096
+        97  0.417124    0.582876
+        98  0.488275    0.511725
+        99  0.407978    0.592022
+        """
+        from pgmpy.inference import VariableElimination
+
+        if set(data.columns) == set(self.nodes()):
+            raise ValueError("No variable missing in data. Nothing to predict")
+
+        elif set(data.columns) - set(self.nodes()):
+            raise ValueError("Data has variables which are not in the model")
+
+        missing_variables = set(self.nodes()) - set(data.columns)
+        pred_values = defaultdict(list)
+
+        model_inference = VariableElimination(self)
+        for index, data_point in data.iterrows():
+            states_dict = model_inference.query(variables=missing_variables, evidence=data_point.to_dict())
+            for k, v in states_dict.items():
+                for l in range(len(v.values)):
+                    state = self.get_cpds(k).state_names[k][l]
+                    pred_values[k + '_' + str(state)].append(v.values[l])
+        return pd.DataFrame(pred_values, index=data.index)
+
     def get_factorized_product(self, latex=False):
         # TODO: refer to IMap class for explanation why this is not implemented.
         pass
diff --git a/pgmpy/models/MarkovChain.py b/pgmpy/models/MarkovChain.py
index 9392f699..846ff993 100644
--- a/pgmpy/models/MarkovChain.py
+++ b/pgmpy/models/MarkovChain.py
@@ -4,7 +4,6 @@ from warnings import warn
 
 import numpy as np
 from pandas import DataFrame
-from scipy.linalg import eig
 
 from pgmpy.factors.discrete import State
 from pgmpy.utils import sample_discrete
@@ -283,11 +282,11 @@ class MarkovChain(object):
             for st in self.transition_models[var]:
                 var_states[var][st] = list(self.transition_models[var][st].keys())
                 var_values[var][st] = list(self.transition_models[var][st].values())
-                samples[var][st] = sample_discrete(var_states[var][st], var_values[var][st], size=size)
+                samples[var][st] = sample_discrete(var_states[var][st], var_values[var][st])[0]
 
         for i in range(size - 1):
             for j, (var, st) in enumerate(self.state):
-                next_st = samples[var][st][i]
+                next_st = samples[var][st]
                 self.state[j] = State(var, next_st)
             sampled.loc[i + 1] = [st for var, st in self.state]
 
@@ -306,7 +305,7 @@ class MarkovChain(object):
         >>> from pgmpy.models.MarkovChain import MarkovChain as MC
         >>> from pgmpy.factors.discrete import State
         >>> model = MC(['intel', 'diff'], [3, 2])
-        >>> intel_tm = {0: {0: 0.2, 1: 0.4, 2:0.4}, 1: {0: 0, 1: 0.5, 2: 0.5}, 2: {2: 0.5, 1:0.5}}
+        >>> intel_tm = {0: {0: 0.2, 1: 0.4, 2:0.4}, 1: {0: 0, 1: 0.5, 2: 0.5}, 2: {2: 0.1, 1:0.9}}
         >>> model.add_transition_model('intel', intel_tm)
         >>> diff_tm = {0: {0: 0.5, 1: 0.5}, 1: {0: 0.25, 1:0.75}}
         >>> model.add_transition_model('diff', diff_tm)
@@ -368,58 +367,6 @@ class MarkovChain(object):
                 self.state[j] = State(var, next_st)
             yield self.state[:]
 
-    def is_stationarity(self, tolerance=0.2, sample=None):
-        """
-        Checks if the given markov chain is stationary and checks the steady state
-        probablity values for the state are consistent.
-
-        Parameters:
-        -----------
-        tolerance: float
-            represents the diff between actual steady state value and the computed value
-        sample: [State(i,j)]
-            represents the list of state which the markov chain has sampled
-
-        Return Type:
-        ------------
-        Boolean
-        True, if the markov chain converges to steady state distribution within the tolerance
-        False, if the markov chain does not converge to steady state distribution within tolerance
-
-        Examples:
-        ---------
-        >>> from pgmpy.models.MarkovChain import MarkovChain
-        >>> from pgmpy.factors.discrete import State
-        >>> model = MarkovChain()
-        >>> model.add_variables_from(['intel', 'diff'], [3, 2])
-        >>> intel_tm = {0: {0: 0.2, 1: 0.4, 2:0.4}, 1: {0: 0, 1: 0.5, 2: 0.5}, 2: {0: 0.3, 1: 0.3, 2: 0.4}}
-        >>> model.add_transition_model('intel', intel_tm)
-        >>> diff_tm = {0: {0: 0.5, 1: 0.5}, 1: {0: 0.25, 1:0.75}}
-        >>> model.add_transition_model('diff', diff_tm)
-        >>> model.is_stationarity()
-        True
-        """
-        keys = self.transition_models.keys()
-        return_val = True
-        for k in keys:
-            # convert dict to numpy matrix
-            transition_mat = np.array([np.array(list(self.transition_models[k][i].values()))
-                                       for i in self.transition_models[k].keys()], dtype=np.float)
-            S, U = eig(transition_mat.T)
-            stationary = np.array(U[:, np.where(np.abs(S - 1.) < 1e-8)[0][0]].flat)
-            stationary = (stationary / np.sum(stationary)).real
-
-            probabilites = []
-            window_size = 10000 if sample is None else len(sample)
-            for i in range(0, transition_mat.shape[0]):
-                probabilites.extend(self.prob_from_sample([State(k, i)], window_size=window_size))
-            if any(np.abs(i) > tolerance for i in np.subtract(probabilites, stationary)):
-                return_val = return_val and False
-            else:
-                return_val = return_val and True
-
-        return return_val
-
     def random_state(self):
         """
         Generates a random state of the Markov Chain.
diff --git a/pgmpy/models/NaiveBayes.py b/pgmpy/models/NaiveBayes.py
index 8f7ab219..bcc67e18 100644
--- a/pgmpy/models/NaiveBayes.py
+++ b/pgmpy/models/NaiveBayes.py
@@ -141,8 +141,9 @@ class NaiveBayes(BayesianModel):
 
     def local_independencies(self, variables):
         """
-        Returns an instance of Independencies containing the local independencies
-        of each of the variables.
+        Returns a list of independencies objects containing the local independencies
+        of each of the variables. If local independencies does not exist for a variable
+        it gives a None for that variable.
 
 
         Parameters
@@ -157,12 +158,15 @@ class NaiveBayes(BayesianModel):
         >>> model.add_edges_from([('a', 'b'), ('a', 'c'), ('a', 'd')])
         >>> ind = model.local_independencies('b')
         >>> ind
-        (b _|_ d, c | a)
+        [(b _|_ d, c | a)]
         """
-        independencies = Independencies()
+        independencies = []
         for variable in [variables] if isinstance(variables, str) else variables:
             if variable != self.parent_node:
-                independencies.add_assertions([variable, list(set(self.children_nodes) - set(variable)), self.parent_node])
+                independencies.append(Independencies(
+                    [variable, list(set(self.children_nodes) - set(variable)), self.parent_node]))
+            else:
+                independencies.append(None)
         return independencies
 
     def fit(self, data, parent_node=None, estimator_type=None):
diff --git a/pgmpy/utils/state_name.py b/pgmpy/utils/state_name.py
index 97dd8ffa..01c28c8a 100644
--- a/pgmpy/utils/state_name.py
+++ b/pgmpy/utils/state_name.py
@@ -1,4 +1,3 @@
-from wrapt import decorator
 """
 The file contains decorators to manage the user defined
 variable state names. It maps the internal representaion
@@ -29,16 +28,17 @@ class StateNameInit():
     >>> print(phi.state_names)
     {'speed': ['low', 'medium', 'high'], 'switch': ['on', 'off'], 'time': ['day', 'night']}
     """
-    @decorator
-    def __call__(self, f, instance, args, kwargs):
-        # Case, when no state names dict is provided.
-        if 'state_names' not in kwargs:
-            # instance represents the self parameter of the __init__ method
-            instance.state_names = None
-        else:
-            instance.state_names = kwargs['state_names']
-            del kwargs['state_names']
-        f(*args, **kwargs)
+    def __call__(self, f):
+        def wrapper(*args, **kwargs):
+            # Case, when no state names dict is provided.
+            if 'state_names' not in kwargs:
+                # args[0] represents the self parameter of the __init__ method
+                args[0].state_names = None
+            else:
+                args[0].state_names = kwargs['state_names']
+                del kwargs['state_names']
+            f(*args, **kwargs)
+        return wrapper
 
 
 class StateNameDecorator():
@@ -158,42 +158,44 @@ class StateNameDecorator():
                     arg_val[var] = self.state_names[var].index(arg_val[var])
             return arg_val
 
-    @decorator
-    def __call__(self, f, instance, args, kwargs):
-        # instance represents the self parameter of the __init__ method
-        method_self = instance
-
-        if not method_self.state_names:
-            return f(*args, **kwargs)
-        else:
-            self.state_names = method_self.state_names
-
-        if self.arg and not self.return_val:
-            # If input parameters are in kwargs format
-            if self.arg in kwargs:
-                arg_val = kwargs[self.arg]
-                kwargs[self.arg] = self.get_mapped_value(arg_val)
+    def __call__(self, f):
+        def wrapper(*args, **kwargs):
+            # args[0] represents the self parameter of the __init__ method
+            method_self = args[0]
+
+            if not method_self.state_names:
                 return f(*args, **kwargs)
-            # If input parameters are in args format
             else:
-                for arg_val in args[:]:
-                    mapped_arg_val = self.get_mapped_value(arg_val)
-                    if mapped_arg_val:
-                        mapped_args = list(args)
-                        mapped_args[args.index(arg_val)] = mapped_arg_val
-                return f(*mapped_args, **kwargs)
-
-        elif not self.arg and self.return_val:
-            return_val = f(*args, **kwargs)
-
-            mapped_return_val = self.get_mapped_value(return_val)
-            # If the function returns only one output
-            if mapped_return_val:
-                return mapped_return_val
-
-            # If the function returns more than one output.
-            for ret_val in list(return_val):
-                mapped_ret_val = self.get_mapped_value(ret_val)
-                if ret_val:
-                    return_val[return_val.index(ret_val)] = mapped_ret_val
-            return return_val
+                self.state_names = method_self.state_names
+
+            if self.arg and not self.return_val:
+                # If input parameters are in kwargs format
+                if self.arg in kwargs:
+                    arg_val = kwargs[self.arg]
+                    kwargs[self.arg] = self.get_mapped_value(arg_val)
+                    return f(*args, **kwargs)
+                # If input parameters are in args format
+                else:
+                    for arg_val in args[1:]:
+                        mapped_arg_val = self.get_mapped_value(arg_val)
+                        if mapped_arg_val:
+                            mapped_args = list(args)
+                            mapped_args[args.index(arg_val)] = mapped_arg_val
+                    return f(*mapped_args, **kwargs)
+
+            elif not self.arg and self.return_val:
+                return_val = f(*args, **kwargs)
+
+                mapped_return_val = self.get_mapped_value(return_val)
+                # If the function returns only one output
+                if mapped_return_val:
+                    return mapped_return_val
+
+                # If the function returns more than one output.
+                for ret_val in list(return_val):
+                    mapped_ret_val = self.get_mapped_value(ret_val)
+                    if ret_val:
+                        return_val[return_val.index(ret_val)] = mapped_ret_val
+                return return_val
+
+        return wrapper
diff --git a/requirements-dev.txt b/requirements-dev.txt
index ab15a26a..206656f9 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -5,4 +5,3 @@ pandas
 pyparsing
 mock
 nose
-wrapt
diff --git a/requirements.txt b/requirements.txt
index fb4c749e..6eed30de 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,5 +3,3 @@ numpy==1.11.1
 scipy==0.18.0
 pandas==0.18.1
 pyparsing==2.1.8
-wrapt==1.10.8
-
diff --git a/setup.py b/setup.py
index cace146c..4c3ef836 100644
--- a/setup.py
+++ b/setup.py
@@ -10,9 +10,7 @@ setup(
     author=open("AUTHORS.rst").read(),
     url="https://github.com/pgmpy/pgmpy",
     classifiers=[
-        "Programming Language :: Python :: 3.5",
-        "Programming Language :: Python :: 3.4",
-        "Programming Language :: Python :: 2.7",
+        "Programming Language :: Python :: 3",
         "Intended Audience :: Developers",
         "Operating System :: Unix",
         "Operating System :: POSIX",


Test patch:
diff --git a/pgmpy/tests/test_models/test_BayesianModel.py b/pgmpy/tests/test_models/test_BayesianModel.py
index 42104838..78f51a09 100644
--- a/pgmpy/tests/test_models/test_BayesianModel.py
+++ b/pgmpy/tests/test_models/test_BayesianModel.py
@@ -452,6 +452,42 @@ class TestBayesianModelFitPredict(unittest.TestCase):
                                              1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1,
                                              1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1,
                                              1, 1, 1, 0]))
+        predict_data = pd.DataFrame(np.random.randint(low=0, high=2, size=(1, 5)),
+                              columns=['A', 'B', 'C', 'F', 'E'])[:]
+        self.assertRaises(ValueError, self.model_connected.predict, predict_data)
+
+    def test_connected_predict_probability(self):
+        np.random.seed(42)
+        values = pd.DataFrame(np.random.randint(low=0, high=2, size=(100, 5)),
+                              columns=['A', 'B', 'C', 'D', 'E'])
+        fit_data = values[:80]
+        predict_data = values[80:].copy()
+        self.model_connected.fit(fit_data)
+        predict_data.drop('E', axis=1, inplace=True)
+        e_prob = self.model_connected.predict_probability(predict_data)
+        np_test.assert_allclose(e_prob.values.ravel(),
+                                    np.array([0.57894737,  0.42105263,  0.57894737,  0.42105263,  0.57894737,
+                                             0.42105263,  0.5       ,  0.5       ,  0.57894737,  0.42105263,
+                                             0.5       ,  0.5       ,  0.57894737,  0.42105263,  0.57894737,
+                                             0.42105263,  0.57894737,  0.42105263,  0.5       ,  0.5       ,
+                                             0.57894737,  0.42105263,  0.57894737,  0.42105263,  0.5       ,
+                                             0.5       ,  0.57894737,  0.42105263,  0.57894737,  0.42105263,
+                                             0.5       ,  0.5       ,  0.57894737,  0.42105263,  0.5       ,
+                                             0.5       ,  0.5       ,  0.5       ,  0.5       ,  0.5       ]), atol = 0)
+        predict_data = pd.DataFrame(np.random.randint(low=0, high=2, size=(1, 5)),
+                              columns=['A', 'B', 'C', 'F', 'E'])[:]
+
+    def test_predict_probability_errors(self):
+        np.random.seed(42)
+        values = pd.DataFrame(np.random.randint(low=0, high=2, size=(2, 5)),
+                              columns=['A', 'B', 'C', 'D', 'E'])
+        fit_data = values[:1]
+        predict_data = values[1:].copy()
+        self.model_connected.fit(fit_data)
+        self.assertRaises(ValueError, self.model_connected.predict_probability, predict_data)
+        predict_data = pd.DataFrame(np.random.randint(low=0, high=2, size=(1, 5)),
+                              columns=['A', 'B', 'C', 'F', 'E'])[:]
+        self.assertRaises(ValueError, self.model_connected.predict_probability, predict_data)
 
     def tearDown(self):
         del self.model_connected
diff --git a/pgmpy/tests/test_models/test_MarkovChain.py b/pgmpy/tests/test_models/test_MarkovChain.py
index 87e57850..fb5e6da1 100644
--- a/pgmpy/tests/test_models/test_MarkovChain.py
+++ b/pgmpy/tests/test_models/test_MarkovChain.py
@@ -5,7 +5,6 @@ import numpy as np
 from pandas import DataFrame
 from mock import patch, call
 
-
 from pgmpy.factors.discrete import State
 from pgmpy.models import MarkovChain as MC
 from pgmpy.extern.six.moves import range, zip
@@ -230,24 +229,6 @@ class TestMarkovChain(unittest.TestCase):
         probabilites = model.prob_from_sample([State('a', 1), State('b', 0)])
         self.assertEqual(list(probabilites), [1] * 50 + [0] * 50)
 
-    def test_is_stationarity_success(self):
-        model = MC(['intel', 'diff'], [2, 3])
-        model.set_start_state([State('intel', 0), State('diff', 2)])
-        intel_tm = {0: {0: 0.25, 1: 0.75}, 1: {0: 0.5, 1: 0.5}}
-        model.add_transition_model('intel', intel_tm)
-        diff_tm = {0: {0: 0.1, 1: 0.5, 2: 0.4}, 1: {0: 0.2, 1: 0.2, 2: 0.6}, 2: {0: 0.7, 1: 0.15, 2: 0.15}}
-        model.add_transition_model('diff', diff_tm)
-        self.assertTrue(model.is_stationarity)
-
-    def test_is_stationarity_failure(self):
-        model = MC(['intel', 'diff'], [2, 3])
-        model.set_start_state([State('intel', 0), State('diff', 2)])
-        intel_tm = {0: {0: 0.25, 1: 0.75}, 1: {0: 0.5, 1: 0.5}}
-        model.add_transition_model('intel', intel_tm)
-        diff_tm = {0: {0: 0.1, 1: 0.5, 2: 0.4}, 1: {0: 0.2, 1: 0.2, 2: 0.6}, 2: {0: 0.7, 1: 0.15, 2: 0.15}}
-        model.add_transition_model('diff', diff_tm)
-        self.assertFalse(model.is_stationarity(0.002, None))
-
     @patch.object(sys.modules["pgmpy.models.MarkovChain"], "sample_discrete")
     def test_generate_sample(self, sample_discrete):
         model = MC(['a', 'b'], [2, 2])
diff --git a/pgmpy/tests/test_models/test_NaiveBayes.py b/pgmpy/tests/test_models/test_NaiveBayes.py
index 3a74d382..3f1b064c 100644
--- a/pgmpy/tests/test_models/test_NaiveBayes.py
+++ b/pgmpy/tests/test_models/test_NaiveBayes.py
@@ -129,10 +129,13 @@ class TestNaiveBayesMethods(unittest.TestCase):
                               ('d', 's')])
 
     def test_local_independencies(self):
-        self.assertEqual(self.G1.local_independencies('a'), Independencies())
-        self.assertEqual(self.G1.local_independencies('b'), Independencies(['b', ['e', 'c', 'd'], 'a']))
-        self.assertEqual(self.G1.local_independencies('c'), Independencies(['c', ['e', 'b', 'd'], 'a']))
-        self.assertEqual(self.G1.local_independencies('d'), Independencies(['d', ['b', 'c', 'e'], 'a']))
+        self.assertListEqual(self.G1.local_independencies('a'), [None])
+        self.assertListEqual(self.G1.local_independencies('b'),
+                             [Independencies(['b', ['e', 'c', 'd'], 'a'])])
+        self.assertListEqual(self.G1.local_independencies('c'),
+                             [Independencies(['c', ['e', 'b', 'd'], 'a'])])
+        self.assertListEqual(self.G1.local_independencies('d'),
+                             [Independencies(['d', ['b', 'c', 'e'], 'a'])])
 
     def test_active_trail_nodes(self):
         self.assertListEqual(sorted(self.G2.active_trail_nodes('d')), ['d', 'g', 'l', 's'])
@@ -146,12 +149,6 @@ class TestNaiveBayesMethods(unittest.TestCase):
         self.assertListEqual(sorted(self.G2.active_trail_nodes('s', observed=['g', 'l'])), ['d', 's'])
         self.assertListEqual(sorted(self.G2.active_trail_nodes('s', observed=['d', 'l'])), ['s'])
 
-    def test_get_ancestors_of(self):
-        self.assertListEqual(sorted(self.G1._get_ancestors_of('b')), ['a', 'b'])
-        self.assertListEqual(sorted(self.G1._get_ancestors_of('e')), ['a', 'e'])
-        self.assertListEqual(sorted(self.G1._get_ancestors_of('a')), ['a'])
-        self.assertListEqual(sorted(self.G1._get_ancestors_of(['b', 'e'])), ['a', 'b', 'e'])
-
     def tearDown(self):
         del self.G1
         del self.G2