Example #1
0
def find_widths_brute(file, keep_atts, edges):
    graph = create_bayes_net(file, keep_atts, edges)
    N = len(keep_atts)
    perms = list(itertools.permutations(keep_atts))
    ATT_DICT = {keep_atts[i]: i + 1 for i in range(0, len(keep_atts))}
    mgraph = graph.to_markov_model()

    inference = VariableElimination(mgraph)
    max_widths = []
    cliques = []
    dictionaries = []
    sat_runtimes = []
    total_sat_runtime = 0
    for perm in tqdm.tqdm(perms):
        adj_matrix = np.zeros((N, N))
        igraph = inference.induced_graph(list(perm))

        edges = igraph.edges
        for ed in edges:
            first, second = ed
            first = ATT_DICT[first] - 1
            second = ATT_DICT[second] - 1
            adj_matrix[first, second] = 1
            adj_matrix[second, first] = 1
            adj_matrix[first, first] = 1
            adj_matrix[second, second] = 1
        adj_matrix = adj_matrix.astype(bool)
        max_width = 0
        curr_clique = []
        curr_dict = {}
        runtime = 0
        start_time = time.time()
        iwidth = inference.induced_width(list(perm))
        end_time = time.time()
        runtime = end_time - start_time
        total_sat_runtime += runtime
        max_widths.append(iwidth)
        cliques.append(curr_clique)
        dictionaries.append(curr_dict)
        sat_runtimes.append(runtime)
    return np.array(
        max_widths), cliques, dictionaries, sat_runtimes, total_sat_runtime
Example #2
0
class TestVariableElimination(unittest.TestCase):
    def setUp(self):
        self.bayesian_model = BayesianModel([('A', 'J'), ('R', 'J'),
                                             ('J', 'Q'), ('J', 'L'),
                                             ('G', 'L')])
        cpd_a = TabularCPD('A', 2, [[0.2], [0.8]])
        cpd_r = TabularCPD('R', 2, [[0.4], [0.6]])
        cpd_j = TabularCPD('J', 2,
                           [[0.9, 0.6, 0.7, 0.1], [0.1, 0.4, 0.3, 0.9]],
                           ['R', 'A'], [2, 2])
        cpd_q = TabularCPD('Q', 2, [[0.9, 0.2], [0.1, 0.8]], ['J'], [2])
        cpd_l = TabularCPD('L', 2,
                           [[0.9, 0.45, 0.8, 0.1], [0.1, 0.55, 0.2, 0.9]],
                           ['G', 'J'], [2, 2])
        cpd_g = TabularCPD('G', 2, [[0.6], [0.4]])
        self.bayesian_model.add_cpds(cpd_a, cpd_g, cpd_j, cpd_l, cpd_q, cpd_r)

        self.bayesian_inference = VariableElimination(self.bayesian_model)

    # All the values that are used for comparision in the all the tests are
    # found using SAMIAM (assuming that it is correct ;))

    def test_query_single_variable(self):
        query_result = self.bayesian_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

    def test_query_multiple_variable(self):
        query_result = self.bayesian_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

    def test_query_single_variable_with_evidence(self):
        query_result = self.bayesian_inference.query(variables=['J'],
                                                     evidence={
                                                         'A': 0,
                                                         'R': 1
                                                     })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

    def test_query_multiple_variable_with_evidence(self):
        query_result = self.bayesian_inference.query(variables=['J', 'Q'],
                                                     evidence={
                                                         'A': 0,
                                                         'R': 0,
                                                         'G': 0,
                                                         'L': 1
                                                     })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_query_multiple_times(self):
        # This just tests that the models are not getting modified while querying them
        query_result = self.bayesian_inference.query(['J'])
        query_result = self.bayesian_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

        query_result = self.bayesian_inference.query(['Q', 'J'])
        query_result = self.bayesian_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

        query_result = self.bayesian_inference.query(variables=['J'],
                                                     evidence={
                                                         'A': 0,
                                                         'R': 1
                                                     })
        query_result = self.bayesian_inference.query(variables=['J'],
                                                     evidence={
                                                         'A': 0,
                                                         'R': 1
                                                     })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

        query_result = self.bayesian_inference.query(variables=['J', 'Q'],
                                                     evidence={
                                                         'A': 0,
                                                         'R': 0,
                                                         'G': 0,
                                                         'L': 1
                                                     })
        query_result = self.bayesian_inference.query(variables=['J', 'Q'],
                                                     evidence={
                                                         'A': 0,
                                                         'R': 0,
                                                         'G': 0,
                                                         'L': 1
                                                     })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_max_marginal(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(),
                                    0.1659,
                                    decimal=4)

    def test_max_marginal_var(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(['G'
                                                                          ]),
                                    0.5714,
                                    decimal=4)

    def test_max_marginal_var1(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(
            ['G', 'R']),
                                    0.4055,
                                    decimal=4)

    def test_max_marginal_var2(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(
            ['G', 'R', 'A']),
                                    0.3260,
                                    decimal=4)

    def test_map_query(self):
        map_query = self.bayesian_inference.map_query()
        self.assertDictEqual(map_query, {
            'A': 1,
            'R': 1,
            'J': 1,
            'Q': 1,
            'G': 0,
            'L': 0
        })

    def test_map_query_with_evidence(self):
        map_query = self.bayesian_inference.map_query(['A', 'R', 'L'], {
            'J': 0,
            'Q': 1,
            'G': 0
        })
        self.assertDictEqual(map_query, {'A': 1, 'R': 0, 'L': 0})

    def test_induced_graph(self):
        induced_graph = self.bayesian_inference.induced_graph(
            ['G', 'Q', 'A', 'J', 'L', 'R'])
        result_edges = sorted([sorted(x) for x in induced_graph.edges()])
        self.assertEqual([['A', 'J'], ['A', 'R'], ['G', 'J'], ['G', 'L'],
                          ['J', 'L'], ['J', 'Q'], ['J', 'R'], ['L', 'R']],
                         result_edges)

    def test_induced_width(self):
        result_width = self.bayesian_inference.induced_width(
            ['G', 'Q', 'A', 'J', 'L', 'R'])
        self.assertEqual(2, result_width)

    def tearDown(self):
        del self.bayesian_inference
        del self.bayesian_model
Example #3
0
class TestVariableEliminationMarkov(unittest.TestCase):
    def setUp(self):
        # It is just a moralised version of the above Bayesian network so all the results are same. Only factors
        # are under consideration for inference so this should be fine.
        self.markov_model = MarkovModel([
            ("A", "J"),
            ("R", "J"),
            ("J", "Q"),
            ("J", "L"),
            ("G", "L"),
            ("A", "R"),
            ("J", "G"),
        ])

        factor_a = TabularCPD("A", 2, values=[[0.2], [0.8]]).to_factor()
        factor_r = TabularCPD("R", 2, values=[[0.4], [0.6]]).to_factor()
        factor_j = TabularCPD(
            "J",
            2,
            values=[[0.9, 0.6, 0.7, 0.1], [0.1, 0.4, 0.3, 0.9]],
            evidence=["A", "R"],
            evidence_card=[2, 2],
        ).to_factor()
        factor_q = TabularCPD("Q",
                              2,
                              values=[[0.9, 0.2], [0.1, 0.8]],
                              evidence=["J"],
                              evidence_card=[2]).to_factor()
        factor_l = TabularCPD(
            "L",
            2,
            values=[[0.9, 0.45, 0.8, 0.1], [0.1, 0.55, 0.2, 0.9]],
            evidence=["J", "G"],
            evidence_card=[2, 2],
        ).to_factor()
        factor_g = TabularCPD("G", 2, [[0.6], [0.4]]).to_factor()

        self.markov_model.add_factors(factor_a, factor_r, factor_j, factor_q,
                                      factor_l, factor_g)
        self.markov_inference = VariableElimination(self.markov_model)

    # All the values that are used for comparision in the all the tests are
    # found using SAMIAM (assuming that it is correct ;))

    def test_query_single_variable(self):
        query_result = self.markov_inference.query(["J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"],
                           cardinality=[2],
                           values=np.array([0.416, 0.584])),
        )

    def test_query_multiple_variable(self):
        query_result = self.markov_inference.query(["Q", "J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["Q", "J"],
                cardinality=[2, 2],
                values=np.array([[0.3744, 0.1168], [0.0416, 0.4672]]),
            ),
        )

    def test_query_single_variable_with_evidence(self):
        query_result = self.markov_inference.query(variables=["J"],
                                                   evidence={
                                                       "A": 0,
                                                       "R": 1
                                                   })
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"], cardinality=[2], values=[0.6,
                                                                     0.4]),
        )

    def test_query_multiple_variable_with_evidence(self):
        query_result = self.markov_inference.query(variables=["J", "Q"],
                                                   evidence={
                                                       "A": 0,
                                                       "R": 0,
                                                       "G": 0,
                                                       "L": 1
                                                   })
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["Q", "J"],
                cardinality=[2, 2],
                values=np.array([[0.081, 0.004], [0.009, 0.016]]),
            ),
        )

    def test_query_multiple_times(self):
        # This just tests that the models are not getting modified while querying them
        query_result = self.markov_inference.query(["J"])
        query_result = self.markov_inference.query(["J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"],
                           cardinality=[2],
                           values=np.array([0.416, 0.584])),
        )

        query_result = self.markov_inference.query(["Q", "J"])
        query_result = self.markov_inference.query(["Q", "J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["Q", "J"],
                cardinality=[2, 2],
                values=np.array([[0.3744, 0.1168], [0.0416, 0.4672]]),
            ),
        )

        query_result = self.markov_inference.query(variables=["J"],
                                                   evidence={
                                                       "A": 0,
                                                       "R": 1
                                                   })
        query_result = self.markov_inference.query(variables=["J"],
                                                   evidence={
                                                       "A": 0,
                                                       "R": 1
                                                   })
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"], cardinality=[2], values=[0.6,
                                                                     0.4]),
        )

        query_result = self.markov_inference.query(variables=["J", "Q"],
                                                   evidence={
                                                       "A": 0,
                                                       "R": 0,
                                                       "G": 0,
                                                       "L": 1
                                                   })
        query_result = self.markov_inference.query(variables=["J", "Q"],
                                                   evidence={
                                                       "A": 0,
                                                       "R": 0,
                                                       "G": 0,
                                                       "L": 1
                                                   })
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["Q", "J"],
                cardinality=[2, 2],
                values=np.array([[0.081, 0.004], [0.009, 0.016]]),
            ),
        )

    def test_max_marginal(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(),
                                    0.1659,
                                    decimal=4)

    def test_max_marginal_var(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(["G"]),
                                    0.1659,
                                    decimal=4)

    def test_max_marginal_var1(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(
            ["G", "R"]),
                                    0.1659,
                                    decimal=4)

    def test_max_marginal_var2(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(
            ["G", "R", "A"]),
                                    0.1659,
                                    decimal=4)

    def test_map_query(self):
        map_query = self.markov_inference.map_query()
        self.assertDictEqual(map_query, {
            "A": 1,
            "R": 1,
            "J": 1,
            "Q": 1,
            "G": 0,
            "L": 0
        })

    def test_map_query_with_evidence(self):
        map_query = self.markov_inference.map_query(["A", "R", "L"], {
            "J": 0,
            "Q": 1,
            "G": 0
        })
        self.assertDictEqual(map_query, {"A": 1, "R": 0, "L": 0})

    def test_induced_graph(self):
        induced_graph = self.markov_inference.induced_graph(
            ["G", "Q", "A", "J", "L", "R"])
        result_edges = sorted([sorted(x) for x in induced_graph.edges()])
        self.assertEqual(
            [
                ["A", "J"],
                ["A", "R"],
                ["G", "J"],
                ["G", "L"],
                ["J", "L"],
                ["J", "Q"],
                ["J", "R"],
                ["L", "R"],
            ],
            result_edges,
        )

    def test_induced_width(self):
        result_width = self.markov_inference.induced_width(
            ["G", "Q", "A", "J", "L", "R"])
        self.assertEqual(2, result_width)

    def tearDown(self):
        del self.markov_inference
        del self.markov_model
Example #4
0
class TestVariableElimination(unittest.TestCase):
    def setUp(self):
        self.bayesian_model = BayesianModel([("A", "J"), ("R", "J"),
                                             ("J", "Q"), ("J", "L"),
                                             ("G", "L")])
        cpd_a = TabularCPD("A", 2, values=[[0.2], [0.8]])
        cpd_r = TabularCPD("R", 2, values=[[0.4], [0.6]])
        cpd_j = TabularCPD(
            "J",
            2,
            values=[[0.9, 0.6, 0.7, 0.1], [0.1, 0.4, 0.3, 0.9]],
            evidence=["A", "R"],
            evidence_card=[2, 2],
        )
        cpd_q = TabularCPD("Q",
                           2,
                           values=[[0.9, 0.2], [0.1, 0.8]],
                           evidence=["J"],
                           evidence_card=[2])
        cpd_l = TabularCPD(
            "L",
            2,
            values=[[0.9, 0.45, 0.8, 0.1], [0.1, 0.55, 0.2, 0.9]],
            evidence=["J", "G"],
            evidence_card=[2, 2],
        )
        cpd_g = TabularCPD("G", 2, values=[[0.6], [0.4]])
        self.bayesian_model.add_cpds(cpd_a, cpd_g, cpd_j, cpd_l, cpd_q, cpd_r)

        self.bayesian_inference = VariableElimination(self.bayesian_model)

    # All the values that are used for comparision in the all the tests are
    # found using SAMIAM (assuming that it is correct ;))

    def test_query_single_variable(self):
        query_result = self.bayesian_inference.query(["J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"],
                           cardinality=[2],
                           values=[0.416, 0.584]),
        )

    def test_query_multiple_variable(self):
        query_result = self.bayesian_inference.query(["Q", "J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["J", "Q"],
                cardinality=[2, 2],
                values=np.array([[0.3744, 0.0416], [0.1168, 0.4672]]),
            ),
        )

    def test_query_single_variable_with_evidence(self):
        query_result = self.bayesian_inference.query(variables=["J"],
                                                     evidence={
                                                         "A": 0,
                                                         "R": 1
                                                     })
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"], cardinality=[2], values=[0.6,
                                                                     0.4]),
        )

    def test_query_multiple_variable_with_evidence(self):
        query_result = self.bayesian_inference.query(variables=["J", "Q"],
                                                     evidence={
                                                         "A": 0,
                                                         "R": 0,
                                                         "G": 0,
                                                         "L": 1
                                                     })
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["J", "Q"],
                cardinality=[2, 2],
                values=np.array([[0.73636364, 0.08181818],
                                 [0.03636364, 0.14545455]]),
            ),
        )

    def test_query_multiple_times(self):
        # This just tests that the models are not getting modified while querying them
        query_result = self.bayesian_inference.query(["J"])
        query_result = self.bayesian_inference.query(["J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"],
                           cardinality=[2],
                           values=np.array([0.416, 0.584])),
        )

        query_result = self.bayesian_inference.query(["Q", "J"])
        query_result = self.bayesian_inference.query(["Q", "J"])
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["J", "Q"],
                cardinality=[2, 2],
                values=np.array([[0.3744, 0.0416], [0.1168, 0.4672]]),
            ),
        )

        query_result = self.bayesian_inference.query(variables=["J"],
                                                     evidence={
                                                         "A": 0,
                                                         "R": 1
                                                     })
        query_result = self.bayesian_inference.query(variables=["J"],
                                                     evidence={
                                                         "A": 0,
                                                         "R": 1
                                                     })
        self.assertEqual(
            query_result,
            DiscreteFactor(variables=["J"], cardinality=[2], values=[0.6,
                                                                     0.4]),
        )

        query_result = self.bayesian_inference.query(variables=["J", "Q"],
                                                     evidence={
                                                         "A": 0,
                                                         "R": 0,
                                                         "G": 0,
                                                         "L": 1
                                                     })
        query_result = self.bayesian_inference.query(variables=["J", "Q"],
                                                     evidence={
                                                         "A": 0,
                                                         "R": 0,
                                                         "G": 0,
                                                         "L": 1
                                                     })
        self.assertEqual(
            query_result,
            DiscreteFactor(
                variables=["J", "Q"],
                cardinality=[2, 2],
                values=np.array([[0.73636364, 0.08181818],
                                 [0.03636364, 0.14545455]]),
            ),
        )

    def test_max_marginal(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(),
                                    0.1659,
                                    decimal=4)

    def test_max_marginal_var(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(["G"
                                                                          ]),
                                    0.5714,
                                    decimal=4)

    def test_max_marginal_var1(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(
            ["G", "R"]),
                                    0.3740,
                                    decimal=4)

    def test_max_marginal_var2(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(
            ["G", "R", "A"]),
                                    0.3061,
                                    decimal=4)

    def test_map_query(self):
        map_query = self.bayesian_inference.map_query()
        self.assertDictEqual(map_query, {
            "A": 1,
            "R": 1,
            "J": 1,
            "Q": 1,
            "G": 0,
            "L": 0
        })

    def test_map_query_with_evidence(self):
        map_query = self.bayesian_inference.map_query(["A", "R", "L"], {
            "J": 0,
            "Q": 1,
            "G": 0
        })
        self.assertDictEqual(map_query, {"A": 1, "R": 0, "L": 0})

    def test_induced_graph(self):
        induced_graph = self.bayesian_inference.induced_graph(
            ["G", "Q", "A", "J", "L", "R"])
        result_edges = sorted([sorted(x) for x in induced_graph.edges()])
        self.assertEqual(
            [
                ["A", "J"],
                ["A", "R"],
                ["G", "J"],
                ["G", "L"],
                ["J", "L"],
                ["J", "Q"],
                ["J", "R"],
                ["L", "R"],
            ],
            result_edges,
        )

    def test_induced_width(self):
        result_width = self.bayesian_inference.induced_width(
            ["G", "Q", "A", "J", "L", "R"])
        self.assertEqual(2, result_width)

    def tearDown(self):
        del self.bayesian_inference
        del self.bayesian_model
Example #5
0
class TestVariableElimination(unittest.TestCase):
    def setUp(self):
        self.bayesian_model = BayesianModel([('A', 'J'), ('R', 'J'), ('J', 'Q'),
                                             ('J', 'L'), ('G', 'L')])
        cpd_a = TabularCPD('A', 2, [[0.2], [0.8]])
        cpd_r = TabularCPD('R', 2, [[0.4], [0.6]])
        cpd_j = TabularCPD('J', 2,
                           [[0.9, 0.6, 0.7, 0.1],
                            [0.1, 0.4, 0.3, 0.9]],
                           ['R', 'A'], [2, 2])
        cpd_q = TabularCPD('Q', 2,
                           [[0.9, 0.2],
                            [0.1, 0.8]],
                           ['J'], [2])
        cpd_l = TabularCPD('L', 2,
                           [[0.9, 0.45, 0.8, 0.1],
                            [0.1, 0.55, 0.2, 0.9]],
                           ['G', 'J'], [2, 2])
        cpd_g = TabularCPD('G', 2, [[0.6], [0.4]])
        self.bayesian_model.add_cpds(cpd_a, cpd_g, cpd_j, cpd_l, cpd_q, cpd_r)

        self.bayesian_inference = VariableElimination(self.bayesian_model)

    # All the values that are used for comparision in the all the tests are
    # found using SAMIAM (assuming that it is correct ;))

    def test_query_single_variable(self):
        query_result = self.bayesian_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

    def test_query_multiple_variable(self):
        query_result = self.bayesian_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

    def test_query_single_variable_with_evidence(self):
        query_result = self.bayesian_inference.query(variables=['J'],
                                                     evidence={'A': 0, 'R': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

    def test_query_multiple_variable_with_evidence(self):
        query_result = self.bayesian_inference.query(variables=['J', 'Q'],
                                                     evidence={'A': 0, 'R': 0,
                                                               'G': 0, 'L': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_query_multiple_times(self):
        # This just tests that the models are not getting modified while querying them
        query_result = self.bayesian_inference.query(['J'])
        query_result = self.bayesian_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

        query_result = self.bayesian_inference.query(['Q', 'J'])
        query_result = self.bayesian_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

        query_result = self.bayesian_inference.query(variables=['J'],
                                                     evidence={'A': 0, 'R': 1})
        query_result = self.bayesian_inference.query(variables=['J'],
                                                     evidence={'A': 0, 'R': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

        query_result = self.bayesian_inference.query(variables=['J', 'Q'],
                                                     evidence={'A': 0, 'R': 0,
                                                               'G': 0, 'L': 1})
        query_result = self.bayesian_inference.query(variables=['J', 'Q'],
                                                     evidence={'A': 0, 'R': 0,
                                                               'G': 0, 'L': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))



    def test_max_marginal(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(), 0.1659, decimal=4)

    def test_max_marginal_var(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(['G']), 0.5714, decimal=4)

    def test_max_marginal_var1(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(['G', 'R']),
                                    0.4055, decimal=4)

    def test_max_marginal_var2(self):
        np_test.assert_almost_equal(self.bayesian_inference.max_marginal(['G', 'R', 'A']),
                                    0.3260, decimal=4)

    def test_map_query(self):
        map_query = self.bayesian_inference.map_query()
        self.assertDictEqual(map_query, {'A': 1, 'R': 1, 'J': 1, 'Q': 1, 'G': 0,
                                         'L': 0})

    def test_map_query_with_evidence(self):
        map_query = self.bayesian_inference.map_query(['A', 'R', 'L'],
                                                      {'J': 0, 'Q': 1, 'G': 0})
        self.assertDictEqual(map_query, {'A': 1, 'R': 0, 'L': 0})

    def test_induced_graph(self):
        induced_graph = self.bayesian_inference.induced_graph(['G', 'Q', 'A', 'J', 'L', 'R'])
        result_edges = sorted([sorted(x) for x in induced_graph.edges()])
        self.assertEqual([['A', 'J'], ['A', 'R'], ['G', 'J'], ['G', 'L'],
                          ['J', 'L'], ['J', 'Q'], ['J', 'R'], ['L', 'R']],
                         result_edges)

    def test_induced_width(self):
        result_width = self.bayesian_inference.induced_width(['G', 'Q', 'A', 'J', 'L', 'R'])
        self.assertEqual(2, result_width)

    def tearDown(self):
        del self.bayesian_inference
        del self.bayesian_model
class TestVariableEliminationMarkov(unittest.TestCase):
    def setUp(self):
        # It is just a moralised version of the above Bayesian network so all the results are same. Only factors
        # are under consideration for inference so this should be fine.
        self.markov_model = MarkovModel([('A', 'J'), ('R', 'J'), ('J', 'Q'), ('J', 'L'),
                                         ('G', 'L'), ('A', 'R'), ('J', 'G')])

        factor_a = TabularCPD('A', 2, values=[[0.2], [0.8]]).to_factor()
        factor_r = TabularCPD('R', 2, values=[[0.4], [0.6]]).to_factor()
        factor_j = TabularCPD('J', 2, values=[[0.9, 0.6, 0.7, 0.1],
                                              [0.1, 0.4, 0.3, 0.9]],
                              evidence=['A', 'R'], evidence_card=[2, 2]).to_factor()
        factor_q = TabularCPD('Q', 2, values=[[0.9, 0.2], [0.1, 0.8]],
                              evidence=['J'], evidence_card=[2]).to_factor()
        factor_l = TabularCPD('L', 2, values=[[0.9, 0.45, 0.8, 0.1],
                                              [0.1, 0.55, 0.2, 0.9]],
                              evidence=['J', 'G'], evidence_card=[2, 2]).to_factor()
        factor_g = TabularCPD('G', 2, [[0.6], [0.4]]).to_factor()

        self.markov_model.add_factors(factor_a, factor_r, factor_j, factor_q, factor_l, factor_g)
        self.markov_inference = VariableElimination(self.markov_model)

    # All the values that are used for comparision in the all the tests are
    # found using SAMIAM (assuming that it is correct ;))

    def test_query_single_variable(self):
        query_result = self.markov_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

    def test_query_multiple_variable(self):
        query_result = self.markov_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

    def test_query_single_variable_with_evidence(self):
        query_result = self.markov_inference.query(variables=['J'],
                                                   evidence={'A': 0, 'R': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

    def test_query_multiple_variable_with_evidence(self):
        query_result = self.markov_inference.query(variables=['J', 'Q'],
                                                   evidence={'A': 0, 'R': 0,
                                                             'G': 0, 'L': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_query_multiple_times(self):
        # This just tests that the models are not getting modified while querying them
        query_result = self.markov_inference.query(['J'])
        query_result = self.markov_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

        query_result = self.markov_inference.query(['Q', 'J'])
        query_result = self.markov_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

        query_result = self.markov_inference.query(variables=['J'],
                                                   evidence={'A': 0, 'R': 1})
        query_result = self.markov_inference.query(variables=['J'],
                                                   evidence={'A': 0, 'R': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

        query_result = self.markov_inference.query(variables=['J', 'Q'],
                                                   evidence={'A': 0, 'R': 0,
                                                             'G': 0, 'L': 1})
        query_result = self.markov_inference.query(variables=['J', 'Q'],
                                                   evidence={'A': 0, 'R': 0,
                                                             'G': 0, 'L': 1})
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_max_marginal(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(), 0.1659, decimal=4)

    def test_max_marginal_var(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(['G']), 0.5714, decimal=4)

    def test_max_marginal_var1(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(['G', 'R']),
                                    0.4055, decimal=4)

    def test_max_marginal_var2(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(['G', 'R', 'A']),
                                    0.3260, decimal=4)

    def test_map_query(self):
        map_query = self.markov_inference.map_query()
        self.assertDictEqual(map_query, {'A': 1, 'R': 1, 'J': 1, 'Q': 1, 'G': 0, 'L': 0})

    def test_map_query_with_evidence(self):
        map_query = self.markov_inference.map_query(['A', 'R', 'L'],
                                                    {'J': 0, 'Q': 1, 'G': 0})
        self.assertDictEqual(map_query, {'A': 1, 'R': 0, 'L': 0})

    def test_induced_graph(self):
        induced_graph = self.markov_inference.induced_graph(['G', 'Q', 'A', 'J', 'L', 'R'])
        result_edges = sorted([sorted(x) for x in induced_graph.edges()])
        self.assertEqual([['A', 'J'], ['A', 'R'], ['G', 'J'], ['G', 'L'],
                          ['J', 'L'], ['J', 'Q'], ['J', 'R'], ['L', 'R']],
                         result_edges)

    def test_induced_width(self):
        result_width = self.markov_inference.induced_width(['G', 'Q', 'A', 'J', 'L', 'R'])
        self.assertEqual(2, result_width)

    def tearDown(self):
        del self.markov_inference
        del self.markov_model
class TestVariableEliminationMarkov(unittest.TestCase):
    def setUp(self):
        # It is just a moralised version of the above Bayesian network so all the results are same. Only factors
        # are under consideration for inference so this should be fine.
        self.markov_model = MarkovModel([('A', 'J'), ('R', 'J'), ('J', 'Q'),
                                         ('J', 'L'), ('G', 'L'), ('A', 'R'),
                                         ('J', 'G')])

        factor_a = TabularCPD('A', 2, values=[[0.2], [0.8]]).to_factor()
        factor_r = TabularCPD('R', 2, values=[[0.4], [0.6]]).to_factor()
        factor_j = TabularCPD('J',
                              2,
                              values=[[0.9, 0.6, 0.7, 0.1],
                                      [0.1, 0.4, 0.3, 0.9]],
                              evidence=['A', 'R'],
                              evidence_card=[2, 2]).to_factor()
        factor_q = TabularCPD('Q',
                              2,
                              values=[[0.9, 0.2], [0.1, 0.8]],
                              evidence=['J'],
                              evidence_card=[2]).to_factor()
        factor_l = TabularCPD('L',
                              2,
                              values=[[0.9, 0.45, 0.8, 0.1],
                                      [0.1, 0.55, 0.2, 0.9]],
                              evidence=['J', 'G'],
                              evidence_card=[2, 2]).to_factor()
        factor_g = TabularCPD('G', 2, [[0.6], [0.4]]).to_factor()

        self.markov_model.add_factors(factor_a, factor_r, factor_j, factor_q,
                                      factor_l, factor_g)
        self.markov_inference = VariableElimination(self.markov_model)

    # All the values that are used for comparision in the all the tests are
    # found using SAMIAM (assuming that it is correct ;))

    def test_query_single_variable(self):
        query_result = self.markov_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

    def test_query_multiple_variable(self):
        query_result = self.markov_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

    def test_query_single_variable_with_evidence(self):
        query_result = self.markov_inference.query(variables=['J'],
                                                   evidence={
                                                       'A': 0,
                                                       'R': 1
                                                   })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

    def test_query_multiple_variable_with_evidence(self):
        query_result = self.markov_inference.query(variables=['J', 'Q'],
                                                   evidence={
                                                       'A': 0,
                                                       'R': 0,
                                                       'G': 0,
                                                       'L': 1
                                                   })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_query_multiple_times(self):
        # This just tests that the models are not getting modified while querying them
        query_result = self.markov_inference.query(['J'])
        query_result = self.markov_inference.query(['J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))

        query_result = self.markov_inference.query(['Q', 'J'])
        query_result = self.markov_inference.query(['Q', 'J'])
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.416, 0.584]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.4912, 0.5088]))

        query_result = self.markov_inference.query(variables=['J'],
                                                   evidence={
                                                       'A': 0,
                                                       'R': 1
                                                   })
        query_result = self.markov_inference.query(variables=['J'],
                                                   evidence={
                                                       'A': 0,
                                                       'R': 1
                                                   })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.60, 0.40]))

        query_result = self.markov_inference.query(variables=['J', 'Q'],
                                                   evidence={
                                                       'A': 0,
                                                       'R': 0,
                                                       'G': 0,
                                                       'L': 1
                                                   })
        query_result = self.markov_inference.query(variables=['J', 'Q'],
                                                   evidence={
                                                       'A': 0,
                                                       'R': 0,
                                                       'G': 0,
                                                       'L': 1
                                                   })
        np_test.assert_array_almost_equal(query_result['J'].values,
                                          np.array([0.818182, 0.181818]))
        np_test.assert_array_almost_equal(query_result['Q'].values,
                                          np.array([0.772727, 0.227273]))

    def test_max_marginal(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(),
                                    0.1659,
                                    decimal=4)

    def test_max_marginal_var(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(['G']),
                                    0.5714,
                                    decimal=4)

    def test_max_marginal_var1(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(
            ['G', 'R']),
                                    0.4055,
                                    decimal=4)

    def test_max_marginal_var2(self):
        np_test.assert_almost_equal(self.markov_inference.max_marginal(
            ['G', 'R', 'A']),
                                    0.3260,
                                    decimal=4)

    def test_map_query(self):
        map_query = self.markov_inference.map_query()
        self.assertDictEqual(map_query, {
            'A': 1,
            'R': 1,
            'J': 1,
            'Q': 1,
            'G': 0,
            'L': 0
        })

    def test_map_query_with_evidence(self):
        map_query = self.markov_inference.map_query(['A', 'R', 'L'], {
            'J': 0,
            'Q': 1,
            'G': 0
        })
        self.assertDictEqual(map_query, {'A': 1, 'R': 0, 'L': 0})

    def test_induced_graph(self):
        induced_graph = self.markov_inference.induced_graph(
            ['G', 'Q', 'A', 'J', 'L', 'R'])
        result_edges = sorted([sorted(x) for x in induced_graph.edges()])
        self.assertEqual([['A', 'J'], ['A', 'R'], ['G', 'J'], ['G', 'L'],
                          ['J', 'L'], ['J', 'Q'], ['J', 'R'], ['L', 'R']],
                         result_edges)

    def test_induced_width(self):
        result_width = self.markov_inference.induced_width(
            ['G', 'Q', 'A', 'J', 'L', 'R'])
        self.assertEqual(2, result_width)

    def tearDown(self):
        del self.markov_inference
        del self.markov_model