Repository: pgmpy/pgmpy

Issue:
Dimensionality error when initializing DynamicBayesianNetwork
### Subject of the issue
Dimensionality error when initializing DynamicBayesianNetwork

### Your environment
* pgmpy_1617178903326
* Python 3.8.2
* Operating System OS X 11.3.1

### Steps to reproduce
```
from pgmpy.models import DynamicBayesianNetwork as DBN
from pgmpy.factors.discrete import TabularCPD
from pgmpy.inference import DBNInference

cancer_model = DBN()
cancer_model.add_edges_from([(('Pollution', 0), ('Cancer', 0)),
                      (('Smoker', 0), ('Cancer', 0)),
                      (('Cancer', 0), ('Xray', 0)),
                      (('Cancer', 0), ('Dyspnoea', 0))])

cpd_poll = TabularCPD(variable=('Pollution', 0), variable_card=2,
                      values=[[0.9], [0.1]])
cpd_smoke = TabularCPD(variable=('Smoker', 0), variable_card=2,
                       values=[[0.3], [0.7]])
cpd_cancer = TabularCPD(variable=('Cancer', 0), variable_card=2,
                        values=[[0.03, 0.05, 0.001, 0.02],
                                [0.97, 0.95, 0.999, 0.98]],
                        evidence=[('Smoker', 0), ('Pollution', 0)],
                        evidence_card=[2, 2])
cpd_xray = TabularCPD(variable=('Xray', 0), variable_card=2,
                      values=[[0.9, 0.2], [0.1, 0.8]],
                      evidence=[('Cancer', 0)], evidence_card=[2])
cpd_dysp = TabularCPD(variable=('Dyspnoea', 0), variable_card=2,
                      values=[[0.65, 0.3], [0.35, 0.7]],
                      evidence=[('Cancer', 0)], evidence_card=[2])


# Associating the parameters with the model structure.
cancer_model.add_cpds(cpd_poll, cpd_smoke, cpd_cancer, cpd_xray, cpd_dysp)

cancer_model.initialize_initial_state()
dbn_inf = DBNInference(cancer_model)
print(dbn_inf.query([('Xray', 0)], {('Smoker', 0): 0})[('Xray', 0)].values)
```

### Expected behaviour
```
Eliminating: ('Cancer', 0): 100%|██████████████████████████████████████████| 2/2 [00:00<00:00, 590.46it/s]
Eliminating: ('Cancer', 0): 100%|██████████████████████████████████████████| 2/2 [00:00<00:00, 651.69it/s]
[0.2224 0.7776]
```

### Actual behaviour
```
Traceback (most recent call last):
  File "test_dynamic_bayesian_network.py", line 69, in <module>
    cancer_model.initialize_initial_state()
  File "/Users/royabitbol/anaconda3/envs/dqf-new/lib/python3.8/site-packages/pgmpy/models/DynamicBayesianNetwork.py", line 570, in initialize_initial_state
    new_cpd = TabularCPD(
  File "/Users/royabitbol/anaconda3/envs/dqf-new/lib/python3.8/site-packages/pgmpy/factors/discrete/CPD.py", line 131, in __init__
    raise ValueError(
ValueError: values must be of shape (2, 1). Got shape: (1, 2)

```

Discussion:
roy651: The 3rd test which I commented out in the code is related to issue #1417 

Patch:
diff --git a/pgmpy/models/DynamicBayesianNetwork.py b/pgmpy/models/DynamicBayesianNetwork.py
index 4be5d4e4..c9a0c244 100644
--- a/pgmpy/models/DynamicBayesianNetwork.py
+++ b/pgmpy/models/DynamicBayesianNetwork.py
@@ -564,13 +564,13 @@ class DynamicBayesianNetwork(DAG):
                             new_cpd = TabularCPD(
                                 temp_var,
                                 cpd.variable_card,
-                                np.reshape(initial_cpd.values, (-1, 2)),
+                                np.reshape(initial_cpd.values, (2, -1)),
                             )
                         else:
                             new_cpd = TabularCPD(
                                 temp_var,
                                 cpd.variable_card,
-                                np.reshape(cpd.values, (-1, 2)),
+                                np.reshape(cpd.values, (2, -1)),
                             )
                     self.add_cpds(new_cpd)
             self.check_model()


Test patch:
diff --git a/pgmpy/tests/test_estimators/test_TreeSearch.py b/pgmpy/tests/test_estimators/test_TreeSearch.py
index 830383bd..e8f3f6c7 100644
--- a/pgmpy/tests/test_estimators/test_TreeSearch.py
+++ b/pgmpy/tests/test_estimators/test_TreeSearch.py
@@ -131,7 +131,7 @@ class TestTreeSearch(unittest.TestCase):
             for n_jobs in [-1, 1]:
                 # learn graph structure
                 est = TreeSearch(self.data12, root_node="A", n_jobs=n_jobs)
-                dag = est.estimate(estimator_type="chow-liu")
+                dag = est.estimate(estimator_type="chow-liu", edge_weights_fn=weight_fn)
 
                 # check number of nodes and edges are as expected
                 self.assertCountEqual(dag.nodes(), ["A", "B", "C", "D", "E"])
@@ -139,7 +139,7 @@ class TestTreeSearch(unittest.TestCase):
 
                 # learn tree structure using A as root node
                 est = TreeSearch(self.data13, root_node="A", n_jobs=n_jobs)
-                dag = est.estimate(estimator_type="chow-liu")
+                dag = est.estimate(estimator_type="chow-liu", edge_weights_fn=weight_fn)
 
                 # check number of nodes and edges are as expected
                 self.assertCountEqual(dag.nodes(), ["A", "B", "C", "D", "E", "F"])
@@ -164,7 +164,9 @@ class TestTreeSearch(unittest.TestCase):
             for n_jobs in [-1, 1]:
                 # learn graph structure
                 est = TreeSearch(self.data22, root_node="R", n_jobs=n_jobs)
-                dag = est.estimate(estimator_type="tan", class_node="A")
+                dag = est.estimate(
+                    estimator_type="tan", class_node="A", edge_weights_fn=weight_fn
+                )
 
                 # check number of nodes and edges are as expected
                 self.assertCountEqual(dag.nodes(), ["A", "B", "C", "D", "E", "R"])
diff --git a/pgmpy/tests/test_models/test_DynamicBayesianNetwork.py b/pgmpy/tests/test_models/test_DynamicBayesianNetwork.py
index b5440786..eb12b874 100644
--- a/pgmpy/tests/test_models/test_DynamicBayesianNetwork.py
+++ b/pgmpy/tests/test_models/test_DynamicBayesianNetwork.py
@@ -3,6 +3,8 @@ import unittest
 import pgmpy.tests.help_functions as hf
 from pgmpy.models import DynamicBayesianNetwork
 from pgmpy.factors.discrete import TabularCPD
+from pgmpy.inference import DBNInference
+
 import numpy as np
 
 
@@ -495,3 +497,185 @@ class TestDynamicBayesianNetworkMethods2(unittest.TestCase):
 
     def tearDown(self):
         del self.G
+
+
+class TestDynamicBayesianNetworkMethods3(unittest.TestCase):
+    def setUp(self):
+        self.cancer_model = DynamicBayesianNetwork()
+        #########################    1    ######################
+        self.cpd_poll = TabularCPD(
+            variable=("Pollution", 0), variable_card=2, values=[[0.9], [0.1]]
+        )
+        self.cpd_smoke = TabularCPD(
+            variable=("Smoker", 0), variable_card=2, values=[[0.3], [0.7]]
+        )
+        self.cpd_cancer = TabularCPD(
+            variable=("Cancer", 0),
+            variable_card=2,
+            values=[[0.03, 0.05, 0.001, 0.02], [0.97, 0.95, 0.999, 0.98]],
+            evidence=[("Smoker", 0), ("Pollution", 0)],
+            evidence_card=[2, 2],
+        )
+        self.cpd_xray = TabularCPD(
+            variable=("Xray", 0),
+            variable_card=2,
+            values=[[0.9, 0.2], [0.1, 0.8]],
+            evidence=[("Cancer", 0)],
+            evidence_card=[2],
+        )
+        self.cpd_dysp = TabularCPD(
+            variable=("Dyspnoea", 0),
+            variable_card=2,
+            values=[[0.65, 0.3], [0.35, 0.7]],
+            evidence=[("Cancer", 0)],
+            evidence_card=[2],
+        )
+
+        #########################    2    ######################
+        self.cpd_poll2 = TabularCPD(
+            variable=("Pollution", 1),
+            variable_card=2,
+            values=[[0.9, 0.1], [0.1, 0.9]],
+            evidence=[("Pollution", 0)],
+            evidence_card=[2],
+        )
+        self.cpd_smoke2 = TabularCPD(
+            variable=("Smoker", 1),
+            variable_card=2,
+            values=[[0.7, 0.3], [0.3, 0.7]],
+            evidence=[("Smoker", 0)],
+            evidence_card=[2],
+        )
+        self.cpd_cancer2 = TabularCPD(
+            variable=("Cancer", 1),
+            variable_card=2,
+            values=[[0.03, 0.05, 0.001, 0.02], [0.97, 0.95, 0.999, 0.98]],
+            evidence=[("Smoker", 1), ("Pollution", 1)],
+            evidence_card=[2, 2],
+        )
+        self.cpd_xray2 = TabularCPD(
+            variable=("Xray", 1),
+            variable_card=2,
+            values=[[0.9, 0.2], [0.1, 0.8]],
+            evidence=[("Cancer", 1)],
+            evidence_card=[2],
+        )
+        self.cpd_dysp2 = TabularCPD(
+            variable=("Dyspnoea", 1),
+            variable_card=2,
+            values=[[0.65, 0.3], [0.35, 0.7]],
+            evidence=[("Cancer", 1)],
+            evidence_card=[2],
+        )
+
+    def test_initialize_and_infer1(self):
+        self.cancer_model.add_edges_from(
+            [
+                (("Pollution", 0), ("Cancer", 0)),
+                (("Smoker", 0), ("Cancer", 0)),
+                (("Cancer", 0), ("Xray", 0)),
+                (("Cancer", 0), ("Dyspnoea", 0)),
+            ]
+        )
+
+        self.cancer_model.add_cpds(
+            self.cpd_poll, self.cpd_smoke, self.cpd_cancer, self.cpd_xray, self.cpd_dysp
+        )
+        self.cancer_model.initialize_initial_state()
+
+        self.assertEqual(len(self.cancer_model.cpds), 10)
+
+        self.cancer_inf = DBNInference(self.cancer_model)
+        self.cancer_query_result = self.cancer_inf.query(
+            [("Xray", 0)], {("Smoker", 0): 0}
+        )[("Xray", 0)].values
+
+        self.assertAlmostEqual(self.cancer_query_result[0], 0.2224, 4)
+        self.assertAlmostEqual(self.cancer_query_result[1], 0.7776, 4)
+
+    def test_initialize_and_infer2(self):
+        self.cancer_model.add_edges_from(
+            [
+                (("Pollution", 0), ("Cancer", 0)),
+                (("Smoker", 0), ("Cancer", 0)),
+                (("Cancer", 0), ("Xray", 0)),
+                (("Cancer", 0), ("Dyspnoea", 0)),
+                (("Pollution", 0), ("Pollution", 1)),
+                (("Smoker", 0), ("Smoker", 1)),
+                (("Pollution", 1), ("Cancer", 1)),
+                (("Smoker", 1), ("Cancer", 1)),
+                (("Cancer", 1), ("Xray", 1)),
+                (("Cancer", 1), ("Dyspnoea", 1)),
+            ]
+        )
+
+        self.cancer_model.add_cpds(
+            self.cpd_poll,
+            self.cpd_smoke,
+            self.cpd_cancer,
+            self.cpd_xray,
+            self.cpd_dysp,
+            self.cpd_poll2,
+            self.cpd_smoke2,
+            self.cpd_cancer2,
+            self.cpd_xray2,
+            self.cpd_dysp2,
+        )
+        self.cancer_model.initialize_initial_state()
+
+        self.assertEqual(len(self.cancer_model.cpds), 10)
+
+        self.cancer_inf = DBNInference(self.cancer_model)
+        self.cancer_query_result = self.cancer_inf.query(
+            [("Xray", 1)], {("Smoker", 0): 0}
+        )[("Xray", 1)].values
+
+        self.assertAlmostEqual(self.cancer_query_result[0], 0.213307, 4)
+        self.assertAlmostEqual(self.cancer_query_result[1], 0.786693, 4)
+
+    def test_initialize_and_infer3(self):
+        self.cancer_model.add_edges_from(
+            [
+                (("Pollution", 0), ("Cancer", 0)),
+                (("Smoker", 0), ("Cancer", 0)),
+                (("Cancer", 0), ("Xray", 0)),
+                (("Cancer", 0), ("Dyspnoea", 0)),
+                (("Pollution", 0), ("Pollution", 1)),
+                (("Smoker", 0), ("Smoker", 1)),
+                (("Pollution", 1), ("Cancer", 1)),
+                (("Smoker", 1), ("Cancer", 1)),
+                (("Cancer", 1), ("Xray", 1)),
+                (("Cancer", 1), ("Dyspnoea", 1)),
+            ]
+        )
+
+        self.cancer_model.add_cpds(
+            self.cpd_poll,
+            self.cpd_smoke,
+            self.cpd_cancer,
+            self.cpd_xray,
+            self.cpd_dysp,
+            self.cpd_poll2,
+            self.cpd_smoke2,
+            self.cpd_cancer2,
+            self.cpd_xray2,
+            self.cpd_dysp2,
+        )
+        self.cancer_model.initialize_initial_state()
+
+        self.assertEqual(len(self.cancer_model.cpds), 10)
+
+        self.cancer_inf = DBNInference(self.cancer_model)
+        self.cancer_query_result = self.cancer_inf.query(
+            [("Xray", 2)], {("Smoker", 0): 0}
+        )[("Xray", 2)].values
+
+        self.assertAlmostEqual(self.cancer_query_result[0], 0.2158, 4)
+
+        self.cancer_query_result = self.cancer_inf.query(
+            [("Dyspnoea", 3)], {("Pollution", 0): 0}
+        )[("Dyspnoea", 3)].values
+        self.assertAlmostEqual(self.cancer_query_result[0], 0.3070, 4)
+
+    def tearDown(self):
+        del self.cancer_model