#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import unittest
import warnings
import json
import io

import numpy as np
import numpy.testing as np_test
import networkx as nx

from pgmpy.readwrite import ProbModelXMLReader, ProbModelXMLWriter, get_probmodel_data
from pgmpy.models import BayesianModel
from pgmpy.factors.discrete import TabularCPD

try:
    from lxml import etree
except ImportError:
    try:
        import xml.etree.cElementTree as etree
    except ImportError:
        try:
            import xml.etree.ElementTree as etree

            print("running with ElementTree on Python 2.5+")
        except ImportError:
            warnings.warn("Failed to import ElementTree from any known place")


class TestProbModelXMLReaderString(unittest.TestCase):
    def setUp(self):
        string = """<ProbModelXML formatVersion="1.0">
      <ProbNet type="BayesianNetwork">
        <AdditionalConstraints>
            <Constraint name="MaxNumParents">
                <Argument name="numParents" value="5" />
            </Constraint>
        </AdditionalConstraints>
        <Comment>Student example model from Probabilistic Graphical Models: Principles and Techniques by Daphne Koller</Comment>
        <Language>English</Language>
        <AdditionalProperties>
            <Property name="elvira.title" value="X ray result"/>
        </AdditionalProperties>
        <DecisionCriteria>
            <Criterion name="cost">
                <AdditionalProperties/>
            </Criterion>
            <Criterion name="effectiveness">
                <AdditionalProperties/>
            </Criterion>
        </DecisionCriteria>
        <Variables>
            <Variable name="intelligence" type="FiniteState" role="Chance">
                <Comment />
                <Coordinates />
                <AdditionalProperties />
                <States>
                    <State name="smart"><AdditionalProperties /></State>
                    <State name="dumb"><AdditionalProperties /></State>
                </States>
            </Variable>
            <Variable name="difficulty" type="FiniteState" role="Chance">
                <Comment />
                <Coordinates />
                <AdditionalProperties />
                <States>
                    <State name="difficult"><AdditionalProperties /></State>
                    <State name="easy"><AdditionalProperties /></State>
                </States>
            </Variable>
        </Variables>
        <Links>
            <Link directed="1">
                <Variable name="difficulty" />
                <Variable name="grade" />
                <Comment>Directed Edge from difficulty to grade</Comment>
                <Label>diff_to_grad</Label>
                <AdditionalProperties />
            </Link>
            <Link directed="1">
                <Variable name="intelligence" />
                <Variable name="grade" />
                <Comment>Directed Edge from intelligence to grade</Comment>
                <Label>intel_to_grad</Label>
                <AdditionalProperties />
            </Link>
            <Link directed="1">
                <Variable name="intelligence" />
                <Variable name="SAT" />
                <Comment>Directed Edge from intelligence to SAT</Comment>
                <Label>intel_to_sat</Label>
                <AdditionalProperties />
            </Link>
            <Link directed="1">
                <Variable name="grade" />
                <Variable name="recommendation_letter" />
                <Comment>Directed Edge from grade to recommendation_letter</Comment>
                <Label>grad_to_reco</Label>
                <AdditionalProperties />
            </Link>
        </Links>
        <Potentials>
          <Potential type="Tree/ADD" role="Utility">
                <UtilityVariable name="U1" />
                <Variables>
                    <Variable name="D0"/>
                    <Variable name="D1"/>
                    <Variable name="C0"/>
                    <Variable name="C1"/>
                 </Variables>
                <TopVariable name="D0"/>
                <Branches>
                   <Branch>
                      <States><State name="no"/></States>
                      <Potential type="Tree/ADD">
                         <TopVariable name="C1"/>
                         <Branches>
                              <Branch>
                                  <Thresholds>
                                       <Threshold value="–Infinity"/>
                                       <Threshold value="0" belongsTo="Left"/>
                                  </Thresholds>
                                  <Potential type="MixtureOfExponentials">
                                      <Variables>
                                         <Variable name="C0"/>
                                         <Variable name="C1"/>
                                      </Variables>
                                      <Subpotentials>
                                         <Potential type="Exponential">
                                             <Potential type="Table">
                                                  <Values>3</Values>
                                              </Potential>
                                          </Potential>
                                          <Potential type="Exponential">
                                              <Potential type="Table">
                                                  <Values>–1</Values>
                                              </Potential>
                                              <NumericVariables>
                                                  <Variable name="C0"/>
                                                  <Variable name="C1"/>
                                              </NumericVariables>
                                              <Coefficients>4 –1</Coefficients>
                                           </Potential>
                                      </Subpotentials>
                                 </Potential>
                              </Branch>
                              <Branch>
                                    <Thresholds>
                                        <Threshold value="0" belongsTo="Left" />
                                        <Threshold value="+Infinity" />
                                     </Thresholds>
                                     <Potential type="MixtureOfExponentials">
                                        <Variables>
                                              <Variable name="C1"/>
                                              <Variable name="D1"/>
                                        </Variables>
                                        <Subpotentials>
                                              <Potential type="Exponential">
                                                 <Potential type="Table">
                                                      <Variables>
                                                          <Variable name="D1"/>
                                                      </Variables>
                                                      <Values>10  5</Values>
                                                 </Potential>
                                                 <NumericVariables>
                                                    <Variable name="C1"/>
                                                 </NumericVariables>
                                                 <Coefficients>0.25</Coefficients>
                                              </Potential>
                                         </Subpotentials>
                                     </Potential>
                              </Branch>
                         </Branches>
                      </Potential>
                   </Branch>
                  <Branch>
                        <States>
                            <State name="yes"/>
                         </States>
                         <Potential type="MixtureOfExponentials">
                                <Variables>
                                    <Variable name="C0"/>
                                </Variables>
                                <Subpotentials>
                                    <Potential type="Exponential">
                                        <Potential type="Table">
                                             <Values>0.3</Values>
                                        </Potential>
                                        <NumericVariables>
                                             <Variable name="C0"/>
                                        </NumericVariables>
                                        <Coefficients>1</Coefficients>
                                    </Potential>
                                   <Potential type="Exponential">
                                        <Potential type="Table">
                                             <Values>0.7</Values>
                                        </Potential>
                                   </Potential>
                                </Subpotentials>
                         </Potential>
                  </Branch>
                </Branches>
          </Potential>
      </Potentials>
    </ProbNet>
    <Policies />
    <InferenceOptions />
</ProbModelXML>
"""
        self.maxDiff = None
        self.reader_string = ProbModelXMLReader(string=string)
        self.reader_file = ProbModelXMLReader(path=io.StringIO(string))

    def test_comment(self):
        comment_expected = (
            "Student example model from Probabilistic Graphical Models: "
            "Principles and Techniques by Daphne Koller"
        )
        self.assertEqual(self.reader_string.probnet["Comment"], comment_expected)
        self.assertEqual(self.reader_file.probnet["Comment"], comment_expected)

    def test_variables(self):
        variables = {
            "difficulty": {
                "Comment": None,
                "Coordinates": {},
                "role": "Chance",
                "type": "FiniteState",
                "States": {"difficult": {}, "easy": {}},
            },
            "intelligence": {
                "Comment": None,
                "Coordinates": {},
                "role": "Chance",
                "type": "FiniteState",
                "States": {"smart": {}, "dumb": {}},
            },
        }
        self.assertDictEqual(self.reader_string.probnet["Variables"], variables)
        self.assertDictEqual(self.reader_file.probnet["Variables"], variables)

    def test_edges(self):
        edge = {
            ("grade", "recommendation_letter"): {
                "directed": "1",
                "Comment": "Directed Edge from grade to recommendation_letter",
                "Label": "grad_to_reco",
            },
            ("intelligence", "grade"): {
                "directed": "1",
                "Comment": "Directed Edge from intelligence to grade",
                "Label": "intel_to_grad",
            },
            ("difficulty", "grade"): {
                "directed": "1",
                "Comment": "Directed Edge from difficulty to grade",
                "Label": "diff_to_grad",
            },
            ("intelligence", "SAT"): {
                "directed": "1",
                "Comment": "Directed Edge from intelligence to SAT",
                "Label": "intel_to_sat",
            },
        }
        self.assertDictEqual(self.reader_string.probnet["edges"], edge)
        self.assertDictEqual(self.reader_file.probnet["edges"], edge)

    def test_additionalconstraints(self):
        additionalconstraints_expected = {"MaxNumParents": {"numParents": "5"}}
        self.assertDictEqual(
            self.reader_string.probnet["AdditionalConstraints"],
            additionalconstraints_expected,
        )
        self.assertDictEqual(
            self.reader_file.probnet["AdditionalConstraints"],
            additionalconstraints_expected,
        )

    def test_additionalproperties(self):
        additionalproperties_expected = {"elvira.title": "X ray result"}
        self.assertDictEqual(
            self.reader_string.probnet["AdditionalProperties"],
            additionalproperties_expected,
        )
        self.assertDictEqual(
            self.reader_file.probnet["AdditionalProperties"],
            additionalproperties_expected,
        )

    def test_decisioncriteria(self):
        decisioncriteria_expected = {"effectiveness": {}, "cost": {}}
        self.assertDictEqual(
            self.reader_string.probnet["DecisionCriteria"], decisioncriteria_expected
        )
        self.assertDictEqual(
            self.reader_file.probnet["DecisionCriteria"], decisioncriteria_expected
        )

    def test_potential(self):
        potential_expected = [
            {
                "role": "Utility",
                "Variables": {"D0": ["D1", "C0", "C1"]},
                "type": "Tree/ADD",
                "UtilityVaribale": "U1",
                "Branches": [
                    {
                        "Potential": {
                            "type": "Tree/ADD",
                            "Branches": [
                                {
                                    "Thresholds": [
                                        {"value": u"–Infinity"},
                                        {"value": "0", "belongsTo": "Left"},
                                    ],
                                    "Potential": {
                                        "Subpotentials": [
                                            {
                                                "Potential": {
                                                    "type": "Table",
                                                    "Values": "3",
                                                },
                                                "type": "Exponential",
                                            },
                                            {
                                                "NumericVariables": ["C0", "C1"],
                                                "Potential": {
                                                    "type": "Table",
                                                    "Values": u"–1",
                                                },
                                                "Coefficients": u"4 –1",
                                                "type": "Exponential",
                                            },
                                        ],
                                        "Variables": {"C0": ["C1"]},
                                        "type": "MixtureOfExponentials",
                                    },
                                },
                                {
                                    "Thresholds": [
                                        {"value": "0", "belongsTo": "Left"},
                                        {"value": "+Infinity"},
                                    ],
                                    "Potential": {
                                        "Subpotentials": [
                                            {
                                                "NumericVariables": ["C1"],
                                                "Potential": {
                                                    "Variables": {"D1": []},
                                                    "type": "Table",
                                                    "Values": "10  5",
                                                },
                                                "Coefficients": "0.25",
                                                "type": "Exponential",
                                            }
                                        ],
                                        "Variables": {"C1": ["D1"]},
                                        "type": "MixtureOfExponentials",
                                    },
                                },
                            ],
                            "TopVariable": "C1",
                        },
                        "States": [{"name": "no"}],
                    },
                    {
                        "Potential": {
                            "Subpotentials": [
                                {
                                    "NumericVariables": ["C0"],
                                    "Potential": {"type": "Table", "Values": "0.3"},
                                    "Coefficients": "1",
                                    "type": "Exponential",
                                },
                                {
                                    "Potential": {"type": "Table", "Values": "0.7"},
                                    "type": "Exponential",
                                },
                            ],
                            "Variables": {"C0": []},
                            "type": "MixtureOfExponentials",
                        },
                        "States": [{"name": "yes"}],
                    },
                ],
                "TopVariable": "D0",
            }
        ]

        self.assertListEqual(
            self.reader_string.probnet["Potentials"], potential_expected
        )
        self.assertListEqual(self.reader_file.probnet["Potentials"], potential_expected)

    def test_get_model(self):
        string = """<ProbModelXML formatVersion="0.2.0">
  <ProbNet type="BayesianNetwork">
    <Comment>Student example model from Probabilistic Graphical Models: Principles and Techniques by Daphne Koller</Comment>
    <Variables>
      <Variable name="X-ray" type="finiteStates" role="chance" isInput="false">
        <Comment><![CDATA[Indica si el test de rayos X ha sido positivo]]></Comment>
        <Coordinates x="252" y="322" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="X" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="Bronchitis" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="698" y="181" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="B" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="Dyspnea" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="533" y="321" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="D" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="VisitToAsia" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="290" y="58" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="A" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="Smoker" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="568" y="52" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="S" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="LungCancer" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="421" y="152" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="L" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="Tuberculosis" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="201" y="150" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="T" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
      <Variable name="TuberculosisOrCancer" type="finiteStates" role="chance" isInput="false">
        <Coordinates x="336" y="238" />
        <AdditionalProperties>
          <Property name="Relevance" value="7.0" />
          <Property name="Title" value="E" />
        </AdditionalProperties>
        <Precision>0.01</Precision>
        <States>
          <State name="no" />
          <State name="yes" />
        </States>
      </Variable>
    </Variables>
    <Links>
      <Link directed="true">
        <Variable name="Bronchitis" />
        <Variable name="Dyspnea" />
      </Link>
      <Link directed="true">
        <Variable name="VisitToAsia" />
        <Variable name="Tuberculosis" />
      </Link>
      <Link directed="true">
        <Variable name="Smoker" />
        <Variable name="Bronchitis" />
      </Link>
      <Link directed="true">
        <Variable name="Smoker" />
        <Variable name="LungCancer" />
      </Link>
      <Link directed="true">
        <Variable name="LungCancer" />
        <Variable name="TuberculosisOrCancer" />
      </Link>
      <Link directed="true">
        <Variable name="Tuberculosis" />
        <Variable name="TuberculosisOrCancer" />
      </Link>
      <Link directed="true">
        <Variable name="TuberculosisOrCancer" />
        <Variable name="Dyspnea" />
      </Link>
      <Link directed="true">
        <Variable name="TuberculosisOrCancer" />
        <Variable name="X-ray" />
      </Link>
    </Links>
    <Potentials>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="X-ray" />
          <Variable name="TuberculosisOrCancer" />
        </Variables>
        <Values>0.95 0.05 0.02 0.98</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="Bronchitis" />
          <Variable name="Smoker" />
        </Variables>
        <Values>0.7 0.3 0.4 0.6</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="Dyspnea" />
          <Variable name="TuberculosisOrCancer" />
          <Variable name="Bronchitis" />
        </Variables>
        <Values>0.9 0.1 0.3 0.7 0.2 0.8 0.1 0.9</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="VisitToAsia" />
        </Variables>
        <Values>0.99 0.01</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="Smoker" />
        </Variables>
        <Values>0.5 0.5</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="LungCancer" />
          <Variable name="Smoker" />
        </Variables>
        <Values>0.99 0.01 0.9 0.1</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="Tuberculosis" />
          <Variable name="VisitToAsia" />
        </Variables>
        <Values>0.99 0.01 0.95 0.05</Values>
      </Potential>
      <Potential type="Table" role="conditionalProbability">
        <Variables>
          <Variable name="TuberculosisOrCancer" />
          <Variable name="LungCancer" />
          <Variable name="Tuberculosis" />
        </Variables>
        <Values>1.0 0.0 0.0 1.0 0.0 1.0 0.0 1.0</Values>
      </Potential>
    </Potentials>
    <AdditionalProperties>
      <Property name="VisualPrecision" value="0.0" />
      <Property name="KindOfGraph" value="directed" />
      <Property name="WhenChanged" value="19/08/99" />
      <Property name="Version" value="1.0" />
      <Property name="WhoChanged" value="Jose A. Gamez" />
    </AdditionalProperties>
  </ProbNet>
</ProbModelXML>"""
        self.maxDiff = None
        self.reader = ProbModelXMLReader(string=string)
        model = self.reader.get_model()
        edges_expected = [
            ("VisitToAsia", "Tuberculosis"),
            ("LungCancer", "TuberculosisOrCancer"),
            ("Smoker", "LungCancer"),
            ("Smoker", "Bronchitis"),
            ("Tuberculosis", "TuberculosisOrCancer"),
            ("Bronchitis", "Dyspnea"),
            ("TuberculosisOrCancer", "Dyspnea"),
            ("TuberculosisOrCancer", "X-ray"),
        ]
        node_expected = {
            "Smoker": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "52", "x": "568"},
                "AdditionalProperties": {"Title": "S", "Relevance": "7.0"},
                "weight": None,
            },
            "Bronchitis": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "181", "x": "698"},
                "AdditionalProperties": {"Title": "B", "Relevance": "7.0"},
                "weight": None,
            },
            "VisitToAsia": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "58", "x": "290"},
                "AdditionalProperties": {"Title": "A", "Relevance": "7.0"},
                "weight": None,
            },
            "Tuberculosis": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "150", "x": "201"},
                "AdditionalProperties": {"Title": "T", "Relevance": "7.0"},
                "weight": None,
            },
            "X-ray": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "AdditionalProperties": {"Title": "X", "Relevance": "7.0"},
                "Coordinates": {"y": "322", "x": "252"},
                "Comment": "Indica si el test de rayos X ha sido positivo",
                "type": "finiteStates",
                "weight": None,
            },
            "Dyspnea": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "321", "x": "533"},
                "AdditionalProperties": {"Title": "D", "Relevance": "7.0"},
                "weight": None,
            },
            "TuberculosisOrCancer": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "238", "x": "336"},
                "AdditionalProperties": {"Title": "E", "Relevance": "7.0"},
                "weight": None,
            },
            "LungCancer": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "152", "x": "421"},
                "AdditionalProperties": {"Title": "L", "Relevance": "7.0"},
                "weight": None,
            },
        }
        edge_expected = {
            "LungCancer": {
                "TuberculosisOrCancer": {"weight": None, "directed": "true"}
            },
            "Smoker": {
                "LungCancer": {"weight": None, "directed": "true"},
                "Bronchitis": {"weight": None, "directed": "true"},
            },
            "Dyspnea": {},
            "X-ray": {},
            "VisitToAsia": {"Tuberculosis": {"weight": None, "directed": "true"}},
            "TuberculosisOrCancer": {
                "X-ray": {"weight": None, "directed": "true"},
                "Dyspnea": {"weight": None, "directed": "true"},
            },
            "Bronchitis": {"Dyspnea": {"weight": None, "directed": "true"}},
            "Tuberculosis": {
                "TuberculosisOrCancer": {"weight": None, "directed": "true"}
            },
        }

        cpds_expected = [
            np.array([[0.95, 0.05], [0.02, 0.98]]),
            np.array([[0.7, 0.3], [0.4, 0.6]]),
            np.array([[0.9, 0.1, 0.3, 0.7], [0.2, 0.8, 0.1, 0.9]]),
            np.array([[0.99], [0.01]]),
            np.array([[0.5], [0.5]]),
            np.array([[0.99, 0.01], [0.9, 0.1]]),
            np.array([[0.99, 0.01], [0.95, 0.05]]),
            np.array([[1, 0, 0, 1], [0, 1, 0, 1]]),
        ]
        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]
            )
        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.assertListEqual(sorted(model.edges()), sorted(edges_expected))


class TestProbModelXMLWriter(unittest.TestCase):
    def setUp(self):
        self.model_data = {
            "probnet": {
                "type": "BayesianNetwork",
                "Language": "English",
                "AdditionalConstraints": {"MaxNumParents": {"numParents": "5"}},
                "AdditionalProperties": {"elvira.title": "X ray result"},
                "DecisionCriteria": {"effectiveness": {}, "cost": {}},
                "Variables": {
                    "difficulty": {
                        "type": "FiniteState",
                        "role": "Chance",
                        "States": {"difficult": {}, "easy": {}},
                        "Comment": None,
                        "Coordinates": {},
                    },
                    "intelligence": {
                        "type": "FiniteState",
                        "role": "Chance",
                        "States": {"smart": {}, "dumb": {}},
                        "Comment": None,
                        "Coordinates": {},
                    },
                },
                "Comment": "Student example model from Probabilistic Graphical Models: "
                "Principles and Techniques by Daphne Koller",
                "edges": {
                    ("difficulty", "grade"): {
                        "directed": "1",
                        "Label": "diff_to_grad",
                        "Comment": "Directed Edge from difficulty to grade",
                    },
                    ("intelligence", "grade"): {
                        "directed": "1",
                        "Label": "intel_to_grad",
                        "Comment": "Directed Edge from intelligence to grade",
                    },
                    ("intelligence", "SAT"): {
                        "directed": "1",
                        "Label": "intel_to_sat",
                        "Comment": "Directed Edge from intelligence to SAT",
                    },
                    ("grade", "recommendation_letter"): {
                        "directed": "1",
                        "Label": "grad_to_reco",
                        "Comment": "Directed Edge from grade to recommendation_letter",
                    },
                },
                "Potentials": [
                    {
                        "role": "Utility",
                        "Variables": {"D0": ["D1", "C0", "C1"]},
                        "type": "Tree/ADD",
                        "UtilityVaribale": "U1",
                        "Branches": [
                            {
                                "Potential": {
                                    "type": "Tree/ADD",
                                    "Branches": [
                                        {
                                            "Thresholds": [
                                                {"value": "-Infinity"},
                                                {"value": "0", "belongsTo": "Left"},
                                            ],
                                            "Potential": {
                                                "Subpotentials": [
                                                    {
                                                        "Potential": {
                                                            "type": "Table",
                                                            "Values": "3",
                                                        },
                                                        "type": "Exponential",
                                                    },
                                                    {
                                                        "NumericVariables": [
                                                            "C0",
                                                            "C1",
                                                        ],
                                                        "Potential": {
                                                            "type": "Table",
                                                            "Values": "-1",
                                                        },
                                                        "Coefficients": "4 -1",
                                                        "type": "Exponential",
                                                    },
                                                ],
                                                "Variables": {"C0": ["C1"]},
                                                "type": "MixtureOfExponentials",
                                            },
                                        },
                                        {
                                            "Thresholds": [
                                                {"value": "0", "belongsTo": "Left"},
                                                {"value": "+Infinity"},
                                            ],
                                            "Potential": {
                                                "Subpotentials": [
                                                    {
                                                        "NumericVariables": ["C1"],
                                                        "Potential": {
                                                            "Variables": {"D1": []},
                                                            "type": "Table",
                                                            "Values": "10  5",
                                                        },
                                                        "Coefficients": "0.25",
                                                        "type": "Exponential",
                                                    }
                                                ],
                                                "Variables": {"C1": ["D1"]},
                                                "type": "MixtureOfExponentials",
                                            },
                                        },
                                    ],
                                    "TopVariable": "C1",
                                },
                                "States": [{"name": "no"}],
                            },
                            {
                                "Potential": {
                                    "Subpotentials": [
                                        {
                                            "NumericVariables": ["C0"],
                                            "Potential": {
                                                "type": "Table",
                                                "Values": "0.3",
                                            },
                                            "Coefficients": "1",
                                            "type": "Exponential",
                                        },
                                        {
                                            "Potential": {
                                                "type": "Table",
                                                "Values": "0.7",
                                            },
                                            "type": "Exponential",
                                        },
                                    ],
                                    "Variables": {"C0": []},
                                    "type": "MixtureOfExponentials",
                                },
                                "States": [{"name": "yes"}],
                            },
                        ],
                        "TopVariable": "D0",
                    }
                ],
            }
        }

        self.maxDiff = None
        self.writer = ProbModelXMLWriter(model_data=self.model_data)

    def test_file(self):
        self.expected_xml = etree.XML(
            """<ProbModelXML formatVersion="1.0">
  <ProbNet type="BayesianNetwork">
    <Variables>
      <Variable name="difficulty" role="Chance" type="FiniteState">
        <Comment/>
        <Coordinates/>
        <AdditionalProperties/>
        <States>
          <State name="difficult">
            <AdditionalProperties/>
          </State>
          <State name="easy">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="intelligence" role="Chance" type="FiniteState">
        <Comment/>
        <Coordinates/>
        <AdditionalProperties/>
        <States>
          <State name="dumb">
            <AdditionalProperties/>
          </State>
          <State name="smart">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
    </Variables>
    <Links>
      <Link directed="1" var1="difficulty" var2="grade">
        <Comment>Directed Edge from difficulty to grade</Comment>
        <Label>diff_to_grad</Label>
        <AdditionalProperties/>
      </Link>
      <Link directed="1" var1="grade" var2="recommendation_letter">
        <Comment>Directed Edge from grade to recommendation_letter</Comment>
        <Label>grad_to_reco</Label>
        <AdditionalProperties/>
      </Link>
      <Link directed="1" var1="intelligence" var2="SAT">
        <Comment>Directed Edge from intelligence to SAT</Comment>
        <Label>intel_to_sat</Label>
        <AdditionalProperties/>
      </Link>
      <Link directed="1" var1="intelligence" var2="grade">
        <Comment>Directed Edge from intelligence to grade</Comment>
        <Label>intel_to_grad</Label>
        <AdditionalProperties/>
      </Link>
    </Links>
    <Potentials>
      <Potential role="Utility" type="Tree/ADD">
        <Variables>
          <Variable name="D0"/>
          <Variable name="C0"/>
          <Variable name="C1"/>
          <Variable name="D1"/>
        </Variables>
        <TopVariable name="D0"/>
        <Branches>
          <Branch>
            <States>
              <State name="no"/>
            </States>
            <Potential type="Tree/ADD">
              <TopVariable name="C1"/>
              <Branches>
                <Branch>
                  <Potential type="MixtureOfExponentials">
                    <Variables>
                      <Variable name="C0"/>
                      <Variable name="C1"/>
                    </Variables>
                    <Subpotentials>
                      <Potential type="Exponential">
                        <Potential type="Table">
                          <Values>3</Values>
                        </Potential>
                      </Potential>
                      <Potential type="Exponential">
                        <Coefficients>4 -1</Coefficients>
                        <Potential type="Table">
                          <Values>-1</Values>
                        </Potential>
                        <NumericVariables>
                          <Variable name="C0"/>
                          <Variable name="C1"/>
                        </NumericVariables>
                      </Potential>
                    </Subpotentials>
                  </Potential>
                  <Thresholds>
                    <Threshold value="-Infinity"/>
                    <Threshold belongsTo="Left" value="0"/>
                  </Thresholds>
                </Branch>
                <Branch>
                  <Potential type="MixtureOfExponentials">
                    <Variables>
                      <Variable name="C1"/>
                      <Variable name="D1"/>
                    </Variables>
                    <Subpotentials>
                      <Potential type="Exponential">
                        <Coefficients>0.25</Coefficients>
                        <Potential type="Table">
                          <Variables>
                            <Variable name="D1"/>
                          </Variables>
                          <Values>10  5</Values>
                        </Potential>
                        <NumericVariables>
                          <Variable name="C1"/>
                        </NumericVariables>
                      </Potential>
                    </Subpotentials>
                  </Potential>
                  <Thresholds>
                    <Threshold belongsTo="Left" value="0"/>
                    <Threshold value="+Infinity"/>
                  </Thresholds>
                </Branch>
              </Branches>
            </Potential>
          </Branch>
          <Branch>
            <States>
              <State name="yes"/>
            </States>
            <Potential type="MixtureOfExponentials">
              <Variables>
                <Variable name="C0"/>
              </Variables>
              <Subpotentials>
                <Potential type="Exponential">
                  <Coefficients>1</Coefficients>
                  <Potential type="Table">
                    <Values>0.3</Values>
                  </Potential>
                  <NumericVariables>
                    <Variable name="C0"/>
                  </NumericVariables>
                </Potential>
                <Potential type="Exponential">
                  <Potential type="Table">
                    <Values>0.7</Values>
                  </Potential>
                </Potential>
              </Subpotentials>
            </Potential>
          </Branch>
        </Branches>
      </Potential>
    </Potentials>
    <AdditionalConstraints>
      <Constraint name="MaxNumParents">
        <Argument name="numParents" value="5"/>
      </Constraint>
    </AdditionalConstraints>
    <Language>English</Language>
    <Comment>Student example model from Probabilistic Graphical Models: Principles and Techniques by Daphne Koller</Comment>
  </ProbNet>
  <AdditionalProperties>
    <Property name="elvira.title" value="X ray result"/>
  </AdditionalProperties>
  <DecisionCriteria>
    <Criterion name="cost">
      <AdditionalProperties/>
    </Criterion>
    <Criterion name="effectiveness">
      <AdditionalProperties/>
    </Criterion>
  </DecisionCriteria>
</ProbModelXML>"""
        )
        self.assertEqual(
            str(self.writer.__str__()[:-1]), str(etree.tostring(self.expected_xml))
        )

    def test_write_file(self):
        self.expected_xml = etree.XML(
            """<ProbModelXML formatVersion="1.0">
  <ProbNet type="BayesianNetwork">
    <Variables>
      <Variable name="difficulty" role="Chance" type="FiniteState">
        <Comment/>
        <Coordinates/>
        <AdditionalProperties/>
        <States>
          <State name="difficult">
            <AdditionalProperties/>
          </State>
          <State name="easy">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="intelligence" role="Chance" type="FiniteState">
        <Comment/>
        <Coordinates/>
        <AdditionalProperties/>
        <States>
          <State name="dumb">
            <AdditionalProperties/>
          </State>
          <State name="smart">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
    </Variables>
    <Links>
      <Link directed="1" var1="difficulty" var2="grade">
        <Comment>Directed Edge from difficulty to grade</Comment>
        <Label>diff_to_grad</Label>
        <AdditionalProperties/>
      </Link>
      <Link directed="1" var1="grade" var2="recommendation_letter">
        <Comment>Directed Edge from grade to recommendation_letter</Comment>
        <Label>grad_to_reco</Label>
        <AdditionalProperties/>
      </Link>
      <Link directed="1" var1="intelligence" var2="SAT">
        <Comment>Directed Edge from intelligence to SAT</Comment>
        <Label>intel_to_sat</Label>
        <AdditionalProperties/>
      </Link>
      <Link directed="1" var1="intelligence" var2="grade">
        <Comment>Directed Edge from intelligence to grade</Comment>
        <Label>intel_to_grad</Label>
        <AdditionalProperties/>
      </Link>
    </Links>
    <Potentials>
      <Potential role="Utility" type="Tree/ADD">
        <Variables>
          <Variable name="D0"/>
          <Variable name="C0"/>
          <Variable name="C1"/>
          <Variable name="D1"/>
        </Variables>
        <TopVariable name="D0"/>
        <Branches>
          <Branch>
            <States>
              <State name="no"/>
            </States>
            <Potential type="Tree/ADD">
              <TopVariable name="C1"/>
              <Branches>
                <Branch>
                  <Potential type="MixtureOfExponentials">
                    <Variables>
                      <Variable name="C0"/>
                      <Variable name="C1"/>
                    </Variables>
                    <Subpotentials>
                      <Potential type="Exponential">
                        <Potential type="Table">
                          <Values>3</Values>
                        </Potential>
                      </Potential>
                      <Potential type="Exponential">
                        <Coefficients>4 -1</Coefficients>
                        <Potential type="Table">
                          <Values>-1</Values>
                        </Potential>
                        <NumericVariables>
                          <Variable name="C0"/>
                          <Variable name="C1"/>
                        </NumericVariables>
                      </Potential>
                    </Subpotentials>
                  </Potential>
                  <Thresholds>
                    <Threshold value="-Infinity"/>
                    <Threshold belongsTo="Left" value="0"/>
                  </Thresholds>
                </Branch>
                <Branch>
                  <Potential type="MixtureOfExponentials">
                    <Variables>
                      <Variable name="C1"/>
                      <Variable name="D1"/>
                    </Variables>
                    <Subpotentials>
                      <Potential type="Exponential">
                        <Coefficients>0.25</Coefficients>
                        <Potential type="Table">
                          <Variables>
                            <Variable name="D1"/>
                          </Variables>
                          <Values>10  5</Values>
                        </Potential>
                        <NumericVariables>
                          <Variable name="C1"/>
                        </NumericVariables>
                      </Potential>
                    </Subpotentials>
                  </Potential>
                  <Thresholds>
                    <Threshold belongsTo="Left" value="0"/>
                    <Threshold value="+Infinity"/>
                  </Thresholds>
                </Branch>
              </Branches>
            </Potential>
          </Branch>
          <Branch>
            <States>
              <State name="yes"/>
            </States>
            <Potential type="MixtureOfExponentials">
              <Variables>
                <Variable name="C0"/>
              </Variables>
              <Subpotentials>
                <Potential type="Exponential">
                  <Coefficients>1</Coefficients>
                  <Potential type="Table">
                    <Values>0.3</Values>
                  </Potential>
                  <NumericVariables>
                    <Variable name="C0"/>
                  </NumericVariables>
                </Potential>
                <Potential type="Exponential">
                  <Potential type="Table">
                    <Values>0.7</Values>
                  </Potential>
                </Potential>
              </Subpotentials>
            </Potential>
          </Branch>
        </Branches>
      </Potential>
    </Potentials>
    <AdditionalConstraints>
      <Constraint name="MaxNumParents">
        <Argument name="numParents" value="5"/>
      </Constraint>
    </AdditionalConstraints>
    <Language>English</Language>
    <Comment>Student example model from Probabilistic Graphical Models: Principles and Techniques by Daphne Koller</Comment>
  </ProbNet>
  <AdditionalProperties>
    <Property name="elvira.title" value="X ray result"/>
  </AdditionalProperties>
  <DecisionCriteria>
    <Criterion name="cost">
      <AdditionalProperties/>
    </Criterion>
    <Criterion name="effectiveness">
      <AdditionalProperties/>
    </Criterion>
  </DecisionCriteria>
</ProbModelXML>"""
        )
        self.writer.write_file("test_xml.pgmx")
        with open("test_xml.pgmx", "r") as myfile:
            data = myfile.read()
        self.assertEqual(
            str(self.writer.__str__()[:-1]), str(etree.tostring(self.expected_xml))
        )
        self.assertEqual(
            str(data), str(etree.tostring(self.expected_xml).decode("utf-8"))
        )

    def tearDown(self):
        try:
            os.remove("test_xml.pgmx")
        except OSError:
            pass


class TestProbModelXMLmethods(unittest.TestCase):
    def setUp(self):
        variables = [
            "VisitToAsia",
            "Tuberculosis",
            "Smoker",
            "LungCancer",
            "Bronchitis",
            "Dyspnea",
            "TuberculosisOrCancer",
            "X-ray",
            "Sinus",
        ]

        edges_list = [
            ("VisitToAsia", "Tuberculosis"),
            ("LungCancer", "TuberculosisOrCancer"),
            ("Smoker", "LungCancer"),
            ("Smoker", "Bronchitis"),
            ("Tuberculosis", "TuberculosisOrCancer"),
            ("Bronchitis", "Dyspnea"),
            ("TuberculosisOrCancer", "Dyspnea"),
            ("TuberculosisOrCancer", "X-ray"),
        ]
        nodes = {
            "Smoker": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "52", "x": "568"},
                "AdditionalProperties": {"Title": "S", "Relevance": "7.0"},
            },
            "Bronchitis": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "181", "x": "698"},
                "AdditionalProperties": {"Title": "B", "Relevance": "7.0"},
            },
            "VisitToAsia": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "58", "x": "290"},
                "AdditionalProperties": {"Title": "A", "Relevance": "7.0"},
            },
            "Tuberculosis": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "150", "x": "201"},
                "AdditionalProperties": {"Title": "T", "Relevance": "7.0"},
            },
            "X-ray": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "AdditionalProperties": {"Title": "X", "Relevance": "7.0"},
                "Coordinates": {"y": "322", "x": "252"},
                "Comment": "Indica si el test de rayos X ha sido positivo",
                "type": "finiteStates",
            },
            "Dyspnea": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "321", "x": "533"},
                "AdditionalProperties": {"Title": "D", "Relevance": "7.0"},
            },
            "TuberculosisOrCancer": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "238", "x": "336"},
                "AdditionalProperties": {"Title": "E", "Relevance": "7.0"},
            },
            "LungCancer": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "152", "x": "421"},
                "AdditionalProperties": {"Title": "L", "Relevance": "7.0"},
            },
            "Sinus": {
                "States": {"no": {}, "yes": {}},
                "role": "chance",
                "type": "finiteStates",
                "Coordinates": {"y": "200", "x": "100"},
                "AdditionalProperties": {"Title": "S", "Relevance": "7.0"},
            },
        }
        edges = {
            "LungCancer": {"TuberculosisOrCancer": {"directed": "true"}},
            "Smoker": {
                "LungCancer": {"directed": "true"},
                "Bronchitis": {"directed": "true"},
            },
            "Dyspnea": {},
            "X-ray": {},
            "VisitToAsia": {"Tuberculosis": {"directed": "true"}},
            "TuberculosisOrCancer": {
                "X-ray": {"directed": "true"},
                "Dyspnea": {"directed": "true"},
            },
            "Bronchitis": {"Dyspnea": {"directed": "true"}},
            "Tuberculosis": {"TuberculosisOrCancer": {"directed": "true"}},
        }

        cpds = [
            {
                "Values": np.array([[0.95, 0.05], [0.02, 0.98]]),
                "Variables": {"X-ray": ["TuberculosisOrCancer"]},
            },
            {
                "Values": np.array([[0.7, 0.3], [0.4, 0.6]]),
                "Variables": {"Bronchitis": ["Smoker"]},
            },
            {
                "Values": np.array([[0.9, 0.1, 0.3, 0.7], [0.2, 0.8, 0.1, 0.9]]),
                "Variables": {"Dyspnea": ["TuberculosisOrCancer", "Bronchitis"]},
            },
            {"Values": np.array([[0.99], [0.01]]), "Variables": {"VisitToAsia": []}},
            {"Values": np.array([[0.5], [0.5]]), "Variables": {"Smoker": []}},
            {
                "Values": np.array([[0.99, 0.01], [0.9, 0.1]]),
                "Variables": {"LungCancer": ["Smoker"]},
            },
            {
                "Values": np.array([[0.99, 0.01], [0.95, 0.05]]),
                "Variables": {"Tuberculosis": ["VisitToAsia"]},
            },
            {
                "Values": np.array([[1, 0, 0, 1], [0, 1, 0, 1]]),
                "Variables": {"TuberculosisOrCancer": ["LungCancer", "Tuberculosis"]},
            },
            {"Values": np.array([[0.3], [0.7]]), "Variables": {"Sinus": []}},
        ]
        self.model = BayesianModel()
        self.model.add_nodes_from(variables)
        self.model.add_edges_from(edges_list)

        if nx.__version__.startswith("1"):
            for node in nodes:
                self.model.nodes[node] = nodes[node]
            for edge in edges:
                self.model.edge[edge] = edges[edge]
        else:
            for node in nodes:
                self.model._node[node] = nodes[node]
            for edge in edges:
                self.model._adj[edge] = edges[edge]

        tabular_cpds = []
        for cpd in cpds:
            var = list(cpd["Variables"].keys())[0]
            evidence = cpd["Variables"][var]
            values = cpd["Values"]
            states = len(nodes[var]["States"])
            evidence_card = [
                len(nodes[evidence_var]["States"]) for evidence_var in evidence
            ]
            tabular_cpds.append(
                TabularCPD(var, states, values, evidence, evidence_card)
            )
        self.maxDiff = None
        self.model.add_cpds(*tabular_cpds)

    def test_get_probmodel_data(self):
        model_data = get_probmodel_data(self.model)
        xmlfile = ProbModelXMLWriter(model_data)
        with open(
            "pgmpy/tests/test_readwrite/testdata/test_probmodelxml_data.json"
        ) as data_file:
            model_data_expected = json.load(data_file)
        xmlfile_expected = etree.XML(
            """<ProbModelXML formatVersion="1.0">
  <ProbNet type="BayesianNetwork">
    <Variables>
      <Variable name="Bronchitis" role="chance" type="finiteStates">
        <Coordinates x="698" y="181"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="B"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="Dyspnea" role="chance" type="finiteStates">
        <Coordinates x="533" y="321"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="D"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="LungCancer" role="chance" type="finiteStates">
        <Coordinates x="421" y="152"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="L"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="Sinus" role="chance" type="finiteStates">
        <Coordinates x="100" y="200"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="S"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="Smoker" role="chance" type="finiteStates">
        <Coordinates x="568" y="52"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="S"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="Tuberculosis" role="chance" type="finiteStates">
        <Coordinates x="201" y="150"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="T"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="TuberculosisOrCancer" role="chance" type="finiteStates">
        <Coordinates x="336" y="238"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="E"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="VisitToAsia" role="chance" type="finiteStates">
        <Coordinates x="290" y="58"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="A"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
      <Variable name="X-ray" role="chance" type="finiteStates">
        <Comment>Indica si el test de rayos X ha sido positivo</Comment>
        <Coordinates x="252" y="322"/>
        <Property name="Relevance" value="7.0"/>
        <Property name="Title" value="X"/>
        <States>
          <State name="no">
            <AdditionalProperties/>
          </State>
          <State name="yes">
            <AdditionalProperties/>
          </State>
        </States>
      </Variable>
    </Variables>
    <Links>
      <Link directed="true" var1="Bronchitis" var2="Dyspnea">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="LungCancer" var2="TuberculosisOrCancer">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="Smoker" var2="Bronchitis">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="Smoker" var2="LungCancer">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="Tuberculosis" var2="TuberculosisOrCancer">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="TuberculosisOrCancer" var2="Dyspnea">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="TuberculosisOrCancer" var2="X-ray">
        <AdditionalProperties/>
      </Link>
      <Link directed="true" var1="VisitToAsia" var2="Tuberculosis">
        <AdditionalProperties/>
      </Link>
    </Links>
    <Potentials>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="X-ray"/>
          <Variable name="TuberculosisOrCancer"/>
        </Variables>
        <Values>0.95 0.05 0.02 0.98 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="Bronchitis"/>
          <Variable name="Smoker"/>
        </Variables>
        <Values>0.7 0.3 0.4 0.6 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="Dyspnea"/>
          <Variable name="Bronchitis"/>
          <Variable name="TuberculosisOrCancer"/>
        </Variables>
        <Values>0.9 0.1 0.3 0.7 0.2 0.8 0.1 0.9 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="VisitToAsia"/>
        </Variables>
        <Values>0.99 0.01 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="Smoker"/>
        </Variables>
        <Values>0.5 0.5 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="LungCancer"/>
          <Variable name="Smoker"/>
        </Variables>
        <Values>0.99 0.01 0.9 0.1 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="Tuberculosis"/>
          <Variable name="VisitToAsia"/>
        </Variables>
        <Values>0.99 0.01 0.95 0.05 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="TuberculosisOrCancer"/>
          <Variable name="LungCancer"/>
          <Variable name="Tuberculosis"/>
        </Variables>
        <Values>1.0 0.0 0.0 1.0 0.0 1.0 0.0 1.0 </Values>
      </Potential>
      <Potential role="conditionalProbability" type="Table">
        <Variables>
          <Variable name="Sinus"/>
        </Variables>
        <Values>0.3 0.7 </Values>
      </Potential>
    </Potentials>
    <AdditionalConstraints/>
    <AdditionalProperties/>
    <DecisionCriteria/>
  </ProbNet>
</ProbModelXML>"""
        )
        self.assertDictEqual(model_data, model_data_expected)
        self.assertEqual(
            str(xmlfile.__str__()[:-1]), str(etree.tostring(xmlfile_expected))
        )
