Repository: pgmpy/pgmpy

Issue:
DBNInference  ValueError: Self loops are not allowed
Hi! 
when I try to construct model with DBN like this:

![20201222145647](https://user-images.githubusercontent.com/76466183/102854491-fce23180-4465-11eb-98af-44c0ee74deec.png)

`from pgmpy.models import DynamicBayesianNetwork as DBN`
`from pgmpy.factors.discrete import TabularCPD`
`from pgmpy.inference import DBNInference`
`dbn = DBN()`
`dbn.add_edges_from([(('a', 0),('b', 0)),(('a', 0),('a', 1)), (('a', 0),('b', 1))])`
`a_0=TabularCPD(('a', 0), 2, [[0.5],[0.5]])`
`b_0=TabularCPD(('b', 0), 2, [[0.3,0.7],[0.7,0.3]],[('a',0)],[2])`
`a_1=TabularCPD(('a', 1), 2, [[0.3,0.7],[0.7,0.3]],[('a',0)],[2])`
`dbn.add_cpds(a_0, b_0, a_1)`
`dbn_inf = DBNInference(dbn)`

But when I execute the code I get this error:

`  File "C:\users\a5767\appdata\local\programs\python\python36\lib\site-packages\pgmpy\models\untitled9.py", line 25, in <module>
    dbn_inf = DBNInference(dbn)
`
  `File "c:\users\a5767\appdata\local\programs\python\python36\lib\site-packages\pgmpy\inference\dbn_inference.py", line 70, in __init__
    start_markov_model.add_edges_from(combinations_slice_0[0])`
`  File "c:\users\a5767\appdata\local\programs\python\python36\lib\site-packages\pgmpy\base\UndirectedGraph.py", line 252, in add_edges_from
    self.add_edge(edge[0], edge[1])`
`  File "c:\users\a5767\appdata\local\programs\python\python36\lib\site-packages\pgmpy\models\MarkovModel.py", line 105, in add_edge
    raise ValueError("Self loops are not allowed")`
`ValueError: Self loops are not allowed`


 Thank you very much for someone who can help me with this error.


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy) Report
> Merging [#1454](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy) (30671ce) into [dev](https://codecov.io/gh/pgmpy/pgmpy/commit/7b691d27f0dc39999db1a44a186813e42c515f7c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy) (7b691d2) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/graphs/tree.svg?width=650&height=150&src=pr&token=UaJMCdHaEF&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy)](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy)

```diff
@@           Coverage Diff           @@
##              dev    #1454   +/-   ##
=======================================
  Coverage   94.56%   94.56%           
=======================================
  Files         141      141           
  Lines       15828    15814   -14     
=======================================
- Hits        14967    14954   -13     
+ Misses        861      860    -1     
```


| [Impacted Files](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy) | Coverage Δ | |
|---|---|---|
| [pgmpy/inference/dbn\_inference.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvaW5mZXJlbmNlL2Ribl9pbmZlcmVuY2UucHk=) | `100.00% <100.00%> (ø)` | |
| [pgmpy/tests/test\_inference/test\_dbn\_inference.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvdGVzdHMvdGVzdF9pbmZlcmVuY2UvdGVzdF9kYm5faW5mZXJlbmNlLnB5) | `100.00% <100.00%> (ø)` | |
| [.../test\_models/test\_LinearGaussianBayesianNetwork.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvdGVzdHMvdGVzdF9tb2RlbHMvdGVzdF9MaW5lYXJHYXVzc2lhbkJheWVzaWFuTmV0d29yay5weQ==) | `39.06% <0.00%> (-3.59%)` | :arrow_down: |
| [...actors/test\_continuous/test\_Linear\_Gaussain\_CPD.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvdGVzdHMvdGVzdF9mYWN0b3JzL3Rlc3RfY29udGludW91cy90ZXN0X0xpbmVhcl9HYXVzc2Fpbl9DUEQucHk=) | `40.00% <0.00%> (-2.86%)` | :arrow_down: |
| [pgmpy/factors/continuous/discretize.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvZmFjdG9ycy9jb250aW51b3VzL2Rpc2NyZXRpemUucHk=) | `34.21% <0.00%> (-1.69%)` | :arrow_down: |
| [pgmpy/tests/test\_estimators/test\_SEMEstimator.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvdGVzdHMvdGVzdF9lc3RpbWF0b3JzL3Rlc3RfU0VNRXN0aW1hdG9yLnB5) | `79.66% <0.00%> (-1.59%)` | :arrow_down: |
| [pgmpy/factors/base.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvZmFjdG9ycy9iYXNlLnB5) | `84.21% <0.00%> (-0.79%)` | :arrow_down: |
| [...gmpy/factors/distributions/GaussianDistribution.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvZmFjdG9ycy9kaXN0cmlidXRpb25zL0dhdXNzaWFuRGlzdHJpYnV0aW9uLnB5) | `69.00% <0.00%> (-0.61%)` | :arrow_down: |
| [pgmpy/independencies/Independencies.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvaW5kZXBlbmRlbmNpZXMvSW5kZXBlbmRlbmNpZXMucHk=) | `87.39% <0.00%> (-0.41%)` | :arrow_down: |
| [pgmpy/factors/continuous/ContinuousFactor.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy#diff-cGdtcHkvZmFjdG9ycy9jb250aW51b3VzL0NvbnRpbnVvdXNGYWN0b3IucHk=) | `86.11% <0.00%> (-0.38%)` | :arrow_down: |
| ... and [15 more](https://codecov.io/gh/pgmpy/pgmpy/pull/1454/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy). Last update [7b691d2...30671ce](https://codecov.io/gh/pgmpy/pgmpy/pull/1454?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pgmpy).

ankurankan: @FelipeGiro Thanks for the PR. I think the test is alright for now. I am working on some simulation/sampling methods for DBN, so I can add tests for comparing the values from the two methods once it's done. 

Patch:
diff --git a/pgmpy/inference/dbn_inference.py b/pgmpy/inference/dbn_inference.py
index 72540d1a..c0c4854e 100644
--- a/pgmpy/inference/dbn_inference.py
+++ b/pgmpy/inference/dbn_inference.py
@@ -64,8 +64,8 @@ class DBNInference(Inference):
         start_markov_model = self.start_bayesian_model.to_markov_model()
         one_and_half_markov_model = self.one_and_half_model.to_markov_model()
 
-        combinations_slice_0 = tee(combinations(self.interface_nodes_0, 2), 2)
-        combinations_slice_1 = combinations(self.interface_nodes_1, 2)
+        combinations_slice_0 = tee(combinations(set(self.interface_nodes_0), 2), 2)
+        combinations_slice_1 = combinations(set(self.interface_nodes_1), 2)
 
         start_markov_model.add_edges_from(combinations_slice_0[0])
         one_and_half_markov_model.add_edges_from(


Test patch:
diff --git a/pgmpy/tests/test_inference/test_dbn_inference.py b/pgmpy/tests/test_inference/test_dbn_inference.py
index 2ce8de00..b81b4206 100644
--- a/pgmpy/tests/test_inference/test_dbn_inference.py
+++ b/pgmpy/tests/test_inference/test_dbn_inference.py
@@ -1,6 +1,7 @@
 import unittest
 import numpy as np
 import numpy.testing as np_test
+from scipy.special import softmax
 
 from pgmpy.inference import DBNInference
 from pgmpy.models import DynamicBayesianNetwork
@@ -119,3 +120,72 @@ class TestDBNInference(unittest.TestCase):
         np_test.assert_array_almost_equal(
             query_result[("X", 1)].values, np.array([0.7621772, 0.2378228])
         )
+
+    def test_super_conncted_network(self):
+        edges = [
+            (("A", 0), ("A", 1)),
+            (("A", 0), ("B", 1)),
+            (("B", 0), ("A", 1)),
+            (("B", 0), ("B", 1)),
+            (("L", 0), ("A", 0)),
+            (("L", 0), ("B", 0)),
+            (("L", 0), ("L", 1)),
+            (("L", 1), ("A", 1)),
+            (("L", 1), ("B", 1)),
+        ]
+
+        bnet = DynamicBayesianNetwork(edges)  # , latents=set('L'))
+
+        bnet_cpds = []
+        bnet_cpds.append(
+            TabularCPD(
+                ("A", 0),
+                2,
+                softmax(np.ones((2, 2)), axis=0),
+                evidence=[("L", 0)],
+                evidence_card=[2],
+            )
+        )
+        bnet_cpds.append(
+            TabularCPD(
+                ("B", 0),
+                2,
+                softmax(np.ones((2, 2)), axis=0),
+                evidence=[("L", 0)],
+                evidence_card=[2],
+            )
+        )
+        bnet_cpds.append(TabularCPD(("L", 0), 2, softmax(np.ones((2, 1)), axis=0)))
+        bnet_cpds.append(
+            TabularCPD(
+                ("A", 1),
+                2,
+                softmax(np.ones((2, 8)), axis=0),
+                evidence=[("A", 0), ("B", 0), ("L", 1)],
+                evidence_card=[2, 2, 2],
+            )
+        )
+        bnet_cpds.append(
+            TabularCPD(
+                ("B", 1),
+                2,
+                softmax(np.ones((2, 8)), axis=0),
+                evidence=[("A", 0), ("B", 0), ("L", 1)],
+                evidence_card=[2, 2, 2],
+            )
+        )
+        bnet_cpds.append(
+            TabularCPD(
+                ("L", 1),
+                2,
+                softmax(np.ones((2, 2)), axis=0),
+                evidence=[("L", 0)],
+                evidence_card=[2],
+            )
+        )
+
+        bnet.add_cpds(*bnet_cpds)
+
+        ie = DBNInference(bnet)
+
+        # TODO: an assertion to test a complex network