"""
********
UnitTest
BayesNet
********

Method	Checks that
assertEqual(a, b)	a == b
assertNotEqual(a, b)	a != b
assertTrue(x)	bool(x) is True
assertFalse(x)	bool(x) is False
assertIs(a, b)	a is b
assertIsNot(a, b)	a is not b
assertIsNone(x)	x is None
assertIsNotNone(x)	x is not None
assertIn(a, b)	a in b
assertNotIn(a, b)	a not in b
assertIsInstance(a, b)	isinstance(a, b)
assertNotIsInstance(a, b)	not isinstance(a, b)

assertAlmostEqual(a, b)	round(a-b, 7) == 0
assertNotAlmostEqual(a, b)	round(a-b, 7) != 0
assertGreater(a, b)	a > b
assertGreaterEqual(a, b)	a >= b
assertLess(a, b)	a < b
assertLessEqual(a, b)	a <= b

assertListEqual(a, b)	lists
assertTupleEqual(a, b)	tuples
assertSetEqual(a, b)	sets or frozensets
assertDictEqual(a, b)	dicts

"""
__author__ = """Nicholas Cullen <ncullen.th@dartmouth.edu>"""

import unittest
from external.pyBN.classes.bayesnet import BayesNet
from external.pyBN.readwrite.read import read_bn

import os
from os.path import dirname


class BayesNetTestCase(unittest.TestCase):

    def setUp(self):
        self.bn = BayesNet()
        self.dpath = os.path.join(
            dirname(
                dirname(
                    dirname(
                        dirname(__file__)))),
            'data')
        self.bn_bif = read_bn(os.path.join(self.dpath, 'cancer.bif'))
        self.bn_bn = read_bn(os.path.join(self.dpath, 'cmu.bn'))

    def tearDown(self):
        pass

    def test_isinstance(self):
        self.assertIsInstance(self.bn, BayesNet)

    def test_V_bif(self):
        self.assertListEqual(
            self.bn_bif.V, [
                'Smoker', 'Pollution', 'Cancer', 'Xray', 'Dyspnoea'])

    def test_E_bif(self):
        self.assertDictEqual(self.bn_bif.E,
                             {'Cancer': ['Xray', 'Dyspnoea'],
                              'Dyspnoea': [],
                              'Pollution': ['Cancer'],
                              'Smoker': ['Cancer'],
                                 'Xray': []})

    def test_F_bif(self):
        self.assertDictEqual(self.bn_bif.F,
                             {'Cancer': {'cpt': [0.03, 0.97, 0.05, 0.95, 0.001, 0.999, 0.02, 0.98],
                                         'parents': ['Pollution', 'Smoker'],
                                         'values': ['True', 'False']},
                                 'Dyspnoea': {'cpt': [0.65, 0.35, 0.3, 0.7],
                              'parents': ['Cancer'],
                              'values': ['True', 'False']},
                                 'Pollution': {'cpt': [0.9, 0.1], 'parents': [], 'values': ['low', 'high']},
                                 'Smoker': {'cpt': [0.3, 0.7], 'parents': [], 'values': ['True', 'False']},
                                 'Xray': {'cpt': [0.9, 0.1, 0.2, 0.8],
                                          'parents': ['Cancer'],
                                          'values': ['positive', 'negative']}})

    def test_V_bn(self):
        self.assertListEqual(
            self.bn_bn.V, [
                'Burglary', 'Earthquake', 'Alarm', 'JohnCalls', 'MaryCalls'])

    def test_E_bn(self):
        self.assertDictEqual(self.bn_bn.E,
                             {'Alarm': ['JohnCalls', 'MaryCalls'],
                              'Burglary': ['Alarm'],
                              'Earthquake': ['Alarm'],
                              'JohnCalls': [],
                              'MaryCalls': []})

    def test_F_bn(self):
        self.assertDictEqual(self.bn_bn.F,
                             {'Alarm': {'cpt': [0.999, 0.001, 0.71, 0.29, 0.06, 0.94, 0.05, 0.95],
                                        'parents': ['Earthquake', 'Burglary'],
                                        'values': ['No', 'Yes']},
                                 'Burglary': {'cpt': [0.999, 0.001], 'parents': [], 'values': ['No', 'Yes']},
                                 'Earthquake': {'cpt': [0.998, 0.002], 'parents': [], 'values': ['No', 'Yes']},
                                 'JohnCalls': {'cpt': [0.95, 0.05, 0.1, 0.9],
                                               'parents': ['Alarm'],
                                               'values': ['No', 'Yes']},
                                 'MaryCalls': {'cpt': [0.99, 0.01, 0.3, 0.7],
                                               'parents': ['Alarm'],
                                               'values': ['No', 'Yes']}})

    def test_nodes(self):
        n = list(self.bn_bn.nodes())
        self.assertListEqual(
            n, ['Burglary', 'Earthquake', 'Alarm', 'JohnCalls', 'MaryCalls'])

    def test_cpt(self):
        cpt = list(self.bn_bn.cpt('Alarm'))
        self.assertListEqual(
            cpt, [0.999, 0.001, 0.71, 0.29, 0.06, 0.94, 0.05, 0.95])

    def test_card(self):
        self.assertEqual(self.bn_bn.card('Alarm'), 2)

    def test_scope(self):
        self.assertListEqual(self.bn_bn.scope('Alarm'),
                             ['Alarm', 'Earthquake', 'Burglary'])

    def test_parents(self):
        self.assertListEqual(self.bn_bn.parents('Alarm'),
                             ['Earthquake', 'Burglary'])

    def test_values(self):
        self.assertListEqual(self.bn_bn.values('Alarm'), ['No', 'Yes'])

    def test_values_idx(self):
        self.assertEqual(self.bn_bn.values('Alarm')[1], 'Yes')


if __name__ == '__main__':
    unittest.main(exit=False)
