codecov[bot]: # [Codecov](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=h1) Report
> Merging [#1216](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=desc) into [dev](https://codecov.io/gh/pgmpy/pgmpy/commit/c37dda4401f23ec73fc5d17d957867cd62e588d3?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pgmpy/pgmpy/pull/1216/graphs/tree.svg?width=650&token=UaJMCdHaEF&height=150&src=pr)](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##             dev   #1216   +/-   ##
=====================================
  Coverage   92.1%   92.1%           
=====================================
  Files        135     135           
  Lines      13167   13167           
=====================================
  Hits       12128   12128           
  Misses      1039    1039
```


| [Impacted Files](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pgmpy/tests/test\_readwrite/test\_XMLBIF.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1216/diff?src=pr&el=tree#diff-cGdtcHkvdGVzdHMvdGVzdF9yZWFkd3JpdGUvdGVzdF9YTUxCSUYucHk=) | `95.96% <ø> (ø)` | :arrow_up: |
| [pgmpy/readwrite/XMLBIF.py](https://codecov.io/gh/pgmpy/pgmpy/pull/1216/diff?src=pr&el=tree#diff-cGdtcHkvcmVhZHdyaXRlL1hNTEJJRi5weQ==) | `96.89% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=footer). Last update [c37dda4...51a12f3](https://codecov.io/gh/pgmpy/pgmpy/pull/1216?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/pgmpy/estimators/BayesianEstimator.py b/pgmpy/estimators/BayesianEstimator.py
index 7e4fbcf2..ac085bb6 100644
--- a/pgmpy/estimators/BayesianEstimator.py
+++ b/pgmpy/estimators/BayesianEstimator.py
@@ -1,5 +1,7 @@
 # -*- coding: utf-8 -*-
 
+from itertools import chain
+
 import numpy as np
 
 from pgmpy.estimators import ParameterEstimator
@@ -66,7 +68,6 @@ class BayesianEstimator(ParameterEstimator):
         <TabularCPD representing P(D:2 | C:2) at 0x7f7b4df822b0>]
         """
         parameters = []
-
         for node in self.model.nodes():
             _equivalent_sample_size = (
                 equivalent_sample_size[node]
@@ -168,7 +169,7 @@ class BayesianEstimator(ParameterEstimator):
             np.array(bayesian_counts),
             evidence=parents,
             evidence_card=parents_cardinalities,
-            state_names=self.state_names,
+            state_names={var: self.state_names[var] for var in chain([node], parents)},
         )
         cpd.normalize()
         return cpd
diff --git a/pgmpy/estimators/MLE.py b/pgmpy/estimators/MLE.py
index 2b1c982e..ce2a513b 100644
--- a/pgmpy/estimators/MLE.py
+++ b/pgmpy/estimators/MLE.py
@@ -1,5 +1,7 @@
 # coding:utf-8
 
+from itertools import chain
+
 import numpy as np
 
 from pgmpy.estimators import ParameterEstimator
@@ -149,7 +151,7 @@ class MaximumLikelihoodEstimator(ParameterEstimator):
             np.array(state_counts),
             evidence=parents,
             evidence_card=parents_cardinalities,
-            state_names=state_names,
+            state_names={var: self.state_names[var] for var in chain([node], parents)},
         )
         cpd.normalize()
         return cpd
diff --git a/pgmpy/readwrite/BIF.py b/pgmpy/readwrite/BIF.py
index cc9cdd35..43a955bb 100644
--- a/pgmpy/readwrite/BIF.py
+++ b/pgmpy/readwrite/BIF.py
@@ -317,6 +317,7 @@ class BIFReader(object):
             delayed(self._get_values_from_block)(block)
             for block in self.probability_block()
         )
+
         variable_cpds = {}
         for var_name, arr in cpd_values:
             variable_cpds[var_name] = arr
@@ -548,7 +549,7 @@ $properties}\n"""
             variable = cpd.variable
             variable_states[variable] = []
             for state in range(cpd.get_cardinality([variable])[variable]):
-                variable_states[variable].append(str(variable) + "_" + str(state))
+                variable_states[variable].append(str(state))
         return variable_states
 
     def get_properties(self):
@@ -602,12 +603,9 @@ $properties}\n"""
          'light-on': ['family-out']}
         """
         cpds = self.model.get_cpds()
-        cpds.sort(key=lambda x: x.variable)
         variable_parents = {}
         for cpd in cpds:
-            variable_parents[cpd.variable] = []
-            for parent in sorted(cpd.variables[:0:-1]):
-                variable_parents[cpd.variable].append(parent)
+            variable_parents[cpd.variable] = cpd.variables[1:]
         return variable_parents
 
     def get_cpds(self):
diff --git a/pgmpy/readwrite/XMLBIF.py b/pgmpy/readwrite/XMLBIF.py
index 989645ce..78bd92fd 100644
--- a/pgmpy/readwrite/XMLBIF.py
+++ b/pgmpy/readwrite/XMLBIF.py
@@ -376,7 +376,7 @@ class XMLBIFWriter(object):
             .transformString(s)
         )
         if not s_fixed[0].isalpha():
-            s_fixed = "state" + s_fixed
+            s_fixed = s_fixed
         return s_fixed
 
     def get_properties(self):
@@ -430,8 +430,8 @@ class XMLBIFWriter(object):
         for cpd in cpds:
             definition_tag[cpd.variable] = etree.SubElement(self.network, "DEFINITION")
             etree.SubElement(definition_tag[cpd.variable], "FOR").text = cpd.variable
-            for child in sorted(cpd.variables[:0:-1]):
-                etree.SubElement(definition_tag[cpd.variable], "GIVEN").text = child
+            for parent in cpd.variables[1:]:
+                etree.SubElement(definition_tag[cpd.variable], "GIVEN").text = parent
 
         return definition_tag
 

writing Bayesian model in a file and read it  later
### Subject of the issue
I am using pgmpy package for learning Bayesian Network from data and predicting using it.
I want to save learned Bayesian Network in a file and use it for predicting in another time.
I saw your example on pgmpy_notebook but i understood that ProbModelXMLWriter did not work correctly.
Is there another approach for doing this work?

Thanks.

### Your environment
* pgmpy version 0.1.3
* Python version 2.7
* Operating System Windows

diff --git a/pgmpy/tests/test_readwrite/test_BIF.py b/pgmpy/tests/test_readwrite/test_BIF.py
index 95d94104..726a171f 100644
--- a/pgmpy/tests/test_readwrite/test_BIF.py
+++ b/pgmpy/tests/test_readwrite/test_BIF.py
@@ -1,3 +1,4 @@
+import os
 import unittest
 
 import numpy as np
@@ -11,7 +12,6 @@ from pgmpy.factors.discrete import TabularCPD
 
 class TestBIFReader(unittest.TestCase):
     def setUp(self):
-
         self.reader = BIFReader(
             string="""
                 // Bayesian Network in the Interchange Format
@@ -219,22 +219,60 @@ class TestBIFReader(unittest.TestCase):
             "light-on": {"weight": None, "position": "(218, 195)"},
         }
         cpds_expected = [
-            np.array([[0.01], [0.99]]),
-            np.array([[0.99, 0.97, 0.9, 0.3], [0.01, 0.03, 0.1, 0.7]]),
-            np.array([[0.15], [0.85]]),
-            np.array([[0.7, 0.01], [0.3, 0.99]]),
-            np.array([[0.6, 0.05], [0.4, 0.95]]),
+            TabularCPD(
+                variable="bowel-problem",
+                variable_card=2,
+                values=np.array([[0.01], [0.99]]),
+                state_names={"bowel-problem": ["true", "false"]},
+            ),
+            TabularCPD(
+                variable="dog-out",
+                variable_card=2,
+                values=np.array([[0.99, 0.97, 0.9, 0.3], [0.01, 0.03, 0.1, 0.7]]),
+                evidence=["bowel-problem", "family-out"],
+                evidence_card=[2, 2],
+                state_names={
+                    "dog-out": ["true", "false"],
+                    "bowel-problem": ["true", "false"],
+                    "family-out": ["true", "false"],
+                },
+            ),
+            TabularCPD(
+                variable="family-out",
+                variable_card=2,
+                values=np.array([[0.15], [0.85]]),
+                state_names={"family-out": ["true", "false"]},
+            ),
+            TabularCPD(
+                variable="hear-bark",
+                variable_card=2,
+                values=np.array([[0.7, 0.01], [0.3, 0.99]]),
+                evidence=["dog-out"],
+                evidence_card=[2],
+                state_names={
+                    "hear-bark": ["true", "false"],
+                    "dog-out": ["true", "false"],
+                },
+            ),
+            TabularCPD(
+                variable="light-on",
+                variable_card=2,
+                values=np.array([[0.6, 0.05], [0.4, 0.95]]),
+                evidence=["family-out"],
+                evidence_card=[2],
+                state_names={
+                    "light-on": ["true", "false"],
+                    "family-out": ["true", "false"],
+                },
+            ),
         ]
         model = self.reader.get_model()
-        for cpd_index in range(0, len(cpds_expected)):
-            np_test.assert_array_equal(
-                model.get_cpds()[cpd_index].get_values(), cpds_expected[cpd_index]
-            )
+        model_cpds = model.get_cpds()
+        for cpd_index in range(5):
+            self.assertEqual(model_cpds[cpd_index], cpds_expected[cpd_index])
+
         self.assertDictEqual(dict(model.nodes), node_expected)
-        if nx.__version__.startswith("1"):
-            self.assertDictEqual(model.edge, edge_expected)
-        else:
-            self.assertDictEqual(dict(model.adj), edge_expected)
+        self.assertDictEqual(dict(model.adj), edge_expected)
 
         self.assertListEqual(sorted(model.nodes()), sorted(nodes_expected))
         self.assertListEqual(sorted(model.edges()), sorted(edges_expected))
@@ -288,7 +326,7 @@ class TestBIFWriter(unittest.TestCase):
         parents = {
             "kid": [],
             "bowel-problem": [],
-            "dog-out": ["family-out", "bowel-problem"],
+            "dog-out": ["bowel-problem", "family-out"],
             "family-out": [],
             "hear-bark": ["dog-out"],
             "light-on": ["family-out"],
@@ -333,32 +371,32 @@ class TestBIFWriter(unittest.TestCase):
         self.expected_string = """network unknown {
 }
 variable bowel-problem {
-    type discrete [ 2 ] { bowel-problem_0, bowel-problem_1 };
+    type discrete [ 2 ] { 0, 1 };
     property position = (335, 99) ;
     property weight = None ;
 }
 variable dog-out {
-    type discrete [ 2 ] { dog-out_0, dog-out_1 };
+    type discrete [ 2 ] { 0, 1 };
     property position = (300, 195) ;
     property weight = None ;
 }
 variable family-out {
-    type discrete [ 2 ] { family-out_0, family-out_1 };
+    type discrete [ 2 ] { 0, 1 };
     property position = (257, 99) ;
     property weight = None ;
 }
 variable hear-bark {
-    type discrete [ 2 ] { hear-bark_0, hear-bark_1 };
+    type discrete [ 2 ] { 0, 1 };
     property position = (296, 268) ;
     property weight = None ;
 }
 variable kid {
-    type discrete [ 2 ] { kid_0, kid_1 };
+    type discrete [ 2 ] { 0, 1 };
     property position = (100, 165) ;
     property weight = None ;
 }
 variable light-on {
-    type discrete [ 2 ] { light-on_0, light-on_1 };
+    type discrete [ 2 ] { 0, 1 };
     property position = (218, 195) ;
     property weight = None ;
 }
@@ -383,3 +421,13 @@ probability ( light-on | family-out ) {
 """
         self.maxDiff = None
         self.assertEqual(self.writer.__str__(), self.expected_string)
+
+    def test_write_read_equal(self):
+        self.writer.write_bif("test_bif.bif")
+        reader = BIFReader("test_bif.bif")
+        read_model = reader.get_model()
+        self.assertEqual(sorted(self.model.nodes()), sorted(read_model.nodes()))
+        self.assertEqual(sorted(self.model.edges()), sorted(read_model.edges()))
+        for var in self.model.nodes():
+            self.assertEqual(self.model.get_cpds(var), read_model.get_cpds(var))
+        os.remove("test_bif.bif")
diff --git a/pgmpy/tests/test_readwrite/test_XMLBIF.py b/pgmpy/tests/test_readwrite/test_XMLBIF.py
index 3631cac7..2e63b8e9 100644
--- a/pgmpy/tests/test_readwrite/test_XMLBIF.py
+++ b/pgmpy/tests/test_readwrite/test_XMLBIF.py
@@ -367,11 +367,11 @@ class TestXMLBIFWriterMethodsString(unittest.TestCase):
         self.assert_models_equivelent(self.model_stateless, model)
         self.assertDictEqual(
             {
-                "G": ["state0", "state1", "state2"],
-                "I": ["state0", "state1"],
-                "D": ["state0", "state1"],
-                "S": ["state0", "state1"],
-                "L": ["state0", "state1"],
+                "G": ["0", "1", "2"],
+                "I": ["0", "1"],
+                "D": ["0", "1"],
+                "S": ["0", "1"],
+                "L": ["0", "1"],
             },
             model.get_cpds("D").state_names,
         )
@@ -381,8 +381,8 @@ class TestXMLBIFWriterMethodsString(unittest.TestCase):
         self.assertSetEqual(set(expected.nodes()), set(got.nodes()))
         for node in expected.nodes():
             self.assertListEqual(
-                list(expected.get_parents(node)), list(got.get_parents(node))
+                sorted(expected.get_parents(node)), sorted(got.get_parents(node))
             )
             cpds_expected = expected.get_cpds(node=node)
             cpds_got = got.get_cpds(node=node)
-            np_test.assert_array_equal(cpds_expected.values, cpds_got.values)
+            self.assertEqual(cpds_expected, cpds_got)

pip install -e .[all]
parse_log_pytest
requirements.txt
pytest pytest-cov
3.6
requirements/runtime.txt requirements/tests.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
black==22.8.0
certifi==2021.5.30
charset-normalizer==2.0.12
click==8.0.4
codecov==2.1.13
coverage==6.2
dataclasses==0.8
decorator==4.4.2
idna==3.10
importlib-metadata==4.8.3
importlib-resources==5.4.0
iniconfig==1.1.1
joblib==1.1.1
mock==5.2.0
mypy-extensions==1.0.0
networkx==2.5.1
numpy==1.19.5
packaging==21.3
pandas==1.1.5
pathspec==0.9.0
patsy==1.0.1
-e git+https://github.com/pgmpy/pgmpy.git@c37dda4401f23ec73fc5d17d957867cd62e588d3#egg=pgmpy
platformdirs==2.4.0
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.27.1
scipy==1.5.4
six==1.17.0
statsmodels==0.12.2
tomli==1.2.3
torch==1.10.2
tqdm==4.64.1
typed-ast==1.5.5
typing_extensions==4.1.1
urllib3==1.26.20
xdoctest==1.1.6
zipp==3.6.0

name: pgmpy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - black==22.8.0
      - charset-normalizer==2.0.12
      - click==8.0.4
      - codecov==2.1.13
      - coverage==6.2
      - dataclasses==0.8
      - decorator==4.4.2
      - idna==3.10
      - importlib-metadata==4.8.3
      - importlib-resources==5.4.0
      - iniconfig==1.1.1
      - joblib==1.1.1
      - mock==5.2.0
      - mypy-extensions==1.0.0
      - networkx==2.5.1
      - numpy==1.19.5
      - packaging==21.3
      - pandas==1.1.5
      - pathspec==0.9.0
      - patsy==1.0.1
      - platformdirs==2.4.0
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.27.1
      - scipy==1.5.4
      - six==1.17.0
      - statsmodels==0.12.2
      - tomli==1.2.3
      - torch==1.10.2
      - tqdm==4.64.1
      - typed-ast==1.5.5
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - xdoctest==1.1.6
      - zipp==3.6.0
prefix: /opt/conda/envs/pgmpy

pgmpy/tests/test_readwrite/test_BIF.py::TestBIFWriter::test_str pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFWriterMethodsString::test_write_xmlbif_stateless
pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_edges pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_model pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_parents pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_property pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_values pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_values_reordered pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_get_variables pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_network_name pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_states pgmpy/tests/test_readwrite/test_BIF.py::TestBIFReader::test_water_model pgmpy/tests/test_readwrite/test_BIF.py::TestBIFWriter::test_write_read_equal pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_get_edges pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_get_parents pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_get_property pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_get_states pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_get_values pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_get_variables pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethods::test_model pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_get_edges pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_get_parents pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_get_property pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_get_states pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_get_values pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_get_variables pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFReaderMethodsFile::test_model pgmpy/tests/test_readwrite/test_XMLBIF.py::TestXMLBIFWriterMethodsString::test_write_xmlbif_statefull
pgmpy/readwrite/XMLBIF.py pgmpy/estimators/BayesianEstimator.py pgmpy/readwrite/BIF.py pgmpy/estimators/MLE.py
pgmpy/readwrite/XMLBIF.py pgmpy/estimators/BayesianEstimator.py pgmpy/readwrite/BIF.py pgmpy/estimators/MLE.py